PHP代码审计相关

Posted by Xiaoxi on May 25, 2016

配置相关

register_globals(全局变量注册开关)

  1. 打开状态下,其会直接把用户GET、POST等方式提交上来的参数注册成全局变量并初始化为参数对应的值,使得提交参数可以直接在脚本中使用。(PHP版本低于5.4.0才有)

    测试: 图1 image

allow_url_include(是否允许包含远程文件)

  1. 在on的情况下,可以直接包含远程文件。(PHP版本5.20以后默认设置为off)

图2 image

magic_quotes_gpc(魔术引号自动过滤)

  1. 只要它被开启,会自动在GET、POST、COOKIE变量中单引号(’)、双引号(“)、反斜杠(\)及空字符(NULL)的前面加上反斜杠(),但在PHP5中,其不会过滤$_SERVER变量,导致很多类似client-ip、refer一类的漏洞可以被利用。
  2. 在PHP5.3以后不被推荐使用该选项,5.4后直接被取消 图3 image

magic_quotes_runtime(魔术引号自动过滤)

主要功能与magic_quotes_gpc类似,不过其与上面的区别是,其只对从数据库或者文件中获取的数据进行过滤。 图4 image

SQL注入漏洞

  1. 普通注入(sql=“SELECT * FROM userinfo where id =$uid“uid为输入的参数)
  2. 编码注入 有时候,开发者会对参数进行过滤,比如使用addslashes、mysql_[real_]escape_string函数。其会对[\x00][\n][\r][][’][”][\x1a]字符前加上\。 针对上面的情况,只有两个方法考虑绕过。

    • 宽字节注入:当编码方式为gbk或者GB系列时,注入参数中带入%df%27,即可把程序的(%5c)吃掉。(PHP连接Mysql时的编码)
    • 二次urldecode注入: 如果在进行mysql操作之前,整个程序还进行了urldecode或者rawurldecode操作,那么可以考虑输入%2527进行注入,其在解码后会形成%27(%25解码为%),即’。

文件操作漏洞

  1. 文件包含函数:include()、include_once()、 require()、require_once()均可能造成文件包含漏洞。前两者遇到错误时,下面的代码仍会执行。后面的报错后,会直接退出程序。
  2. 挖掘方式
    • 远程文件包含 当allow_url_include = On 时,可以进行远程文件包含操作
    • 文件包含截断(正常程序往往会设置文件后缀,我们需要截断正常的后缀,加上我们想要的恶意后缀)
      1. %00截断(受限于GPC,GPC开启便无法截断)
      2. 利用多个英文句号(.)和反斜杠(/)来截断(不限于GPC,在PHP5.3之后被修复) windows下 一般时240个.或者240./ linux下2038个/.组合下能截断
      3. ?问号伪截断,不受GPC和PHP版本限制。

变量覆盖漏洞

  1. 需要注意以下几个函数:extract\parse_str\import_request_variables
  2. import_request_variables()函数则是用在没有开启全局变量注册的时候,调用了这个函数则相当于开启了全局变量注册,在PHP 5.4之后这个函数已经被取消。

命令执行漏洞

system()、exec()、shell_exec()、passthru()、pcntl_exec()、popen()、proc_open()

命令执行过滤

1、escapeshellcmd(), 过滤整条命令.

2、escapeshellarg(),保证传入命令执行函数的参数是一字符串的形式存在的.

过滤了 ‘&’、’;’、’`’、’|’、’*’、’?’、’~’、’<’、’>’、’^’、’(’、’)’、’[‘、’]’、’{‘、’}’、’$’、’\’、’\x0A’、’\xFF’、’%’,’和”


逻辑处理漏洞

  1. in_array()函数:用来判定一个值是否在某一个数组列表里面。示例:in_array(‘b’,array(‘a’,’b’,’c’))返回True 但是,如果我们把b替换成b‘ union select 也返回true。因此,容易爆出漏洞
  2. is_numeric函数:这个函数一般用来判定是不是数字,(我觉得基本就是为了防止sql注入)。 但是存在一种情况,就是可能输入的数字是hex时,便可绕过。MySQL是可以直接使用hex编码代替字符串明文的。 即 存在二次注入和XSS等漏洞隐患
  3. == === 的区别。 双等于在判断等于之前先会做变量类型替换,三等于不会。因此,==非常危险
  4. 有些开发者,在写程序时,有时会忘记exit或者return、,也会引起漏洞

一点小技巧

  1. 钻GPC等转义的空子。GPC对$_SERVER变量没有过滤 常见 user-agent、referer、client-ip/x-forward-for。因为大多数应用都会纪录访问者对IP以及referer等信息。还有一个变量也不受GPC保护,$_FILES。
  2. 编码转换问题 宽字节注入!
  3. 字符串截断
    1. %00空字符截断
    2. iconv函数字符编码转换截断
  4. php://输入输出流
    1. php://input 访问请求的原始数据的只读流,读取提交上来的post数据
    2. php://output 只写的数据流,将数据流输出
      1. php://
  5. PHP代码解析标签
    1. 脚本标签<script language="php">,...</script>可正常解析PHP代码
    2. 短标签<?...?>需要在php.ini中设置short_open_tag=on,默认为on
    3. asp标签 <%…%> 在PHP3.0.4版以后可用,需要在php.ini中设置asp_tags=on,默认是off
  6. MYSQL报错注入(floor(),updatexml(),extractvalue(),GeometryCollection(),polygon(),GTID_SUBSET(),multipoint(),multilinestring(),multipolygon(),LINESTRING(),exp())
  7. 报错注入

    floor()、updatexml()以及extractvalue()
    
    GeometryCollection()、polygon()、GTID_SUBSET()、multipoint()、multilinestring()、multipolygon()、LINESTRING()、exp()
    
    GeometryCollection()
    
    id = 1 AND GeometryCollection((select from(select from(select user())a)b))
    
    polygon()
    
    id = 1 AND polygon((select from(select from(select user())a)b))
    
    multipoint()
    
    id = 1 AND multipoint((select from(select from(select user())a)b))
    
    multilinestring()
    
    id = 1 AND multilinestring((select from(select from(select user())a)b))
    
    multipolygon()
    
    id = 1 AND multipolygon((select from(select from(select user())a)b))
    
    linestring()
    
    id = 1 AND LINESTRING((select from(select from(select user())a)b))
    
    exp()
    
    id = 1 and EXP(~(SELECT*from(SELECT user())a))
    
  8. Windows FindFirstFile利用 利用方法:只要将文件名不可知部分之后的字符用”«“或者”»“代替即可。
  9. PHP特殊执行(在PHP中,单引号和双引号是有区别的,单引号代表纯字符串,而双引号则会解析中间变量)
    1. $a=”${@phpinfo()}”;
    2. $a=”${ phpinfo() }”;
    3. $a=”${ /**/phpinfo() }”;
    4. $a=”${ (回车符) phpinfo() }”;
    5. $a=”${+phpinfo() }”;
    6. $a=”${-phpinfo() }”;
    7. $a=”${!phpinfo() }”;