PHP漏洞五个小示例【第三期】 - ic翼

860 阅读2分钟
原文链接: bingyishow.top

前言

断更啦。最近事情太多了。这次就记录一下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) {