Skip to content

Commit

Permalink
Merge pull request #7 from avilum/feature/yaml_templates_and_docs
Browse files Browse the repository at this point in the history
Added pickle documentation and improved docs
  • Loading branch information
avilum authored Aug 21, 2022
2 parents 85a3aed + 510e8dd commit ce4b23b
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 24 deletions.
73 changes: 64 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,66 @@ Secure import for python modules using dtrace under the hood.<br>


# Quick Start
`secimport` can be used out of the box in the following ways:
1. Inside your code using `module = secimport.secure_import('module_name', ...)`.
- Replacing the regular `import` statement with `secure_import`
- Only modules that were imported with `secure_import` will be traced.
2. As a sandbox, by specifying the modules and their policies.
- Use this repository to:
- Generate a YAML policy from your code
- Compile that YAML to dscript.
- Use `dtrace` command to run your main python application, with your tailor-made sandbox.
- No need for `secure_import`, you can keep using regular `import`s

For the full list of examples, see <a href="docs/EXAMPLES.md">EXAMPLES.md</a>.

# Pickle Example
### How pickle can be exploited in your 3rd party packages:
```python
>>> import pickle
>>> class Demo:
... def __reduce__(self):
... return (eval, ("__import__('os').system('echo Exploited!')",))
...
>>> pickle.dumps(Demo())
b"\x80\x04\x95F\x00\x00\x00\x00\x00\x00\x00\x8c\x08builtins\x94\x8c\x04eval\x94\x93\x94\x8c*__import__('os').system('echo Exploited!')\x94\x85\x94R\x94."
>>> pickle.loads(b"\x80\x04\x95F\x00\x00\x00\x00\x00\x00\x00\x8c\x08builtins\x94\x8c\x04eval\x94\x93\x94\x8c*__import__('os').system('echo Exploited!')\x94\x85\x94R\x94.")
Exploited!
0
```
With `secimport`, you can control such action to do whatever you want:
```python
In [1]: import secimport
In [2]: pickle = secimport.secure_import("pickle")
In [3]: pickle.loads(b"\x80\x04\x95F\x00\x00\x00\x00\x00\x00\x00\x8c\x08builtins\x94\x8c\x04eval\x94\x93\x94\x8c*__import__('os').system('echo Exploited!')\x94\x85\x94R\x94.")

[1] 28027 killed ipython
```
A log file is automatically created, containing everything you need to know:
```
$ less /tmp/.secimport/sandbox_pickle.log
@posix_spawn from /Users/avilumelsky/Downloads/Python-3.10.0/Lib/threading.py
DETECTED SHELL:
depth=8
sandboxed_depth=0
sandboxed_module=/Users/avilumelsky/Downloads/Python-3.10.0/Lib/pickle.py
TERMINATING SHELL:
libsystem_kernel.dylib`__posix_spawn+0xa
...
libsystem_kernel.dylib`__posix_spawn+0xa
libsystem_c.dylib`system+0x18b
python.exe`os_system+0xb3
KILLED
:
```

## YAML Template Example
For a full tutorial, see <a href="docs/YAML_PROFILES.md">YAML Profiles Usage</a>
```shell
# An example yaml template for a sandbox.

modules:
requests:
destructive: true
Expand All @@ -45,9 +101,8 @@ modules:
- stat64

```
See <a href="docs/YAML_PROFILES.md">YAML Profiles Usage</a>

## Python Shell Interactive Example
## Python Processing Example
```python
Python 3.10.0 (default, May 2 2022, 21:43:20) [Clang 13.0.0 (clang-1300.0.27.3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
Expand Down Expand Up @@ -93,7 +148,7 @@ Type "help", "copyright", "credits" or "license" for more information.
killed.
```

