Wire - Writeup by AI

Wire - Writeup by AI

题目信息

  • 题目名称: Wire
  • 题目类型: Misc
  • 文件: timu.pcapng (4.8MB)

题目描述

本题提供了一个网络流量捕获文件(pcapng 格式),需要分析其中的数据包,提取出隐藏的 flag。

考点分析

  1. 流量分析: 使用 Wireshark 或 Python 工具分析 pcapng 文件
  2. HTTP 协议理解: 识别 HTTP 请求和响应
  3. SQL 注入攻击检测: 识别 SQL 盲注攻击模式
  4. 盲注原理: 理解基于布尔的 SQL 盲注工作原理
  5. 数据提取: 从大量流量中提取关键信息

解题思路

1. 初步分析

首先查看 pcapng 文件的内容,发现其中包含大量的 HTTP 流量。通过初步分析发现:

  • 总共有 25331 个数据包
  • 包含大量的 HTTP GET 请求
  • 请求目标为 /ctf/Less-5/,这是一个典型的 SQL 注入练习环境

2. 识别 SQL 注入模式

通过分析 HTTP 请求,发现明显的 SQL 盲注攻击特征:

复制代码
GET /ctf/Less-5/?id=1'%20and%20ascii(substr((select%20flag%20from%20t),1,1))=33--+

URL 解码后:

sql 复制代码
id=1' and ascii(substr((select flag from t),1,1))=33--+

这是典型的基于布尔的 SQL 盲注

  • 使用 ascii() 函数获取字符的 ASCII 码
  • 使用 substr() 函数逐位截取 flag
  • 通过遍历 ASCII 值(32-126)来猜测每个位置的字符

3. 盲注原理

SQL 盲注的工作原理:

  • 当条件为真时(ASCII 值匹配),页面返回正常内容(长度较短)
  • 当条件为假时(ASCII 值不匹配),页面返回错误内容(长度较长)

通过分析响应包的长度差异,可以判断哪个 ASCII 值是正确的。

4. 解题步骤

步骤 1: 读取 pcapng 文件

使用 Python 的 scapy 库读取流量文件:

python 复制代码
from scapy.all import rdpcap, Raw
packets = rdpcap('timu.pcapng')
步骤 2: 提取 HTTP 请求和响应

解析每个数据包,提取:

  • HTTP GET 请求中的 SQL 注入参数(位置和 ASCII 值)
  • HTTP 响应的内容长度
步骤 3: 配对请求和响应

将每个注入请求与其对应的响应配对,用于后续分析。

步骤 4: 分析响应长度差异

对于每个位置(position):

  • 统计所有测试的 ASCII 值对应的响应长度
  • 找到使响应长度特殊的那个 ASCII 值(通常是正确的那个)
步骤 5: 重组 flag

将所有位置的正确字符按顺序组合,得到完整的 flag。

详细步骤

核心代码实现

python 复制代码
from scapy.all import rdpcap, Raw
import re
from collections import defaultdict

def analyze_traffic(file_path):
    packets = rdpcap(file_path)
    
    requests = {}
    responses = {}
    
    for i, pkt in enumerate(packets):
        if Raw in pkt:
            data = bytes(pkt[Raw].load)
            try:
                text = data.decode('utf-8', errors='ignore')
                
                # 提取 SQL 注入请求
                if text.startswith('GET'):
                    match = re.search(
                        r'id=1.*?ascii\(substr\(\(select%20flag%20from%20t\),(\d+),1\)\)=(\d+)',
                        text
                    )
                    
                    if match:
                        position = int(match.group(1))
                        ascii_value = int(match.group(2))
                        
                        requests[i] = {
                            'position': position,
                            'ascii': ascii_value,
                            'char': chr(ascii_value)
                        }
                
                # 提取 HTTP 响应
                elif text.startswith('HTTP/'):
                    body_start = text.find('\r\n\r\n')
                    body = text[body_start + 4:] if body_start > 0 else text
                    
                    responses[i] = {
                        'body_length': len(body)
                    }
                    
            except:
                continue
    
    return requests, responses

