实战技巧 | 知其代码方可审计

Gcow安全团队

共 15531字,需浏览 32分钟

 · 2020-08-30

0x001 审计前言

0x00 简介

终于来到了代码审计篇章。希望看了朋友有所收获,我们通常把代码审计分为黑盒和白盒,我们一般结合起来用。

通常我们白盒审计有多种方法我们可以归纳为:

1.通读全文

2.回溯


其中通读全文费时间,但是有利于代码审计的经验积累,也能更深入的挖掘一些难以发现的漏洞。功能回溯我们可以定向的审计一些功能和函数,最常见的就是对命令执行函数的回溯,和上传等功能的审计。通过熟悉白盒审计有利于漏洞的发掘,因为代码审计和开发都能熟悉到程序中那些地方会存在对数据库的操作和功能函数的调用,举个简单的例子当我们看到download的时候,我们就会想到是不是有任意文件下载。


0x01 环境与工具

我们在代码审计中又可以分为静态和动态,静态我们通常用于无法搭建原来的环境只能看代码逻辑来判断是否存在漏洞,而动态调试就可以debug、输出、监控SQL语句来看非常方便。

接下来代码审计工具基本就用到SublimeText3、VSCode、Seay源代码审计系统、PHPStorm+XDebug、文件对比、MYSQL监控、编码转换、正则调试等。其中文件对比工具可以拿来和更新补丁后的文件进行对于对比定位漏洞代码区,PHPStorm+XDebug可以动态调试定位漏洞成因,也有利于漏洞的发掘。当然你也可以用那些自动化审计的,貌似还支持代码回溯,还是能审计到一些漏洞的。环境能用基本就用phpstudy了。


0x02 知识准备

代码审计我们需要对php有一定的了解,当然是越深入越好,我们也不纠结,代码审计需不需要精通php什么的,只能说知识面在什么层次就能审计到什么层次的漏洞,但是至少你得看得懂代码。

我们应该具备一些知识:

1.基本的正则

2.数据库的一些语法(这个我在前面的数据库维基已经讲的差不多了)

3.至少你得看懂php代码

4.php配置文件以及常见函数


0x03 关于文章的一些问题

前面我们的实验环境我基本上不会使用框架类的,我尽量使用一些很普通的网站,还有如何用phpstudy之类的来本地搭建网站这些我也不会讲,这些基础的问题搜索一下就有,不能独立解决问题怎么能进步,遇到一些特殊的问题我还是会说一下的。


0x04 文末

当然如果你跟我一样是一个新手才入门代码审计,看这篇文章最好不过了,因为我会讲的很细,当然我可能很多东西也讲不到,还请大家多看看别人的审计思路,只有不断的学习才有提高。


0x002 SQL注入审计

0x00 简介

为什么第一章我们学习,因为看这篇文章的朋友大概也看过我前面写的MySQL_wiki系列,这里来SQL注入的话我们能方便理解,同时sql注入也是审计中我们经常想要找到的,比较以来就getshell什么的也不现实这种漏洞也不多。


0x01 字符型注入

这里我们看到sqli-libs第一关的代码