## Shell blocking
## Shell Blocking Example
```python
# example.py - Executes code upon import;
import os;
Expand All @@ -117,7 +172,7 @@ Killed: 9
- If a syscall like `spawn/exec/fork/forkexec` will be executed
- The process will be `kill`ed with `-9` signal.

## Network blocking
## Network Blocking Example
```
>>> import requests
>>> requests.get('https://google.com')
Expand Down Expand Up @@ -166,11 +221,11 @@ Not related for python, but for the sake of explanation (Equivilant Demo soon).
<br><br>

## TODO:
- ✔️ Allow/Block list configuration
- ✔️ Create a .yaml configuration per module in the code
- ✔️ Use secimport to compile that yml
- ✔️ Create a single dcript policy
- ✔️ Run an application with that policy using dtrace, without using `secure_import`
- Node support (dtrace hooks)
- Go support (dtrace hooks)
- Allow/Block list configuration
- Use current_module_str together with thread ID
- Create a .yaml configuration per module in the code
- Use secimport to compile that yml
- Create a single dcript policy
- Run an application with that policy using dtrace, without using `secure_import`
2 changes: 1 addition & 1 deletion docs/EXAMPLES.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ To understand how to trace you process and create custom profiles for modules or
- YAML to Sandbox Example
- `examples/create_profile_from_yaml.sh`
- Create a sandbox template code for your app from a single YAML file.
- See <a href="docs/YAML_PROFILES.md">YAML Profiles Usage</a>
- See <a href="YAML_PROFILES.md">YAML Profiles Usage</a>
- Python (import inline):
- `requests` example - secure import vs regular import (Killed because of socket related syscall)
- `python examples/http_request.py`
Expand Down
4 changes: 2 additions & 2 deletions docs/TRACING_PROCESSES.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Tracing processes for syscalls
There are several ways to create a secimport profile for your modules.
- Using a YAML template
- See <a href="docs/YAML_PROFILES.md">YAML Profiles Usage</a>
- Using a YAML build
- See <a href="YAML_PROFILES.md">YAML Profiles Usage</a>
- Using `secure_import` from python:
- `secimport.secure_import(..., log_syscalls=True, destructive=False)`
- The log output will contain all the syscalls made by your process.
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "secimport"
version = "0.4.1"
version = "0.4.2"
description = "A sandbox/supervisor for python modules."
authors = ["Avi Lumelsky"]
license = "MIT"
Expand Down
18 changes: 8 additions & 10 deletions src/secimport/templates/actions/kill_on_processing.d
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
printf("\t\t\t\tDETECTED SHELL, depth=%d sandboxed_depth=%d\r\n", self->depth, depth_matrix["###MODULE_NAME###"]);
if(depth_matrix["###MODULE_NAME###"] != 0 && self->depth >= depth_matrix["###MODULE_NAME###"]){
printf("\t\tTERMINATING shell...\r\n");
ustack();
stop();
printf("\t\tKILLING...\r\n");
system("\t\tkill -9 %d", pid);
printf("\t\tKILLED.\r\n");
exit(-1);
}
printf("\t\t\t\tDETECTED SHELL, depth=%d sandboxed_depth=%d sandboxed_module=%s current_module=%s\r\n", self->depth, depth_matrix["###MODULE_NAME###"], "###MODULE_NAME###", _current_module_str);
printf("\t\tTERMINATING shell...\r\n");
ustack();
stop();
printf("\t\tKILLING...\r\n");
system("\t\tkill -9 %d", pid);
printf("\t\tKILLED.\r\n");
exit(-1);
2 changes: 1 addition & 1 deletion src/secimport/templates/actions/log_syscall.d
Original file line number Diff line number Diff line change
@@ -1 +1 @@
printf("\n@%s", probefunc);
printf("\n@%s from %s", probefunc, current_module_str);
4 changes: 4 additions & 0 deletions tests/test_sandbox_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,3 +243,7 @@ def test_build_module_sandbox_from_yaml_template(self):

self.assertIsInstance(module_sandbox_code, str)
self.assertFalse("###SUPERVISED_MODULES_PROBES###" in module_sandbox_code)


if __name__ == '__main__':

0 comments on commit ce4b23b

Please sign in to comment.