V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
jackyspy
V2EX  ›  问与答

天融信防火墙密码恢复手记

  •  3
     
  •   jackyspy · 2016-10-14 11:54:14 +08:00 · 7173 次点击
    这是一个创建于 2748 天前的主题,其中的信息可能已经有所发展或是发生改变。

    天融信防火墙密码恢复手记

    公司在用的一款天融信防火墙,密码意外遗失,无法登陆管理平台。虽然防火墙可以正常工作,但却无法修改配置,不能根增加和删除访问列表中的 IP 地址,不能调整访问策略。防火墙默认仅开通 https web 管理界面,未开启 telnet 、 ssh 等其他管理通道。

    联系天融信厂家寻求技术支持,被告知必须返厂更换芯片,费用大约在 2000 元左右(网上搜了一下,几乎所有密码遗失的客户最终都只能选择返厂)。公司用于该网络联网的仅此一台防火墙设备,终端数量在 500 以上,无其他硬件备份方案。因用户众多,管理要求细致,防火墙配置非常复杂,保存的配置文件也不是最新的。若返厂维修的话,则无法找到完备的替代方案。

    于是决定先自己想办法,开启密码恢复之旅。 Go !

    猜测密码,自动验证

    首先想到的是根据可能的密码规则和常用组合,构造一个密码字典,通过编写简单的 Python 脚本进行登录验证。万一不行的话,就穷举来尝试暴力破解。

    可是开始跑脚本的时候发现想法实在太天真了,存在两个致命的问题:

    1. 防火墙白天负荷过重, Web 响应非常慢。有时候一个请求可能在半分钟以上。
    2. Web 管理平台有登录次数限制,大约 6 次密码错误以后,就会锁定账号一段时间。

    在尝试了几十个最可能出现的密码组合后,彻底放弃了这条捷径。

    看来偷懒是不成了,必须得动真格的。

    搜寻漏洞,获取控制权

    nmap 扫描发现防火墙只开通了 https 端口。不是专业的安全研究人员,只能在网上搜索该款防火墙的漏洞资料,不(suo)幸的是,还真发现了不少。

    找到的第一篇文章 《看我如何在 2 小时内控制 100+天融信安全设备的》 提到了 Heartbleed 漏洞,却未对漏洞利用方式做过多解释。需要更多学习资料,根据这个方向继续搜索,又找到了一些文章:

    其中, NSA Equation Group 那篇文章信息量最高,对漏洞的特征和产生的原因分析的非常透彻,利用方式也做了简要说明。按照文章的提示,用 Brup 进行 Eligible Candidate 漏洞测试(打算用 Postman ,但因 chrome 的 https 证书问题放弃),漏洞果然还在!

    怀着激动的心情,尝试了 ls -la />/www/htdocs/1find / -type f>/www/htdocs/1 等指令,对防火墙文件系统的目录结构进行初步了解,也看到了配置文件存放的位置。执行 cp /tos/conf/config>/www/htdocs/1 ,把配置文件 down 下来一看,果然是新鲜的味道。

    启动 telnetd 服务并尝试连接,报错,估计是没有加特定启动参数的缘故,没做深入研究。看来暂时还是只能通过 https 漏洞方式跑命令了。

    随着执行命令次数越来越多, Brup 构造请求的方式效率太低,于是写了简单的 Python 函数在 IPython 下面跑,终觉得灵活性不够。最后决定采用 HTTPie 命令行的方式发送 https 请求( curl 没有 httpie 方便),后续所有命令都通过这种方式交互。

    $ http --verify=no https://x.x.x.x/cgi/maincgi.cgi 'Cookie: session_id=x`ls -la /tmp>/www/htdocs/1`'
    

    文件上传,执行脚本文件

    之前都是一次请求执行一条命令,效率太低,也存在诸多限制。最好的方式是上传一个 sh 脚本在防火墙上执行,这就需要以某种方式传送文件到防火墙上去。

    另一方面,根据漏洞名称和 Equation Group 搜索到这篇文章:Equation Group 泄露文件分析,才注意到这是国际顶尖黑客组织,也是 NSA 合作的方程式黑客组织( Equation Group ),被另一个名为“ The ShadowBrokers ”的黑客组织攻下了,珍藏的系列高级工具被打包分享。这可是个好东西!赶紧下载解密,找到 ELCA 的漏洞利用代码,运行后却发现没有如逾期般的启动 nopen 远程管理软件,原因未知,颇有些失望。不过在 py 源码中看到了文件上传的方式,其实就是利用了 cgi 文件上传处理方式,它每次会在 /tmp 目录下生成一个 cgi*的临时文件。 ELCA 利用代码的流程是连续执行多次指令,第一次 rm /tmp/cgi*清理 tmp 目录,接着 post 上传文件同时复制保存一份 cp /t*/cg* /tmp/.a,再加执行权限 chmod +x /tmp/.a,最后执行 /tmp/.a

    upload_run.png

    当然,代码并没有直接上传一个可执行文件,而是巧妙(恕见识少,我知道*nix 下经常这样干)的将需要的多个文件用 tar 打包后,附到 sh 脚本的最后。在 sh 脚本中用 dd 命令将 tar 包 copy 出来再解压运行。下面是工具中 stage.sh 的部分代码:

    stager.png

    文件 tar 打包的 Python 代码片段:

    build_exploit_payload.png

    就我的需求而言,只是上传脚本执行,就不用做得那么复杂了。简单的 post 我的 sh 脚本,同时执行 sh /tmp/cgi*。前提是我的 sh 脚本中都做了清理工作 rm /tmp/cgi*

    http --verify=no -b -f POST https://x.x.x.x/cgi/maincgi.cgi 'Cookie: session_id=x`sh /t*/cg*`' [email protected]; http --verify=no https://x.x.x.x/1
    

    HTTPie 可以用 uploadfilename@localfilename 的方式很方便的实现文件上传。之所以两条指令在一行是为了方便查看前一个脚本的输出。

    #!/bin/sh
    # 清除 /tmp/cgi*,防止干扰下次运行
    rm -f /t*/cgi*
    
    echo =============================== >/www/htdocs/1
    date >>/www/htdocs/1
    
    echo "***************" >>/www/htdocs/1
    cd /tmp
    ps >>/www/htdocs/1
    netstat -nltp >>/www/htdocs/1
    ls -la /tos/etc /data/auth/db /tmp >>/www/htdocs/1
    

    上面的示例脚本就可以一次进行多种操作,获取进程信息、网络连接情况、目录文件等多种信息,大幅减少交互次数提高效率。

    逆向分析,寻找密码

    做了很多准备工作,找到了比较便捷的脚本执行方式。而且根据 ps 结果来看,指令是以 root 权限运行的。接下来要开始干正事了,tar cf /home/htdocs/1 / 打包文件系统, down 下来准备逆向分析。因为 web 登录入口指向 maincgi.cgi ,就从它开始。

    逆向分析的过程相当繁杂、漫长、枯燥乏味,具有相当的挑战性,所以需要坚定的毅力和不时涌现的灵感。无数次调整思路和方向,无数次寻找新的突破口。

    我现在也记不清当初分析时的前因后果,就把一些分析的结果整理下,做一个简单的分享。

    入口 maincgi.cgi

    maincgi.cgi 位于 /www/cgi/ 目录下。用 IDA 进行逆向分析。

    根据登录 form 提交的 usernamepasswd 在 string 窗口搜索, x 跟踪调用情况分析,最终来到 000403D4 函数内。

    maincgi_403D4.png

    下面是更容易理解的 C 伪代码(我开始分析的时候没找到可用的 hexrays ,这是事后撰写此文时找到的。:-( 工欲善其事必先利其器啊!):

    maincgi_403D4_c.png

    可以看到, username 和 passwd 参数都原封不动的传入到 login 函数,想必沿着这个方向一定能找到密码保存的地方。

    跟进发现 login 是 import 函数,不在 maincgi.cgi 中实现。为了方便,我把 lib 和 so 目录下所有文件的符号表都进行了分析,结果保存在一个文件中备查。

    $ nm -D tos/lib/* tos/so/* > symbols.txt
    

    很快发现 login 函数在 /tos/so/libwebui_tools.so 中实现。

    入了 RPC 的坑

    本以为找到 libwebui_tools.so 中的 login 实现,一切皆可水落石出。谁料还是 too young, too naive

    根据 export 表很快定位到 login 函数的实现,开始是 TLS 连接 127.0.0.1 : 4000 ,接着是一堆错误处理代码。

    login.png

    login_4000.png

    其中有一个 gui_send_reqx 函数的调用参数 CFG_AUTH 引起了我的注意,猜测是一种自定义的类 RPC 实现。

    login_cfg_auth.png

    唉,还是 C 伪代码看得清楚啊!再次哭晕在厕所 :-(

    login_c.png

    既然不是通过本地.so 调用,那只有知道到底是谁提供了这个 rpc 服务,才能找到接下来的路。

    好用的 netstat

    好在我们有执行代码的权限,好在防火墙里面有 netstat 命令。执行 netstat -nltp >>/www/htdocs/1 得到下面的结果:

    netstat.png

    一目了然。原来服务是 tos_configd 提供的呀!被 ELCA 漏洞利用脚本误导了,以为是只是一个命令行 shell ,之前跟过,但没有细看。这不,还是要回头找它。

    百转千回

    tos_configd 分析过程并非一帆风顺。

    根据 RPC 传递的参数 CFG_AUTH 作为线索进行追踪,看到 RPC 支持多个命令。当命令为 CFG_AUTH 时,将数字 5 写到参数传入的内存区域某个变量中。没有其他更多的信息,看来只能根据 caller 向上一步步追了。

    tos_configd_cfg_auth.png

    代码回到 rpc 的消息处理 thread 中,经过逐步分析,定位到消息处理函数中。

    tos_configd_rpchandle.png

    跟进去,可以看到大致的处理流程。有一个 switch 过程, case 5 后面就是 CFG_AUTH 的处理代码。 5 就是前面第一个过程中设置的变量。 topsec_manager_auth 函数用于接管用户密码鉴权工作,它是一个 import 函数,按照前面的方法查到它在 /tos/so/libmanager.so 中实现。

    tos_configd_rpchandlelogin.png

    胜利的曙光

    libmanager 的 export 表非常简练,似乎每一个都让人颇感兴趣。

    libmanager_export.png

    先看看我们的目标函数 topsec_manager_auth :

    libmanager_auth.png

    信息量很大,到这里基本上就看到了胜利的曙光。

    首先看到的是用户名+密码的 MD5 ,然后传入到 j_match_manager_name 函数中进行校验。这不就是经典的用户名密码校验过程嘛(未加 salt )。

    需要说明一下的是,上图中看到的 username 参数名称是我综合各类分析得知内容后改名的,并不是想当然,更不是 IDA 智能更名。 username+32 是密码明文,这也是在前面的分析过程中得出的结论。

    跟进 match_manager_name 函数,并没有立即发现直观的密码文件读取过程。取而代之的是,内存中存在最多 500 个 struct ,其中包含了用户名和 MD5 值,鉴权过程就是与其一一进行匹配比对。 Local_db_dev_node 是一个全局 buffer ,搞清楚它的数据来源就找到根源了。

    libmanager_match_manager_name.png

    按 X 查看 Local_db_dev_node 的 reference ,还真不少。

    libmanager_xref.png

    第一个 read_dev_manager_file 就很像,跟进去看一下。

    libmanager_read_dev_manager_file.png

    Bingo !就是它了! /tos/etc/Tos_dev_manager_info 其实这个文件之前也注意到,不过没曾想它居然保存了鉴权信息,而且是用户名密码拼接 MD5 这么简单!

    用 hexdump 查看之前下载的 Tos_dev_manager_info 进行验证,大小 104 字节,与分析得到的 struct 大小完全一致。再看用户名和密码的位置,和分析 Local_db_dev_node 结构完全一致。

    清除最后的障碍

    终于找到密码保存到文件了,三下五除二,自己设定一个密码,计算 MD5 值,修改 Tos_dev_manager_info 对应的区域。文件上传,覆盖,重启,等结果……

    import hashlib
    print(hashlib.md5('superman' + '111111').hexdigest())
    

    几分钟后,设备起来了,赶紧试一下密码,错误!!!

    郁闷,怎么会呢? down 下 /tos/etc/Tos_dev_manager_info 一看,还是老数据。看来是工作还没到位。

    想起 libmanager 不是有那么多可疑的函数吗?挑感兴趣的进去看看,比如 write_memdata2flash :

    libmanager_write_memdata2flash.png

    对,就它了。一般网络设备修改配置以后,不都还来一个 wr mem 吗?估计 /data/auth/db/ 才是最终保存数据的地方,/tos/etc 可能重启的时候会重新 copy 覆盖。

    再重新上传一次修改好的 Tos_dev_manager_info 文件,只不过这次同时覆盖了几个目录下的文件。重启,用设定的密码登录,搞定!!!

    走过的弯路

    当然,我分析过的文件远不止上面这些,也不是按照本文的思路一步一步走下来,走了不少弯路。凭感觉,或为了寻找新线索,或漫无目的地毯式搜索。除了上面列举的部分之外,还分析过其他几个.so 文件,跟踪过上百个函数,多数与我需要的东西关系并不太大。

    逆向分析就是这样,不可能一帆风顺,也没有既定的方法和思路。就是要有一种执着的精神,在不断的尝试、纠错和总结过程中达到目的地。成功后那一刻豁然开朗的成就感一直是我所痴迷的。

    关于 MD5 破解不得不说的事

    既然知道了算法,也有了 MD5 数据,是不是可以真正的找回当初的密码呢?

    和第一步猜测密码类似,用 python 按照一定规则,生成可能的密码序列。调用 hashlib.md5() 计算 hash 值与目标进行比对,结果跑了一天没结果。

    想着这种计算密集型的程序,在 python 和 c 之间切换太频繁可能影响效率。又在网上找到一个 Fast MD5 hash implementation in x86 assembly 汇编实现的快速算法,并且根据实际需求做了一定的优化。运行,依然无结果。

    不甘心,再到网上搜索资料,发现人家都用 GPU 跑字典。好吧,我也找来一个 Hashcat,在 i5 8G 内存 的 iMac 上试跑,的确速度非常快。然而,由于密码长,计算量过大,最终也没跑出结果,就此作罢。

    现在想想,如果没有密码长度、规则等任何信息的话,光凭暴力破解一个非典型密码,几乎是 Mission Impossible 。

    搞定,收工

    很久没写过长文,也没发过技术类文章。上一次可能要追溯到 2001 年 8 月的时候,曾以打鸡血似的饱满激情写过一篇软件逆向习作

    此次防火墙密码成功恢复,其漏洞功不可没。对我而言,又重温了一把当初年少时对技术的执着。

    最后,小结一下:

    • 软件逆向分析是个体力活。
    • 工欲善其事必先利其器。
    • 安全问题无时无刻不在。
    21 条回复    2017-06-01 08:21:28 +08:00
    senghoo
        1
    senghoo  
       2016-10-14 12:18:29 +08:00
    好文。不错。
    redsonic
        2
    redsonic  
       2016-10-14 12:21:17 +08:00
    Equation Group 里面有现成的爆破工具,不过我试了没有成功。 script 里说的版本是实际里面带的不一样,不知道是不是这个原因。
    coolair
        3
    coolair  
       2016-10-14 12:22:12 +08:00
    我看到最后密码没有跑出来,怎么收工了?
    jackyspy
        4
    jackyspy  
    OP
       2016-10-14 12:28:35 +08:00
    @redsonic 不知道,反正 nopen 就是起不来。 Equation Group 的工具里面有脚本,应该是可以执行成功的,不知道具体原因,可能跟防火墙 tos 版本对 nopen 的兼容性有关。反正我也不用这工具,能上传文件,能执行代码就 ok 。那脚本不短,我也没细看,没用上。
    jackyspy
        5
    jackyspy  
    OP
       2016-10-14 12:29:34 +08:00
    @coolair 实际上只是改了密码,可以登录。密码我实在找不出来了,估计要构造合适的字典才能跑出来。
    redsonic
        6
    redsonic  
       2016-10-14 12:42:38 +08:00
    你这文章一出估计天融信下个版本要改改了,不然 2000 块没得赚了。
    jackyspy
        7
    jackyspy  
    OP
       2016-10-14 12:47:35 +08:00
    @redsonic 是个老漏洞了,估计很多设备都已经打了补丁。
    icedx
        8
    icedx  
       2016-10-14 12:57:36 +08:00
    人才
    cmxz
        9
    cmxz  
       2016-10-14 13:11:41 +08:00 via Android
    ihacku
        10
    ihacku  
       2016-10-14 13:17:01 +08:00 via Android
    小伙子 你想换工作不 同程安全招人
    jackyspy
        11
    jackyspy  
    OP
       2016-10-14 14:27:31 +08:00
    @ihacku 有这个想法,纠结中
    tcpper
        12
    tcpper  
       2016-10-14 19:10:32 +08:00
    好腻害的骚年
    owlsec
        13
    owlsec  
       2016-10-14 19:47:58 +08:00
    楼主可以,感谢分享~~~大部分人估计密码忘了肯定是返厂了!。
    ye10010
        14
    ye10010  
       2016-10-14 20:24:26 +08:00
    文件乱改,不怕恢复不过去吗?钻研精神值得学习,生产环境中搞出问题就不是 2000 能解决的了..
    不过还是很佩服你.
    czkwg8
        15
    czkwg8  
       2016-10-14 21:13:36 +08:00
    精彩的逆向文章!
    ihacku
        16
    ihacku  
       2016-10-15 00:27:59 +08:00 via Android
    @jackyspy 加我微信聊聊? 微信号就是 v2 id
    jackyspy
        17
    jackyspy  
    OP
       2016-10-15 08:00:44 +08:00
    @ye10010 你说的没错,的确存在一定的风险。不过经过细致的分析,好歹还算比较有把握。现在应该庆幸没有出意外^_^
    jackyspy
        18
    jackyspy  
    OP
       2016-10-15 08:05:07 +08:00
    @ihacku 已加,请多指教^_^
    WilliamKyle
        19
    WilliamKyle  
       2016-12-08 00:44:08 +08:00
    《 NSA Equation Group 泄露的天融信产品漏洞分析(一)》 这个文章里面不是说了密码存在那个 cookie 的文件里面了么,而且还是 base64 保存的。
    jackyspy
        20
    jackyspy  
    OP
       2016-12-08 08:15:40 +08:00
    @WilliamKyle 说的没错,可是我的里面是错误的密码。估计尝试错误密码次数太多,覆盖了原先的密码数据。
    jjchen1989
        21
    jjchen1989  
       2017-06-01 08:21:28 +08:00
    @jackyspy Tos_dev_manager_info 怎么下载和上传
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1026 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 175ms · UTC 22:21 · PVG 06:21 · LAX 15:21 · JFK 18:21
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.