通用思路
- 通读全文代码,从功能函数代码开始阅读,例如include文件夹下的
common_fun.php
,或者有类似关键字的文件。 - 看配置文件,带有config关键字的文件,找到
mysql.class.php
文件的connect()函数,查看在数据库连接时是否出现漏洞。 - 继续跟读首页文件
index.php
了解程序运作时调用了哪些函数和文件,以index.php
文件作为标线,一层一层去扩展阅读所包含的文件,了解其功能,之后进入其功能文件夹的首页文件,进行扩展阅读。
漏洞总结:
1.文件操作漏洞
①.文件包含漏洞:(详细可看:https://www.jianshu.com/p/41bb503abe61)
(1) 本地文件包含:
一般存在于模块加载,模板加载,cache调用
包括函数:include()/include_once(),require()/require_once()寻找可控变量
(2) 远程文件包含:
前提条件:allow_url_include = on
(3) 文件包含截断:
%00截断(php版本小于5.3)
问号截断(问号后面相当于请求的参数,伪截断)
英文(.) 反斜杠(/) 截断
②.文件读取(下载)漏洞:
搜索关键函数:1
2
3
4
5
6
7
8
9
10
11file_get_contents()
highlight_file()
fopen()
read file()
fread()
fgetss()
fgets()
parse_ini_file()
show_source()
file()
......
③.文件上传漏洞:
搜索关键函数:move_uploaded_file()
接着看调用这个函数的代码是否存在为限制上传格式或者可以绕过。
(1) 未过滤或本地过滤:
服务器端未过滤,直接上传PHP格式的文件即可利用。
(2) 黑名单扩展名过滤:
限制不够全面:IIS默认支持解析.asp,.cdx, .asa,.cer等。
(3) 文件头 content-type验证绕过:
getimagesize()
函数:验证文件头只要为GIF89a,就会返回真。- 限制
$_FILES["file"]["type"]
的值 就是人为限制content-type为可控变量。
④.文件删除漏洞:
搜索关键函数:unlink()
利用回溯变量的方式
老版本下的session_destroy()
,可以删除文件,现已基本被修复。
2.代码执行漏洞
①代码执行函数:
搜索关键函数:1
eval(), assert(), preg_replace(), call_user_func(), call_user_func_array(), array_map()
(1) preg_replace()函数:
1
mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )
当$pattern处存在e修饰符时,$replacement 会被当做php代码执行。
(2)call_user_func()函数1
mixed call_user_func( callable $callbank [ , mixed $parameter [ , mixed $…):
第一个参数为回调函数,第二个参数是回调函数的参数
(3)eval()和assert():
当assert()的参数为字符串时 可执行PHP代码1
2eval(" phpinfo(); ");【√】 eval(" phpinfo() ");【X】
assert(" phpinfo(); ");【√】 assert(" phpinfo() ");【√】
②.动态函数执行:
动态函数后门:1
2
3<?php
$_GET['a']($_GET['b']);
?>
③.命令执行函数:
搜索关键函数:
1
system(), exec(), shell_exec(), passthru() ,pcntl_exec(), popen(),proc_open()
(1) popen()和proc_open():1
2
3<?php
popen( 'whoami >> 1.txt', 'r' );
?>
所在路径就会出现一个1.txt ,里面的内容为命令执行后的结果
(2) 反引号命令执行:1
2
3
4
5<?php
echo `whoami`;
?> //直接就可以执行命令
```
双引号和单引号的区别:
<?php
$a = 1;
echo “ $a “ ; //1
echo ‘ $a ‘ ;//$a
?> //双引号时,可以直接解析变量,造成代码执行漏洞。1
2
3
#### 3.变量覆盖漏洞
**①.函数使用不当:**
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 )1
**②.$$变量覆盖:**
<?php
include “flag.php”;
if ($_SERVER[“REQUEST_METHOD”] != “POST”)
die(“flag is here”);
if (!isset($_POST[“flag”]) )
die($_403);
foreach ($_GET as $k => $v){
$$k = $$v;
}
foreach ($_POST as $k => $v){
$$k = $v;
}
if ( $_POST[“flag”] !== $flag )
die($_403);
echo “flag: “. $flag . “\n”;
die($_200);
?>1
2
3
4
5
6使用了两个`foreach`并且也使用了`$$.`两个`foreach`中对 `$$key`的处理是不一样的,满足条件后会将`$flag`里面的值打印出来。
但是由于`后两个if语句及foreach`代码会将$flag的值给覆盖掉了,所以需要先将`$flag`的值赋给`$_200或$_403`变量,然后利用`die($_200)或 die($_403)`将flag打印出来。
解题方法:
利用第一个foreach先将$flag的值赋给`$_200`,然后利用`die($_200)`将原本的flag值打印出来。
最终PAYLOAD:
GET DATA:?_200=flag
POST DATA:flag=aaaaaaaaaaaaaaaaaaaaa1
2
3
4
5
6
7
8
9
10
11
12
13
#### 4.逻辑漏洞
**需要思考的问题:**
* 程序是否可以重复安装
* 修改密码是否存在越权,修改其他用户密码
* 找回密码验证码是否可以暴力破解
* cookie是否可以预测 验证存在绕过
**①.账户体系中的越权问题:**
* 水平越权:A用户能够以B用户的身份,进行B用户的全部权限操作。前提A用户和B用户拥有相同的权限。
* 垂直越权:A用户能够以C用户的身份,进行C用户的全部权限操作,前提C用户比A用户拥有更高的权限。
(1) 未`exit`/`return`/`die`:
<?php
if(file_exists(‘install.lock)){
header(“Location:xxx.com”);
}
echo “test”;
?>
1 | test 依旧会被输出,替换成安装流程,PHP依旧会进行。 |
<?php
if (check_money($price)){
//Do something
//花费几秒
$money = $money - $price;
}
?>
1
2
**可能导致漏洞函数:** `str_replace()`
<?php
$a = addslashes($_GET[‘a’]);
$b = addslashes($_GET[‘b’]);
echo “$a
$b
“;
$c = str_replace($a,’’,$b);
echo trim($c);
?>`
5.会话认证漏洞
- COOKIE验证:没有使用SESSION验证,将信息直接保存在COOKIE中
- 找到传入sql语句的参数的传递过程,回溯变量到最原始的函数,看它保存在cookie的算法是否可逆
- 审计代码时,查看登录处代码