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 等工具的使用
相关推荐
奇迹暖暖暖16 小时前
企业邮箱选型与部署:公司用什么邮箱比较好、如何注册企业邮箱
安全·架构·邮箱
Privasa-隐私实验室17 小时前
全程无死角安全测评|从开机上锁、硬核加密到彻底销毁,Privasa 全生命周期隐私防护详解
笔记·安全·本地存储·隐私安全·aes-256
上海云盾-小余20 小时前
CC 高频请求 + DDoS 流量攻击实战防御:全链路 WAF 流量清洗部署完整流程
网络·爬虫·安全·小程序·ddos
论迹复利21 小时前
平台安全架构(PSA)概述——从方法论到工程实践
嵌入式硬件·安全·psa
江湖有缘21 小时前
保姆级教程:使用Docker一键部署Hoodik轻量级安全云盘
安全·docker·容器
千里念行客2401 天前
迈向晚期TNBC一线治疗!芦康沙妥珠单抗(sac-TMT)第六项NDA获受理
科技·安全·健康医疗
数据库安全1 天前
灾备演练双月报|美创 DRCC 筑牢红十字医院医疗系统安全底线
数据库·安全
2501_915921431 天前
iOS手游安全反外挂解决方案:基于Xcode的加固混淆特色详解
android·安全·ios·小程序·uni-app·iphone·xcode
xia5420464461 天前
云原生与云原生安全概念介绍
安全·云原生
维基框架1 天前
GitHub供应链安全再升级 真正改变的是发布流程
人工智能·安全·github