<p><strong>影响范围涉及4个国家及常见型号</strong></p><p>通常来说,思科路由器的植入后门以前经常被认为是理论可行或较难实现,但近日有国外安全公司Fireeye发现这种针对路由器的植入式后门正悄然流行,涉及Cisco 1841/Cisco 2811/Cisco 3825路由器及其他常见型号。目前发现在乌克兰、菲律宾、墨西哥和印度这4个国家中正有至少14个类似的植入后门在传播。</p><p><strong>通过弱口令登录替换思科路由器固件</strong></p><p>这个后门是通过修改思科路由器的固件植入恶意代码实现的,类似病毒感染正常文件。攻击者需要通过其他途径将这个后门固件上传或者加载到目标路由器上。目前看攻击者并没有利用任何的0day<a href="http://blog.nsfocus.net/category/%e6%bc%8f%e6%b4%9e%e5%88%86%e6%9e%90/" target="_blank">漏洞</a>来上传固件,而是利用路由器的缺省口令或者弱口令来登录路由器,然后上传后门固件,替换原有正常固件。只要路由器管理员不升级固件,攻击者就可以持久获得对路由器的长期控制。</p><p><strong>将僵尸木马的手法移植到路由器上</strong></p><p>这个后门植入了一个万能后门口令,攻击者可以利用这个后门口令通过telnet或者控制台登录路由器。它还采用了动态加载模块的技术,可以非常方便的随时加载新的恶意功能模块,在Windows/Unix系统下的僵尸木马网络中这已是很常见的技术了,但用在路由器后门中还是比较少见。每个模块都可以通过HTTP协议来更新、加载和删除。</p><p>这个后门被命名为” SYNful Knock”,可能是因为后门的网络控制功能(CnC)会通过一个特殊的TCP SYN包来触发。</p><h2>思科路由器植入后门的技术细节</h2><p>这个后门通过篡改一个正常的Cisco IOS映像文件来植入恶意功能,主要的修改操作包括:</p><ul><li>修改所有translation lookaside buffer (TLB)的属性为可读可写(RW)</li></ul><p>正常IOS映像文件中,有些TLB的属性是只读的(RO),而此后门会将所有TLB的属性都设置为可读可写(RW),这可能是为了实现通过Hook IOS函数来加载模块。如果TLB属性不是可读可写(RW),那对缓存内存页的修改就不能被同步到内存中原始内存页中。可以通过” show platform”命令来检查TLB的属性情况,如果发现全部TLB属性都被设置为RW(如下图所示),那可能意味着系统被植入了恶意后门。</p><p><img src="http://blog.nsfocus.net/wp-content/uploads/2015/09/14.png" alt=""></p><ul><li>修改一个正常的IOS函数,初始化恶意软件</li></ul><p>据信是修改了一个与进程调度相关的函数入口,将其指向一段恶意代码,这段代码完成恶意软件的初始化后,再执行原有正常函数功能。选择该函数是因为其在每次系统重启时都会被调用,这样攻击者就可以持续获得控制权。</p><ul><li>用恶意代码重写一些正常的协议处理函数</li></ul><p>为了防止映像文件大小发生变化,此后门会直接用恶意代码替换原有的一些正常函数的代码。</p><ul><li>用恶意代码需要使用的字符串重写正常函数用到的字符串</li></ul><p>同样为了防止大小变化,攻击者还会将CnC通信时用到的一些字符串直接替换正常函数使用的字符串。这样导致在执行一些正常IOS命令时,就可能返回一些如下的异常结果:</p><p><img src="http://blog.nsfocus.net/wp-content/uploads/2015/09/23.png" alt=""></img></p><h3>后门口令</h3><p>攻击者在后门映像中植入了一个万能口令,保证攻击者可以绕过正常口令限制随时登录系统。这个后门口令可以通过控制台、Telnet、enable(提升到管理员时)时输入,一旦匹配则赋予攻击者管理权限,否则就会继续正常的口令检查过程。目前看SSH和HTTPS登录时没有设置后门口令。</p><h3>网络命令和控制(CnC)</h3><p>此后门还使用了模块化方式来完成命令控制,可以随时将恶意功能加载到路由器中执行,这在路由器后门中还是比较少见的。这大大增强了恶意软件的可扩展性。一旦路由器重启,所有加载的恶意模块都会消失,攻击者需要重新上传恶意模块。</p><p>攻击者通过发送一些特殊的TCP报文来开启CnC控制,即使路由器管理员设置了一些过滤策略,后门仍然会接收并处理这些报文。</p><p>进行CnC控制的主要过程如下:</p><p>1.首先攻击者会发送一个特制的TCP SYN报文到已植入后门的路由器的80端口。这也是路由器HTTP服务器的默认端口。这个报文的SEQ序号和ACK序号的差值必须是0xC123D,ACK序号不需要一定是0。 2.后门会响应一个TCP SYN-ACK报文。报文格式满足:</p><ul><li>ACK序号和SEQ序号差值变为0xC123E</li><li>TCP选项被固定设置为: “02 04 05 b4 01 01 04 02 01 03 03 05″</li><li>TCP紧急指针设置为0x0001, 但紧急标志位URG未置位</li><li>SEQ序号拷贝自第一个SYN报文中的ACK序号,而通常情况下,SEQ序号是随机生成的。</li></ul><p>3.在三方握手完成后,控制端会发送下列命令报文:</p><ul><li>PUSH和ACK标志位置位</li><li>TCP头开始偏移0x62字节处写入一个字符串”text”</li><li>TCP头偏移0x67字节处开始是CnC命令数据</li></ul><p>命令格式如下:</p><table><colgroup><col width="NaN%"><col width="NaN%"><col width="NaN%"></colgroup><tbody><tr><td><p>命令长度(4字节)</p></td><td><p>命令数据(异或)</p></td><td><p>命令校验和(4字节)</p></td></tr></tbody></table><p> </p><p>命令数据部分是正常命令数据与一个静态串异或的结果。</p><p>4.植入的后门会返回包括命令执行结果的正常HTTP服务器响应数据,但执行结果并没有进行编码或加密处理。响应数据如下:</p><p><img src="http://blog.nsfocus.net/wp-content/uploads/2015/09/33.png" alt=""></p><h3>CnC命令格式</h3><p>后门支持5种控制命令,包括显示模块状态、为模块加载分配内存、加载模块、激活模块、卸载模块,最多可加载100个模块。</p><p>每个命令消息都以8个字节开头,前4个字节都置0,后四个字节是命令编号(0到4)。每个命令编号的含义见下表:</p><p>后门支持5种控制命令,包括显示模块状态、为模块加载分配内存、加载模块、激活模块、卸载模块,最多可加载100个模块。</p><p>每个命令消息都以8个字节开头,前4个字节都置0,后四个字节是命令编号(0到4)。每个命令编号的含义见下表:</p><table><colgroup><col width="NaN%"><col width="NaN%"></colgroup><tbody><tr><td><p>编号</p></td><td><p>描述</p></td></tr><tr><td><p><strong>0</strong></p></td><td><p>显示所有加载模块和当前状态。</p><p>响应格式如下:<br></p><table><colgroup><col width="NaN%"><col width="NaN%"></colgroup><tbody><tr><td><p>模块编号(4字节)</p></td><td><p>模块状态代码(4字节)</p></td></tr></tbody></table><br><p> </p><p>状态代码如下:<br> 00 – 内存已分配</p><p> 01 – 模块已加载入内存</p><p> 02 – 模块已激活</p></td></tr><tr><td><p><strong>1</strong></p></td><td><p>为要加载的模块分配内存。</p><p>请求命令提供2个缓冲区长度,第一个缓冲区大小是可执行代码的大小,第二个可能是配置和存储区的大小。后门会根据这两个长度分配缓冲区,并返回缓冲区地址。</p><p>请求格式如下:</p><table><colgroup><col width="NaN%"><col width="NaN%"><col width="NaN%"></colgroup><tbody><tr><td><p>模块ID(4字节)</p></td><td><p>第一个缓冲区长度(4字节)</p></td><td><p>第二个缓冲区长度(4字节)</p></td></tr></tbody></table><br><p> </p><p>响应格式如下:<br></p><table><colgroup><col width="NaN%"><col width="NaN%"></colgroup><tbody><tr><td><p>第一个缓冲区地址(4字节)</p></td><td><p>第二个缓冲区地址(4字节)</p></td></tr></tbody></table><br><p><br>命令执行后会设置该模块状态为0.</p></td></tr><tr><td><p><strong>2</strong></p></td><td><p>将可执行代码和数据加载到已分配的内存中。</p><p>请求格式如下:</p><table><colgroup><col width="NaN%"><col width="NaN%"><col width="NaN%"></colgroup><tbody><tr><td><p>HOOK数据(0x80字节)</p></td><td><p>第一个缓冲区长度(4字节)</p></td><td><p>第二个缓冲区长度(4字节)</p></td></tr><tr><td><p>第一个缓冲区数据…</p></td><td><p>第二个缓冲区数据…</p></td></tr></tbody></table><br><p><br>命令执行后会设置该模块状态为1.<br></p></td></tr><tr><td><p><strong>3</strong></p></td><td><p>激活一个已加载的模块。</p><p>后门映像会解析命令2中发送的HOOK数据,并在IOS寻找合适的函数进行HOOK,然后执行模块代码。</p><p> </p><p>请求格式如下:<br></p><table><colgroup><col width="NaN%"></colgroup><tbody><tr><td><p>模块编号(4字节)</p></td></tr></tbody></table><br><p><br>命令执行后会设置该模块状态为2.<br></p></td></tr><tr><td><p><strong>4</strong></p></td><td><p>卸载一个模块。</p><p>后门映像会释放已经分配的内存,并设置其状态为0。</p></td></tr></tbody></table><p> </p><p>如果一个命令消息的前4字节不是0,则前4字节会被认为是一个模块ID,这个模块ID对应的代码会直接被执行。</p>
暂无评论