代码审计入门总结

标签: 技术分享 | 发表时间:2016-02-15 01:31 | 作者:
分享到:
出处:http://drops.wooyun.org

0x00 简介


之前看了seay写的PHP代码审计的书,全部浏览了一遍,作为一个代码审计小白,希望向一些和我一样的小白的人提供一下我的收获,以及一个整体的框架和常见漏洞函数。这也算是这本书的一个学习笔记吧,可以结合我捋顺的思路来看这本书。: )

0x01 整体


学习代码审计的目标是能够独立完成对一个CMS的代码安全监测。其通用的思路有:

  • 通读全文代码,从功能函数代码开始阅读,例如 include文件夹下的 common_fun.php,或者有类似关键字的文件。
  • 看配置文件,带有 config关键字的文件,找到mysql.class.php文件的connect()函数,查看在数据库连接时是否出现漏洞。
  • 继续跟读首页文件, index.php,了解程序运作时调用了哪些函数和文件 以index.php文件作为标线,一层一层去扩展阅读所包含的文件,了解其功能,之后进入其功能文件夹的首页文件,进行扩展阅读。

0x02 各种洞洞


a.文件操作漏洞

  • 能不用文件名参数就不用 尽量不要让用户可控
  • 平行用户的权限 管理员的权限 操作权限
  • 禁止传入参数类似于这种 .. , /, \ 检查传入的参数,做出限制,停止程序往下执行

1.文件包含漏洞:

(1) 本地文件包含:

  • 一般存在于模块加载,模板加载,cache调用
  • 包括函数: include()/include_once()require()/require_once()寻找可控变量

p1

p2

(2) 远程文件包含:

  • 前提条件: allow_url_include = on
  • 出现频率不如本地包含

(3) 文件包含截断:

  • %00截断(php版本小于5.3)
  • 问号截断(问号后面相当于请求的参数,伪截断)
  • 英文(.) 反斜杠(/) 截断

2.文件读取(下载)漏洞:

搜索关键函数:

file_get_contents(), highlight_file(), fopen(), read file(), fread(), fgetss(), fgets(), parse_ini_file(), show_source(), file()

3.文件上传漏洞:

搜索关键函数:

move_uploaded_file() 接着看调用这个函数的代码是否存在为限制上传格式或者可以绕过。

(1) 未过滤或本地过滤:服务器端未过滤,直接上传PHP格式的文件即可利用。

(2) 黑名单扩展名过滤:

  • 限制不够全面:IIS默认支持解析 .asp, .cdx, .asa, .cer等。
  • 扩展名可绕过:

p3

不被允许的文件格式 .php,但是我们可以上传文件名为 1.php(注意后面有一个空格)

(3) 文件头 content-type验证绕过:

  • getimagesize()函数:验证文件头只要为GIF89a,就会返回真。
  • 限制 $_FILES["file"]["type"]的值 就是人为限制content-type为可控变量。

(4) 防范:

  • 使用 in_array()或 利用三等于 ===对比扩展名。
  • 保存上传文件是重命名,规则采用时间戳拼接随机数: md5(time() + rand(1,1000))

4.文件删除漏洞:

搜索关键函数:

  • unlink()利用回溯变量的方式
  • 老版本下的 session_destroy(),可以删除文件,现已基本被修复。

Metinfo的任意文件删除漏洞:

p4

$action = delete即可删除 .sql的文件,如果文件不是 sql直接删除提交的文件名

target.com/recovery.php?&action=delete&filename=../../index.php

b.代码执行漏洞

1.代码执行函数:

搜索关键函数: eval(), assert(), preg_replace(), call_user_func(), call_user_func_array(), array_map()

(1) preg_replace()函数:

mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )

当$pattern处存在e修饰符时,$replacement 会被当做php代码执行。

