【转】我与代码审计[一]

0x01. 背景

好久没写文章了,来写一篇水文。2016年对自己最大的愿望就是养成看书的习惯,改掉以前只买书不看书的“坏习惯”。2016年看的第一本书是Seay法师的代码审计的书。还记得当程序员时的梦想:“要把开发和安全结合起来,写出安全的代码!”,虽然现今早已不走在开发的路上,但这个梦还是值得去追寻。

0x02. 起因

上周我司XX群突然被一张聊天截图炸开了锅,从该图上的信息可以看到从某代码托管平台发现了我司WAF产品相关源码以及同事的内网账号信息。这一爆炸性新闻直接把总裁办的领导吸引到了群里,于是各路大牛们纷纷上各大代码托管平台搜索着我司的信息。

像这样的因为企业员工使用互联网公开的代码托管平台不当,导致企业敏感信息泄露的案例多不甚数,从WooYun上搜索了一下关键字:Github得到591条记录,截图如下:

图片[1]-【转】我与代码审计[一]-安全小百科

可见对于企业来说,自己员工的安全意识有必要提升加强!

0x03. 获取源码

获取源代码的最好途径就是从公开的代码托管平台去寻找或者从目标的svn|Git泄露获得源码。从Github上获取源码简单的用法就是打开Github网站,选中左边区“Code”,表示我们只搜索代码,下面的“Language”表示偏好搜索的语言类型,然后输入关键字进行搜索。下面是示意截图:

图片[2]-【转】我与代码审计[一]-安全小百科

一般思路是从乌云等漏洞平台上找目标企业已经泄露的内部职员账号,手机号,内部邮箱,内部系统名称,或服务器信息等等,然后作为关键字放到代码托管平台进行搜索信息。从搜出来的信息中,进一步去打开分辨提取有用的信息,这里贴一篇前辈写的检索语法参考文章:Github上寻找敏感信息技巧分享-getshell1993

这里是一个例子:捡到一只规模还不小的游戏公司的运维狗的github,

Github地址:https://github.com/jokimina/(已告知对方删除该Github项目)

截图如下:

图片[3]-【转】我与代码审计[一]-安全小百科

图片[4]-【转】我与代码审计[一]-安全小百科

(目测这是一个运维汪的Github,不同的人拿到这个有不同的用处,我拿着呢就是学习学习脚本,里面的更多信息没有深度挖掘。提醒下看到这篇文章的无论程序猿、运维汪、还是工程狮们请一定要注意保护自己企业的隐私,如果因为自己的安全意识不强导致企业遭受巨大损失就亏大了!)

我在github找到了这个地址:https://github.com/Mcfell/

图片[5]-【转】我与代码审计[一]-安全小百科

通过查看源代码初步分析,找到并确认了正在线上运行的网站地址:

图片[6]-【转】我与代码审计[一]-安全小百科

于是开始了下面的故事。

0x04. 审计源码

1. 做好审计前的准备

在拿到目标的源码后,我马上打开熟悉的Eclipse工具、import导入项目、根据是否乱码调整IDE环境编码,一般审计的时候很难取得与线上的网站一样的运行环境,所以更多的时候是不能代码在本地模拟线上环境正常跑起来的,所以一些报错缺少包的问题就没管了。

图片[7]-【转】我与代码审计[一]-安全小百科

2. 预编译模型防SQL注入正确用法

