# 小米路由器劫持用户浏览器事件回顾
0x00 概述
=======
* * *
小米路由器开发版固件(并非稳定版固件,不会影响大多数用户,如果你不明白这是什么意思,它不会影响到你)使用黑客技术劫持用户浏览器向用户投送广告,该技术在黑客界广泛用于偷取用户密码甚至可能控制用户电脑和手机,目前小米已经回应该事件,称该事件为“借机炒作恶意煽动”,并解释“所谓的广告”是友好的新功能提示。目前小米官方已经做出相应调整,该功能已经暂时失效。
![ad](http://drops.javaweb.org/uploads/images/1d4483edd5056c8d13c5d07b2ce496a4fdb1c8d2.jpg)
2015年6月初,有用户举报说最新开发版(2.3.31)的小米路由器固件劫持了用户浏览器,在用户完全不知情的情况下向浏览器发送广告代码并执行,本文以官方提供下载的2.3.5版本进行代码分析,论证其功能的技术实现以及可能影响,并对照小米官方微博的声明进行技术核对和解释。
0x01 用户举报
=========
* * *
在V2EX上由用户反映在通过小米路由器浏览网页时,网页被注入了JS代码,而这段代码目前还只是被用来显示广告。[《小米路由器先劫持 http 错误码, 现在又在部分网站添加小尾巴, 什么节奏?》](https://www.v2ex.com/t/199701)这意味着你在完全不知情的前提下,你看到的所有内容其实都受小米路由器的控制,这段代码可以被用来显示广告,也可以偷取你的密码,可以随便修改任何网页的内容来欺骗你,甚至如果你的浏览器有漏洞的话,小米路由器还可能会控制你的电脑或手机。
0x02 原理分析&代码分析
==============
* * *
在代码分析之前概述一下:简单说,他是一个路由器,你通过它来上网,你把数据先交给它,然后它才把数据通过网线送出你家,而小米路由器对你交给它的数据做了手脚,不仅看了,还修改了。 以下代码来自官方网站提供下载的2.3.5版本,使用binwalk解压固件fs,再分析得到的代码
[http://bigota.miwifi.com/xiaoqiang/rom/r1cm/miwifi_r1cm_firmware_7054f_2.3.5.bin](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),至于什么是反向代理,请参考乌云知识库之前的文章[《钓鱼?这是反代理!》](http://drops.wooyun.org/tips/6570),那么,这个/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