Part A · 概念题(30 分,凭记忆作答)
要求:请用自己的话回答,不要背定义。
1. SQL 注入为什么能发生?攻击者利用它能做到哪三件事?
-
发生原因: 开发者在编写代码时,没有将用户输入的"数据"与 SQL 语句的"代码"进行严格的分离,直接把用户的输入拼接到了 SQL 查询语句中,导致数据库把用户输入的内容当成了可执行的 SQL 命令来运行。
-
能做到的三件事:
-
数据窃取: 绕过登录验证,或者直接读取数据库中的敏感信息(如管理员密码、用户隐私数据)。
-
数据篡改/破坏: 修改、删除数据库中的数据,甚至执行
DROP TABLE删库。 -
权限提升/系统控制: 利用数据库的高权限,写入木马文件,或者执行系统命令,进而控制整个服务器。
-
2. XSS 有哪三种类型?各举一个触发场景。
-
反射型 XSS: 恶意代码作为请求参数发给服务器,服务器直接将其反射回浏览器执行。
- 场景: 搜索框。用户搜索
<script>alert(1)</script>,服务器把搜索词直接显示在页面上,导致脚本执行。
- 场景: 搜索框。用户搜索
-
存储型 XSS: 恶意代码被服务器存储到数据库中,其他用户访问该页面时触发。
- 场景: 留言板或评论区。攻击者发布一条带有恶意脚本的留言,所有查看该留言的用户都会中招。
-
DOM 型 XSS: 漏洞发生在浏览器端,前端 JavaScript 代码从 URL 或 DOM 中获取数据并直接输出到页面,不经过服务器。
- 场景: 前端通过
location.hash获取内容并使用innerHTML渲染到页面上。
- 场景: 前端通过
3. HTTP 中 Cookie 和 Session 的区别?为什么要配合使用?
-
区别:
-
存储位置: Cookie 存储在客户端浏览器;Session 存储在服务器端。
-
安全性: Cookie 容易被篡改或窃取;Session 相对安全。
-
生命周期: Cookie 可以设置长期保存;Session 通常随浏览器关闭或超时失效。
-
-
配合使用的原因: HTTP 是无状态协议。为了识别用户,服务器需要给用户发一个"凭证"。如果只发 Session ID 给客户端,客户端需要有个地方存,Cookie 正好充当了这个存储容器。所以通常是将 Session ID 存放在 Cookie 中,每次请求时浏览器自动带上 Cookie,服务器通过这个 ID 找到对应的 Session 数据,从而维持用户的登录状态。
4. 文件上传漏洞常见的绕过手段有哪些?至少写 3 种。
-
前端绕过: 修改前端 JS 代码,或者直接使用 Burp Suite 抓包修改文件后缀名(如将
.php改为.jpg绕过前端检查)。 -
MIME 类型绕过: 抓包修改
Content-Type字段,比如将application/x-php改为image/jpeg绕过服务器对文件类型的检查。 -
黑名单绕过: 利用服务器黑名单不全的漏洞,使用特殊后缀(如
.php3、.phtml、.php5),或者利用大小写(.PHP)、双写(.pphphp)、空格/点号绕过(如1.php.在 Windows 下)。 -
%00 截断: 在文件名后加
%00截断后面的后缀检查(针对低版本 PHP)。 -
.htaccess 文件: 上传
.htaccess文件,将特定后缀(如.jpg)解析为 PHP 执行。
5. CSRF 和 XSS 的区别?为什么 CSRF 需要「用户已登录」这个前提?
-
区别:
-
XSS(跨站脚本): 攻击者利用网站漏洞,在受害者浏览器中执行恶意脚本,窃取用户数据或冒充用户操作。攻击的是用户对网站的信任。
-
CSRF(跨站请求伪造): 攻击者诱导受害者点击链接,利用受害者当前已登录 的身份,以受害者的名义向目标网站发送恶意请求。攻击的是网站对用户浏览器的信任。
-
-
需要"已登录"前提的原因: CSRF 的核心是"借刀杀人"。它本身无法获取用户的 Cookie 或 Session,而是依赖浏览器在发送请求时会自动携带目标网站的 Cookie(即用户的身份凭证)。如果用户没有登录,服务器就不会携带有效的 Session,请求就会被服务器拒绝,CSRF 攻击也就无法生效。
Part B · 实战题(30 分,本地 DVWA · Low 难度)
要求:每个任务记录操作步骤 + 你理解的漏洞成因。
注:以下为标准 DVWA 靶场 Low 难度的典型解题思路,实际操作时请结合本地环境记录。
1. 暴力破解:用 Burp Intruder 拿到正确密码。
-
操作步骤:
-
在 DVWA 中设置安全级别为 Low,进入 Brute Force 页面。
-
输入任意用户名(如
admin)和密码(如123),开启 Burp Suite 代理拦截。 -
点击 Login,在 Burp 中抓到请求包,发送到 Intruder。
-
在 Intruder 的 Positions 标签中,清除所有变量,将
password参数的值选中并添加为 payload 位置。 -
在 Payloads 标签中,加载一个常用密码字典(如
passwords.txt)。 -
点击 Start Attack 开始爆破。观察返回结果,通常成功登录的响应长度(Length)与其他失败请求不同,据此找到正确密码。
-
-
漏洞成因: 应用程序没有对登录尝试次数进行限制(无验证码、无锁定机制),且允许用户使用弱口令,使得攻击者可以进行无限次的自动化密码猜测。
2. 命令注入:让服务器执行 whoami 与 ipconfig(或 ifconfig)。
-
操作步骤:
-
进入 Command Injection 页面。在输入框中输入
127.0.0.1点击提交,可以看到服务器返回了 ping 的结果。 -
尝试拼接命令。输入
127.0.0.1 && whoami。 -
页面返回了当前执行命令的用户权限(如
www-data或apache)。 -
继续输入
127.0.0.1 && ipconfig(Windows)或127.0.0.1 && ifconfig(Linux)。
-
-
完整 Payload:
-
127.0.0.1 && whoami -
127.0.0.1 && ipconfig(或ifconfig)
-
-
漏洞成因: 应用程序直接将用户输入拼接到系统命令中执行,没有对特殊字符(如
&、&&、|、;)进行过滤或转义,导致攻击者可以执行任意系统命令。
3. 文件包含:读取目标系统的一个敏感文件。
-
操作步骤:
-
进入 File Inclusion 页面。点击页面上的文件链接,观察 URL,例如
?page=file1.php。 -
尝试修改 URL 中的参数,利用路径穿越读取系统文件。
-
-
文件路径与 Payload:
-
目标路径: Linux 系统下的
/etc/passwd文件(存放用户账户信息)。 -
Payload: 在 URL 中输入
?page=../../../../../../etc/passwd。 -
Windows 目标路径(可选):
C:\Windows\win.ini,Payload 为?page=../../../../../../Windows/win.ini。
-
-
漏洞成因: 应用程序没有对包含的文件路径进行严格的校验和过滤,允许用户通过
../等相对路径符号跳出原本的目录限制,从而包含并读取服务器上的任意敏感文件。
Part C · 代码题(20 分,读代码找问题)
C1 登录查询代码
1. 这段代码有什么漏洞?
这段代码存在严重的 SQL 注入漏洞 。
原因分析: 代码在第 2 行直接通过 $_GET['id'] 获取用户输入,并在第 4 行将该输入直接拼接到了 SQL 查询语句 $sql 中。程序没有对用户输入进行任何过滤、转义或类型检查,导致用户输入的"数据"被数据库当作了"代码"来执行。
2. 攻击者传入 id=1' OR '1'='1 会发生什么?为什么?
-
会发生什么: 攻击者将成功绕过身份验证,查询出数据库中
users表里的所有用户记录(通常是返回第一行,即管理员账号)。 -
为什么: 拼接后的 SQL 语句变成了:
SELECT first_name, last_name FROM users WHERE user_id = '1' OR '1'='1'由于
'1'='1'永远为真(True),整个WHERE子句的条件恒成立。这意味着数据库会返回users表中的所有行,而不再仅仅匹配user_id = 1的那一条记录。
3. 给出两种修复方案。
-
方案一:使用预处理语句(Prepared Statements)与参数化查询(推荐)
这是最根本的修复方法。将 SQL 语句模板与数据分离,数据库会预先编译 SQL 语句,用户输入的数据只能作为参数值传入,无法改变 SQL 语句的结构。
php
$stmt = $conn->prepare("SELECT first_name, last_name FROM users WHERE user_id = ?"); $stmt->bind_param("s", $id); // 's' 表示字符串类型 $stmt->execute(); $result = $stmt->get_result(); -
方案二:对用户输入进行严格的类型转换与转义
如果
user_id是数字类型,可以强制将其转换为整数;如果是字符串,则使用mysqli_real_escape_string进行转义。php
// 方案二 A:强制类型转换(适用于数字型 ID) $id = intval($_GET['id']); // 方案二 B:转义特殊字符(适用于字符串) $id = mysqli_real_escape_string($conn, $_GET['id']);
(注:实际开发中强烈建议使用方案一,方案二在应对复杂字符集时仍有绕过风险。)
C2 文件上传校验代码
1. 这种校验能被绕过吗?怎么绕?
-
能被绕过。
-
绕过方法: 代码在第 1 行仅通过
$_FILES['file']['type'](即 HTTP 请求头中的Content-Type)来校验文件类型。这个值完全由客户端(浏览器或攻击者) 控制。攻击者可以使用 Burp Suite 等抓包工具拦截上传请求,将文件的Content-Type从application/x-php修改为image/jpeg,而文件的实际后缀名(如shell.php)保持不变。服务器由于只检查了Content-Type,就会误以为这是合法的图片,从而将其上传并保存到服务器上。
2. 你会怎么修?
修复的核心原则是:永远不要信任客户端提交的任何数据(包括 MIME 类型),必须在服务器端进行严格的综合校验。
-
修复方案一:检查文件扩展名(白名单机制)
在服务器端获取文件的后缀名,并严格限定只允许上传特定的后缀(如
jpg,png,gif),采用白名单而非黑名单。php
$allowed_ext = ['jpg', 'jpeg', 'png', 'gif']; $ext = strtolower(pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION)); if (!in_array($ext, $allowed_ext)) { die("只允许上传图片文件"); } -
修复方案二:检查文件真实内容(魔术字节/Magic Bytes)
利用
finfo或getimagesize()函数,读取文件头部的二进制数据(Magic Bytes),判断其是否真的是图片,而不是伪装成图片的脚本文件。php
$finfo = finfo_open(FILEINFO_MIME_TYPE); $mime = finfo_file($finfo, $_FILES['file']['tmp_name']); if ($mime !== 'image/jpeg' && $mime !== 'image/png') { die("文件内容不是合法的图片"); } -
修复方案三:重命名文件
上传后不要使用用户提供的文件名(因为可能包含
../或特殊字符),而是由服务器生成一个随机的文件名(如md5(uniqid()) . '.jpg'),并存储在非 Web 根目录的路径下,防止恶意脚本被直接解析执行。
Part D · 情景题(20 分,开放作答)
1. 写出你接下来的信息收集步骤(至少 5 步),并说明每步想得到什么信息。
-
步骤一:WHOIS 与 DNS 信息查询
-
操作: 查询域名的注册信息、注册人、邮箱、NS 记录等(由于目标给的是 IP,此步可能略过,但如果是域名则必须做)。
-
想得到的信息: 获取目标的所有者信息、注册时间、以及可能的子域名线索。
-
-
步骤二:端口扫描与服务识别(Nmap)
-
操作: 使用 Nmap 对
192.168.1.100进行全端口扫描(如nmap -p- -sV -sC 192.168.1.100)。 -
想得到的信息: 发现目标开放了哪些端口(如 80, 8080, 22, 3306 等),以及每个端口上运行的服务和版本号(如 Apache 2.4.49, OpenSSH 7.2)。这直接决定了后续的攻击面。
-
-
步骤三:Web 目录与敏感文件扫描
-
操作: 针对发现的 Web 端口(如 80, 8080),使用目录扫描工具(如 Dirsearch, Gobuster)进行扫描。
-
想得到的信息: 发现隐藏的后台登录页(如
/admin)、备份文件(如www.zip)、配置文件(如.git、robots.txt)或未授权的 API 接口。
-
-
步骤四:Web 指纹识别与组件版本探测
-
操作: 使用 Wappalyzer 插件或 WhatWeb 工具,识别目标网站使用的 CMS(如 WordPress, ThinkPHP)、开发语言(PHP, Java)、中间件(Nginx, Tomcat)及前端框架。
-
想得到的信息: 确定目标使用的具体技术栈和版本,以便去漏洞库(如 CVE, Exploit-DB)查找对应的已知漏洞(Nday)。
-
-
步骤五:操作系统与网络拓扑探测
-
操作: 通过 TTL 值、Nmap 的
-O参数或 Web 报错信息判断目标操作系统(Windows 或 Linux)。 -
想得到的信息: 确定目标操作系统类型,这有助于选择正确的提权方式和利用工具。
-
-
步骤六(可选):搜索引擎与公开信息搜集(OSINT)
-
操作: 利用 Google Hacking(如
site:192.168.1.100)、GitHub 代码搜索等。 -
想得到的信息: 寻找泄露的账号密码、API 密钥或内部网络架构信息。
-
2. 如果 80 端口没发现漏洞,但 8080 端口跑着一个登录框,你会怎么测试?(说思路即可)
-
思路一:弱口令与暴力破解测试
- 尝试常见的默认口令(如
admin/admin,admin/123456,root/root)。如果系统没有验证码或登录次数限制,可以尝试使用 Burp Suite Intruder 加载字典进行暴力破解。
- 尝试常见的默认口令(如
-
思路二:SQL 注入测试
- 在用户名和密码输入框中尝试输入
' OR '1'='1或admin' --等 payload,看是否能绕过登录验证。
- 在用户名和密码输入框中尝试输入
-
思路三:查看前端源码与 JS 文件
-
查看登录页面的 HTML 源码,寻找隐藏的输入框、注释掉的代码或硬编码的凭据。
-
分析引用的 JavaScript 文件,看是否有 API 接口地址泄露、加密逻辑(如 MD5 加盐)或者前端路由信息,尝试直接调用 API 绕过前端登录。
-
-
思路四:尝试其他 HTTP 方法
- 除了 POST 请求,尝试使用 GET、PUT、OPTIONS 等方法访问登录接口,看是否有意外的响应或信息泄露。
-
思路五:撞库测试
- 如果之前通过信息收集拿到了该目标相关的用户名或邮箱,可以尝试使用这些信息配合常见密码进行撞库测试。
-
思路六:检查是否存在其他漏洞
- 测试登录框是否存在 CSRF (跨站请求伪造)、XSS (跨站脚本)或 用户名枚举(通过错误提示判断用户名是否存在)。
-
思路七:分析 8080 端口服务
- 确认 8080 端口运行的具体服务(如 Tomcat 管理后台、Jenkins、WebLogic 等)。如果是已知的中间件,直接查找该版本对应的已知漏洞进行利用(例如 Tomcat 的弱口令部署 WAR 包)。