大概扫了一下项目的构成,这里没有用上Java的重量级框架,就是一个简单的Java Web项目。WebRoot目录下面除了WEB-INF/*和META-INF外都是可以用浏览器直接访问的文件。关于Java Web基础可以见园长的文章:JavaWeb应用[1]-JavaEE 基础

对于Java Web项目,可以看每一个jsp页面里面的Servlet地址。一般来说请求的Servlet地址,在服务器端都有个名字差不多的完成请求和响应的JavaBean类。这个准确的对应关系我们不能靠猜,可以去WEB-INF/web.xml文件里去看映射关系。

比如下面:

图片[8]-【转】我与代码审计[一]-安全小百科

举例如下面的这段代码:

  <servlet-mapping><servlet-name>dealQuery</servlet-name><url-pattern>/dealQuery.do</url-pattern></servlet-mapping><servlet><display-name>jsonSevlet</display-name><servlet-name>dealQuery</servlet-name><servlet-class>myServlet.dealQuery</servlet-class></servlet>

从上面的代码我们可以知道,当浏览器请求 /dealQuery.do 这个地址时,由服务器端myServlet包下dealQuery这个java类来完成客户端的请求和响应。这个项目的所有处理的Servlet类都放在myServlet文件夹下面,

知道这个流程后,我开始检查myServlet文件下每一个处理的Servlet类,有如下的java文件:

图片[9]-【转】我与代码审计[一]-安全小百科

第一个dealCoorrect.java文件内容如下:

  publicvoid doPost(HttpServletRequest request,HttpServletResponse response)throwsServletException,IOException{ request.setCharacterEncoding(“utf-8”); response.setCharacterEncoding(“utf-8”);PrintWriter out = response.getWriter();JSONObject ms =newJSONObject();HttpSession ss = request.getSession(); usInformation usInf =(usInformation)ss.getAttribute(“usInf”);StringCSId,CSName,CSAddr,CSDate,CSMode,CSFast,CSlow,Operator,ParkFee,CSPub,CSState,CSPhone,CSNotes;System.out.println(“进入dealCorrect”);CSId=newString( request.getParameter(“CSId”));CSName=newString( request.getParameter(“CSName”));CSAddr=newString( request.getParameter(“CSAddr”));CSDate=newString( request.getParameter(“CSDate”));CSMode=newString( request.getParameter(“CSMode”));CSFast=newString( request.getParameter(“CSFast”));CSlow=newString( request.getParameter(“CSlow”));Operator=newString( request.getParameter(“Operator”));ParkFee=newString( request.getParameter(“ParkFee”));CSPub=newString( request.getParameter(“CSPub”));CSState=newString( request.getParameter(“CSState”));CSPhone=newString( request.getParameter(“CSPhone”));CSNotes=newString( request.getParameter(“CSNotes”));String usId = usInf.getUsId();

这里定义了不同的字符串CSId,CSName,CSAddr,CSDate,CSMode,CSFast,CSlow,Operator,ParkFee,CSPub,CSState,CSPhone,CSNotes;用来表示从请求中获取到的不同参数的值。

往下:

图片[10]-【转】我与代码审计[一]-安全小百科

看到了熟悉的insert操作的sql语句。一条正常的SQL语句在放入数据库引擎中执行前,是会先经过各种词法错误、语义逻辑等识别和分析。通常的SQL注入也就是通过构造参数利用SQL语句在解析时解析引擎对参数中特殊符号的解析产生了偏差,使得一条唯一性的SQL语句变成了多重语义的执行语句,从而达到攻击者想要的目的。

虽然这里从请求中获取的变量值没有经过任何的处理直接带入了SQL语句,但是这里使用了参数绑定的预编译模型,也就是使用?占位符的帮助下这条Insert的语句执行模型已经编译确定了。按照预编译好的模型使用setter方法将参数值依次代替占位符?并进行执行。在Java中SQL注入对于像使用PreparedStatement预编译模式是无效的,这是因为PreparedStatement不允许在插入值时改变查询的逻辑结构。

所以得出结论

结论:这个Servlet处理是不存在SQL注入漏洞的!

3. 预编译模型之错误使用导致SQL注入漏洞

上面的代码中,开发人员虽然没有过滤SQL注入的安全意识,但是使用的方法却有效的把SQL注入漏洞拒之门外了。怀着忐忑的心继续往下一个处理Servlet类开始看。

图片[11]-【转】我与代码审计[一]-安全小百科

这个类同样的还是定义了很多字符串变量接收浏览器传递来的参数的值,未获取到值的变量赋予默认值。

图片[12]-【转】我与代码审计[一]-安全小百科

从上面代码中可以看到创建了一个数据库实例对象,定义了condition字符串,这是一个select查询语句,用StringBuffer来拼接sql语句。先追踪dataBase类可以看到:

图片[13]-【转】我与代码审计[一]-安全小百科

看到了Sql

Server数据库连接信息,用的sa用户,第一次见到数据库名是汉字

的 !!! telnet试了下1433端口不能连接

图片[14]-【转】我与代码审计[一]-安全小百科

于是继续看代码

图片[15]-【转】我与代码审计[一]-安全小百科

拼接完SQL查询语句后,用拼接后的SQL语句创建了一个预编译对象并执行。这里犯了一个很多程序员都会犯的错——错误的使用了prepareStatement对象。可能大多数程序员知道使用预编译对象可以防SQL注入,但是很多人都理解为创建一个预编译对象,然后用它的executeQuery来执行SQL语句就能防止SQL注入了。这样的想法是错误的,拼接后的语句再放入预编译对象是徒劳的,因为在预编译之前拼接的SQL语句执行逻辑已经被破坏,原 SQL语句的本意已经被改变了。

所以得出下面结论:

结论:错误使用PreparedStatement预编译对象导致这个查询功能存在SQL注入漏洞!

4. 退出系统功能

图片[16]-【转】我与代码审计[一]-安全小百科

当用户请求退出系统时,浏览器会使用GET请求地址/dealExit.do,处理退出的功能由上面的代码实现。这里从Http请求的Session会话中获取参数usInf,如果获取到就使用removeAttribute从session中移除获取到的usInf。这里销毁的usInf是从当前会话中获取到的,所以这里的退出功能不存在越权漏洞。

所以得出如下结论:

结论:不存在漏洞

5. 用户是否已注册判断存在SQL注入

在注册页面输入任意用户名admin123,看一下下发出去的请求:http://www.ezchong.com/dealPhoneMessage?act=checkIsReg&usId=admin123

图片[17]-【转】我与代码审计[一]-安全小百科

通过查看web.xml映射关系找到这个逻辑处理代码在:dealPhoneMessage.java类里:

打开文件找到checkIsReg函数:

图片[18]-【转】我与代码审计[一]-安全小百科

可以看到传入的usId参数被直接拼接进了checkCondition字符串定义的select语句,然后把这条sql语句作为参数传入数据库帮助类的query()函数,这个函数代码如下:

图片[19]-【转】我与代码审计[一]-安全小百科

这里的query()函数接收的参数是:sql字符串,和可变长参数pras。不得不说这个函数写的真的漂亮,这里使用了String…的特性,使得作者可以写更少的代码,满足更多的场景做更多的事。这个函数可以接收下面的方式的调用:

图片[20]-【转】我与代码审计[一]-安全小百科

下面是用prepareStatement对象预编译这条SQL语句后,用一个for循环将参数绑定,这里的代码正好体现了预编译对象参数绑定思想。

但是这里判断用户是否注册时,传入的是一个已经封装好的SQL语句,参数没有经过预编译再绑定,所以这里很明显存在SQL注入漏洞。

1、手工验证:

分别请求:

http://www.ezchong.com/dealPhoneMessage?act=checkIsReg&usId=admin123%27or%271%27=%272  和

http://www.ezchong.com/dealPhoneMessage?act=checkIsReg&usId=admin123%27or%271%27=%271

图片[21]-【转】我与代码审计[一]-安全小百科

第二个截图传值:admin’or’1’=’1 这是一个典型的SQL注入绕过参数。

1、SQLMAP验证:

图片[22]-【转】我与代码审计[一]-安全小百科

此时已经无需多说,漏洞就摆在这里了!

6. 用户注册逻辑绕过实现任意用户注册

首先看到用户注册处理逻辑的代码截图如下:

图片[23]-【转】我与代码审计[一]-安全小百科

依我我审计水平在上面的doPost函数实现代码上,能看到存在4个漏洞。

l 预编译用法的错误使用导致的SQL注入漏洞

l 任意用户注册漏洞

l 潜在的XSS漏洞

l 跨站请求伪造CSRF漏洞

这里的SQL注入漏洞依然还是先拼接SQL语句导致的,和上面发现的2处注入点是一样的。

这里的任意用户注册漏洞很好理解,从这里的实现逻辑分析,从客户端的POST请求中获取各种用户信息的值,然后先执行有SQL注入漏洞的查询语句,如果未查询到该用户名的记录,就直接把获取到的信息作为新用户添加到数据库记录里。也就是说,我们直接带上用户注册页面上必填的注册信息直接POST请求这个Servlet地址,服务器会直接给我们新加一个我们随意控制的用户,完全不用输入验证码短信!

这里的潜在的XSS漏洞,是因为这里作为用户信息的输入点和保存到数据库的SQL插入点,这里没有对我们的输入值进行XSS过滤处理,那么我们可以构造XSS攻击脚本进行XSS攻击。。

CSRF请求伪造漏洞倒是有些牵强,如果这里是管理员调用来添加新用户的Servlet就可以说攻击者可以利用CSRF让管理悄悄加个用户。但是,那样的话这里还不如叫越权添加用户呢,这里很明显连基本的权限判断都没有做。

一些证明

构造POST请求添加两个新用户:fuckme 和 FuckGod

Post参数:username=fuckme&email=111&tel=222&password=123456

图片[24]-【转】我与代码审计[一]-安全小百科

Post参数:username=FuckGod&[email protected]&tel=188888888&password=123456

图片[25]-【转】我与代码审计[一]-安全小百科

这里的XSS漏洞没有找到用户信息的输出点,不过这里的用户名是一个输出点。但是要注意的是这里的XSS payload里面要避免单引号,双引号出现,因为在插入之前有个存在SQL注入的查询,单双引号可能破坏上面的查询导致不会执行到下面的添加用户的流程,我构造的payload简单如:

POST参数:

username=FuckaGod<>alert(1);</>&[email protected]&tel=188888888&password=123456

图片[26]-【转】我与代码审计[一]-安全小百科

7. 验证码短信绕过实现任意手机号注册

这个漏洞的发现更简单,先黑盒分析:

我们观察一下发送验证码的过程,先输入手机号,然后输入图形验证码,然后点击发送验证短信:

  http://www.ezchong.com/dealPhoneMessage?act=sendSMS&phone=15555555555

图片[27]-【转】我与代码审计[一]-安全小百科

可以看到截图的右边,发送验证码请求的响应里面是一个JSON对象,里面有message和isSuccess,message是一个6位数的字符串,相信你的直觉这就是发送到注册手机上的验证码。为了知其所以然,我们定位到这段逻辑处理的服务端代码:

图片[28]-【转】我与代码审计[一]-安全小百科

服务器端通过Java的Random类以899999作为种子数生成一个随机数然后加100000所得到随机数验证码,关于Random产生随机数的类我所知道的是这个类产生的随机数是不安全的因为在同一环境用同样的种子是可以预测每一次将要产生的随机数的:

贴一张做程序猿时测试的贴图:

图片[29]-【转】我与代码审计[一]-安全小百科

结果:r1 产生的随机数

3030++++++++++++++++++++++3 r2产生的随机数030

换成:

System.out.println(r1.nextDouble(5))System.out.println(r2.nextDouble(5))

结果:

0.73043029674342720.25780279059578040.0592019658112445950.24411725056425315++++++++++++++++++++++0.73043029674342720.25780279059578040.0592019658112445950.24411725056425315

不过目前我还没有遇到因为这个Random随机数可被预测,失去随机性的案例(也可能是自己认知上存在问题,希望大牛指点!)这里的问题在于代码829行:data.put(“message”,result); 这里不应该把发给用户的验证码添加到JSON对象返回给客户端,现在攻击者完全不用看手机短信就知道用户收到的验证码是多少了,从而就可以伪造任意手机号进行注册。

写到这里实在不想写了,基本都是这些类型的漏洞太多了最后贴一张图片!

图片[30]-【转】我与代码审计[一]-安全小百科

提示:在某一个端口有xxx

0x05. 最后总结

1、代码托管平台是个很好的获得各种源代码的地方。

2、作为企业或公司的员工,一定要注意保护自己企业的隐私。

3、菜鸟学审计,不知哪门飞,望老鸟们带路。

*信息源:heysec.org

*铸剑网络安全实验室CSNS-Lab

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论