信息收集与尝试
进入页面后是一个登录框,尝试进行 SQL 注入:
user='or '1'='1--+&pass='or '1'='1
返回提示:'为什么欺负我',说明触发了违禁词过滤。尝试使用 %09(Tab 字符)绕过空格:
user='or%09'1'='1--+&pass='or%09'1'='1--
返回提示:'请不要让我崩溃',这是一道具有中小规模过滤的 SQL 注入题。 CTF 解题第一步是信息收集,通过 F12 查看 HTML 源码发现隐藏路径,进入后发现是一道代码审计题。
代码分析与逻辑梳理
关键代码一:过滤机制分析
核心函数 is_trying_to_hak_me() 包含三层过滤逻辑:
- 关键词黑名单:过滤了单引号、空格、双引、反撇、尖括号等组合,但允许单个单引号存在。空格可通过
%09绕过。 - 单引号位置判断:检查传递字符串中的单引号是否被夹在两个数字或字母之间(如
a'b)。若不符合此结构(如'or),则触发拦截。 - foreach 遍历检查:将黑名单数组传递给
$token,再次判断字符串中是否含有违禁字符。
已知必须构造'两个数字或字母夹住单引号'的结构才能通过过滤。可使用 union select 联合查询,例如 a'union select 1 符合条件。参与过滤的参数仅为 user。
关键代码二:登录验证逻辑
$result = ...; // 提取 sql 语句中的 $user
if (sql_error) {
return "pls dont break me";
}
$parts = explode('$', $result['password']);
$password_hash = $parts[0];
$salt = $parts[1];
// sha256 运算比对
逻辑如下:
- 用户名不能为空且无违禁词。
- 密码字段格式为
hash$salt。 - 系统截取数据库中的哈希值与盐值,对用户输入的密码进行 sha256 哈希运算,比对结果决定是否登录成功。
最终 Payload
利用联合注入特性,需保证字段数一致(user 和 password)。自定义 user 值为 a'union select 1,并构造符合格式的哈希值。
- 生成固定哈希值:
7d0515bb9407af379e2ab13a58ee470d1f8815f56ffffa07ee5c0136e00fea0d - 拼接盐值:
ttack - 组合为:
7d0515bb9407af379e2ab13a58ee470d1f8815f56ffffa07ee5c0136e00fea0d$ttack