//including the Mysql connect parameters.include("../sql-connections/sql-connect.php");error_reporting(0);// take the variables if(isset($_GET['id'])){$id=$_GET['id'];//logging the connection parameters to a file for analysis.$fp=fopen('result.txt','a');fwrite($fp,'ID:'.$id."\n");fclose($fp);// connectivity $sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";$result=mysql_query($sql);$row = mysql_fetch_array($result);
if($row) { echo ""; echo 'Your Login name:'. $row['username']; echo "
";
echo 'Your Password:' .$row['password']; echo "
"; } else { echo ''; print_r(mysql_error()); echo ""; }} else { echo "Please input the ID as parameter with numeric value";}?>

我们可以看到调用$_GET['id']获取参数内容,没有经过任何过来带入了SQL语句的查询,也就是代码没有任何过来且没开魔术引号,那么将会形成注入,如果开启魔术引号遇到数字型的我们还是能够注入的,因为magic_quotes_gpc只会转义单引号、双引号、反斜线、NULL,但是数字型注入我们可以不试用到这些。

http://127.0.0.1/sqli/Less-1/?id=-1%27union%20select%201,user(),3-


0x02 编码类注入

有些为了业务需要他会把传入一些编码后的参数再解码带入数据库查询,我们常见的有base64编码,也有的程序会内置url解码,这类写法通常见于框架。

1.base64

include("../sql-connections/sql-connect.php");$id=base64_decode($_GET['id']);$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";$result=mysql_query($sql);$row = mysql_fetch_array($result);
if ($row) { echo "id:".$row['id']."
";
echo "用户名:".$row['username']."
";
echo "密码:".$row['password']."
";
}else{ print_r(mysql_error());}echo '
';
echo "查询的语句是:$sql";?>

传入的值base64解密后带入查询,这种注入魔术引号是没办法拦截的,当我们遇到网站为base64编码的参数时可以留意下。

http://127.0.0.1/sqli/Less-1/base64.php
    ?id=JyB1bmlvbiBzZWxlY3QgMSx1c2VyKCksMyAtLSAr

2.urldecodeinclude("../sql-connections/sql-connect.php");$id=urldecode($_GET['id']);$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";$result=mysql_query($sql);$row = mysql_fetch_array($result);
if ($row) { echo "id:".$row['id']."
";
echo "用户名:".$row['username']."
";
echo "密码:".$row['password']."
";
}else{ print_r(mysql_error());}echo '
';
echo "查询的语句是:$sql";?>

因为接受的参数只会被url解码一次,传入的值不是魔术引号认识的值所以可以

绕过

http://127.0.0.1/sqli/Less-1/base64.php
    ?id=%2527union%20select%201,user(),3--%20+


0x03 宽字节注入

$conn = mysql_connect('localhost', 'root', 'root');mysql_select_db("security",$conn);mysql_query("set names 'gbk' ",$conn);$id=urldecode($_GET['id']);$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";$result=mysql_query($sql);$row = mysql_fetch_array($result);
if ($row) { echo "id:".$row['id']."
";
echo "用户名:".$row['username']."
";
echo "密码:".$row['password']."
";
}else{ print_r(mysql_error());}echo '
';
echo "查询的语句是:$sql";?>
网上有很多解释大家可以搜索一下我这里就不详细介绍了大概原因就是:

id=1'->id=1\'->id=1%5c%27

id=1%df'->id=1%df%5c%27->id=1%DF5C%27->id=1運'

当然还有其他各种类型的注入这里就不一一列举了,看了mysql系列文章的大概都知道,不知道的可以看看。


0x04 过滤

通常情况下一个成熟的cms是不存在不过滤的情况,一般的程序选择用函数来过滤比如addslashes(),也可以开启魔术引号,但是更多的程序它采用正则匹配来过滤, 使用不正确的匹配替换方式反而导致被绕过的机会更大,比如有的程序把union替换为空,那么我们就可以双写ununionion绕过从而还可能绕过外部WAF,对于整数型一般采用intval()等字符转换,后期通过实战一步一步讲解。


0x05 实战审计

找了半天源码,还是用这款熊海CMS V1.0吧,这款CMS感觉不错,什么洞都有,非常适合我们学习审计,同时审计这个cms的文章很多,大家如果觉得我写的不如人意,还能看看别人。

首先我们审计对传入的参数如果想快速的看是否有全局过滤,不妨找个文件输出一下$_POST$_GET等等。

echo $_POST['b'];echo $_GET['a'];

没有全局过滤 我们来到后台登陆文件admin/files/login.php 看看login.php一般登陆存在注入的可能性还是很大的

很明显 带入查询的user没有经过任何过滤,同时输出了错误,所以可以用报错查询,当然你也选择万能密码。

payload:

user=1111' and (updatexml(1,concat(0x7e,(select user()),0x7e),1))-- +&password=111&login=yes


在看看留言板 files/submit.php

传入参数没有过滤

同时插入的时候,这里使用了mysql_error()所以可以用报错注入,否则只能使用盲注了。

payload:

cid=0&name='or updatexml(1,concat(0x7e,(version())),0) or'&mail=1111&url=http%3A%2F%2F1&content=%E9%98%BF%E5%BE%B7&save=%E6%8F%90%E4%BA%A4&randcode=&jz=1&tz=1
开始我们说过不是使用了过滤函数就万事大吉了,数字型注入可以不使用引号

我们看到传入的cid已经被addslashes()函数转义了,查询的地方都没啥问题,但是到浏览计数的时候调用了它,那么我们就可以使用盲注或者报错注入了,因为有错误回显。


payload:

http://127.0.0.1/xhcms/?r=content&cid=1%20and%20If(ascii(substr(database(),1,1))%3C10,0,sleep(10))

这个系统还有其他注入,想练手的自己下载审计一下,总体思路有用户交互的地方

都有可能存在注入,这也是我们没有通读代码的一个审计思路。


0x003 代码执行审计

0x00 简介

代码执行也是我们经常遇到的,通常是eval()assert()当然还有回调函数比如call_user_func() array_map(),正则函数,动态调用等等,因为程序对传入的参数过滤不严或者没有过滤,导致代码执行,看过我前面写的php的webshell总结的话,你就会发现很多知识是相辅相成的。


0x01 代码执行

这里说说eval的命令执行assert在php7后面移除了。我们来看一个简单的eval代码执行

test.php

$id = $_GET['x'];eval($id);?>
payload:
test.php?x=phpinfo();

简单到waf以为他是个webshell了,当然我们实际情况肯定遇不到这么简单的,可能需要多重组合利用,这里下面我以一个实例为例


0x02 实战审计

这里使用的是zzzphp V1.6.0的一个解析标签过程中引发的代码执行,网上也有其他人的审计思路,这里我是帮朋友复现的时候弄的。

找个的审计思路是全局搜索eval,当然你也可以搜索其他的能够引发代码执行的函数,但是这个这-1里没有。

路径:\inc\zzz_template.php

我们发现eval里面有变量,那么他是可能存在代码执行的

大概看了下parserIfLabel()函数没有什么过滤,能够达到我们传入任意参数的目的,到了这里我们就是回溯那里调用了这个函数呗,全局搜索下parserIfLabel(),没搜索到,看了下是个类,所以搜索类名ParserTemplate

既然 \admin\save.php 调用了我们这个,不妨看看后台那里有模板操作这个

当然完全你也可以回溯代码去分析,但是既然有源码能看就看。

随便找个文件放入我们遵循他正则的代码即可,不过一般我们测试的过程中,尽量选择对目标影响小的文件。

payload:

{if:assert(phpinfo())}x{end if}

于此同类的还有苹果cms8.x,都是在解析标签过程中出现的问题,一般看到可以自定义解析标签那么就值得注意,命令执行与此类似,这里就不说了。


0x004 XSS与CSRF审计

0x00 XSS简介

XSS分为反射型储存型,一般来说反射型的用处不是很大利用难度相对较高,存储型XSS一般常见于发布评论、留言、收获地址、个人信息等等。对于xss的审计我们一般就在这些点找,有用户控制输入信息输出的地方都是它出现的地方,很多网站的突破口可能就是一个XSS。


0x01 XSS实战审计

这次选用的CMS还是熊海,我们通过搭建环境查看输入的地方来审计,学习下高效率审计方式。

随意留言抓包看看他请求的url再去找相对的文件/?r=submit&type=message当然你还是得看看他是怎么调用文件的,这里就是加载submit文件中的message方法。

我们来到 files/submit.php

前面的输入基本都没过过滤,到了最后一步$contentaddslashes(strip_tags($content));过滤,所以我们XSS其他地方即可,看到这里我们在挖洞的过程中所以不要纠结一点。

一般过滤xss的函数还有htmlspecialchars,我们审计他的注意点就是查看一些输出函数print、print_r、echo、printf、die、var_dump、var_export


0x02 Csrf

CCSRF实际上就是利用你的身份去发送恶意请求,我们需要知道CSRF分为GET型提交的和POST,前者危害更大,后者一般可以寻找XSS来配合我们。

GET型的比如一个链接 访问即可删除账号,然后你在论坛发帖构造 那么访问这个帖子的人账号都将会删除,POST的见下文,造成CSRF的原因就是没有使用token或者验证其他值,审计就看页面有没有token、referer验证,验证是否可以绕过,不过我推荐还是先黑盒,看看有没有token,删除了referer是否能够访问,再结合代码来看。

我们来看到zzzphp的后台,他是没有token的,同时我们前面审计到了他的代码执行,配合这个csrf就可以直接getshell。

如果你不会自己写这个代码,不妨使用burp生成一个测试页面,右键选择即可。

这是个需要点击的表单,你可以加一段JavaScript代码来自动提交。



0x03 组合利用

这里只是个简单的组合,由于没找到具体实验环境我只有简单的演示一下(懒) 本次选妃zzzphp,由于他后台没有的xss,我只能登陆后台后查看前台了。

1.构造CSRF表单自动提交 payload:

             //burp生成的表单      
2.插入iframe标签

payload: