前几天与大家分享了我自己用C++实现的用于企业内部环境的ssh弱密码审计工具。在实际的工作中,我们还需要对多种常见的协议定期进行弱密码审计。为了灵活地适应企业内部复杂的网络环境,以及领导希望稳定可控的需求,我在Linux环境下基于Python和相关的库实现了telnet、smb、mssql、mysql、ftp等多个协议的弱密码审计工具,并取得了不错的效果,在此也与大家分享相关的代码和经验,希望能够给大家做弱密码审计时能够带来帮助。

一、弱密码审计工作的执行流程

下面是各种协议共通的弱密码审计执行流程:

(1)使用开源工具zmap对全网进行相关协议端口的扫描,发现所有潜在的目标主机;

(2)运行相应协议的弱密码审计工具对所有目标主机执行审计,必要时进行二次验证和过滤;

(3)将找到的弱密码记录存入mysql数据库;

当所有的任务跑完之后,按照部门统计弱密码数量,绘制分布图表和总体趋势图表,输出详细的弱密码列表,再交给负责漏洞管理的同事分发给各责任单位要求进行整改。

二、用Python实现弱密码审计工具的优缺点

在做弱密码审计工具这件事情上,Python最大的好处是:程序简单易懂易实现;有丰富的库资源,每种协议都能找到支持的库。而它的缺点则有:多线程的性能和稳定性不够理想,例如线程数超过100个就不稳定很大概率出现假死;部分协议库在复杂网络环境下可能会出现异常,例如接收数据时没有超时机制,导致永久的等待。

而应对它的缺点,我也尝试了不少的办法,走了一些弯路,最终的解决经验是:

(1)同时使用多进程和多线程来在并发与稳定性之间取得平衡,比如同时起20个进程,每个进程20个线程,实现400个并发;

(2)深入研究相关的协议库源代码,对相关的代码进行优化修改,例如smb协议我就是修改的impacket库的某文件,增加了timeout参数。有些情况下,可能也会基于源文件做一下大改,近似于重写了,比如telnet协议我就是改动了很多;

(3)懂得适时放弃,另寻它径。ssh协议就是如此,虽然它的paramiko库很强大,但是大并发的时候就会有各种问题,协议复杂,代码量又很大,于是果断放弃,转而使用C++结合libssh2库实现主要功能,再在外层用Python包装一下,完成参数和数据的传递工作就好了。

三、Python弱密码审计工具的设计思路

不同于ncrack、hydra等集多种协议于一身、功能强大的弱密码工具,我们实际是为每一种协议单独编写程序,虽然可能会比较零散,但是通过结合crontab、shell脚本等,也能很好地完成任务。

大家可以参考我的github目录:https://github.com/penoxcn/PyWeakPwdAudit,我将最核心的Python代码放在里面了。至于zmap扫描以及与数据库的存取部分,则没有包含在本文范围内,但我相信聪明的读者应该会根据自己的实际情况灵活实现的。

下面说一下代码的框架以及各个代码的作用:

(1)BruteThread.py 是个多线程调度的库。

(2)BruteRunner.py 本文件提供一个接口类Bruter来完成字典文件的加载、目标的加载、扫描进程的创建、扫描结果的保存。该文件需要你们补充一些代码来完成实际的目标加载和扫描结果保存工作,无论是从文件或者数据库。下面代码片段展示了Bruter类启动弱密码扫描任务的过程:

BruteRunner.png

(3)XxxBrute.py 每种协议的用户验证代码,一般有一个XxxAuth类完成单一一次的登录验证过程,一个XxxBruteTester类来完成单个主机的依密码字典审计过程。例如mssql的登录验证就是在MssqlBrute.py里实现的,它调用于pymssql来完成一次Mssql Server的登录验证尝试。如下面的代码片段所展示的:

mssql.png

mssql2.png

