之前看了seay写的PHP代码审计的书,全部浏览了一遍,作为一个代码审计小白,希望向一些和我一样的小白的人提供一下我的收获,以及一个整体的框架和常见漏洞函数。这也算是这本书的一个学习笔记吧,可以结合我捋顺的思路来看这本书。: )
学习代码审计的目标是能够独立完成对一个CMS的代码安全监测。其通用的思路有:
(1) 本地文件包含:
(2) 远程文件包含:
(3) 文件包含截断:
搜索关键函数:
file_get_contents() , highlight_file() , fopen() , read file() , fread() , fgetss() , fgets() , parse_ini_file() , show_source() , file() 等
搜索关键函数:
move_uploaded_file() 接着看调用这个函数的代码是否存在为限制上传格式或者可以绕过。
(1) 未过滤或本地过滤:服务器端未过滤,直接上传PHP格式的文件即可利用。
(2) 黑名单扩展名过滤:
不被允许的文件格式 .php ,但是我们可以上传文件名为 1.php (注意后面有一个空格)
(3) 文件头 content-type 验证绕过:
(4) 防范:
搜索关键函数:
$action = delete 即可删除 .sql 的文件,如果文件不是 sql 直接删除提交的文件名
target.com/recovery.php?&action=delete&filename=../../index.php
搜索关键函数: 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 ]] )
(2) mixed call_user_func( callable $callbank [ , mixed $parameter [ , mixed $…) :
(3) eval() 和 assert() :
【区分】:
eval(" phpinfo(); ");【√】 eval(" phpinfo() ");【X】assert(" phpinfo(); ");【√】 assert(" phpinfo() ");【√】
动态函数后门:
#!php<?php$_GET['a']($_GET['b']);?>
搜索关键函数: system() , exec() , shell_exec() , passthru() , pcntl_exec() , popen() , proc_open()
(1) popen 和 proc_open() :
#!php<?php popen( 'whoami >> /Users/bingdaojueai/Desktop/1.txt', 'r' ); ?>
所在路径就会出现一个1.txt 里面的内容为命令执行后的结果
(2) 反引号命令执行:
echo whoami ; 直接就可以执行命令
双引号和单引号的区别:
#!php$a = 1echo " $a " output:1echo ' $a ' output:$a
需要思考的问题:
(1) in_array() : 比较之前会自动转换类型
(2) is_numeric() : 当传入参数为hex时 直接通过并返回true 并且MYSQL可以直接使用hex编码代替字符串明文 可以二次注入 并且可能造成XSS漏洞
(3)双等于 == 和三等于 === :
(1) 未 exit / return / die :
#!php<?phpif(file_exists('install.lock)){ header("Location:xxx.com"); //exit();}echo "test";?>
test 依旧会被输出,替换成安装流程,PHP依旧会进行。
(2) 支付漏洞:
重复发包利用时间差:
#!php<?phpif (check_money($price)){ //Do something //花费几秒 $money = $money - $price;}?>
可能导致漏洞函数: str_replace()
#!php<?php$a = addslashes($_GET['a']);$b = addslashes($_GET['b']);echo "$a<br>$b<br>";$c = str_replace($a,'',$b);echo trim($c);?>
COOKIE验证:没有使用SESSION验证,将信息直接保存在COOKIE中
审计代码时,查看登录处代码
(1) 钻GPC等转义的空子:
编码问题转换:
mb_convert_encoding() :
#!php<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)字符串问题:
字符串截断:
%00空字符截断:【PHP版本小于5.3】
#!php<?php include($_GET['file'].'.php'); //1.php?file=2.txt%00//2.txt里面是 <?php phpinfo()?>?>
iconv函数字符编码转换截断:【对PHP版本有要求】
#!phpchr(128)—chr(255)可以截断字符<?php $a = '1'.chr(130).'2’; echo $a."<br>"; //1�2echo iconv("UTF-8", "GBK", $a); //1?>
php:// 输入输出流:
#!php<?php include($_GET[‘file']);?>1.php?file=php://filter/convert.base64-encode(内容被base64编码)/resource=example.txt(远程文件)
php代码解析标签:
正则表达式:
报错注入:
windows findfirstfile 利用: 若要搜索12345.txt文件,可使用 1" ,因为单独一个只是代表了一个字符,两个代表多个字符。
自己走上安全这条路既是兴趣也是偶然,选择白盒完全是因为喜欢php,毕竟是初识代码审计,seay的书确实帮了我不少,抱作者大腿 (我是萌妹纸) ,希望这篇文章能够帮助像我一样小白的人,花了两天总结的,如果有什么缺陷也等着大家指出。
不会开发的谈审计都是耍流氓! :)