代码审计思路讨论
作者:admin | 时间:2020-1-3 00:14:57 | 分类:黑客技术 隐藏侧边栏展开侧边栏
前言
首先感谢手电筒的建议,建议我从Bluecms来开始学习代码审计。感谢桑桑格,风哥的问题解答。文章主要是写下我自己在代码审计的时候所思所想。当然并不是太过严谨,也有可能存在错误。这里主要是写出了审计SQL、XSS、CSRF、文件包含漏洞的思路。当然,还有比如变量覆盖,代码执行,逻辑漏洞,会话认证等等。以后有时间会整理。这里的思路是我自己的。当然也有大神有更好的想法。今后我还需要加油。
文章使用审计软件seay源代码审计,Bluecms 版本v1.6sp1
最后,希望每个学习的小伙伴都能劈风斩浪。
一、常用代码审计思路
常见的代码审计漏洞方式有:根据敏感关键字回溯参数,查询可控变量,寻找敏感功能点,通读全文。
下面是我的代码审计方式,不正宗。各位随意看看。以bluecms为例:
1、初步查看源码,了解其架构。特别需要注意的是common.fun.php,mysql.class.php,user.fun.php等文件。(判断出来没有关系,来来来,通读一遍就好。)
e.g:data文件夹包含一些配置文件,include文件夹包含了自定义的函数,类等文件。
2、我们都知道渗透的话,我们着重关注三点:输入点,数据流,输出点。那么首先我们可以打开网页来判断输入点位置,常见输入点位置用户登录界面,搜索栏,留言板,一些公告URL参数位置。
3、通过对应输入点位置的代码,追踪数据流,主要关注是否存在过滤代码。
4、判断出错函数是否被其他文件调用。大可能概率其他包含的文件也是存在的。
二、SQL注入漏洞审计
2.1、SQL注入总结
正常情况,sql注入的位置经常出现在登陆页面,订单处理等。注意x-forward-for以及client-ip也会经常出现。因为该值是主动获取的。并不需要用户输入,所以经常性的不会进行过滤。在订单系统里面多个订单与购物车的交互,导致复杂性提升,容易出现二次注入。值得注意。
2.2、BlueCmssql注入审计举例
首先查看用户登录位置,查看表单代码,发现数据传送给user.php文件。那么我们尝试在源码以及web前端当中分析该文件。
WEB界面展示:
很明显这是一个登陆界面,那么我们尝试输入信息,抓包看看具体的参数。在抓取数据包当中我们发现输入的变量有:user_name,pwd,safeconde,userful_time,from,act。结合我们输入的信息,很容易判定user_name表示用户名称,pwd表示密码,safecode表示验证码,useful_time我们猜测可能是时间戳。剩下的from,act暂时不清楚。
查看源代码user.php文件,通读全文我们了解到变量act的作用,代码根据cat参数不同的值来执行不同的SQL语句。所以,我们通过seay源代码审计系统来打开代码文件并且搜索“do_login”,来查看参数值为“do_login”时,执行什么样的sql语句。(注意:个人习惯我喜欢用nodepad++来查看,部分截图是使用nodepad++打开,不影响阅读)
由代码可以发现输入参数符合上面一系列if语句的判定之后会执行一个select语句。利用这个getone函数以及login函数来执行。很明显这是自定义函数。我们定位一下该函数来查看一下该函数是如何定义的。发现该getone函数是mysql.class.php文件当中类class自定义的一个成员函数。Login函数是文件user.fun.php当中定义的函数。下面我们来分析一下该函数:
A、getone函数调用了一个query函数来执行,并且将结果赋值给变量$query,且通过函数mysql_fetch_array函数处理赋值到变量$row,最后返回变量$row。
注释:mysql_fetch_array在结果集中取得一行作为数字数组或关联数组。MYSQL_ASSOC表示关联数组。
B、这里我们发现query函数依旧是一个自定义函数。定位函数来查看一下该函数。发现该函数依旧是在文件mysql_fetch_array当中。Query函数利用mysql_query来执行sql语句,并且返回。如果查询失败指定报错信息内容
C、login函数登陆函数。利用getone函数执行SQL语句。num=1
那么总结一下,getone函数作用:执行sql语句,控制报错信息,以关联数组形式返回值。(注意查询语句当中存在字符串“count(*)asnum”会将查询结果转化。查询成功num=1,查询失败num=0)Login函数作用是带入用户名,密码进入数据库查询并且返回第一行查询结果且结果进行转化查询成功num=1,查询失败num=0。
到目前为止,我们可以分析一下数据流了。首先数据从前端上传到文件user.php文件当中,act=do_login位置代码。经过if语句进行基本判定然后执行sql语句,将数据上传到数据库。这里我们没有发现任何过滤的函数。看到这里我们很有理由怀疑该位置存在漏洞。值得注意的是,这里的login()函数首先判定用户名是否存在在执行用户名以及密码的联合查询。这里我的想法是验证用户名。那么我合法的注册一个就是咯。下面我们查看playload:
我这里注册了一个账号abc123/abc123
注入位置参数$pwd。‘)用来闭合md5加密。
Playload:abc123‘)or 1=1 #
注意:在我测试的过程中发现了一个很不愉快的事情。我发现这么注入没有任何效果。感觉像是单引号被干掉了。关于这个问题,我的思路是,采用var_dump来看看情况。下面是我处理该问题的思路:
使用var_dump来查看输出变量的值:
很明显这里的单引号被转义了。这个时候我们想过造成该转义的大多是使用函数addslashes(),通过搜索,我们发现在文件common.inc.php当中发现自定义函数deep_addslashes()
接着我查询什么文件包含了该文件。通过搜索发现在文件common.inc.php文件被调用且该文件也被user.php文件使用。
那么问题就很好解决了。通过%df来尝试绕过该函数。结果发现成功了。
那么更新payload:abc123%df’)
这里我决定使用sqlmap来扫描。结果扫描成功。
截至到目前,一个sql注入已经被挖掘出来了。这个时候我们考虑一下,文件user.php当中还有其他的执行的sql语句,并且没有过滤。嘿嘿。是不是也存在相应的漏洞呢。
三、XSS漏洞审计
3.1、XSS跨站脚本攻击总结
首先我们先了解一下XSS漏洞,说白了就是让客户端执行了一串恶意代码。无论是一次性执行还是存在在服务器里面多次执行。那么他的危害是什么呢?准确来说,前端利用代码能够做到什么,XSS就可以做到什么。那么想要达到这个效果。我们该过程的核心是什么?输入点?还是数据流?我的理解是数据流。即在数据传输过程中的变化。也可以这么说我们提交的数据在传送过程中是否被过滤。
既然核心在于数据流,我们反过来考虑。我们在输出点的位置查看变量。回溯看看该变量是否存在过滤,以及输入位置。常见的一些输出函数有:print,print_r,echo,printf,sprintf,die,var_dump,var_export。
常见的XSS漏洞位置:文章发表,评论回复,留言,资料设定等位置。
注意:浏览器的容错,编码等特性
3.2、XSS漏洞举例
这里我打算举个存储XSS例子。首先我们思考一个问题,存储XSS是将代码存入数据库当中。那么在PHP代码当中存入输入所使用的sql语句是什么呢?没错insert into 。那是不是存在存储XSS必要条件是存在该语句呢。好的,现在我们搜索一下。
大家是不是很奇怪,红框为什么不包含下面的文件。嗯,各位仔细看看,那特么特么需要管理员权限才能进去的。我要是有管理员权限,我会折腾这个???
好的,我们依旧选中user.php文件,打开并且定位到insert位置。
现在语句位置我们已经清楚了。现在我们查看赋值变量是否存在过滤。或者我们可以先登录界面看看什么样的变量是我可控的。即输入点。奇怪的是变量act=do_reg的时候不能打开界面,我们发现参数等于reg的时候可以开。
右击查看源码就可以发现,点击“提交注册”,act的值会修改为do_reg。
好的,现在我们发现可控的参数用户名,密码,邮箱,验证码,当中验证码需要与后台验证不可控。密码会经过MD5加密,折腾了意义也是不大的。那么接下来看看用户名,邮箱,用户名长度限制。这里最好的选择就是邮箱这个参数。结合上下文看看,变量邮箱没有被htmlspeciaichars函数过滤。我们来试试弹一个。<script>alert(XSS)</script> 。
很快我发现了一个很尴尬的问题,格式不对。回头查看源码,发现报错信息。并且当变量uid等于-4的时候,会出现这样的报错。找了半天发现没有找到。估摸着是前端验证。抓包输入吧。
注意:这里我们需要考虑一个问题,即输出点的位置是否在属性内。
抓包并且成功注入。(做完忘记截图了,各位自己想象吧)
查看数据库当中确实已经存储:
登陆账号弹框:
代码执行位置:
四、CSRF漏洞审计
4.1、CSRF漏洞总结
简单说CSRF就是攻击者通过手段来利用被攻击者来执行被攻击者具备权限的操作行为。在针对这些CSRF漏洞通过token就可以很好的防护。那么对于我们代码审计来说。是不是重点关注存不存在token就可以很好的判定是否存在CSRF漏洞了呢?完美!!!
这里有必要说明一下token的认证方式:
1、前端传账号密码给后端。
2、后端验证成功之后将账号密码作处理加密生成token,并返回给前端。
3、前端收到token之后会存储。
4、以后每次前端请求资源,需要验证token,验证成功则返回请求资源。
4.2、CSRF漏洞举例
有点难受啊,代码水平的不足让我没有办法例举出典型CSRF。有点小失望。话说回来,针对该漏洞的审计我更喜欢黑盒。绝大多数会登陆几个页面,看看有没有token,或者,删除referer信息。看看访问是否存在问题。如果不存在那么大多数情况可以确定存在CSRF漏洞的。至于白盒。我没有太多的心得。基本就是看看有没有设定token的代码。
哎,我在考虑怎么来更好的说明这个呢。看了一圈Blucecm好像没有这个token,这样没有办法更好的说明。下面是我找打的一串设定token的代码。看看这个。做到心中丘壑,这样更好的为方便以后审计。
下面代码是定义了一个token,使用时间戳以及随机数生成的token。
下面我们可以看到,当我首次登陆的时候点击按钮是返回flase,这个时候并没有获取token,再次点击按钮会发现返回success.
注释:这里的警告是因为我使用了php5.2版本,调整为7.3就没有问题了。
五、文件操作漏洞
5.1、文件操作漏洞总结
这里我将文件包含,上传文件,文件读取,文件删除,修改什么的等漏洞都统一称呼文件操作漏洞吧。下面我们来聊聊这些操作文件的漏洞。
文件包含漏洞:在正常的编写网页当中一些代码,类,对象定义之后会需要重复的使用。这个时候就需要用到一些包含的函数,比如include,include_once,require,require_once。可以在代码运行的时候调用其它文件当中已经定义好的文件,类。本来是没有问题的。但是,如果文件包含位置的内容是可控的呢?那么味道就改变了。一旦可控就可以去控制包含一些恶意代码的文件。也就形成了漏洞。
注意:文件包含往往需要截断。因为你的变量可控的位置后面还有拼接的字符串。而且恰好这个字符串是我们不需要的。截断的手法往往和PHP版本有关。比如%00截断
文件读取(下载):这个怎么说呢,就是还是可控的问题,读取文件的变量可控,就可能造成读取任意具备权限的文件或者下载。寻找这个漏洞,可以在网站先看看部分功能读取什么样的文件,抓包查看对应的变量。或则直接搜索文件读取的函数。
文件上传:这个玩意,主要出现点再能够上传文件的位置,比方说头像上传,文件上传等位置。这个审计就比较直接了。找到具体上传位置,查看对应位置代码,看看有么有过滤就可以了。有的话就看看能不能绕过。当然了一下中间件本身自带的漏洞也是可以利用的。
5.2、文件包含漏洞举例
上面说了一些废话,这里关于文件操作的漏洞,我选择用一个文件包含漏洞来举例。首先我们回顾一下文件包含漏洞的形成。可控的变量?是的。还有其他的吗?答案是有的,函数include以及类似功能的函数对吧。那么我们先通过工具来全文搜索一下。来找到一个相对可能性比较大的目标。俗称“踩点”
很明显,我们一眼就相中了图片红框位置的包含函数。其中post传参变量pay。那么下面我们点击进去搂一眼,看看是不是打了眼。
看这一串代码,发现如果变量是pay,那么就对一些变量进行赋值。说实在的啊,没有太多的想法,打算到前端看看这到底是个什么玩意儿。在前端我们看到,这是一个“在线支付”按钮的一个传参。
既然输入点已经找到了,下面我们在服务器里面放一个一句话木马文件。看看能否利用该变量来打开我所放入的文件。
抓包,添加传参:
注意:这里我看看传参的位置:include ‘include/payment/’.$_POST['pay'].”/index.php”;
这里是后面添加的字符串“/index.php”是我们不需要的。这时候考虑的是如何截断它,常见的截断方式以后再整理。这里我们使用“.”来截断。在window当中256个点可以达到截断的效果。Linux需要2038
注意:因为这里我用的截断是在PHP版本5.2上面测试的。如果有验证不成功的。考虑一下php版本问题。
*本文作者:掌控安全独行,转自FreeBuf