ARTICLE DETAIL

资讯详情

深耕网站SEO优化与搜索引擎排名提升的一线实战洞察。

CTF实战复盘:从Web渗透到逆向工程的网络安全攻防思维

CTF实战复盘:从Web渗透到逆向工程的网络安全攻防思维 1. 从“陇原战‘疫’2021”看一场典型CTF的攻防实战复盘去年我作为战队成员参加了“陇原战‘疫’2021”网络安全大赛。这不仅仅是一次比赛更像是一次在特定主题下对网络安全综合能力的集中检验。比赛名称里的“战‘疫’”点明了当时的时代背景而题目设计也或多或少融入了相关场景比如医疗数据、健康码系统、信息上报平台等这让解题过程除了技术挑战还多了一层现实代入感。今天我就以这场比赛的Writeup为引子拆解一下CTF比赛的常见题型、解题思路以及那些在真实渗透测试和应急响应中同样宝贵的实战经验。无论你是刚入门的新手还是想查漏补缺的老手希望这篇复盘能给你带来一些实实在在的启发。CTF夺旗赛核心就是找到隐藏的“flag”。这面旗子可能是一串由flag{...}或ctf{...}包裹的特定字符。比赛通常涵盖Web渗透、逆向工程、密码学、杂项Misc、二进制漏洞利用Pwn等方向。“陇原战‘疫’2021”的题目覆盖面很广难度梯度设置合理从基础的命令执行到需要多重知识组合的复杂漏洞链都有体现。接下来我会挑选几个有代表性的题目类别深入剖析其背后的原理、解题步骤以及我踩过的坑。2. Web安全从信息泄露到命令执行的纵深突破Web题目永远是CTF的重头戏也是与现实网络攻击关联最紧密的部分。在这次比赛中Web题目的场景设置非常“接地气”比如模拟疫情信息上报系统、物资管理后台等。2.1 信息收集与敏感文件泄露很多Web题的突破口往往始于最基础的信息收集。一道题目给了一个简单的登录页面页面源码、HTTP响应头、甚至robots.txt都空空如也。新手可能就在这里卡住了。但经验告诉我们不要放过任何常见的备份文件、源码泄露文件。我当时的做法是使用dirsearch这类目录扫描工具配合一个强大的字典。关键不在于工具本身而在于字典的完备性和扫描策略。我习惯先用一个较小的通用字典快速扫描常见路径如/admin,/backup,/www.zip,/.git如果没有发现再启用大型字典进行深度扫描。在这次比赛的一道题中正是通过扫描发现了/www.zip文件下载解压后获得了网站源码。注意在实战或授权的渗透测试中目录扫描的速率需要控制避免对目标服务器造成拒绝服务攻击。在CTF环境中虽然限制较少但养成良好的习惯很重要。获得源码后就是一场“白盒审计”。我首先会全局搜索关键词如flag,exec,system,eval,include,$_GET,$_POST等。在一道题目的config.php文件中我发现了数据库配置信息其中包含一个疑似flag的字符串但提交无效。这说明flag可能不是直接写死的而是需要通过程序逻辑动态生成或获取。2.2 绕过过滤与命令执行漏洞另一道典型的Web题是一个“疫情数据查询”界面输入框提示输入城市名称。初步测试发现输入Beijing会返回该城市的模拟数据。这里立刻要想到是否存在注入或命令执行。尝试输入Beijing; ls页面返回了错误信息显示存在某种过滤。进一步测试输入Beijing ls同样被拦截。这时就需要判断过滤规则。我常用的方法是fuzz测试即用Burp Suite的Intruder模块循环提交一系列特殊字符和命令片段如|,,;,,$(,whoami,cat等观察哪些被拦截哪些能通过。测试发现空格、cat、flag等关键词被过滤但反引号和$()没有被过滤。于是构造payloadBeijing;echo$IFSY2F0IC9mbGFn|base64$IFS-d|sh。这个payload的拆解如下;用于结束前一个命令。echo$IFS$IFS是shell的内部字段分隔符默认为空格这里用来绕过空格的过滤。echo命令输出后面的一串Base64编码。Y2F0IC9mbGFn这是cat /flag命令的Base64编码。因为cat和flag关键词被过滤所以用编码绕过。|base64$IFS-d|sh将前面echo输出的Base64字符串通过管道|传给base64 -d解码再传给sh执行。-d参数前同样用$IFS绕过空格。执行后成功获取到flag。这道题考察了命令执行的多种绕过技巧编码绕过、内联执行反引号或$()、以及利用$IFS替代空格。2.3 SQL注入与二次注入还有一道题涉及用户注册和登录。在注册时用户名处存在过滤但个人简介字段过滤不严。这里就可能存在“二次注入”漏洞。即恶意数据先被存入数据库之后在另一个逻辑如数据展示、查询中被取出并执行。注册一个用户在个人简介字段填入 union select database()#。但页面没有直接显示。随后题目有一个“查看抗疫英雄榜”的功能会展示用户的用户名和简介。当我注册的用户出现在榜上时简介字段的内容被触发执行页面显示了当前数据库名。这就证实了二次注入的存在。后续利用此注入点通过union select逐步获取表名、列名最终在某个表的某个字段里找到了flag。这个过程需要熟练使用SQL注入的常用语句如group_concat(table_name) from information_schema.tables where table_schemadatabase()获取所有表名。group_concat(column_name) from information_schema.columns where table_name可疑表名获取列名。最后select 目标列 from 目标表读出数据。实操心得在CTF的Web题中遇到登录/注册功能要格外关注所有用户可控的输入点不仅包括登录名密码还有注册时的其他字段、找回密码、个人信息修改等。一个地方过滤严格另一个地方可能就是突破口。3. 逆向工程剥开程序外壳直指核心逻辑逆向工程题目通常会给出一个可执行文件如ELF、PE或一段字节码如Python的pyc、Java的class要求分析其逻辑找到或生成正确的flag。3.1 静态分析与动态调试结合比赛中遇到一个32位的Windows控制台程序。运行后它提示输入“抗疫口令”输入错误则程序退出。首先使用file和strings命令进行基础信息收集strings输出中能看到一些有趣的字符串比如“Access Denied!”、“Congratulations!”但没直接看到flag。接下来使用IDA Pro进行静态反编译。找到main函数F5生成伪代码。分析发现程序的核心逻辑是将用户输入经过一个自定义的变换函数处理然后与程序内部硬编码的一段字节数组进行比较。如果相等则输出成功信息。关键在于这个“自定义变换函数”。静态看它由一系列位运算与、或、异或、移位和算术运算组成逻辑略显复杂。单纯靠人脑去逆推算法比较耗时。这时就需要动态调试来验证猜想和获取中间值。我用x64dbg附加进程在比较函数通常是strcmp或memcmp处下断点。运行程序随意输入一串字符比如“123456”。当程序断在比较处时查看寄存器或栈内存就能看到我输入经变换后的结果以及程序期待的正确结果那个硬编码的字节数组。3.2 编写求解脚本既然知道了目标结果和变换函数那么有两种思路逆向算法仔细分析IDA中的变换函数写出其逆函数。这对于复杂的非线性变换可能很困难。正向爆破因为输入空间可能有限比如题目提示是6位数字或者变换本身可逆且我们通过调试能“看到”内部映射关系。更通用的方法是直接使用调试器或模拟执行框架如Unicorn来“黑盒”调用这个变换函数。在这道题中我发现变换是逐字节进行的且算法固定。我选择用Python模拟这个变换过程。我将IDA中那个函数的关键运算逻辑“翻译”成Python代码形成一个transform(input_str)函数。然后我知道程序内部期待的最终字节数组target_bytes。我只需要写一个脚本遍历所有可能的输入如果提示是数字就遍历000000-999999对每个候选输入调用transform函数看结果是否等于target_bytes。由于只有100万种可能计算机瞬间就能跑完。最终脚本找到了唯一的匹配输入这就是正确的“抗疫口令”提交后获得flag。踩坑记录在动态调试时要注意程序的“反调试”机制。有些题目会检测调试器一旦发现被调试就会改变执行流程或直接退出。常见的反调试技术包括检查BeingDebugged标志、NtGlobalFlag、CheckRemoteDebuggerPresentAPI等。遇到程序行为异常时要想到这一点并使用插件或手动patch来绕过这些检测。4. 密码学不只是数学更是脑洞CTF的密码学题目往往不是纯粹的数学难题而是将古典密码、现代密码与编码、编程相结合需要灵活的思维。4.1 编码识别与转换一道杂项Misc题给了一个文本文件里面是一串看似乱码的字符dGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHN0cmluZw。有经验的同学一眼就能看出这是Base64编码因为其字符集符合Base64特征A-Z, a-z, 0-9, , /, 并且末尾可能有等号填充。使用在线工具或命令行echo “字符串” | base64 -d即可解码得到提示“this is a base64 encoded string”。但这不是flag可能只是第一步。解码后的信息可能又是一层其他编码如Base32、Hex、ASCII码值、莫尔斯电码、培根密码等或者是一段指向下一步的提示。需要根据字符的形态是否只有0-9A-F是否只有点和划是否只有AB进行判断和尝试。4.2 古典密码与现代密码分析另一道题给了一段密文“KYVIV NRJ KF ZJ UVRIK ZJ”。观察发现单词间有空格像是英文句子但单词无意义。这提示可能是替换密码如凯撒密码移位、仿射密码或单表替换。首先尝试凯撒密码。写一个Python脚本遍历所有25种可能的移位观察输出是否有意义。当移位为17时得到明文“THERE IS NO FLAG HERE”。这显然是一个“欺骗”或中间步骤。题目可能考察了“凯撒密码”本身但flag藏在别处。需要仔细阅读解密后的这句话它可能暗示了下一步比如“NO FLAG HERE”可能意味着要去别处找或者这是一个“Null Cipher”即取每个单词的第几个字母组合成新词。更复杂的题目会涉及RSA、AES等现代密码。通常不会让你去破解算法本身那是不现实的而是考察对算法原理的理解和误用。例如RSA给了一组n, e, c模数、公钥、密文但n可能很小可以分解或者使用了相同的模数n或者公钥e很小比如3可能存在低加密指数攻击。需要使用工具如yafu分解n或使用RsaCtfTool进行自动化攻击。AES可能给出了ECB模式下的密文和部分明文或者IV初始化向量相关的问题。例如CBC模式的“字节翻转攻击”如果知道密文和明文可以构造新的IV来篡改解密后的明文。注意事项密码学题目经常是“套娃”模式一层解密后得到的是另一层加密的提示或密钥。一定要耐心系统地记录每一步的结果和使用的技术。建立一个自己的“密码工具箱”脚本集合Base编解码、凯撒/ROT、频率分析、RSA相关计算等能极大提高效率。5. 杂项与隐写术在细节中寻找蛛丝马迹Miscellaneous题目包罗万象常见的有隐写术、流量分析、内存取证、编码转换、游戏破解等。5.1 图片隐写术一道题给了一张“抗疫宣传图”propaganda.jpg。直接用图片查看器打开毫无异常。第一步永远是检查文件完整性并提取可能隐藏的信息binwalk分析文件内部是否嵌入了其他文件。binwalk -e propaganda.jpg可能会提取出一个ZIP文件或另一个文本文件。strings查看图片中的字符串信息可能在文件末尾附加了flag或提示。strings propaganda.jpg | grep -i ctf或strings propaganda.jpg | grep -i flag。exiftool查看图片的元数据EXIF信息。摄影师、相机型号、注释字段都可能藏有信息。exiftool propaganda.jpg。Stegsolve这是一款经典的图片隐写分析工具。可以逐通道RGB查看、分析LSB最低有效位隐写。如果题目使用了LSB隐写在Stegsolve中切换不同的色彩平面和位平面可能会看到隐藏的二维码或文字。检查文件结构用十六进制编辑器如010 Editor打开查看文件头尾是否有异常数据。有时flag会直接附加在FF D9JPEG结束符之后。在这道题中使用binwalk发现图片尾部附加了一个ZIP压缩包解压需要密码。这时尝试用zip2john提取哈希然后用john约翰大叔进行爆破。如果密码简单可能很快就能破解。如果不行密码可能藏在图片的LSB隐写中。最终通过Stegsolve在蓝色通道的LSB中提取出了一串字符这正是ZIP的密码解压后得到flag。5.2 网络流量分析给了一个capture.pcapng文件通常是Wireshark抓取的网络流量包。场景可能是“疫情数据上报终端被入侵”。整体浏览先用Wireshark打开统计一下协议分层看看主要是什么流量HTTP, HTTPS, DNS, TCP。过滤追踪题目常与Web相关所以可以先过滤HTTP流量http。然后逐个查看HTTP请求和响应。关注POST请求可能上传了webshell、异常的GET请求参数很长可能包含命令执行。搜索关键词在Wireshark中使用“分组字节流”搜索功能搜索flag,ctf,exec,system,passwd,shadow等关键词。文件提取Wireshark可以导出传输的文件。在文件 - 导出对象 - HTTP中可以列出所有通过HTTP传输的文件可能发现上传的恶意脚本或下载的敏感文件。协议分析如果不是HTTP可能是DNS隧道传输数据查看异常的、长长的子域名请求或者是FTP、SMB等协议传输了文件。在一道流量分析题中我发现大量HTTP请求访问同一个PHP文件且Cookie头非常长看起来像Base64。将Cookie值解码发现是一段PHP代码其功能是执行$_GET[‘cmd’]。这就定位到了攻击者的webshell。随后过滤出含有cmd参数的请求追踪TCP流可以看到攻击者执行了ls,cat /flag等命令flag就在其中一个响应的数据包里。实操心得对于流量分析时间线很重要。在Wireshark中可以右键数据包选择“追踪 - TCP流”或“UDP流”这能让你以会话的视角完整看到一次通信的全过程对于理解攻击步骤至关重要。另外注意编码返回的数据可能是Hex、Base64等格式需要正确解码才能看到明文。6. 实战中的问题排查与技巧沉淀CTF比赛和真实渗透一样不会一帆风顺。下面分享几个我遇到问题和解决问题的通用思路。6.1 工具失效或环境问题场景使用sqlmap跑一个注入点半天没结果或者直接报错。排查手动验证首先用and 11和and 12测试页面回显是否有差异确认注入点是否存在、是何种类型盲注、报错注入等。sqlmap不是万能的特别是面对自定义过滤或复杂逻辑时。查看流量开启sqlmap的-v参数如-v 3查看它发送的payload或者用--proxyhttp://127.0.0.1:8080将流量代理到Burp Suite观察哪些payload被服务器拒绝或触发了WAF。调整策略如果遇到过滤尝试使用sqlmap的--tamper参数加载脚本如space2comment.py对payload进行混淆。或者回归手动注入更精确地控制payload。技巧永远不要完全依赖自动化工具。手动测试和理解漏洞原理是根本。把sqlmap当作一个“验证”和“数据提取”的加速器而不是“漏洞发现”的黑盒。6.2 思路卡壳与信息利用场景一道题毫无头绪所有常规方法都试过了。排查重新审题仔细阅读题目描述、标题、附件文件名。每一个词都可能是提示。比如题目叫“simple_ecc_trick”那肯定和椭圆曲线密码有关即使你一开始没看出来。利用所有输出程序给出的任何错误信息、回显内容甚至是不同输入下响应时间的微小差异时间盲注都是信息。一个“Access Denied”和“Invalid Input”可能意味着不同的过滤环节。团队协作与搜索如果是团队赛及时和队友沟通思路。如果是个人练习善于使用搜索引擎。但不要直接搜索flag而是搜索题目中出现的特定字符串、函数名、错误信息。很多CTF题目是基于已知漏洞或经典技巧改编的。技巧建立一个自己的“武器库”笔记记录遇到过的各种题型、技巧、工具命令和有用资源如在线加解密网站、编码识别工具。在卡壳时系统性地翻阅笔记尝试每一种可能的方向。6.3 脚本编写与效率优化场景需要爆破一个4位数字验证码或者遍历一个不大的密钥空间。技巧使用Python的requests库这是处理Web交互的首选。学会使用session对象来维持Cookie处理重定向。使用concurrent.futures或多线程/进程当爆破量较大时单线程太慢。简单的线程池可以大幅提升效率。import requests from concurrent.futures import ThreadPoolExecutor, as_completed def try_code(code): url ‘http://target.com/check’ data {‘code’: f‘{code:04d}’} # 格式化为4位数字 resp requests.post(url, datadata) if ‘success’ in resp.text: return code return None with ThreadPoolExecutor(max_workers20) as executor: futures [executor.submit(try_code, i) for i in range(10000)] for future in as_completed(futures): result future.result() if result: print(f‘Found code: {result}’) executor.shutdown(waitFalse, cancel_futuresTrue) break使用pwntools对于Pwn和逆向题目pwntools是神器它能极大地简化与本地或远程进程的交互发送数据、接收数据、处理打包解包。最后我想说CTF的魅力在于它模拟了网络安全攻防中的核心思维过程信息收集、漏洞分析、利用链构造、权限提升和痕迹清理。写Writeup不仅是分享答案更是梳理思路、沉淀经验的过程。“陇原战‘疫’2021”中的题目很多都体现了与现实场景的结合。通过这样的比赛和复盘我们锻炼的不仅仅是解出某道题的能力更是一种面对未知系统时如何有条不紊地进行分析、测试和突破的思维方式。这种能力无论是在未来的CTF赛场上还是在真实的网络安全工作中都是无比宝贵的。
返回列表