(2) mixed call_user_func( callable $callbank [ , mixed $parameter [ , mixed $…)

第一个参数为回调函数,第二个参数是回调函数的参数

p5

p6

(3) eval()assert()

当assert()的参数为字符串时 可执行PHP代码

【区分】:

  eval(" phpinfo(); ");【√】 eval(" phpinfo() ");【X】
assert(" phpinfo(); ");【√】 assert(" phpinfo() ");【√】

2.动态函数执行:

动态函数后门:

<?php
$_GET['a']($_GET['b']);
?>

p7

3.命令执行函数:

搜索关键函数: system(), exec(), shell_exec(), passthru() , pcntl_exec(), popen(), proc_open()

(1) popenproc_open()

<?php 
popen( 'whoami >> /Users/bingdaojueai/Desktop/1.txt', 'r' ); 
?>

所在路径就会出现一个1.txt 里面的内容为命令执行后的结果

(2) 反引号命令执行:

  • echo whoami; 直接就可以执行命令

  • 双引号和单引号的区别:

    $a = 1
    echo " $a "    output:1
    echo ' $a '    output:$a
    

双引号时,可以直接解析变量,造成代码执行漏洞,过狗绕过。

c.变量覆盖漏洞

1.函数使用不当:

  • int extract( array &$var_array , int $extract_type = EXTR_OVERWRITE , string $prefix = null )
  • void parse_str( string $str , array &$arr )
  • bool import_request_variables( string $type , string $prefix )

2.$$变量覆盖:

p8

p9

d.逻辑漏洞

需要思考的问题:

  • 程序是否可以重复安装
  • 修改密码是否存在越权修改其他用户密码
  • 找回密码验证码是否可以暴力破解
  • cookie是否可以预测 验证存在绕过

1.等于与存在判断绕过:

(1) in_array(): 比较之前会自动转换类型

p10

p11

(2) is_numeric(): 当传入参数为hex时 直接通过并返回true 并且MYSQL可以直接使用hex编码代替字符串明文 可以二次注入 并且可能造成XSS漏洞

(3)双等于 ==和三等于 ===

  • 双等于会在变量比较时,进行类转换,与 in_array()是一样的问题。
  • 三等于是 typevalue的双重比较,相比之下更加安全。

2.账户体系中的越权问题:

  • 水平越权: A用户能够以B用户的身份,进行B用户的全部权限操作。前提A用户和B用户拥有相同的权限。
  • 垂直越权: A用户能够以C用户的身份,进行C用户的全部权限操作,前提C用户比A用户拥有更高的权限。

(1) 未 exit/ return/ die

<?php
if(file_exists('install.lock)){
    header("Location:xxx.com");
    //exit();
}
echo "test";
?>

test 依旧会被输出,替换成安装流程,PHP依旧会进行。

(2) 支付漏洞:

  • 客户端修改单价
  • 客户端修改总价和购买数量
  • 服务端未校验严格
  • 重复发包利用时间差:

    <?php
    if (check_money($price)){
      //Do something
      //花费几秒
      $money = $money - $price;
    }
    ?>
    

可能导致漏洞函数: str_replace()

p12

<?php
$a = addslashes($_GET['a']);
$b = addslashes($_GET['b']);
echo "$a<br>$b<br>";
$c = str_replace($a,'',$b);
echo trim($c);
?>

p13

e.会话认证漏洞

  • COOKIE验证:没有使用SESSION验证,将信息直接保存在COOKIE中

    1. 找到传入sql语句的参数的传递过程 回溯变量到最原始的函数 看它保存在cookie的算法 是否可逆
    2. 和MD5比起 sha1更安全 解密sha1的网站更少
    3. 限制一个用户只能同时在一个IP上登录
  • 审计代码时,查看登录处代码

f.二次漏洞

1.类型:

  • 不是逻辑问题,是可信问题。
  • 业务逻辑复杂度,与二次漏洞触发率 成正比。
  • 购物车 / 订单 / 引用数据 / 文章编辑 / 草稿 ==> SQL注入 / XSS

p14

p15

2.技巧:

(1) 钻GPC等转义的空子:

  • 不受GPC保护的 $_SERVER变量: PHP5以后,$_SERVER取到的header不再受GPC影响,就算开启特殊字符也不会被转义,存在注入
  • 编码问题转换:

    1. GBK的宽字节注入: %df ' 单引号自动被转义成(%5c),同时 %df%5c连在一起组合成 字单引号依然在,成功闭合。【php与mysql交互过程中发生的编码转换问题】
    2. mb_convert_encoding()

      <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/> 
      <?php
      $sql = "WHERE id='".urldecode("-1%df%5c' == ")."'"; 
      print_r(mb_convert_encoding($sql,"UTF-8","GBK"));
      ?>
      

(2)字符串问题:

  • 利用报错,找到敏感信息
  • 字符串截断:

    1. %00空字符截断:【PHP版本小于5.3】

      <?php                                 
      include($_GET['file'].'.php');      
      //1.php?file=2.txt%00
      //2.txt里面是 <?php phpinfo()?>
      ?>
      
    2. iconv函数字符编码转换截断:【对PHP版本有要求】

      chr(128)—chr(255)可以截断字符
      <?php 
      $a = '1'.chr(130).'2’; 
      echo $a."<br>";                   //1�2
      echo iconv("UTF-8", "GBK", $a);   //1
      ?>
      
  • php:// 输入输出流:

    <?php
        include($_GET[‘file']);
    ?>
    1.php?file=php://filter/convert.base64-encode(内容被base64编码)/resource=example.txt(远程文件)
    
  • php代码解析标签:

    1. <script language="php">…</script>
    2. <?…?>php3.0.4版本后可用
    3. <%…%>asp标签,需要asp_tags=on,默认是off
  • 正则表达式:

    1. 没有使用^ 和 $ 限定匹配开始位置:
    2. 特殊字符未转义:
  • 报错注入:

    p16

    p17

  • windows findfirstfile 利用: 若要搜索12345.txt文件,可使用 1<<来代替或者 12<<,不可以单独使用一个 "<"">",因为单独一个只是代表了一个字符,两个代表多个字符。

0x03 End


自己走上安全这条路既是兴趣也是偶然,选择白盒完全是因为喜欢php,毕竟是初识代码审计,seay的书确实帮了我不少,抱作者大腿 (我是萌妹纸),希望这篇文章能够帮助像我一样小白的人,花了两天总结的,如果有什么缺陷也等着大家指出。

不会开发的谈审计都是耍流氓!:)

相关 [代码 审计 总结] 推荐:

代码审计入门总结

- - WooYun知识库
之前看了seay写的PHP代码审计的书,全部浏览了一遍,作为一个代码审计小白,希望向一些和我一样的小白的人提供一下我的收获,以及一个整体的框架和常见漏洞函数. 这也算是这本书的一个学习笔记吧,可以结合我捋顺的思路来看这本书. 学习代码审计的目标是能够独立完成对一个CMS的代码安全监测. 通读全文代码,从功能函数代码开始阅读,例如 include文件夹下的 common_fun.php,或者有类似关键字的文件.

代码重构总结

- - 开源软件 - ITeye博客
重构:对软件内部结构的一种调整,目的是在不改变软件之可察行为前提下,提高其理解性,降低其修改成本. 创建一个新方法,命名以它做什么来命名,而不是怎么做来命名. 如果只是简单的委托,可以将方法内联. 被子类继承的方法不能内联. 如果一个临时变量只被简单的表达式赋值一次,就可以将它内联. 将这个临时变量申明为final.

Java代码审计基础(一)

- - 阿德马Web安全
本文重点是让大家了解JAVA代码审计的基础,会以漏洞示例的方式介绍JAVA代码中常见Web漏洞的形成和针对的修复方案,文章是在国外网站上看到的,因为在接触JAVA代码审计,感觉挺高大上的文章,很适合对JAVA代码审计感兴趣的童鞋找感觉之用,就根据自己的理解翻译了过来,拿去某平台投稿,被鄙视说太基础,就只好发自己的Blog上了.

Python安全编码与代码审计

- - FreeBuf.COM | 关注黑客与极客
现在一般的web开发框架安全已经做的挺好的了,比如大家常用的django,但是一些不规范的开发方式还是会导致一些常用的安全问题,下面就针对这些常用问题做一些总结. 代码审计准备部分见《php代码审计》,这篇文档主要讲述各种常用错误场景,基本上都是咱们自己的开发人员犯的错误,敏感信息已经去除. 未对输入和输出做过滤,场景:.

Android代码优化小技巧总结

- - 移动开发 - ITeye博客
关注微信号:javalearns   随时随地学Java. 这篇文章主要是介绍了一些小细节的优化技巧,当这些小技巧综合使用起来的时候,对于整个Android App的性能提升还是有作用的,只是不能较大幅度的提升性能而已. 选择合适的算法与数据结构才应该是你首要考虑的因素,在这篇文章中不会涉及这方面.

浅谈代码审计入门实战:某博客系统最新版审计之旅

- - 神刀安全网
第一次正式的审一次CMS,虽然只是一个很小的博客系统(提交都不一定收的那种),漏洞也都很简单,但是也算是积累了不少经验,所以最后想来还是在此做个分享,博客系统的CMS就不说了,毕竟有个官网挂着. 缘起某日翻阅某朋友博客的时候无意间发现有个小型的CMS,反正暑假闲的无聊就去审了一下代码(正好拿来练练手),问题挺严重的,好多参数都没有进行过滤,光注入就有好多处,因为文章篇幅有限,这里就不一一列举了,这里只把我找到的漏洞中每类最典型的剖析一下.

写好Java代码的30条经验总结

- - Java - 编程语言 - ITeye博客
成为一个优秀的Java程序员,有着良好的代码编写习惯是必不可少的. 下面就让我们来看看代码编写的30条建议吧. (1) 类名首字母应该大写. 字段、方法以及对象(句柄)的首字母应小写. 对于所有标识符,其中包含的所有单词都应紧靠在一起,而且大写中间单词的首字母. 若在定义中出现了常数初始化字符,则大写static final基本类型标识符中的所有字母.

职业感悟:代码审计与编程在渗透中的重要性

- - Seay's blog 网络安全博客
   配图:3D立体街头涂鸦.      博客连着断了一个月没更新,期间写过好几篇各个方向的文,都是写到一半就夭折,这篇文章强迫自己耐心写出来的. 最近跟出版社沟通好了在写一本关于代码审计和安全编程的书,算是把我这几年的技术积累做一个总结,刚好昨天跟safekey team几个搞渗透的朋友说到编程的问题,就想写个文来好好讲讲.

代码审计:eyou(亿邮)邮件系统两个getshell和两个有意思的漏洞

- - Seay's blog 网络安全博客
最近在给一家市值过百亿美金的公司做渗透测试,发现其中一个域名用的亿邮邮件系统,就顺便下了套亿邮的源码看了看,发现这套系统的安全性还停留在零几年,问题一大堆,找到一些getshell,简单列两个,再拧两个稍微有意思的漏洞分享一下,就不写详细分析了. 另外过段时间会更新一版代码审计系统,会加几种漏洞类型的审计规则,还有优化误报.

2009年总结

- 火丁 - 槽边往事
午夜刚过,正式进入2009年的最后一天. 我坐在电脑前,使用代理越洋访问自己的Blog,在极为缓慢的网速下试图发布一篇长贴子,送别即将离去的2009年. 此时此刻我发布Blog的方式,胜过万语千言,道出了独立Blogger在这一年的真实处境. 如果说这些Blogger如同茫茫比特海上的点点渔火,一度赏心悦目,那么现在,它们分明在一盏盏第次熄灭,陷入黑暗之中.