使用mitmproxy嗅探双向认证ssl链接——嗅探AWS IoT SDK的mqtts
亚马逊AWS IoT使用MQTTS(在TLS上的MQTT)来提供物联网设备与云平台直接的通信功能。出于安全考虑,建议给每个设备配备了证书来认证,同时,设备也要安装亚马逊的根证书;这样,在使用8883端口建立TLS连接时,客户端SDK既对AWS进行验证,同时AWS IoT也对设备的证书进行验证。由此,便对中间人攻击带来了较高的要求,下面记录一下这几天的爬坑经理。
0.方案
整体方案类似于这个:https://wiki.dequis.org/notes/facebook/
用Host-Only模式的virtual box虚拟机当受害者,用iptables使其可以上网,并在虚拟网卡vboxnet0上搭建mitmproxy来嗅探。
VBox虚拟机(安装SDK) ====> VBoxnet0网络接口(搭建mitmproxy)======>eth0(公网访问AWS)
用到的工具:
Kali Linux
Virtual Box
mitmproxy
wireshark
dnsmasq
iptables
openssl
1.注册AWS IoT
注册AWS比较麻烦,还需要可支付美元的信用卡,不过因为担心被扣费刷爆,我随便baidu了一个填上。但是,由于扣费1USD不成功,导致下一步验证码总是过不去,所以填真实的信用卡比较靠谱。(奇怪的是,我静置1天后莫名其妙通过了;期间AWS发邮件说因为虚假信息要封号,我靠三寸不烂之舌通过了验证。)之后就是根据AWS的说明下载并试用SDK,特别值得一提的是,他提供了一个向导,直接注册设备生成证书和对应平台SDK,非常方便,我选用了生成的Linux Python SDK来实验。
2. Kali下安装virtual box
请参考网上其他教程。特别说明,一定要apt-get update ,apt-get upgrade ,apt-get dist-upgrade 升级到最新,并且reboot,到最新的内核版本安装,否则各种Linux headers和内核版本对应不上产生的问题。
3. virtual box采用host-only模式
https://www.virtualbox.org/manual/ch06.html#network_hostonly
使用host-only联网可参考:https://unix.stackexchange.com/questions/383791/virtualbox-host-only-with-internet
注意,virtual box修改网络模式的时候要关掉虚拟机!(在windows上用惯了VMare注意一下)
开始打算直接使用NAT,然后在host主机上(宿主机)搭建中间人代理mitmproxy,然而不知为何一直抓不到包,并且不像VMare可以看到虚拟网络接口,故使用host-only配合iptables
4.设置iptables使用mitmproxy中间人代理
https://media.readthedocs.org/pdf/mitmproxy/latest/mitmproxy.pdf
iptables教程:http://www.cnblogs.com/haven/archive/2012/09/27/2705859.html
(常用-t指定表,-S显示设置的规则,-F对该表的规则进行删除)
开启ipv4转发 sysctl -w net.ipv4.ip_forward=1
我设置的规则:(eth0外网连接,vboxnet0是host上的虚拟接口)
首先两个网络接口可以互相转发
iptables -A FORWARD -i eth0 -o vboxnet0 -j ACCEPT iptables -A FORWARD -i vboxnet0 -o eth0 -j ACCEPT
设置中间人代理以及NAT:
iptables -t nat -A PREROUTING -i vboxnet0 -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 8080 iptables -t nat -A PREROUTING -i vboxnet0 -p tcp -m tcp --dport 443 -j REDIRECT --to-ports 8080 iptables -t nat -A PREROUTING -i vboxnet0 -p tcp -m tcp --dport 8883 -j REDIRECT --to-ports 8080 //8883端口是mqtts iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE //在eth0设置nat改变原地址
注意,这里将mitmproxy搭建在vboxnet0,开始我选择搭建在eth0,但是不知为何一直抓不到包。
5. 设置SSL证书
http://docs.mitmproxy.org/en/stable/certinstall.html#the-mitmproxy-certificate-authority
首先让客户端SDK信任mitmproxy的证书,但是,AWS提供的证书和mitmproxy提供的证书在格式上不同,不能仅仅替换证书文件,还需要转换,在执行脚本时-r参数替换为mitmproxy的证书文件。
openssl x509 -in mitmproxy-ca-cert.pem -inform PEM -out foo.crt //更改证书格式
python aws-iot-device-sdk-python/samples/basicPubSub/basicPubSub.py -e axxxxxx9x.iot.us-east-2.amazonaws.com -r foo.crt -c 0000.cert.pem -k 0000.private.key
客户端设备的证书也要经过转换才能提供给mitmproxy,不然服务器会断开连接。
格式转换参考:https://stackoverflow.com/questions/28712088/unable-to-load-certificate-6300error0906d06cpem-routinespem-read-biono-star
使用客户端证书:http://docs.mitmproxy.org/en/stable/certinstall.html#using-a-client-side-certificate (文档有个坑,这里其实不能单纯指定文件夹,最好指定证书文件,官网文档没及时更新)
填坑:https://github.com/mitmproxy/mitmproxy/pull/494/commits/ff6bfba4a6a1c440018c4873d9edeb64da0f8e7f (这里说明了客户端证书怎么用,若指定文件夹要求文件名和访问域名一致)
openssl rsa -in 0000.private.key -out unprotected.0000.private.key
cat unprotected.0000.private.key 0000.cert.pem > mitm_0000.cert.pem
特别注意,这里不明原因客户端SDK和mitmproxy都会检测到域名不匹配(安全问题?),需要特别处理。SDK我选择注释掉了出错的那一行/usr/local/lib/python2.7/dist-packages/AWSIoTPythonSDK/core/protocol/paho/client.py的800行左右的self._tls_match_hostname();mitmproxy使用--insecure参数,届时会显示警告,但是不会断开连接。
192.168.56.2:52369: Certificate Verification Error for 52.15.111.27:8883: hostname 'no-hostname' doesn't match either of u'*.iot.us-east-2.amazonaws.com', u'iot.us-east-2.amazonaws.com'
192.168.56.2:52369: Ignoring server verification error, continuing with connection。
6.wireshark解密ssl
http://docs.mitmproxy.org/en/stable/dev/sslkeylogfile.html
设置环境变量让mitmproxy记录下ssl的密钥:
export SSLKEYLOGFILE=~/IoT/keylog (会影响浏览器 ,最好选用下面这个环境变量)
export MITMPROXY_SSLKEYLOGFILE=~/IoT/keylog
7.最后
1)运行代理:
mitmdump -T --insecure --client-certs ~/IoT/connect_device_package/mitm_0000.cert.pem --host --raw-tcp -w 11111
-v可以显示详细信息。
一定要设置--raw-tcp,否则代理会因为mqtt不是标准的http协议而出错。
2)打开wireshark并设置过滤条件为ssl && tcp.port==8883
3)运行sdk脚本:
python aws-iot-device-sdk-python/samples/basicPubSub/basicPubSub.py -e axxxxxx9x.iot.us-east-2.amazonaws.com -r foo.crt -c 0000.cert.pem -k 0000.private.key
4)将密钥导入wireshark即可解密出mqtts消息:
编辑——首选想——protocals——ssl—— (Pre)-Master-Secret log filename
,选择记录下的密钥。
- 面试机器学习、大数据岗位时遇到的各种问题
- ThinkPHP连续签到小案例
- Windows环境配置Apache+Mysql+PHP
- 如何使用Retrofit获取服务器返回来的JSON字符串
- Python相对、绝对导入浅析
- spring profile 多环境配置管理
- 论linux下计划任务
- 20条Linux命令面试问答
- CentOS 6 使用 yum 安装MongoDB及服务器端配置
- java处理高并发高负载类网站的优化方法
- 每一个程序员需要了解的10个Linux命令
- php_curl.dll libssh2.dll 始终无法加载的原因 及解决办法
- ant安装、环境变量配置及验证
- MySQL性能优化的最佳20+条经验
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- android仿微信通讯录搜索示例(匹配拼音,字母,索引位置)
- Android通过overScrollBy实现下拉视差特效
- Android使用手势实现翻页效果
- Android应用内悬浮窗的实现方案示例
- Android实现View拖拽跟随手指移动效果
- Android中button的onClick事件几种方法
- Android利用Glide获取图片真正的宽高的实例
- Android 自定义AlertDialog对话框样式
- Android自定义一个图形单点移动缩小的效果
- 详解Android实现购物车页面及购物车效果(点击动画)
- Android利用LitePal操作数据库存取图片
- Android 改变图标原有颜色和搜索框的实例代码
- Android自定义滑动验证条的示例代码
- Android实现图片转高斯模糊以及高斯模糊布局
- android多媒体类VideoView使用方法详解