(4)XxxBruteScan.py 每种协议的主程序入口,在github上我仅提供了MssqlBruteScan.py作为例子,其它的协议几乎完全相同的。在程序main函数中,你需要解析命令行参数,初始化日志,加载配置文件,然后创建Bruter实例,执行实例的start函数就自动完成该协议的弱密码审计任务了。如下面的代码片段所展示的:

主函数.png

其实这个main函数对于协议来说,绝大部分代码雷同,只是Bruter传递的类不同,完全可以优化为一个通用的函数,避免每个协议实现时都拷贝一遍。

(5)密码字典文件,格式和样例请参考dictionaries目录下的各个txt文件。弱密码条目应该根据自己企业的实际情况进行调整优化,大而全的字典是不可取的。

四、依赖的库

下面是各协议所依赖的库,以及可能需要做的修改:

(1)ftp协议,依赖于ftplib,python自带,无需另外安装;

(2)mssql协议,依赖于pymssql,而pymssql又依赖于freetds;

(3)mysql协议,依赖于MySQL-python,系统上需要先安装mysqlclient库;

(4)smb协议,依赖于impacket库。我使用的是0.9.15版本。你需要修改impacket目录下的nmb.py文件,在相创建smb连接的函数中添加默认的超时控制,不然在遇到tcp黑洞(就是三次握手后再无任何收据收发)时,会因为无法超时而一直挂住。请参考github目录impacket/modified/nmb.py,我传了两次,第一次是原版,第二次是修改后的,然后你可以在github上看提交历史,就可以清晰地看到修改的地方。在验证是否登录成功的时候,需要判断多个返回代码,并且会尝试去连接ADMIN$默认共享进行确认。

下面的片段展示了nmb.py中修改的部分内容。

changed nmb.png

(5)telnet协议,基于Python自带的telnetlib文件所修改的,请见itelnet.py。在其中,除了handle连接的建立与数据的收发外,还重点关注登录验证这一步,添加了很多判断不同设备类型的特征码,基本涵盖了一个大企业里面可能遇到的设备类型:交换机、路由器、AIX服务器、Windows Telnet服务器、各种品牌的打印机、扫描仪、视频会议设备、IP电话、视频监控机、各种UPS、串口服务器、Avaya呼叫网关等等,还有一些无法确知的嵌入式设备等。有些设备类型是可以忽略的,比如打印机、扫描仪、视频会议设备等,有些是不应该忽略的,例如视频监控机、交换机和路由器等。下面的代码片段展示了我所遇到的可以忽略的设备的特征:

忽略的.png

虽然是最古老的协议,但在认证的代码流里面,却也是代码最多的,情况比较复杂,除了通讯的异常外,还有其它的情况,例如有设备不需要用户名和密码,连接上就是shell的;有些设备是只需要输入密码的;有些又是需要输入用户名和密码的,不一而足。

我们也可以依据设备的类型对弱密码字典做优化,比如我会专门针对交换机和路由器做一个简化的的字典,因为它们通常数量很多,但是一般要么没有设置密码,要么使用有限的用户名称,例如admin/cisco,而不会使用root、administrator之类。

(6)其它的协议,尽管我并没有在本文中提供,但是依赖于相关的库,也是很容易实现的,例如我公司使用较多的oracle和db2数据库,都有Linux的Driver和Python接口库,API与mysql等其它数据库类似,大家可以自行尝试实现。Web协议的也可以依赖于requests和urllib等库来实现。

当然不是每种协议都需要实现一遍,从APT的威胁来说,我觉得关注ssh、telnet、smb和mssql这几种协议就足够了。

五、总结

在有相关的协议库的帮助下,用Python实现弱密码审计的工具还是很快捷的,效果也不错。展示下我们小小的效果图:

总数量趋势图:

趋势.png

看过了我分享出来的示例代码,是不是觉得很简单?如果它能够对你的工作有所帮助,欢迎对它进行完善并在实际中使用:)