前言
断更啦。最近事情太多了。这次就记录一下PHP吧。这次的PHP漏洞五个小示例包括变量覆盖漏洞、IP 伪造漏洞、编码绕过、反序列化漏洞、截断漏洞。
变量覆盖漏洞
介绍
变量覆盖指的是用我们自定义的参数值替换程序原有的变量值,一般变量覆盖漏洞需要结合程序的其它功能来实现完整的攻击
漏洞代码 1
<?php
$auth = '0';
extract($_GET);
if ($auth == 1) {
echo "private!";
} else {
echo "public!";
}
?>
- 分析:将可控的数组变量解析,导致变量覆盖漏洞
漏洞代码 2
<?php
$var='init';
parse_str($_SERVER['QUERY_STRING']);
print $var;
?>
- 分析:parse_str 将字符串解析成多个变量,导致变量覆盖漏洞
漏洞代码 3
<?php
$magic_quotes_gpc = ini_get('magic_quotes_gpc');
function _FilterAll($fk, &$svar)
{
global $cfg_notallowstr, $cfg_replacestr;
if (is_array($svar)) {
foreach ($svar as $_k => $_v) {
$svar[$_k] = _FilterAll($fk, $_v);
}
} else {
if ($cfg_notallowstr != '' && preg_match("#" . $cfg_notallowstr . "#i", $svar)) {
ShowMsg(" {$fk} has not allow words!", '-1');
exit;
}
if ($cfg_replacestr != '') {
$svar = preg_replace('/' . $cfg_replacestr . '/i', "***", $svar);
}
}
if (!$magic_quotes_gpc) {
$svar = addslashes($svar);
}
return $svar;
}
?>
- 分析:该片段取自于 dedecms 变量覆盖漏洞
IP 伪造漏洞
介绍
header 里 CLIENT-IP 与 X-FORWARDED-FOR 都是可以用随意伪造的,当这些值未经处理直接用,会导致 XSS 、 SQL 注入等漏洞
漏洞代码 1
<?php
function getIP() {
if (getenv('HTTP_CLIENT_IP')) {
$ip = getenv('HTTP_CLIENT_IP');
} elseif (getenv('HTTP_X_FORWARDED_FOR')) {
$ip = getenv('HTTP_X_FORWARDED_FOR');
} elseif (getenv('HTTP_X_FORWARDED')) {
$ip = getenv('HTTP_X_FORWARDED');
} elseif (getenv('HTTP_FORWARDED_FOR')) {
$ip = getenv('HTTP_FORWARDED_FOR');
} elseif (getenv('HTTP_FORWARDED')) {
$ip = getenv('HTTP_FORWARDED');
} else {
$ip = $_SERVER['REMOTE_ADDR'];
}
return $ip;
}
echo getIP();
?>
修复建议:对传入内容进行 addslashes 和 htmlspecialchars 过滤
建议修复代码
return addslashes($ip);
编码绕过
介绍
一般程序带有全局 addslashes 过滤,但是后面又对传入内容进行解码,解码之后内容没有进行过滤
漏洞代码 1
<?php
$mysqli = new mysqli('localhost', 'root', 'root', 'code');// 数据库连接
if(!empty($_POST['username']))
{
$username = base64_decode(addslashes($_POST['username']));
$data = $mysqli->query("select * from user where username='$username'");
if($data->num_rows !== '0')
{
$arr = $data->fetch_row();
//.....
}
}
?>
- 分析:虽然对 POST 传入内容过滤,可经过二次编码绕过过滤
在解码之后再进行一次字符串过滤
建议修复代码
$username = addslashes(base64_decode(addslashes($_POST['username'])));
反序列化漏洞
介绍
php 反序列化漏洞又称对象注入,调用某一类并执行魔术方法 (magic method) ,之后可以执行类中函数,产生安全问题
漏洞代码 1
<?php
class test
{
public $username = '';
public $password = '';
public $file = '';
public function out()
{
echo "username: " . $this->username . "<br>" . "password: " . $this->password;
}
public function __toString()
{
return file_get_contents($this->file);
}
}
unserialize($_POST['str']);
?>
- test 类的魔术方法中存在可以利用的地方,通过反序列化漏洞可以控制变量,达到写入文件的效果
如果代码中有反序列化,不要在类的魔术方法中进行敏感操作
截断漏洞
介绍
PHP<5.3.4 中, %00 可截断字符串,在写入文件时截断路径导致任意文件名写入
漏洞代码 1
<?php
$id = $_GET['id'];
$file = file_get_contents('upload/'.$id.'.txt');
echo $file;
?>
- 分析:这里限制了前缀跟后缀,但是没有过滤 ../ 跟 %00 截断漏洞,导致可以任意文件读取
不允许 .. 等跨目录字符出现,使用 addslashes 过滤 %00 防止被截断包含
建议修复代码
<?php
$id = addslashes($_GET['id']);
if(strstr($id, '..'))
{
echo ' 输入不合法 ';
exit;
}
$file = file_get_contents('upload/'.$id.'.txt');
echo $file;
?>
漏洞代码 2
<?php
if (isset($_GET['password'])) {
if (ereg("^[a-zA-Z0-9]+\$", $_GET['password']) === FALSE) {
echo '<p>You password must be alphanumeric</p>';
} else {
echo 'success';
}
}
?>
- 分析:ereg 函数存在 NULL 截断漏洞
停止使用 ereg 与 eregi 函数
建议修复代码
if (preg_replace("/[a-zA-Z0-9]+/", $_GET['password']) === FALSE) {