ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

AWDP源码审计实战指南:从赛制破解到攻防闭环

AWDP源码审计实战指南:从赛制破解到攻防闭环 这是网络安全竞赛圈子里绕不开的一个话题。2025年长城杯线下半决赛的AWDP模式网上一直在传“源码完整版”的各种版本很多新手拿到手之后一脸懵不知道从哪儿看起也不知道这东西到底该怎么用。我结合自己打线下赛的经验把AWDP这个模式的玩法、源码审计的重点、攻防双方的实操套路好好拆一遍希望能帮你把这套源码真正吃透而不是放在硬盘里吃灰。1. 先搞明白AWDP到底是什么以及源码在这里面的价值1.1 赛制特点决定了源码就是“藏宝图”AWDPAttack With Defense Plus是线下赛最常见的模式之一它和传统的CTF解题赛最大的区别在于你既要做攻方也要做守方。一整轮比赛里主办方会给出若干套存在漏洞的Web应用源码你的任务有两部分——一方面要找到并利用这些漏洞去拿别人的Flag另一方面要给自己维护的靶机打补丁防止别人打进来。在这个模式下源码就是整场比赛的“藏宝图”。为什么这么说因为漏洞就明明白白写在代码里只是藏得深或浅的问题。拿到源码就等于拿到了出题人埋下的所有陷阱的位置索引。你不需要像在真实渗透测试里那样去猜、去探测直接通过源码审计就能定位漏洞点然后构造攻击脚本去打别人。1.2 这套“完整版”源码通常包含什么我现在说的“长城杯线下半决赛awdp源码完整版”一般指的是赛事结束后放出来的那批题目源码或者赛前模拟训练使用的历史赛题包。一个标准的AWDP题目包通常包含靶机环境文件Dockerfile、docker-compose.yml用于快速搭建和真实比赛一致的环境Web应用源码PHP、Java、Python等不同语言实现初始化脚本数据库初始化、配置初始化部分题目附带的WriteUp或利用思路说明这里要提醒一下不同的发布渠道放出来的“完整版”质量参差不齐。有的确实是官方赛后公开的有的可能是选手自己整合的有的甚至是从比赛平台上直接扒下来的残缺品。拿到手之后第一步不是急着去读代码而是先确认这套源码的完整性——能不能跑起来环境能不能复现。1.3 热身准备一套可复现的训练环境是前提拿到源码后你得先把环境跑起来。这里我建议直接用Docker原因很简单——AWDP比赛本身就是基于容器化的你在本地跑Docker Compose和比赛现场的隔离环境比赛通常用Isolation技术把每个队伍的靶机隔离开是高度一致的。有一个点必须提前说AWDP的靶机环境默认是不出网的至少对参赛选手的网络是受限的。所以本地复现时不需要去开什么特殊通道直接把容器映射端口到本地就能测试。你需要准备的工具清单大致如下Docker和Docker ComposeBurp SuiteWeb抓包和改包工具一个趁手的代码审计IDEVS Code或PHPStorm都行Python3和常用的漏洞利用脚本框架requests库必须要有一个本地的数据库客户端MySQL、Redis等看具体题目而定这些工具不新鲜但AWDP的特殊之处在于——你要在极短的时间内完成“审代码→写利用→打补丁→验证”这一整套流程所以工具的熟练度比你拥有多少工具更重要。2. 拿到源码后的第一件事整体架构分析和资产盘点2.1 先看目录结构再读代码顺序不能反很多新手拿到源码就一头扎进代码细节里结果看了两小时什么都没看出来。正确姿势是先做“资产盘点”也就是搞清楚这套系统由哪些部分组成用了什么框架连接了什么组件。用我之前拆解过的一套FastAdmin框架的AWDP题目举例一打开目录先看到application、public和extend这几个目录这就很典型了——这是一套基于ThinkPHP二次开发的FastAdmin框架站点。看到这个信息你的脑子里就应该立刻浮现出几个关键词FastAdmin后台、前台用户中心、Api接口、文件上传组件、数据库操作行为。这些关键词会告诉你接下来审计的时候重点关注哪里。具体来说你应该做这三步查看composer.json或requirements.txt确定框架和第三方库的版本号查看路由配置文件了解系统对外暴露了哪些接口和控制器查看数据库初始化脚本了解有哪些数据表、每个表存什么数据、有没有默认用户这三步做完你对这套题目的攻击面就有了一个全局的概念再去看具体漏洞就会目标明确效率翻倍。2.2 确认代码版本和已知漏洞之间如何快速关联为什么第一步要看框架版本因为框架本身的已知漏洞就是最快的攻击路径。比如ThinkPHP的5.0.x和5.1.x版本都有多个公开的RCE漏洞远程代码执行如果比赛题目用了一个老版本的框架但没做二次开发加固那基本等于送分题。当然比赛题目一般不会这么简单。出题人通常会在框架原本安全的基础上在业务逻辑里人为埋入漏洞。但版本信息依然重要——有一个思路是先确认框架版本然后去查这个版本对应的安全公告看看有没有原生漏洞可以用老CVE编号直接打。这实际上是在给你争取时间。我的习惯是本地保存一份常见框架的漏洞利用备忘单包括FastAdmin、ThinkPHP、Laravel、Spring Boot、Django等。拿到源码后快速定位版本再对应查备忘单能命中就直接打不能命中再转换到业务代码审计模式。这套操作在AWDP的“首轮快速攻击”阶段特别管用——比赛开始的前10分钟往往就是你白拿Flag的黄金时间。2.3 环境复现时要检查的几个关键点本地起环境的时候最容易踩的坑有三个端口冲突docker-compose.yml里面默认的映射端口可能和本地已有的服务冲突需要修改端口数据库连接参数不对很多题目的数据库连接配置在.env文件或config/database.php等配置文件中默认配置可能是针对比赛内网环境的本地跑不起来初始化数据缺失有些源码包少了一部分初始化脚本导致跑起来之后用户表是空的某些功能用不了这些坑看着小但处理起来很烦。而AWDP本身又是一个极其看重时间效率的比赛如果你在环境搭建阶段就花了两个小时后面审代码的时间就没了。所以那种“拿到的源码还在本地跑不起来”的朋友我建议你先去折腾环境因为这个环节的熟练度会直接影响比赛成绩。3. 源码审计的核心重点攻击面在哪里通杀漏洞怎么找3.1 白盒审计的“猴子路线”入口文件扫一遍逻辑就出来了AWDP是白盒审计比黑盒渗透测试友好太多了。你不用去猜哪里有参数哪里可以SQL注入——打开代码就能看到SQL语句拼接的痕迹。我的习惯是先写一个“猴子脚本”按框架的路由规则自动提取所有的控制器和对应的方法再把每个方法的代码片段打出来。这样能快速生成一个“路由→文件→代码”的映射表接下来逐个方法去审就行了。以PHP框架为例FastAdmin的application/api/controller/目录就是Api接口层application/admin/controller/是后台管理接口层application/index/controller/是前台页面。哪一块最容易出漏洞后台管理功能因为后台天然自带“用户认证”很多出题人觉得已经有登录控制了就可以不搞安全过滤结果就是后台的搜索框、上传框、排序字段到处都是洞。具体来说按“猴子路线”审代码时有几个重点必须盯数据库操作直接拼SQL的都是高危用ORM但参数没做类型处理的中危文件操作包括文件上传、文件读取、文件下载、文件删除任何一个都可能变成RCE或任意文件读取命令执行system()、exec()、shell_exec()、proc_open()以及Python的os.system()、subprocess.call()这些函数见过的都要标记模板渲染如果用了Smarty、Twig等模板引擎没有正确过滤的模板参数可能造成模板注入或RCE反序列化PHP的unserialize()和Java的ObjectInputStream都是高危入口特别是配合魔术方法时3.2 最常考的六类漏洞AWDP实战中的优先级排序根据我自己打过的线下赛和对公开赛题的分析AWDP中最常考、性价比最高的六类漏洞是这样的漏洞类型攻击难度利用成功后的效果在AWDP中的常见位置SQL注入低数据泄露、后台绕过、布尔盲注拿Flag搜索框、排序参数、用户中心接口命令注入/RCE低直接执行系统命令读Flag或反弹Shell不安全的系统调用、定时任务渲染文件上传中上传WebShell直接接管靶机头像上传、附件上传、导入导出文件包含/读取中读任意文件配合日志Getshell模板文件加载、语言包切换越权访问低直接获取其他用户的数据或执行操作IDOR、未授权接口、水平越权反序列化高RCE或任意对象操作用户输入被直接反序列化处这里要说一个实操经验在AWDP比赛里SQL注入和越权漏洞是拿分效率最高的因为利用脚本好写而且稳定。命令注入和文件上传虽然危害大但一个是要构造payload一个是要保证上传后的文件能被解析执行在紧张的比赛状态下更容易出错。所以如果你时间不够优先把站点里的SQL注入点和未授权接口测完基本能满足前期的拿分需求。3.3 用对比方式解释“看似正常但实际有漏洞”的逻辑新手审代码最容易犯的错误是看到一段代码“好像做了过滤”就觉得安全了。实际上很多过滤是可以绕过的。我举一个最典型的例子——htmlspecialchars()函数。很多人知道它能转义HTML实体于是就用它来防护XSS攻击但在特定场景下如果调用时没有指定编码或者在某些拼接环境中使用了错误的上下文过滤就会失效。再举个例子数字型的SQL注入。代码里写了if(is_numeric($id)) { echo 参数合法; }这让很多人觉得安全了。但实际上如果数据库查询是SELECT * FROM users WHERE id$idis_numeric()并不能阻止1 or 11这种纯数字组成的注入语句。所以审计代码时不要看一个过滤函数就放过去而是要把“输入怎么进来、经过什么处理、最终拼接到哪个位置”整条链路看完才能判断漏洞是否真的存在。我自己看代码时有一个习惯强制自己追问“这段代码的目的是什么完成这个目的需要用户提供哪些输入输入到达了什么危险函数”。沿着这条线走通常比漫无目的的扫描有效得多。4. 攻击侧的实操——从审计到打穿靶机的完整过程4.1 快速寻找Web服务的入口和出网能力先来解决一个基础问题AWDP里的靶机通常是不出网的也就是说你的攻击机和靶机之间除了业务端口通常是80/8080之外其他网络通信是完全被限制的。这就意味着传统的反弹Shell方案比如攻击机上监听端口靶机主动连出来在大部分AWDP赛题里是行不通的因为靶机连不出网。那你拿了RCE之后怎么拿Flag答案是直接读文件。AWDP里Flag的位置通常是比较固定的一般在网站根目录、/tmp目录或者数据库某一个特定表里。常见路径包括/flag.txt、/flag、/var/www/html/flag.txt、/tmp/flag等。所以拿到RCE后的第一件事就是列目录、找文件、读Flag。如果题目是每个队伍有独立Flag那你需要拿到自己靶机的Flag后先提交再拿这个Flag去换别人的Flag这个过程叫“交互Flag”。具体机制每个赛略有差异但总体思路都是“先拿自己的再想办法拿别人的”。4.2 攻击脚本的写法稳、快、可复用AWDP的攻击脚本和打CTF时用的exp不太一样。CTF里你写一个exp跑通了就结束了。AWDP里你需要的是“批量打多个目标”的脚本而且每个目标的利用参数可能略有差异比如路径前缀不同、Flag位置不同所以脚本的可复用性和健壮性很重要。我之前写过一个针对SQL注入的脚本核心结构大概是这样的目标URL列表从主办方给的IP段和端口生成对每个URL发送构造好的注入请求从响应中提取Flag用正则匹配特征格式如果提取到就自动提交到Flag提交接口关键点是用Python写这套脚本的时候要把网络请求超时设置得短一点比如3秒因为批量打几十台靶机时只要有一两台卡住整个脚本就会被拖死。同时要做好异常处理单台靶机报错不能中断循环。脚本写完之后先拿自己的靶机测一遍确认能用再放到整个IP段去扫。千万别一开始就对着全段跑——万一脚本有bug你连怎么调试都不知道。4.3 从“打下来”到“站稳”的利用链实操记录我拿一个以前打过的文件上传RCE的题目讲讲利用链的完整流程。那个题在后台用户编辑处有一个头像上传功能代码大概是这样处理的$target_dir uploads/avatars/; $target_file $target_dir . basename($_FILES[file][name]); move_uploaded_file($_FILES[file][tmp_name], $target_file);这段代码的问题显而易见——没有做任何后缀名检查上传的临时文件直接被移动到Web目录下。我构造了一个带PHP代码的文件命名为evil.php直接上传然后访问uploads/avatars/evil.php就成功执行了WebShell。接下来用蚁剑或直接构造HTTP请求来执行命令先读取Web目录下的文件列表找Flag找不到再去根目录和临时目录找。如果之后发现靶机有别的服务开启还可以把这些信息记录下来扩大战果。但是记住AWDP的目标不是渗透全内网而是拿Flag不要在不必要的事情上浪费太多时间。4.4 一定要掌握“脱敏”后的通用Payload模板很多初学者遇到的问题是看了WriteUp知道怎么打但到了现场自己构造payload时速度太慢。AWDP时间紧张如果你每个payload都要现场查手册肯定来不及。所以平时要把常用的payload模板整理成自己的速查手册现场照着改改就能用。我个人整理过的AWDP速查手册里包括SQL注入的多种绕过模板空格绕过、union查询、时间盲注反弹Shell命令虽然AWDP里基本用不到但防御时要防一句话木马的各种语言版本PHP、ASPX、JSPLinux下快速列目录、找Flag的命令组合反序列化payload的常用链针对Java和PHP这些模板平时看着不起眼但真到了比赛时它们就是你最大的底气。我强烈建议每个准备打AWDP的人都花一个下午把这些模板整理好存到本地笔记里。5. 防御侧的硬碰硬——隔离修复、加WAF和日志审计5.1 什么是“隔离修复”为什么AWDP必须用隔离而不是改源码AWDP一个让很多新手困惑的点是发现漏洞后到底该怎么修复直接改源码不就行了吗其实不行。在真实赛制里你的靶机是运行在一套统一环境里的你不能擅自改动某些基础设施而且比赛用的是“隔离修复”机制——你只需要给被判定为漏洞的位置加上一层“补丁”或“规则”让攻击流量无法触达漏洞代码而不是把整个业务逻辑重写一遍。用大白话解释如果你家里的窗户坏了小偷能从窗户翻进来。你的任务是“把这扇窗户封上”而不是“把整栋房子拆了重建”。隔离修复的核心理念就是“最小修复、最大防御”尽量保证原有功能正常同时阻断攻击路径。常见的隔离方式有两种如果赛题是在Nginx/Apache层面运行的有一个很通用但非常“毒”的黑科技写法是在当前目录下上传一个包含php_flag engine off的.htaccess文件。这样Apache就会把当前目录及其子目录下所有PHP文件的执行权限关掉攻击者即使上传了WebShell或找到了文件上传点也无法执行PHP代码PHP框架层面的话则可以写一个自动加载的过滤器在请求进入业务代码之前统一做参数检查拦截恶意payload5.2 利用Isolation机制不改变业务行为的“外科手术式”修复这里要重点说一说隔离修复最经典的实操场景。假设你的靶机是Apache PHP环境你读源码发现后台有个文件上传漏洞攻击者可以上传PHP木马从而Getshell。这时候如果你直接删除上传功能会导致正常业务无法使用失分更多。正确做法是在上传目录放置一个.htaccess文件内容如下php_flag engine off RemoveHandler .php .phtml .php3 .php4 .php5 RemoveType .php .phtml .php3 .php4 .php5这段配置的意思是关闭当前目录下PHP引擎的解析功能同时从Apache的处理器列表里移除所有PHP相关的文件类型。攻击者上传的evil.php虽然还在那里但访问时只会被当作纯文本显示不会执行任何代码。这个修复方式不改动业务代码不破坏上传功能但文件上传漏洞的攻击效果直接被拦腰截断。需要注意的是断网环境下两端的机制有些不同如果题目运行在Nginx PHP-FPM环境下.htaccess就不生效你需要改用Nginx的配置方法或者其他方式。判断环境类型是决定防御方案的第一步。5.3 Nginx环境下的等价操作和常见的部署陷阱如果你的靶机是Nginx PHP-FPM架构上传目录默认就有执行权限那封堵方案请换成在Nginx的配置文件中增加一条location规则把上传目录的PHP解析请求直接返回403。修改Nginx配置的方式需要找到Web服务的站点配置文件通常在/etc/nginx/sites-available/default或/etc/nginx/nginx.conf在里面加上这样的规则location ~ ^/uploads/.*\.(php|php5|phtml)$ { deny all; }然后执行nginx -t检查语法再nginx -s reload重载配置。这样请求uploads目录下任何PHP文件都会被拒绝木马文件即使上传成功也无法被解析。这里有一个常见的坑很多新手改了Nginx配置后忘记重载导致改了等于没改。这就像你锁了门但没把钥匙拔下来攻击者推门照样能进。所以请把“改完配置一定要重载服务”这几个字刻在脑门上。5.4 WF(based)的搭建和使用注意事项除了隔离修复另一个AWDP防御核心是WAF。很多队伍会在自己的靶机前面加一层WAF来拦截攻击payload。比赛现场通常是允许你自己架设轻量级WAF的常见做法有在Nginx层面加nginx-lua-waf模块单独部署一套OpenResty作为反向代理配合自定义拦截规则在PHP入口文件里统一做参数过滤简单暴力版我个人的习惯是如果时间允许优先用Nginx层级的WAF因为它在数据到达业务代码之前就做了拦截安全性更高。但是要记住WAF不是万能的——AWDP的出题人其实很熟悉WAF很多题目会用编码绕过、分块传输等方式来逃过WAF检测所以WAF只是防御的第一道防线隔离修复还是要做。有一点值得注意设置WAF时千万别把自己人拦住了。我见过有队伍部署WAF后自己打测试payload结果被拦截还以为是脚本写错了查了半天才发现是WAF干的好事。所以部署完成后一定要做一轮全流程的自我测试确保业务功能正常、利用脚本确实被拦。5.5 日志审计高效判断谁在打你、用什么方式打你防御的另一个重要组成部分就是日志审计。AWDP比赛中你需要实时关注自己的靶机被人打了没有、用什么方式打的。最常用的方法是实时跑Nginx/Apache的访问日志tail -f /var/log/nginx/access.log tail -f /var/log/apache2/access.log如果看到大量带有union select、phpinfo()、/uploads/、antSword等特征的请求那就说明已经有人在尝试攻击你了。这时候你要做的不是慌而是迅速根据日志里的攻击特征去加固对应的漏洞点。我在这里必须强调一个很多新手忽略的细节AWDP中主办方是会计算你的防御得分的——也就是拦截了多少次攻击、成功抵御了多少波攻击都会转化为防御分。日志审计不光是“知道谁打你”更重要的是“证明你防御了”。如果主办方的计分系统会对攻击流量做检测你的WAF或隔离规则拦住了流量系统就会记录一次成功防御。所以平时养成看日志的习惯比赛时也得安排专人负责盯日志这属于最基本的信息战能力。6. AWDP赛中的排兵布阵前10分钟和后80分钟的节奏控制6.1 理想的开局节奏——三线并行AWDP一般单轮持续30分钟到2小时不等长城杯线下赛常见的单轮是1到2小时期间持续出题、持续开新轮。这么短的时间里如果你按部就班地“先审完再打”肯定来不及。正确的打法是“三线并行”一号位负责快速审计源码优先扫描路由和控制器列表找出明显的注入和上传点二号位负责搭建防御结构开启日志监控选择关键位置快速做隔离修复三号位负责批量攻击脚本的编写和调试拿一号位给出的漏洞点快速利用如果你们队伍只有两个人甚至一个人那就把“防守先行”放在最前面——先把自己靶机的漏洞堵住至少不让别人先打进来扣防御分再腾出手去攻击。因为AWDP的得分公式一般是攻击得分和防御得分加总你要是只顾着攻击结果被别人打穿了防御分照样哗哗掉。6.2 后半程的变招——动态Flag和轮次更迭很多比赛中每轮会更新Flag。也就是说你上一轮打的Flag提交完下一轮靶机上的Flag就变了你需要重新去打。所以攻击脚本不能一锤子买卖必须支持批量和重复执行。这就是为什么前面强调脚本要稳、要快、要健壮。我的习惯是脚本设计成可以反复轮询的每轮结束后自动重新发送攻击请求如果有新的Flag就提取提交。另外某些比赛还会在部分轮次中切换靶机IP或端口脚本要支持从配置文件读取目标列表而不是写死在代码里。这些都是实战中血的教训。6.3 得分别慌失分别慌——分数波动的应对策略AWDP现场的一个常态是你的防守得分忽高忽低攻击得分别人已经涨了几千你还在原地。这种时候最忌讳心态崩了乱操作。根据我的经验分数波动有几个常见原因别人在某个时刻打穿了你的靶机防御分被扣掉一部分你没有及时提交Flag导致攻击分没吃满主办方在轮次之间更换了Flag或重置了漏洞状态你还在用旧脚本打处理办法很简单先稳定防御再做攻击。对于没有头绪的题目宁可先花10分钟把自己靶机上的明显漏洞都补上再去研究别人的WordPress插件漏洞。这套“先守后攻”的风格在多人团队里特别有用因为总有人负责稳住基本盘。7. 复盘和工具链怎么把一套源码变成自己的攻击力7.1 源码包的二次整理——建立自己的“漏洞索引”拿到“长城杯线下半决赛awdp源码完整版”之后我强烈建议你做一次“二次整理”。不要只是解压放着而是花时间写一个漏洞索引文档。这个文档记录每个题目的攻击入口、利用链、修复点、责任人、状态是否打通/是否修复。这个索引的做法一开始会占点时间但后面每个轮次你都可以快速查找不用重新翻代码。我的一个习惯是给每个源码题目的目录建一个NOTES.md在里面记录代码审计的关键结论和利用脚本的路径。比如某目录下的api/userinfo.php存在SQL注入admin/upload.php存在文件上传漏洞我都记在这个文件里。这样哪怕我和队友交接也不会一头雾水。7.2 制作一份“一击必杀”的攻击脚本库源码包的另一个用途是用来测试和积累攻击脚本。每审计出一个漏洞就立刻写对应的利用脚本并且把脚本沉淀到自己的工具库中。时间长了你的库里面的脚本涵盖SQL注入、命令执行、文件上传、反序列化等多种类型比赛时直接拿出来修改目标参数就能用。这里我多说一句沉淀脚本时要养成写注释的习惯。别觉得多此一举——半个月后你再回头看自己写的脚本没有注释的话你根本看不懂那一堆正则表达式和编码逻辑是干嘛用的。7.3 真正的进步不在比赛而在复盘最后聊一下复盘。打完一场AWDP后不管你拿了第几都值得花时间做一次完整的复盘。复盘的核心不是“我哪里没做好”这种空话而是具体的“下一次我要调整什么流程、更新哪个脚本、补充哪块知识”。复盘时我会问自己几个问题从拿到源码到第一个可利用漏洞点确认花了多长时间有没有更快的方法隔离修复的覆盖面够不够有没有漏掉的后门点攻击脚本的稳定性怎么样有没有因为网络波动或参数变化导致大面积失败日志里被攻击的特征是什么我下次是不是可以提前在源码里就找出这些特征对应的漏洞这些问题想清楚了你每次打比赛都会比上次强。源码这东西放在那里永远是死的真正让源码活起来的是你解读它的那套方法论和你的实战经验。希望这篇东西能给你的AWDP之路提供一点实质性的帮助。
返回列表