def extract_flag(requests, responses):
    # 按位置分组
    position_data = defaultdict(list)
    
    for req_idx, req_info in sorted(requests.items()):
        pos = req_info['position']
        
        # 找到对应的响应
        for resp_idx, resp_info in sorted(responses.items()):
            if resp_idx > req_idx:
                position_data[pos].append({
                    'ascii': req_info['ascii'],
                    'char': req_info['char'],
                    'response_length': resp_info['body_length']
                })
                break
    
    # 找出每个位置的正确字符
    flag_chars = {}
    
    for pos in sorted(position_data.keys()):
        items = position_data[pos]
        
        # 统计响应长度
        length_counts = defaultdict(list)
        for item in items:
            length_counts[item['response_length']].append(item)
        
        # 找到出现次数最少的长度(正确的字符)
        lengths = sorted(length_counts.items(), key=lambda x: len(x[1]))
        
        if lengths:
            min_len, matching_items = lengths[0]
            flag_chars[pos] = matching_items[0]['char']
    
    # 重组 flag
    flag = ''.join([flag_chars.get(i, '?') for i in range(1, max(flag_chars.keys()) + 1)])
    
    return flag

执行结果

运行脚本后,成功提取出每个位置的字符:

复制代码
位置 1: 'f' (ASCII: 102, 响应长度:716)
位置 2: 'l' (ASCII: 108, 响应长度:716)
位置 3: 'a' (ASCII: 97, 响应长度:716)
位置 4: 'g' (ASCII: 103, 响应长度:716)
位置 5: '{' (ASCII: 123, 响应长度:716)
位置 6: 'w' (ASCII: 119, 响应长度:716)
位置 7: '1' (ASCII: 49, 响应长度:716)
位置 8: 'r' (ASCII: 114, 响应长度:716)
位置 9: 'e' (ASCII: 101, 响应长度:716)
位置 10: 's' (ASCII: 115, 响应长度:716)
位置 11: 'h' (ASCII: 104, 响应长度:716)
位置 12: 'A' (ASCII: 65, 响应长度:716)
位置 13: 'R' (ASCII: 82, 响应长度:716)
位置 14: 'K' (ASCII: 75, 响应长度:716)
位置 15: '_' (ASCII: 95, 响应长度:716)
位置 16: 'e' (ASCII: 101, 响应长度:716)
位置 17: 'z' (ASCII: 122, 响应长度:716)
位置 18: '_' (ASCII: 95, 响应长度:716)
位置 19: '1' (ASCII: 49, 响应长度:716)
位置 20: 's' (ASCII: 115, 响应长度:716)
位置 21: 'n' (ASCII: 110, 响应长度:716)
位置 22: 't' (ASCII: 116, 响应长度:716)
位置 23: 'i' (ASCII: 105, 响应长度:716)
位置 24: 't' (ASCII: 116, 响应长度:716)
位置 25: '}' (ASCII: 125, 响应长度:716)

总结

技术要点

  1. SQL 盲注识别:

    • 通过 URL 参数中的 ascii(substr(...)) 模式识别盲注攻击
    • 理解攻击者如何逐字符获取敏感数据
  2. 流量分析技巧:

    • 使用 scapy 库解析 pcapng 文件
    • 提取和配对 HTTP 请求与响应
    • 通过响应长度差异判断注入结果
  3. 数据处理:

    • 从大量流量中筛选关键数据
    • 使用正则表达式提取注入参数
    • 统计分析响应特征

拓展学习

  • SQL 注入类型: 了解不同类型的 SQL 注入(联合查询、盲注、报错注入等)
  • 防御方法: 学习如何防止 SQL 注入(参数化查询、输入验证等)
  • 流量分析工具: 熟悉 Wireshark、tshark 等工具的使用
相关推荐
陈天伟教授3 小时前
人工智能应用- AI 增强显微镜:01.显微镜的瓶颈
前端·人工智能·安全·xss·csrf
科普体验馆3 小时前
《【VR安全体验馆】深度测评:优质服务商与推荐厂家全景解析》
安全·vr
星幻元宇VR3 小时前
VR生产安全学习机|将安全教育带入沉浸式实训新时代
科技·学习·安全·vr·虚拟现实
kang0x03 小时前
Check - Writeup by AI
安全
终端鹿3 小时前
Vue3 + TypeScript 大型项目状态管理:Pinia 类型安全最佳实践
安全·ubuntu·typescript
酿情师3 小时前
2026软件系统安全赛初赛MISC--steganography
数据库·安全
小陈工4 小时前
2026年3月25日技术资讯洞察:开源芯片革命、Postgres文件系统与AI Agent安全新范式
开发语言·数据库·人工智能·python·安全·web安全·开源
csdn_aspnet4 小时前
MySQL安全加固十大硬核操作,从账号权限最小化到SSL加密,构建生产环境基础防护层
mysql·安全·ssl·waf
hanniuniu134 小时前
F5发布AI防护全新产品矩阵,定义企业级AI安全新标准
人工智能·安全