网络空间安全技术丛书

物联网渗透测试

IoT Penetration Testing Cookbook

（美）亚伦·古兹曼（Aaron Guzman）　等著

王滨　等译

ISBN：978-7-111-62507-0

本书纸版由机械工业出版社于2019年出版，电子版由华章分社（北京华章图文信息有限公司，北京奥维博世图书发行有限公司）在中华人民共和国境内（不包括香港、澳门特别行政区及台湾地区）制作与发行。

版权所有，侵权必究

客服热线：+ 86-10-68995265

客服信箱：service@bbbvip.com

官方网址：www.hzmedia.com.cn

新浪微博 @华章数媒

微信公众号 华章电子书（微信号：hzebook）

译者序

首先让我们来看一组事件：

·2016年9月至10月，美国域名解析服务提供商Dyn公司遭受Mirai僵尸网络攻击，导致近半个美国出现断网。事后的分析报告中指出，DDoS攻击流量峰值超过了1Tbps，这是已知攻击中规模最大的攻击流量。而攻击流量来自家用路由器、监控摄像头等物联网设备。

·2017年9月，360公司安全研究人员监控发现IoT_reaper僵尸网络，该僵尸网络借鉴了Mirai的部分代码，但是在恶意代码植入时不再使用弱口令猜测，而是通过集成D-link、Goahead、Netgear、Linksys等9款物联网设备漏洞进行传播。

·2018年1月，Bitdefender公司安全研究人员监控发现HNS僵尸网络，该僵尸网络主要利用智能家居设备中的漏洞（如HomeMatic Zentrale CCU2远程代码执行漏洞）以及Belkin无线摄像头等物联网设备中的漏洞进行传播。

·2018年5月，Cisco公司安全研究人员监控发现VPNfilter僵尸网络，该僵尸网络主要通过Linksys、Mikrotik、Netgear、TP-Link、QNAP等物联网设备的相关漏洞进行传播感染。

从上面一系列安全事件中不难发现，物联网设备已经成为攻击者的主要目标。因此，如何确保物联网设备安全成了亟须解决的重要问题。

那么，什么是物联网设备呢？

其实，早在1982年就已经出现了智能联网设备的概念，当时在卡内基-梅隆大学有一群程序员，他们不想每次下楼买可乐时，只能看着可乐自动贩卖机空手而回，或者是买到不够凉的可乐，于是他们就把可乐贩卖机接上网络，并写程序监控可乐贩卖机内的可乐瓶数量，以及是否是冰的，这样一台经过改造的可乐贩卖机就是第一台联网设备。普适计算之父马克·维瑟（Mark Weiser）在1991年发表了论文《21世纪的计算机》，并在UbiComp和PerCom等学术会议中刻画出了物联网的愿景。

“物联网”这个词是由麻省理工学院的自动识别实验室的凯文·阿什顿（Kevin Ashton）教授在1999年提出的，在当时，他将无线射频（RFID）技术看作物联网中必不可少的一部分，通过RFID技术能够让计算机来管理所有单独的事物。但是，随着技术和应用的发展，物联网的内涵已经发生了较大变化。2005年，在突尼斯举行的信息社会世界峰会（WSIS）上，国际电信联盟（ITU）发布《ITU互联网报告2005：物联网》，其中引用了“物联网”的概念。此时，物联网的定义和范围已经发生了变化，覆盖范围有了较大的拓展，不再只是指基于RFID技术的物联网。

随着实时分析、机器学习、商用传感器和嵌入式系统等多种技术的不断融合，物联网的定义不断演进。嵌入式系统、无线传感器网络、控制系统、自动化系统以及其他诸多内容都可以用来构建物联网。

开始介绍本书内容之前，我们首先引入分层的概念。这是因为物联网的实现涉及多个层次，没有一种解决方案能够应对针对物联网的所有威胁，为了给予物联网最适宜的保护措施，需要对物联网安全进行分层处理。也有人将物联网安全比成一块蛋糕，我们认为还是有些道理的。下面我们先来了解几种对物联网安全的分层方式。

2016年，权威物联网研究机构IoT Analytics将物联网安全架构分为设备层、通信层、云平台层、生命周期管理层4个层次[1]。

·设备层：设备层指的是物联网解决方案中的硬件层，就是“物联网”中“物”的实体或产品。当前ODM和OEM不断在物联网硬件与软件中添加安全特性以提高设备层的安全性。设备层主要涉及芯片安全、安全引导、物理安全等保护措施。

·通信层：通信层指的是物联网解决方案中的连通网络，即数据传输、数据接收的媒介。当敏感数据通过物理层（例如Wi-Fi、802.15.4或Ethernet）、网络层（例如IPv6、Modbus或OPC-UA）或者应用层（例如MQTT、CoAP或Web套接字）进行传输时，不安全的通信信道很容易遭受中间人攻击。通信层主要涉及数据加密、访问控制等保护措施。

·云平台层：云平台层指的是物联网解决方案的后端，对所接收的数据进行提取分析并解释。云平台层主要涉及完整性校验、数字证书等保护措施。

·生命周期管理层：生命周期管理层指的是确保IoT解决方案安全的持续过程。其中安全设计是确保方案安全的第一步，其他跨越生命周期的步骤还包括策略实施、常规审计以及供应链管理等措施。

在中国电信和绿盟科技公司联合发布的《2017物联网安全研究报告》中[2]，将物联网安全架构分为感知层安全、网络层安全、平台层安全与应用层安全4个层次。

·感知层安全：感知层安全的设计中需要考虑物联网设备有限的计算能力、通信能力、存储能力等因素，难以直接在物理设备上应用复杂的安全技术。可采取的防护技术和措施包括物理安全、接入安全、硬件安全、操作系统安全、应用安全、数据安全等。

·网络层安全：传统网络层安全机制大部分依然适用于物联网，此外还要基于物联网网络层特征采取特殊防护机制。可采取的防护技术和措施包括通用网络防护、网络入侵防护、接入防护、加密传输、物联网专有协议与应用识别等。

·平台层安全：平台层安全主要保障信息和数据在计算和存储过程中的安全，云平台必须采取适当的安全策略来保证物联网中数据的完整性、保密性和不可抵赖性，此外还要保障接入安全及API安全。

·应用层安全：应用层安全主要是保障各类应用在用户使用过程中的安全，包括对用户的身份鉴别、访问控制、应用漏洞管理、外部攻击防护、APP安全、隐私保护等。

在中国信息通信研究院2018年9月发布的《物联网安全白皮书（2018年）》中[3]，根据物联网应用系统模型将物联网安全防护层次分为终端安全、通信网络安全、服务端安全3个层次。

·终端安全：物联网中的终端设备种类繁多，各终端设备的体积大小不一，功能复杂程度多样。除传统计算机病毒外，终端所面临的安全威胁还包括木马、间谍软件、劫持攻击、钓鱼邮件、钓鱼网站等。综合考虑物联网终端本身及其面临的安全威胁特点，主要从硬件、接入、操作系统、业务应用等方面着手，采取适当的安全防护措施，确保物联网终端安全乃至物联网整网安全。

·通信网络安全：目前物联网中采用了多种网络接入技术，其中包含窄带物联网络、无线局域网、蜂窝移动通信网、无线自组网等多种异构网络，使得物联网在通信网络环节所面临的安全问题异常复杂，主要通过引入网络节点身份认证机制、强化终端数据完整性保护、加强数据传输加密操作和通信网络安全态势感知等对整个网络层进行安全防护。

·服务端安全：服务端安全防护主要解决针对数据管理系统、基于云计算的Web应用、业务分级保护等方面的安全问题。

还有很多科研院所与公司也提出了自己的物联网安全分层方法[4][5]，感兴趣的读者可以自行了解。在这里我们想说的是，上述对物联网安全的分层方法各有特点，并没有标准答案，读者可以结合自身需求运用物联网安全模型。但是，在本书的阅读过程中，我们希望读者在脑海中始终具有物联网安全分层架构的意识，建立本书所介绍的渗透测试技术与物联网安全架构之间的对应关系，从而纲举目张，形成自己的物联网攻防知识体系。

本书从渗透测试的角度介绍了如何对物联网设备开展分析，在当前关于物联网设备安全的相关图书中，本书较为全面、系统地梳理了物联网设备的攻击面，并且书中所介绍的方法具有较强的可操作性，相信可为物联网安全研究人员提供有益的参考。同时需要提醒读者的是，限于篇幅，NB-IoT、LoRa等应用日益广泛的无线通信技术在本书中没有涉及，但是这些技术的安全性同样会影响IoT的安全，感兴趣的读者可以自行了解。

基于我们对书中各章内容的理解，我们认为本书可以分为三部分：

第一部分：威胁建模（第1～2章）。主要对物联网设备的基本概念进行介绍，重点分析如何对IoT设备进行威胁建模。在对IoT开展分析时，研究人员可能会有线索纷繁复杂、无从下手的感觉，通过威胁建模，能够有效、系统地梳理IoT设备攻击面，初步确定测试方法，为后面的渗透测试奠定基础。

第二部分：渗透测试（第3～7章）。结合第2章所介绍的威胁建模方法梳理出IoT设备的攻击面后，分别从固件、Web应用、移动应用、硬件设备、无线电等角度开展针对IoT设备的安全分析。受篇幅所限，仅对基于每个角度开展测试的基本方法、基本工具进行介绍。但是在实际工作中，每个角度都可以展开来讲，建议读者以上述各章为纲，在日后的工作和学习中开展深入的研究。

第三部分：防护措施（第8～11章）。针对第3～7章在安全分析中暴露出来的安全隐患，分别从固件、移动应用、硬件设备、集成开发等角度介绍IoT设备的安全实践。

本书第1和2章由冷门翻译，第3、5、7、8章由王滨博士翻译，第4、6、11章由戴超博士翻译，第9和10章由张鹿博士翻译，最后由王滨博士与戴超博士对全书进行了审校。另外，在本书翻译的过程中得到了杭州海康威视网络与信息安全实验室的叶良策、万里、陈加栋等的大力协助，感谢他们在工作之余花费大量的业余时间来校对相关内容。最后，感谢机械工业出版社的朱劼在本书策划、翻译过程中提供的帮助，她作为经验丰富的出版人，每次交流都让我们受益匪浅。

在本书翻译完成的时候，我们的译者团队人员出现了一些变化，在这里我们想说的是，“聚是一团火，散是满天星”，希望无论大家身在何时、身处何地，都能够不忘初心，不断前行！

在本书的阅读过程中，无论是由于译者水平有限在翻译过程中出现的错漏，还是读者在阅读过程中遇到的问题，都欢迎广大读者来交流沟通，将错漏之处与问题反馈给我们，联系邮箱为iotpentest@163.com。

王滨　戴超

[1] https://iot-analytics.com/understanding-iot-security-part-1-iot-security-architecture/。

[2] http://www.nsfocus.com.cn/content/details_62_2646.html。

[3] http://www.caict.ac.cn/kxyj/qwfb/bps/201809/t20180919_185439.htm。

[4] https://developer.ibm.com/dwblog/2016/peeling-back-layers-security-iot/。

[5] https://www.cisco.com/c/en/us/about/security-center/secure-iot-proposed-framework.html。

前言

IoT（物联网）主要指通过某种方式连接到网络的嵌入式设备。有些IoT设备通过为嵌入式设备添加联网模块改造而来，还有些IoT设备则是专门为特定需求开发的新型设备。无论是哪种形式，这些设备都可能给企业、国家与个人带来安全隐患。无论读者是刚入门渗透测试的新手还是渗透测试的老手，本书都能够帮助安全从业人员加深对IoT生态系统的全面了解，进而开展安全防护。

主要内容

第1章主要介绍IoT的基本概念以及开展IoT渗透测试的基础知识。

第2章主要深入介绍威胁建模，以及如何对IoT设备的生态系统开展威胁建模。

第3章主要研究如何对IoT设备固件进行逆向分析，以及如何针对常见的漏洞开展漏洞利用。

第4章介绍不同类型的嵌入式Web应用，以及如何挖掘可利用的漏洞进而获取IoT设备的控制权。

第5章介绍如何针对IoT移动应用进行逆向分析以及常见漏洞挖掘的基本原理，进而获取未授权功能模块的访问权限。

第6章介绍基本的硬件攻击技术，以及如何入侵IoT设备的组件。

第7章介绍基于软件定义的无线电概念，以及IoT设备中常见无线协议的漏洞挖掘与利用工具。

第8章主要介绍嵌入式开发人员如何将安全控制措施融入IoT设备固件当中，使其避免出现常见漏洞。

第9章主要介绍移动应用如何采用主动防御措施来确保IoT应用的安全。

第10章深入介绍改进硬件安全性的最佳实践，以提高逆向分析的难度。

第11章介绍如何开展漏洞利用，以及如何将一组漏洞结合起来进而获得对IoT设备的控制权限。此外，该章还演示了如何在持续集成环境中实现针对应用的自动化安全扫描。

应用工具

本书用到的软件包括：

·Microsoft Threat Modeling Tool 2016

·Binwalk、Firmadyne、Firmwalker、Angr（可选）、firmware-mod-toolkit、Firmware Analysis Toolkit、GDB、Radare2（可选）、Binary Analysis Tool（BAT）、Qemu、IDA Pro（可选）

·Burp Suite、OWASP ZAP

·Mobile Security Framework（MobSF）、Idb、SQLite Browser 3.10.1、Cydia、open-URL、dumpdecrypted、ipainstaller、SSL Kill Switch 2、Clutch2、Cycript、JD-GUI、Hopper

·RTL-SDR

·Node安全项目（Node security project，Nsp）、Retirejs、Dependency-check、flaw-finder、Jenkins 2.60.3

本书用到的硬件包括：

Attify Badge（也可以选择C232HM-DDHSL-0线缆和Adafruit公司FTDI Breakout开发板的搭配）、Salae逻辑分析仪（8通道）、刷入KillerBee攻击框架的RzRaven USB设备、JTAGulator、带有Xbee Shield模块的Xbee扩展板[1]、Ubertooth[2]、BLE适配器。

本书的读者对象

本书主要面向想要熟悉IoT设备漏洞的挖掘和利用的软件开发人员、质量保障人员、安全从业人员，以及对主动防御措施感兴趣的读者。

章节结构说明

在本书中，读者可能会发现有几个标题频繁出现（例如准备工作、测试流程、测试分析、拓展学习以及延伸阅读）。为了清楚地介绍测试方法，下面我们对这些标题加以说明。

准备工作

这部分主要告知读者当前测试方法的目标，并对需要安装的软件或者其他需要预先设置的测试环境进行介绍。

测试流程

这部分内容主要包括开展测试过程中所涉及的每个步骤。

测试分析

这部分内容通常是对测试流程中所出现情况的详细分析与说明。

拓展学习

这部分内容主要包括与所介绍测试方法有关的其他内容，目的在于加深读者对测试方法的了解。

延伸阅读

这部分内容主要包括与所介绍测试方法有关的部分链接，可以帮助读者进一步了解测试方法。

格式约定

本书中，读者会发现文中用到了多种文本格式，用以区分不同的信息。下面将给出一些示例并解释它们各自的含义。

代码采用以下格式：

命令行输入与输出的格式如下：

指示警告信息或者重要的注释。

指示提示信息或者小技巧。

下载示例代码及彩色插图

本书的示例代码及插图，可以从http://www.packtpub.com通过个人账号下载，也可以访问华章图书官网http://www.hzbook.com，通过注册并登录个人账号下载。

[1] Digi公司出品的一款采用ZigBee技术的无线模块。——译者注

[2] 蓝牙嗅探器。——译者注

致谢

谨以此书献给我的祖母Sharon Ortiz。我真的好想您！感谢我的家人和女友带给我的笑声与关爱，这些给予了我莫大的支持。你们真是太棒了！

——Aaron Guzman

谨以此书献给所有信息安全从业人员，包括黑客、建设人员和运维人员。献给挖掘漏洞和修复漏洞的人们，还有红队、蓝队和紫队。

激情不灭，新知永续，让我们一起把知识传递给新人吧，毕竟我们也都曾经是新人，也许现在仍然如此。

特别感谢Packt出版社的编辑Deepti、Nilesh，还有本书的策划出版团队。没有你们的不懈努力和奉献，这本书就不会顺利出版。

——Aditya Gupta

作者简介

Aaron Guzman是洛杉矶地区知名的安全顾问，在Web应用安全、移动应用安全以及嵌入式设备安全领域具有丰富的经验。Aaron Guzman在众多国际会议以及一些地区性会议上分享过他的安全研究成果，这些国际会议包括DEF CON、DerbyCon、AppSec EU、AppSec USA、HackFest、Security Fest、HackMiami、44Con以及AusCERT等。此外，Aaron是开放式Web应用程序安全项目（Open Web Application Security Project，OWASP）洛杉矶分会与云安全联盟（Cloud Security Alliance，CSA）南加利福尼亚分会的负责人，还是Packt出版的《Practical Internet of Things Security》一书的技术审稿人。他为CSA、OWASP、PRPL等组织出版发行的很多IoT安全指南类书籍提供过帮助。Aaron主持了OWASP嵌入式应用安全项目，为嵌入式与IoT社区解决常见的固件安全漏洞提供了卓有成效的指导。读者可以关注Twitter账号@scriptingxss了解Aaron的最新研究进展。

这里向本书的读者致以特别的谢意，希望这本书能够对他们开展IoT安全研究以及渗透测试有所帮助。

Aditya Gupta是IoT与移动安全公司Attify的创始人，同时也是IoT和移动安全研究员。他开发了广受欢迎的培训课程Offensive IoT Exploitation（IoT漏洞利用技术），同时也是黑客在线商店Attify-Store的创始人。

Gupta文能提笔写论文，武能编码写工具，并多次在BlackHat、DefCon、OWASP AppSec、ToorCon等国际会议上发表演讲。

在过往的经历中，Gupta曾与多个机构合作，帮助它们构建安全架构，开发内部自动化检测工具，挖掘Web和移动应用漏洞，主持制订安全规划方案等。

读者可以通过Twitter账号@adi1391或邮箱adityag@attify.com联系Gupta。

我要感谢我的父母和姐姐，感谢他们为我提供了成功所必需的支持和动力，并让我对于“世间万物的运作机制”充满了好奇，这推动着我日复一日地追求自己钟爱的事业。

最后也是最重要的是，感谢Attify公司的同事——非常幸运能够同最好的渗透测试人员、逆向分析师和擅长解决问题的人们一起共事——正是在大家的通力协作下我们攻克了几乎所有的IoT设备。你们是最棒的！

审稿者简介

Francesco Azzola是一名从业时间超过15年的电子工程师，在计算机编程和JEE架构方面具有丰富的经验。他先后取得了Sun认证企业架构师（Sun Certified Enterprise Architect，SCEA）、Sun认证Web组件开发工程师（Sun Certified Web Component Deve-loper，SCWCD）和Sun认证Java软件工程师（Sun Certificated Java Programmer，SCJP）等资质。他醉心于Android和IoT开发，并热衷于采用Arduino、树莓派、Android以及其他平台进行IoT项目开发。

他对IoT和移动应用之间的融合甚感兴趣，早前在移动开发领域工作多年。还创建了博客网站survivingwithandroid.com，用于分享在Android和IoT项目开发方面的博文。他编著了《Android Things Projects》一书，该书已由Packt出版社出版。

Paul Massey在计算机编程开发领域拥有20余年的从业经历，其中包括在软件开发公司Scriptwerx担任了11年的CEO。他是JavaScript和移动应用技术方面的专家，多年来一直致力于Arduino平台（以及与之类似的平台）的开发工作，并主持了多个IoT、音视频和汽车技术领域的软硬件开发项目。

第1章　IoT渗透测试

虽然1999年美国麻省理工学院（MIT）的自动识别实验室（Auto-ID Labs）就首次提出了IoT（物联网）的概念，但嵌入式设备技术在数十年之前就已存在了。IoT设备同嵌入式设备之间的区别在于，在嵌入式设备的设计决策和配置过程中，从未将建立自身同公共互联网的连接考虑在内。正是由于众多制造业公司没有考虑到设备联网的后果，所以随着联网设备数量的不断增多，当前出现了针对IoT设备的大规模漏洞利用，并导致了多起创纪录的大规模分布式拒绝服务（Distributed Denial of Service，DDoS）攻击。本书中，我们将从多个方面介绍针对IoT设备的渗透测试，为测试人员提供具有可操作性的安全实践指导，并帮助用户在现实环境中实现对IoT设备的攻击防护。

读者可以访问以下链接了解IoT的起源：http://autoid.mit.edu/iot_research_initiative。

要了解针对IoT设备的DDoS攻击详情，可以访问以下链接：https://www.us-cert.gov/ncas/alerts/TA16-288A。

本章将主要介绍以下主题：

·定义IoT生态系统与渗透测试生命周期。

·固件入门。

·IoT中的Web应用。

·IoT中的移动应用。

·硬件设备基础。

·IoT无线通信简介。

·IoT渗透测试环境的部署。

1.1　简介

本章主要关注开展IoT渗透测试所需的基础知识，向读者介绍IoT设备攻击面的基本概念，为帮助测试人员构建IoT渗透测试的实验环境奠定基础。

我们首先讨论当前IoT渗透测试的现状，以及所有可能存在的攻击面，进而了解渗透测试的进展情况。之后我们将介绍固件安全、Web应用安全、移动应用安全、硬件安全和无线电通信方面的基础知识。

最后，我们将向读者介绍如何对开展渗透测试所需的软硬件工具进行配置。

1.2　定义IoT生态系统与渗透测试生命周期

在过去的几年中，基于IoT设备不断上涨的数量、为业务提供的便利性、自身的易用性以及为信息安全带来的潜在风险等诸多因素，IoT设备赢得了广泛关注。由于IoT概念的火爆就出现在我们身边，所以即便是作为一个普通人也可以感受到这个技术奇点[1]距离自己并不遥远。而对IoT和互联网越来越高的依赖度使得人们不由地对人身安全、隐私安全与信息安全产生了担忧。同时，IoT设备几乎已经用在所有行业领域，如消费、娱乐业、工商业、医疗业、工业、能源业以及制造业等领域。但是，过往案例已经证明了无论是消费者还是将IoT技术商用的厂商和开发者，都难以采取有效的方式来确保设备安全。如果指望设备厂商在制造设备时采用诸如安全设计之类的方法提供安全保障，又严重依赖于设备所面向的行业，那么需要厂商对行业业务具有深刻的理解，这对厂商显然提出了非常高的要求。

各个行业也可能因垂直细分与所处区域而制订不同的测试规范。因此，为了确保不违反相关法律规定，在对IoT设备开展渗透测试之前需要了解有关的法律法规。在部分地区，我们以美国为例，只要研究是出于符合社会规范的善意目的，通过合法渠道获得被测设备，在受控环境下开展测试，并且也未违反2016年10月颁布的《计算机欺诈和滥用法案》（Computer Fraud and Abuse Act，CFAA），那么是允许安全人员对消费级设备开展安全研究的，并且不受《数字千年版权法》（Digital Millennium Copyright Act，DMCA）的追究。这也就意味着当前对网联汽车、摄像头、各种智能家居设备、视频游戏机和越狱移动设备的安全研究都是合法的。在经过与《数字千年版权法》和安全界的漫长协调之后，广大安全研究人员取得了一个巨大的胜利。

在取得相关法律法规许可的情况下（这也是我们开展安全测试的依据所在），接下来将对设备固件、Web应用、移动应用、硬件和无线电通信开展安全评估。首先，我们需要了解IoT所涉及的所有领域，包括渗透测试方法和生命周期，进而识别出所有可能的攻击面。下面我们来了解一下IoT设备中各组件的基本原理，以便知晓其攻击原理。

渗透测试方法

无论是否出现攻击事件，对应用、网络和设备开展安全测试、查找其中隐藏的漏洞对于保障互联网安全都是至关重要的。无论是由厂商、第三方咨询公司、企业安全团队，还是由普通的安全人员来实施测试，测试方法的选择都取决于能够提供给测试人员的信息。理想情况下，一次全面的测试应该包括整个IoT系统及其基础设施，而不仅仅是IoT设备本身，但考虑到成本与技术能力，现实中的通常只针对IoT系统中的某个子集开展测试。

1.黑盒测试

由于黑盒测试成本相对较低，因此黑盒测试是最为常见的测试方法。黑盒测试是在不了解设备所采用的技术原理或实现方式的情况下进行的测试。通常情况下，安全研究人员或第三方咨询公司都会采用黑盒测试方法，但有时内部安全团队也会采用该方法进行风险评估。

漏洞公开注意事项

如果在安全研究过程中挖掘出了漏洞，那么披露漏洞时需要遵循厂商要求的漏洞公开流程。如果厂商未制订漏洞公开流程，那么计算机安全应急响应中心（CERT）可以协助安全研究人员以适当的方式提交漏洞。关于CERT的漏洞公开处理流程的详细内容可以参考链接http://www.cert.org/vulnerability-analysis/vul-disclosure.cfm中的内容。

2.白盒测试

如果测试人员能够接触到源代码、网络拓扑图、架构图、数据流图以及其他目标设备所采用技术的详细信息，那么此时开展的测试即白盒测试。通常来说，预先能够向测试人员提供的目标设备或应用的信息越多，测试效果就会越好。白盒测试的成本相对较高，但能够确保对设备的安全控制措施及其实现情况进行更加全面、彻底的筛查。

3.灰盒测试

相对于被测机构内部人员而言，如果测试人员对被测系统的了解有限，仅能获取到被测系统的部分信息，那么此时所开展的测试即灰盒测试。在灰盒测试过程中，测试人员通常只知道所用到的应用程序栈和库文件，但是没有关于API的详细文档。

读者可以访问以下链接了解更多开展安全研究过程中有关《数字千年版权法》（DCMA）的内容：https://www.ftc.gov/news-events/blogs/techftc/2016/10/dmca-secu-rity-research-exemption-consumer-devices。

[1] 技术奇点是一个根据技术发展史总结出的观点，认为未来将要发生一件不可避免的事件：技术发展将会在很短的时间内发生极大的接近于无限的进步。一般设想技术奇点由超越现今人类并且可以自我进化的机器智能或者其他形式的超级智能的出现所引发。由于其智能远超今天的人类，因此技术的发展会完全超乎全人类的理解能力，甚至无法预警其发生。之所以被称为奇点，就是像物理学上引力接近无穷大时产生的黑洞的物理属性一样，已经超出一般正常模型所能预测的范围。——译者注

1.3　固件入门

固件是一种写入硬件设备的软件，作用是对应用和各项系统功能实施控制。固件中包含底层代码，这些代码能够帮助软件实现对硬件的操作。运行固件的设备称为嵌入式系统，嵌入式系统的硬件资源在存储能力以及内存等方面往往具有诸多限制。举例来说，智能手机、交通信号灯、网联汽车、某些类型的专用计算机、无人机和有线机顶盒都是运行固件的嵌入式设备。

显然，从城市运行所依赖的关键基础设施，到人们生活中必不可少的银行ATM和智能家居，嵌入式技术及运行在嵌入式设备之上的固件控制着我们的日常生活。理解固件的二进制文件中都包含哪些内容以及与之关联的属性是非常重要的。固件通常由bootloader、内核、文件系统以及其他资源组成。根据嵌入式Linux、嵌入式Windows、Windows IoT内核以及各种实时操作系统（Real Time Operating System，RTOS）的区别，固件也有多种类型。本书主要针对基于嵌入式Linux的环境进行介绍，但是，本书中所涉及的原理对于其他平台也是同样适用的。

读者可以从以下链接中了解更多关于固件的内容：https://wiki.debian.org/Firmware。

图1-1展示了固件的组成，即闪存、bootloader、内核和根文件系统。

图1-1　固件组成示意图

1.3.1　固件深度分析

首先让我们先了解一下bootloader。bootloader的作用主要包括RAM初始化（目的是存储易失性数据）、串口初始化、机器类型检测、内核参数链表（kernel tagged list）设置、initramfs（基于RAM的初始文件系统）加载以及内核镜像调用等。bootloader通过板级支持包（Board Support Package，BSP）初始化硬件驱动，其中板级支持包通常由第三方厂商开发。可以将bootloader存储在单独的电可擦除可编程只读存储器（Electrically Erasable Programmable Read-Only Memory，EEPROM）中，但这种情况一般不太常见，更为常见的形式是直接将bootloader写入闪存存储器。从某种程度上说，我们可以将bootloader看作启动PC时的BIOS。深入分析bootloader的各项功能已经超出了本书所讨论的范畴，这里我们只对本书用到的bootloader特性进行介绍。ARM、MIPS架构中部分常见的bootloader包括：Redboot、u-boot以及barebox等。当bootloader启动内核之后，文件系统就完成了加载。

固件可以采用的文件系统类型有很多，有时根据设备的区别也会采用某些专有文件类型。部分较为常见的文件系统类型包括SquashFS、cramFS、JFFS2、YAFFS2以及ext2等。其中设备（尤其是消费级电子设备）最常采用的文件系统是SquashFS。分析人员可以使用诸如unsquashfs或者改进后的unsquashfs等工具从SquashFS文件系统中提取数据。有部分厂商会对SquashFS文件系统进行改进，以确保能够对非标准的SquashFS文件系统压缩算法提供支持，比如说LZMA压缩算法（在SquashFS 4.0之前，官方支持的唯一压缩格式为.zlib），而此时就需要用到改进后的unsquashfs工具进行解压，同常规的标准SquashFS文件系统相比，非标准的SquashFS文件系统启动时的偏移量同之前会有所区别。在本书后面的内容中，我们将会对偏移的定位与识别进行专门的介绍。

读者如果想了解有关嵌入式Linux文件系统的更多内容，可以访问以下链接：http://elinux.org/images/b/b1/Filesystems-for-embedded-linux.pdf。

Sasquatch是一套能够对非标准SquashFS文件系统进行解压、从中提取文件系统的工具，即可以从以下链接下载：https://github.com/devttys0/sasquatch。

与之类似，固件镜像也可以采用LZMA、.gzip、.zip、.zlip和.arj等多种文件压缩类型。每种文件类型在压缩后的文件尺寸、压缩时间、解压时间以及设备自身的业务需求等方面都各有擅长。从渗透测试的角度出发，我们可以把文件系统看作存储配置文件、服务、账户口令、散列值、应用程序代码以及启动脚本的地方。在下一章中，我们将介绍如何查找设备中的文件系统，以及如何确定其采用的压缩方式。

1.3.2　固件的开发供应链

文件系统中包含同设备强相关的代码，这些代码通常采用C、C++或者Lua之类的编程语言编写。与设备相关的代码，甚至是固件自身，都可以外包给第三方开发人员，即原始设计制造商（ODM），也可以由内部开发人员同原始设备制造商（OEM）协作开发。ODM是嵌入式设备开发供应链中的一个重要环节。在亚洲，有很多这样的小公司，并且开发成本也较为低廉。有些OEM信任自己产品线上的ODM，而有些OEM则会选择对单一产品报价最低的ODM。在某些行业中，ODM也可以称为供应商。需要特别注意的是，ODM是能够同多家不同的OEM开展合作的，甚至可以采用相同的代码库。读者可能已经知道这个情况，或者惊讶于为什么一个严重的软件漏洞公告就会影响到十余家设备厂商。究其原因就在于ODM自身并未建立安全开发生命周期流程，而OEM对此也疏于验证。一旦ODM完成了应用开发成果的交付，这个成果可能是OEM的一个SDK也可能是固件，OEM就会直接把交付的代码融入固件之中，实现起来可能就是简单地在Web界面添加OEM的一个logo。根据ODM和OEM代码融合方式的不同，实现过程也有所区别，其中一种较为常见的方式是，ODM向OEM直接提供二进制文件。OEM负责固件分发、固件管理以及对设备自身提供支持，其中也包括解决第三方研究人员提交的固件安全问题，如果ODM持有源代码，而OEM仅能拿到二进制文件，那么OEM难以有效缓解固件中的安全隐患，从而将面临巨大的压力。

在第3章中，我们将通过了解如何识别文件系统、压缩方式，以及如何构建二进制文件的仿真测试环境来实现对固件二进制镜像的逆向分析，进而对固件中常见的漏洞开展利用。

1.4　IoT中的Web应用

网站，也称为Web应用，已经无须对其进行过多的介绍了。基本的Web应用程序通常最少由前端HTML页面、JavaScript脚本、1台后台Web服务器、1台应用程序服务器和1套数据库组成。随着Web应用的发展，为了降低后端架构或设备的计算载荷，Web应用程序开始更多地依赖JavaScript脚本等前端代码。但是运行在互联网中的Web应用同运行在嵌入式设备中的Web应用略有不同。

读者所熟悉的Web应用组件之间存在更多的依赖关系，因为常见的Web应用会将Web服务器、应用服务器、数据库服务器以及后台运行的微服务进行分离。其中服务器的分离是出于性能和可用性等方面的考虑。而通常嵌入式Web应用被设计为在自包含的环境中运行。从更深层次上来说，也就是对嵌入式Web应用的性能和可用性方面关注较少。

目前IoT领域中主要有两种不同的Web应用模型，分别是混合云模型与独立嵌入式服务器模型。混合云模型中包含了厂商或者供应商提供的基于软件即服务（Software as a Service，SaaS）的Web应用，作用是同运行在嵌入式设备固件中的Web应用程序建立连接，然后，将数据从厂商的云服务器中同步到本地网络的嵌入式设备中。有些IoT设备则会直接使用IoT云服务提供商的SDK，例如AWS提供的IoT SDK和Azure提供的IoT SDK，并且将这些SDK编译进设备的Web应用程序栈中。为了确保符合机构的服务条款并且遵循所在区域的法律规范，混合云模型的识别非常重要。许多采用混合云模型的IoT公司经常以OEM的方式借助第三方软件开发公司或ODM来管理其Web应用。这些ODM的Web应用通常被贴牌为某款OEM产品，在没有设置通信流量代理的情况下，用户通常不会注意到这种情况。

IoT设备的混合云模型如图1-2所示，其中IoT设备能够连接到互联网。该场景中，在厂商云平台与用户设备之间由设备接口提供Web服务，用户访问设备接口进行操作或者进行数据收集。

图1-2　混合云Web应用模型

如前所述，嵌入式设备的Web应用在设备固件内部运行，以light tpd或者nginx等程序作为嵌入式Web服务器，而不存在外部依赖。读者可能对这些独立嵌入式Web应用比较熟悉，在打印机、VoIP电话和家庭路由器中都可以找到这些应用。通常情况下，用户输入直接发送到设备固件，如果未对用户输入进行验证或过滤，攻击者则可以向设备发起攻击尝试执行任意命令。在某些情况下，出于防止外部攻击或者便于管理的目的，嵌入式Web应用设计为仅在局域网（Local Area Network，LAN）环境中运行。这也是家用IoT、工控设备和商用设备中的典型情况。通常将设备限定在局域网环境下是出于安全方面的考量，但从我们所了解的情况来看，这种方式难以有效地缓解攻击。这是因为，持有这种观点的设备厂商在现实中发现客户总是会有意无意地将设备连接到互联网上，从而给用户网络带来安全隐患。

图1-3展示了用户通过Web浏览器连接独立嵌入式Web应用的过程，其中该应用不依赖于外部系统。

图1-3　本地嵌入式Web应用模型

Web通信

浏览器、嵌入式服务器和Web应用服务器之间的通信通常要么借助简单对象访问协议（Simple Object Access Protocol，SOAP）/XML等Web服务，要么借助基于http/httpS符合REST规范的API来实现。SOAP请求中通常包含1个envelope元素、1个xmlns：soap命名空间、1个encodingStyle属性，此外还包括其他元素，例如SOAP中的body元素。读者可以通过访问链接https://www.w3schools.com/xml/xml_soap.asp了解更多关于SOAP协议的内容。

下面展示了一个查询账户余额的http SOAP请求示例：

REST风格的API用到了多个http方法，而这些方法的使用并不符合传统Web应用的用法，例如传统Web应用采用PUT方法更新资源，采用DELETE方法删除资源，而采用REST风格的请求则是通过URL（对于敏感数据不推荐采用此方法进行处理），或者以JSON格式表示的http协议报文等方式调用参数。

在电子邮件分发列表中添加邮件地址test@example.com的REST请求示例如下：

可以采用中间人代理来查看基于SOAP协议或符合REST风格的请求报文。常用的Web代理工具包括Burp Suite与OWASP ZAP，借助这些工具可以查看从浏览器和移动应用发送到Web应用后端的所有请求。我们将在第4章中详细介绍如何配置代理来查看应用流量。

对于IoT设备而言，常常采用Web应用对其设备进行控制，因此，无论是从网络内部还是网络外部来看，Web应用都是发起攻击的常见途径。在第4章中，我们将会了解如何识别IoT设备中Web应用的缺陷与漏洞。

1.5　IoT中的移动应用

在IoT领域，移动应用模型同前面介绍的Web应用模型类似。虽然对移动设备平台的安全模型进行深入探讨超出了本书的范围，但是了解移动应用开发模型的基本概念将有助于后面的学习。

1.5.1　混合应用

安装在Android、iOS或Windows Phone设备中的移动应用可以是混合应用也可以是原生应用。虽然同Web应用相比，混合和原生在移动应用中具有不同的含义，但是其原理相似。混合应用既用到了HTML/HTML 5、CSS和JavaScript等Web技术，也用到了部分原生平台硬件，如GPS模块或蓝牙模块。只有使用混合框架提供的插件才能够访问硬件资源。可以将混合应用看作包含了Web应用的封装包，而原生平台可以使用该封装包。这意味着Web开发人员无须学习新的开发语言即可编写移动应用。

混合应用在Windows Phone、Android和iOS等多个平台上可以使用同一个代码库，当考虑将IoT设备应用投放市场时这是一个巨大的优势。通过嵌入式Web浏览器WebView就可以调用Web应用。当前，市场中流行的应用有多种流行的混合框架可以选择，包括Apache Cordova、Adobe PhoneGap以及Xamarin等。

每套移动混合框架都包含一个第三方市场，在其中提供可以实现各种功能的插件。为了实现快速开发，部分框架会采用一种编程语言（C#）编写，然后再翻译成另一种本地语言（Objective C或者Java），例如Xamarin就是如此。然而，从原生平台的高危远程代码执行到隐私泄露，这些移动框架存在着诸多安全隐患，这也并非什么秘密。如果读者在应用中恰好发现用到了某套移动混合框架，那么最好查阅一下相应的漏洞库，兴许就能够找到可以直接利用的漏洞。

为了帮助读者更好地了解混合应用运行的架构，图1-4展示了应用代码、WebView、插件以及移动设备自身之间的各个组件。需要注意的是，大多数封装包的代码和插件都是由混合框架或参与混合框架开发的第三方开发人员开发的。

图1-4　混合应用示例

1.5.2　原生应用

原生应用是为特定操作系统开发的，采用Java、Objective C、Swift等设备平台原生语言编写，其中对于Windows Phone平台而言则需要采用C#语言。原生应用使用各自平台的SDK实现同摄像头、蓝牙和GPS等硬件的交互。原生应用的性能和安全性取决于开发人员对原生平台语言的熟悉程度。如果平台API经常更新并且经常弃用某些类或方法，那么将会增加开发工作的难度。越来越多的平台，例如iOS和Android等平台，正在开发安全的原生API，这样开发人员就无须再利用第三方库即可直接使用安全API，进而提高通信和数据存储的安全性。

同混合应用架构相比，原生应用架构简单得多。图1-5展示了原生应用在设备上直接运行原生代码访问硬件资源的过程，在应用访问硬件资源的过程中未借助第三方组件。

图1-5　原生应用示例

了解每种移动应用模型的优缺点对于高效地开展渗透测试而言非常重要。由于移动应用拥有设备的控制权，因此是针对设备实施攻击的另一个重要突破口，并且同其他方法比起来，有时通过移动应用突破IoT设备要更加容易一些。在第5章中，我们将分解IoT设备，对IoT移动应用中最常见的漏洞展开深入分析。

1.6　硬件设备基础

下面从印制电路板（Printed Circuit Board，PCB）开始，对IoT设备中所涉及的硬件进行介绍。PCB由玻璃纤维、铜箔、阻焊层、丝印层、布线层和基板组成，在其上焊接有电阻、电容、Wi-Fi芯片、EEPROM、串口和微控制器等元件。板上布有多层铜箔作为PCB的导电体，而绝缘层则不导电。在查看印制电路板外观时，准确识别出感兴趣的元件非常重要。这些元件主要包括设备固件直接或间接的输入源。其中，EEPROM芯片、NAND闪存芯片、UART（Universal Asynchronous Receiver/Transmitter）接口和JTAG（Joint Test Action Group）接口通常都是渗透测试过程中最为关注的元件。

数字视频录像机（Digital Video Recorder，DVR）的PCB如图1-6所示。

图1-6　印制电路板实例图

硬件输入

EEPROM是非易失性存储器，以单个字节为单位进行读写。EEPROM可以通过电荷或紫外线照射擦除数据。同其他闪存类似，EEPROM芯片的读写次数有限。我们关注EEPROM芯片的原因在于，固件一方面可以加载到EEPROM芯片中，另一方面也可以从PCB中擦除而读取到EEPROM读写器上，从而便于进一步的分析。图1-7是EEPROM的示意图。

图1-7　EEPROM实例图

图片来源：https://cdn.sparkfun.com/assets/parts/3/0/5/EEPROM.jpg

NAND闪存以区块为单位读写，通常用在USB驱动器中，但也可以用在IoT设备和游戏机中。NAND闪存中通常存储着设备的bootloader，bootloader依据指令引导操作系统启动，此外用户还可以对bootloader进行操作，关于bootloader的内容我们将在后文详细介绍。

UART接口是访问设备最为常见的方式。厂商在部署设备时可以使用UART接口进行设备诊断、日志记录等操作，还可以作为调试接口来验证配置，这使得UART接口成为固件中最常见的输入源之一。由于厂商主要使用UART接口进行设备调试，所以通常连接该接口后即可获得root权限。然而有些情况下，通过UART接口访问设备需要输入口令，这时可能需要分析人员额外花费时间进行暴力破解。UART接口芯片包含两条串行线，这两条串行线分别用于接收数据和传输数据（Rx/Tx）。UART收发数据均需要借助数据总线。数据以并行方式从数据总线传输至UART传输器。UART传输器从数据总线中取得并行数据（并行数据通常包含5～8位数据位，其中7位数据位和8位数据位较为常见，因为ASCII标准字符集采用7位编码，扩展字符集采用8位编码）后，添加起始位、校验位以及停止位创建数据帧。接下来，数据帧以串行方式在Tx引脚逐位传输。UART接收器则从Rx引脚逐位读取数据帧，继而将串行数据转换为并行数据，并删除起始位、校验位以及停止位。最后，UART接收器以并行方式将数据帧传输至接收端数据总线。由于是异步通信，因此UART接口工作时不需要外部时钟，发送端和接收端会按照固定的波特率来进行数据采样。PCB上UART接口的引脚定义中包括了Tx、Rx、Vcc（电压）和GND（接地）4个引脚。连接UART接口前需要使用万用表识别出Tx、Rx和GND引脚。有时，个别设备中UART接口的识别可能会比其他设备更加困难一些。有些厂商可能会直接移除PCB上UART接口的排针插座，对于这种情况，研究人员就需要将排针插座重新焊接到PCB上去。还有些厂商会选择覆盖掉UART接口排针插座的丝印，还会将另一块集成电路覆盖在接口的插座上，而对于这种情况解决起来就比较麻烦了。

JTAG接口是遵循IEEE 1149.1标准的另一种国际标准测试协议，主要用于芯片级与系统级测试。类似于UART接口，厂商也可以采用JTAG接口作为调试的输入。JTAG接口能够提供口令保护，但是也可以通过BYPASS（旁路）模式进行访问。通过JTAG接口可以进行固件转储，方便后续对固件的分析，也可以用于固件升级。JTAG接口可以直接访问闪存或者RAM等板载硬件。JTAG接口包含TDI（数据输入）、TDO（数据输出）、TMS（测试模式选择）、TCK（测试时钟）和TRST（测试复位）等5个引脚。JTAG接口可以连接到芯片上的TAP（测试访问口），通过TAP访问芯片上的寄存器时可以改变寄存器状态。与UART接口类似，厂商也会隐藏JTAG接口的排针插座或者线路。

通过拆解设备或者搜索https://fccid.io等第三方网站，可以观察IoT设备中的PCB构造并定位元件位置。美国联邦通信委员会（Federal Communications Commission，FCC）ID是FCC分配的产品ID，其作用是掌握市场上无线产品的具体数据。fccid.io网站真是棒极了！该网站提供了大量关于设备的详细信息。其中，FCC还会公布设备的设计文档、数据表、内部结构图片、外观图片、测试报告、各种手册、设备采用的无线频率等内容。在第6章中，我们将会对硬件攻击方法、硬件细节进行介绍。

1.7　IoT无线通信简介

同IoT设备建立连接并与其进行交互的最常见方式是采用无线射频（Radio Frequ-ency，RF）通信方式。目前市场上有许多不同的无线频率、调制模块和协议，其中既有专有无线协议，也有标准协议。因此打开设备外壳，用户往往能够发现其中包含了一个或多个用于无线通信的芯片。这对于需要接收多种不同无线通信协议和频率的IoT网关和IoT Hub来说尤为常见。无线技术与无线通信设备的一个优势在于能够实现设备的远程控制。当通过无线通信方法对设备开展漏洞利用时也正是利用了这一点。因此，了解每种无线技术所能达到的最远通信距离对实际测试而言非常重要。有的无线协议支持105英尺（约32米）远的距离，而有的可能只支持20厘米远，差别非常大。在IoT生态系统的众多无线协议中，最常用的协议主要包括Wi-Fi（802.11）、ZigBee（802.15.4）、Z-Wave、蓝牙（802.15.1）和低功耗蓝牙等。

1.7.1　Wi-Fi

多年以来，Wi-Fi一直是众多设备最常采用的无线技术，其通常使用2.4GHz或5GHz ISM频段。同时也提出了多套Wi-Fi协议标准，例如802.11a、802.11b、802.11g、802.11n和802.11ac等。其中802.11b和802.11g协议使用2.4GHz频段，802.11a、802.11n和802.11ac协议使用5GHz频段。2.4GHz频段根据不同频率又分为14个无线子信道。在部分地区，Wi-Fi路由器还必须采用特定的广播信道。

1.7.2　ZigBee

ZigBee是基于IEEE 802.15.4协议为物理层和媒体接入控制层实现的规范，支持低功耗无线Mesh网络。不同地区的ZigBee协议使用不同的ISM频段，但主要还是在全球使用2.4GHz频段，在美国使用915MHz频段，欧盟使用868MHz频段。ZigBee网络由协调器（ZigBee Coordinator，ZC）、路由器（ZigBee Router，ZR）和终端节点（ZigBee End Device，ZED）组成。建立ZigBee网络时协调器自动启动进行组网。每个网络只允许有一个协调器，它是整个网络的信任中心，负责对入网节点的认证与验证，并且拥有唯一的入网密钥。路由器主要负责在各节点之间传送数据，并将协调器与终端节点连接起来。

为了确保报文在网络中的正确传递，路由器需要一直处于工作状态。终端节点就是IoT设备，例如电灯开关、传感器、摄像头或者监控设备。终端节点不能在网络中路由数据，在没有数据传输的情况下会以低功率模式休眠。ZigBee网络基于两个安全密钥，即网络密钥和链路密钥。网络密钥是网络中所有设备共享的128位密钥，主要用于确保传输通信的安全。链路密钥是只在相互通信的两个设备之间共享的128位密钥，主要用于确保ZigBee应用层单播通信的安全。链路密钥可以预先分配给设备或通过密钥交换进行分发。但是在ZigBee网络中，已知设备配对过程中的密钥交换存在漏洞，攻击者能够利用该漏洞嗅探网络密钥交换过程，进而影响整个网络的安全。

2015年，Blackhat安全大会上分享了一个关于ZigBee网络漏洞利用的议题，该议题的幻灯片链接为https://www.blackhat.com/docs/us-15/materials/us-15-Zillner-ZigBee-Ex-ploitedThe-Good-The-Bad-And-The-Ugly-wp.pdf。

1.7.3　Z-Wave

Z-Wave是另一种低功耗无线通信协议，该协议支持主从模型的Mesh网络。Z-Wave使用低于1GHz的频段，具体频段因地区而异（美国使用916 MHz频段，欧盟使用868.42MHz频段）。基于Z-Wave协议实现的物理层和媒体接入控制层经ITU认可成为国际标准G.9959。采用Z-Wave协议的设备最远通信距离能够达到328英尺（约100米），但在Mesh网络中，当流量通过Z-Wave设备时最远距离能够达到600英尺（约200米）。Z-Wave网络采用4字节（32比特）的HomeID进行标识，该标识也是控制器或主节点的唯一标识。每个节点加入网络时，控制器会为其分配1字节（8比特）的NodeID。HomeID不同的节点间不能通信。Z-Wave协议可以采用AES加密算法，这也是Z-Wave Hub所支持的加密算法，但是到底是否实现对于厂商而言是可选的。Z-Wave协议还具有良好的信号干扰检测特性，能够防止拒绝服务（Denial of Service，DoS）攻击。

关于Z-Wave协议的更多内容请访问网站http://www.z-wave.com。

1.7.4　蓝牙

蓝牙是一种常用的短距离数据通信的无线技术标准（IEEE 802.15.1）。蓝牙在2.4GHz～2.485GHz频段进行广播，最远通信距离可以达到100米，但常用于10米以内的通信。由于大量IoT设备采用蓝牙作为主要通信手段，后文将对蓝牙和低能耗蓝牙（Bluetooth Low Energy，BLE）的渗透测试技术进行介绍。关于蓝牙的其他内容可以参看链接https://www.bluetooth.com/what-is-bluetooth-technology/how-it-works。

1.8　IoT渗透测试环境的部署

介绍完了IoT技术的所有基础概念，下面我们开始着手搭建IoT渗透测试环境。由于IoT设备用到了多种技术，因此在对软硬件开展渗透测试时会用到多款工具。其中既包括需要花钱采购的商用工具，也包括免费工具。为了不影响测试，部分硬件和无线电分析工具需要提前采购。尽管Web应用代理工具的许可费用并不高，但是在这里我们还是尽可能地选择花费不多的工具，如果有免费工具的话则尽可能使用免费工具。

1.8.1　软件工具要求

软件工具主要包括固件、Web应用以及移动应用测试工具。对于这三种类型的测试工具而言，除了用于Web测试的Burp Suite之外，大多数测试工具都是免费的。为了方便应用，建议最好提前部署好虚拟环境，并将固件分析、Web应用测试、移动应用测试（测试内容有限）以及无线电分析过程需要用到的大多数工具安装好。本节中，我们将所有可能用到的工具进行了汇总。

1.固件分析工具

幸运的是，大多数固件分析工具都是免费并且开源的。有些工具会自动更新，而另一些工具虽然已经长期没有更新，但仍然可以用于测试。读者可以使用下面列出的固件工具来分析固件镜像、提取镜像以及在运行时附加到固件进程中以方便调试：

·Binwalk

·Firmadyne

·Firmwalker

·Angr

·firmware-mod-toolkit

·Firmware Analysis Toolkit

·GDB

·Radare2

·Binary Analysis Tool（BAT）

·Qemu

·IDA Pro（可选）

2.Web应用渗透测试工具

Web应用渗透测试的常见工具主要包括Burp Suite和OWASP ZAP。Burp Suite有免费版和专业版之分，专业版的价格也不算离谱。而ZAP则是完全免费并且开源的，在需要控制成本的情况下，ZAP不失为一种比较好的选择。在对Web服务和API进行测试时，还可以加载插件。但是，如果要安装Burp Suite的插件，则需要先购买专业版。这里列出的所有工具都是跨平台的，它们要么是基于Java开发的，要么可以内置在浏览器中：

·Burp Suite

·OWASP Zed Attack Proxy（ZAP）

·REST Easy Firefox Plugin

·Postman Chrome Extension

3.移动应用渗透测试工具

同固件分析工具一样，大多数移动应用安全工具也都是免费并且开源的。根据下面所列出的移动平台可以对移动应用渗透测试工具进行分类。

（1）Android

在撰写这本书的时候，网上已经有很多Android渗透测试工具和虚拟机了。有些工具完全侧重于APK代码的静态分析，还有些工具则侧重于应用运行时的动态分析。已发行的大多数Android渗透测试虚拟机都是免费的，其中包含了测试Android SDK等Android应用所需要的工具。虽然我们列出了一些Android渗透测试工具，但是依然建议读者下载与自己的测试需求最为契合的Android渗透测试虚拟机，并在虚拟机中安装其他用到的渗透测试工具。

在这里，虽然没有明确要求Android测试工具同本机相互隔离，但是为了确保移动应用测试环境更加稳定，并避免出现文件依赖问题，我们还是建议读者将Android测试环境同本机隔离起来。

·发行版Android渗透测试虚拟机：Android SDK、Android Emulator

·Enjarify

·JD-Gui

·Mob-SF

·SQLite Browser

·Burp Suite

·OWASP ZAP

（2）iOS

由于iOS平台比较特殊，因此在开始渗透测试前需要准备好OS X计算机和已越狱的苹果设备。如果不满足这两个前提条件，那么是无法对iOS应用开展渗透测试的。下面是对iOS应用进行渗透测试时用到的部分工具。

下面列出的是需要在OS X计算机上安装的iOS应用渗透测试工具和安全评估工具：

·idb

·Xcode Tools

·Class-Dump

·Hopper（可选）

·Mob-SF

·SQLite Browser

·Burp Suite

·OWASP ZAP

下面列出的是为开展渗透测试需要安装在越狱设备上的软件：

·Cydia

·openURL

·dumpdecrypted

·ipainstaller

·SSL Kill Switch 2

·Clutch2

·Cycript

1.8.2　硬件分析工具需求

根据所分析设备的不同，硬件分析工具也有所不同。然而，有一些基本的分析工具对于所有硬件甚至是电气元件都是适用的。设备商在制造设备时会使用不同型号的螺丝、外壳和保密位以防止用户拆解硬件。有时，螺丝会隐藏在标签或橡胶垫下，分析人员需要撕开标签或者揭开橡胶垫才能找到封装设备的螺丝。在硬件拆解过程中，确定螺丝型号至关重要。只有确定了螺丝型号，我们才能够借助专用工具拆解设备，绕过厂商设置的阻碍。图1-8可以帮助测试人员区分出螺丝类型。

下面列出了本书中将要用到的硬件工具和硬件分析软件。

1.硬件工具

开始硬件测试前需要提前购买一些硬件工具。以下是拆解设备、查找接地引脚以及访问设备接口所需要的工具：

·万用表

图　1-8

图片来源：http://www.instructables.com/id/When-a-Phillips-is-not-a-Phillips/

·用于硬件拆解的IFixit classic pro tech toolkit工具套装

·Bus Pirate

·USB转串口转接器：Shikra、FTDI FT232、CP2102、PL2303、Adafruit FTDI Friend

·JTAG接口转接器：Shikra、JTAGulator、Arduino with JTAGenum、JLINK、Bus Blaster

·逻辑分析仪（可选）：Saleae Logic等

读者可以访问以下链接了解更多的信息：

·https://www.ifixit.com/Store/Tools/Classic-Pro-Tech-Toolkit-/IF145-072-1

·http://int3.cc/products/the-shikra

·https://www.sparkfun.com/products/12942

·http://www.grandideastudio.com/jtagulator/

·https://www.saleae.com/

2.硬件分析工具

下面列出的都是免费的硬件分析工具。这些工具能够帮助读者连接Console口等硬件接口，或者将固件以side-loading方式刷入设备：

·OpenOCD

·Spiflash

·Minicom

·Baudrate

1.8.3　无线电分析工具需求

为了嗅探无线网络流量，需要准备特定的无线芯片组。在本书中我们将主要关注ZigBee和Z-Wave协议流量的嗅探。在无线网络流量嗅探过程中，部分特定软件需要配合无线网卡与软件狗进行使用。无线网卡和分析软件的使用建议如下。

1.无线电分析硬件

下面列出了用于分析无线电频谱的硬件设备：

·Atmel RZ Raven USB设备（KillerBee攻击框架）

·Attify Badge[1]（或者C232HM-DDHSL-0线缆同Adafruit FTDI Breakout开发板的搭配）

·HackRF One

·Yardstick One

·带有Xbee Shield模块的XBee扩展板

·Ubertooth

·BLe适配器

2.无线电分析软件

下面列出了常用的无线电分析软件工具，列出的大部分工具在本书中都会用到。

·KillerBee框架

·Attify ZigBee框架

·GNU Radio

·BLEAH

·GQRX

·Ubertooth tools

·Blue Hydra

·RTL-sdr

·Hackrf packages

·EZ-Wave

[1] Attify Badge是Attify公司出品的一款硬件设备，用户使用该设备可以同多种硬件接口进行交互，包括UART、SPI、I2C、JTAG以及GPIO等。——译者注

第2章　IoT威胁建模

本章将主要介绍以下主题：

·威胁建模概念简介。

·IoT设备威胁建模剖析。

·固件威胁建模。

·IoT Web应用威胁建模。

·IoT移动应用威胁建模。

·IoT设备硬件威胁建模。

·IoT无线电通信威胁建模。

2.1　简介

无论读者具有软件研发背景还是具有系统或者网络运维背景，可能都对各自领域中的攻击面或者攻击向量都已经比较熟悉了。攻击面指的是通过某一输入源实现设备入侵的多种途径。输入源可以来自硬件、软件，也可以来自无线方式。一般来说，设备中包含的攻击面越多，被入侵的可能性就越大。所以，攻击面其实就是进入IoT设备的入口点。有些IoT设备或应用在设计开发时默认信任这些入口点。但是所发现的攻击面都有与之相关联的入侵风险、入侵概率以及入侵影响。因此从本质上来说，攻击面就是可能对设备带来不良影响，进而导致设备执行非预期操作的威胁。为了识别出所有攻击面，在开展渗透测试或开发软件之前需要尽可能详尽地列出理论上存在的威胁用例，这一过程称为威胁建模。

本章将讨论威胁建模的基本原理，以及如何借助威胁建模开展IoT设备的漏洞利用。对固件、Web应用、移动应用、设备硬件和无线电通信建立基本的威胁模型能够帮助读者找到适当的切入点开展渗透测试。

虽然本章仅是对威胁建模的一个介绍。但是关于这一主题已经出版了不少相关书籍。如果读者想深入理解威胁建模概念并需要查阅相关资料的话，可以选择有关威胁建模的书籍或者参考第三方网站进行了解。

2.2　威胁建模概念简介

威胁建模同软件开发存在一定联系，因为威胁建模是在软件设计阶段之后、软件部署阶段之前开展的一次演练。演练通常由软件开发团队、系统运维团队、网络运维团队以及安全团队在重大软件发布之前开展，通过绘制完整的端-端数据流图，或者通过绘制数据流与网络图，都能够对部署安全控制措施与入侵对抗措施提供帮助。上述图表可以画在白板上也可以借助软件来绘制，例如微软就提供了免费的威胁建模工具Threat Modeling Tool，此外还有Web应用https://draw.io也可以用来完成这项工作，链接中给出的Web应用提供了大量模板可以用于绘制多种用途的图表。图表绘制的思路是将设备的所有功能、特性同与之关联的技术建立映射。而如何绘制威胁模型的版式则取决于机构或者绘制者自身。需要谨记的是，当将组件逐个分解时，威胁模型会进一步细化。对于威胁建模而言，非常重要的一方面在于需要不断进行文档迭代，因为当设备添加了新特性之后或者对设备所采用的技术有了更深了解时，对威胁的认识也会不断深化。

一旦确定了IoT设备的攻击面之后，就需要使用STRIDE等方法确定威胁用例，STRIDE方法将会放在后面的章节中进行讨论。这些威胁需要通过评级系统进行评级，进而确定所识别出的威胁的风险等级。在不同的行业中，可以采用不同的威胁评级系统，其中最常见的是DREAD评级系统以及通用安全漏洞评分系统（Common Vulnerability Scoring System，CVSS）。下面分别对CVSS评分系统和DREAD评级系统进行介绍。

CVSS系统的评分粒度更加细致，该系统囊括了3个度量组共14个度量维度，3个度量组分别是：基本得分、临时得分和环境得分。这3个度量组又分别包含了6个基本度量维度、3个临时度量维度和5个环境度量维度。当向厂商提交漏洞时，CVSS系统的评级结果是非常有用的，但是对于威胁建模来说则可能不够直观。想要了解更多关于CVSS系统的内容可以访问链接https://www.first.org/cvss/user-guide。

DREAD评级系统名称中的每个字母分别表示如下含义：

·潜在危害（Damage potential）：如果漏洞利用成功可能造成的危害有多大？

·可重现性（Reproducibility）：重现攻击的难易度如何？

·可利用性（Exploitability）：发起攻击的难易度如何？

·受影响用户（Affected users）：大概会有多少用户受到影响？

·发现难度（Discoverability）：发现该漏洞的难易度如何？

DREAD评级系统的风险评级范围为1～3。其中1代表低风险，2代表中风险，3代表高风险。

表2-1展示了各评级类别的评级结果所对应的含义。

表2-1　DREAD评级系统风险对照表

在开展威胁评级之前，需要识别出威胁。为了准确地阐释安全隐患，进而识别出潜在威胁，可以采用STRIDE模型。STRIDE模型将威胁分为6种类型。这6种威胁类型分别对应于英文缩写STRIDE的首字母，其含义如下：

·身份欺骗（Spoofing Identity）：身份欺骗即通过使用虚假身份信息来尝试获取系统的访问权限。攻击者可以使用窃取的用户认证信息或者伪造的IP地址来实现身份欺骗。当攻击者以合法用户或者本地主机的身份成功获得目标系统访问权限后，就可以进一步以授权身份开展权限提升或者其他恶意操作。

·数据篡改（Tampering with Data）：篡改是指在未经授权的情况下恶意修改数据，例如篡改网络中两台计算机之间的通信数据。

·抵赖（Repudiation）：抵赖是指用户能够（以合法或者不合法的形式）否认其执行了某项操作或业务。如果未配备适当的审计措施，则难以证实攻击者发起了抵赖攻击。

·信息泄露（Information Disclose）：信息泄露是指私有数据的意外公开。例如，用户能够查阅未授权表格或文件的内容，或者监控通过网络发送的明文数据。信息泄露漏洞的部分实例包括隐藏的表单字段、Web页面注释中遗留的数据库连接语句和连接信息，以及可能向用户泄露内部系统信息的不完善的异常处理等。所有这些信息对于攻击者实施攻击都大有帮助。

·拒绝服务（Denial of Service）：拒绝服务是指导致系统或应用不可用的过程。举个例子，通过向服务器发送海量请求消耗掉目标系统所有可用的系统资源就可以实现针对目标的拒绝服务攻击，此外，发送足以导致应用进程崩溃的畸形输入也可以实现拒绝服务攻击。

·权限提升（Elevation of Privilege）：当拥有有限权限的用户以特权用户的身份取得了某应用的特权操作权限时即实现了权限提升。例如，权限受限的攻击者通过提权可以实现入侵，或者接管具有较高权限并且受信任的进程或账户。

可以通过以下链接来了解关于STRIDE模型的更多细节：

https://msdn.microsoft.com/en-us/library/ee823878(v=cs.20).aspx

https://msdn.microsoft.com/en-us/library/ff648641.aspx

微软公司提出了一种非常好的威胁建模方法，该方法采用多步处理来确定新应用或者新系统所引入威胁的严重程度。其威胁建模处理步骤如图2-1所示。

图2-1　威胁建模处理步骤

了解微软威胁建模过程的更多内容可以参考以下链接：

https://msdn.microsoft.com/en-us/library/ff648644.aspx

后面我们将采用STRIDE模型和DREAD评级系统以黑盒测试的方式开展威胁建模演练，并将IoT设备进行分解，对其中的各个组件分别进行威胁建模。这里我们建议，读者无论在开展任何安全测试之前，最好都先进行威胁建模，通过威胁建模来保障测试的覆盖面。思考所有潜在威胁发生的概率并对其分类的过程很有意思，需要读者好好动动脑筋。

2.2.1　准备工作

在逐一介绍威胁建模方法时，我们将会用到微软公司提供的免费威胁建模工具Threat Modeling Tool以及基于制图网站https://draw.io所绘制的图表。在本书撰写阶段，我们从链接https://www.microsoft.com/en-us/download/details.aspx?id=49168下载了微软的威胁建模工具Threat Modeling Tool 2016。

2.2.2　测试流程

在本节中，我们使用微软威胁建模工具Threat Modeling Tool来进行图表绘制，采用该工具绘制网络图表非常简单：

1）启动微软威胁建模工具Threat Modeling Tool 2016。选择“创建模型”（Create A Model）选项，如图2-2所示。

图2-2　创建威胁模型

2）然后，熟悉工具中所提供的用于表示设备、通信传输以及输入输出可信边界的模板（Stencils）。微软针对不同的模板与选项提供了用户指南，当下载工具时可以一并下载，但并不做强制要求。

2016版的微软威胁建模工具Threat Modeling Tool中允许用户自定义模板，用户可以创建模板（Stencils），从而更加准确地刻画各个组件同威胁之间的关系，如图2-3所示。

图2-3　创建威胁模板

3）每套模板的属性都可以根据设备、网络或者应用的实际情况加以调整，如图2-4所示。

4）至此，我们通常就可以从一个较高的角度来识别IoT系统的资产了，并且，当通过研究或逆向分析对目标设备具备了更深的了解之后，可以进一步聚焦于所感兴趣的领域。资产识别的过程可以采用表格或者思维导图的形式加以记录。表2-2列出了一份基本的资产清单，其中对各项资产进行了简要说明。

5）图2-5展示了部署了智能门铃、LED灯具、移动应用以及IoT Hub的智能家居环境。

图2-4　修改模板属性

表2-2　IoT系统资产清单

图2-5　IoT智能家居环境

上面的例子只是威胁建模演练的开始。我们已经介绍了如何下载微软威胁建模工具Threat Model Tool，并熟悉了模板及其相关属性。然后，我们通过研究或逆向分析对智能家居环境进行了简单描述，进行了智能家居环境中的资产识别。接下来我们绘制了架构图，形象地展示了识别出的资产。下一步将是威胁建模的核心，即通过分解IoT系统的各个组成部分，帮助读者发现攻击入口点、确定攻击方法，以及分析IoT系统的某一部分遭受攻击后所造成的影响。与其他安全分析工作一样，测试人员对目标测试平台越熟悉，成功实施入侵的可能性也就越大。

2.3　IoT设备威胁建模剖析

2016年，我们见证了一起针对IoT设备的大规模漏洞利用事件，事件中的IoT设备主要包括网络摄像头和数字视频录像机（Digital Video Recorder，DVR），攻击者利用这些设备发起了全球有史以来最大规模的分布式拒绝服务攻击（Distributed Denial of Service，DDoS）。这次DDoS攻击缘起于厂商对IoT设备安全问题的轻视，而这些问题通过基本的威胁建模演练就可以避免。考虑到上述类型的设备在互联网中普遍存在以及它们可能给互联网带来的风险，我们将对联网DVR与网络摄像头安防系统开展威胁建模，并详细介绍威胁建模过程。普通个人用户或者中小型企业通过电商平台或者众多电子用品商店以相当低的价格就可以购买到这些联网的安防系统。联网DVR系统可以作为IoT系统的一个绝佳示例，因为为了能够查看摄像头监控视频，设备中包含了很多入口点，用户还可以在路由器无须开放端口的情况下连接到第三方服务提供商以远程查看监控视频。从黑盒测试的角度来看，搜集IoT设备及其应用程序的细节信息可能有点棘手。但是，这些产品一般都有大量在线资源可以利用，从而有助于威胁建模。

测试流程

开展针对联网DVR系统的威胁建模时，我们将继续采用之前介绍的微软多步威胁建模方法。[1]

步骤1　资产识别

首先统计所有DVR资产并形成文档，以便了解哪些设备最可能遭受攻击从而予以重点关注。对于攻击者而言，如果能够找到那些存在已知漏洞的资产，那么在针对DVR系统开展漏洞利用时将节省大量时间。部署设备时，查看设备背部粘贴的标签以及用户手册就可以了解到有关DVR系统资产的信息，具体信息如表2-3所示。

表2-3　DVR系统资产清单

步骤2　IoT设备架构概况构建

通过构建架构概况，可以采用可视化的方式形象地展示出攻击者如何攻击DVR系统，进而以非预期的手段利用系统。在构建IoT设备架构概况时，我们的目标是基于在整套流程中搜集或了解到的数据将DVR系统的功能、应用及其物理架构形成文档。我们希望能够发现DVR系统设计和实现中的漏洞，其中也包括识别出系统所采用的不同技术。接下来我们将架构概况的构建分为以下3项工作：

·编制DVR系统功能特性文档

·构建架构图，详细刻画DVR生态系统

·识别系统所采用的技术

在编制DVR系统功能特性文档之前，我们先准备一组用例。

用例1：用户在本地网络中通过本地Web应用查看视频

1）用户安装DVR设备及摄像头。

2）用户创建用户账户。

3）用户对DVR设备和摄像头配置进行设置。

4）用户通过以太网连接DVR设备并确保网络连通。

5）用户记录下DVR设备的IP地址。

6）用户安装厂商提供的插件与软件。

7）用户通过Web浏览器登录DVR设备。

8）用户选择摄像头并查看监控视频。

用例2：用户通过移动应用远程查看视频

1）用户对平台配置进行设置，确保能够访问厂商的SaaS服务。

2）用户下载并安装Android或iOS应用。

3）在应用安装时，用户为厂商的SaaS应用创建独立的用户账户。

4）用户登录移动应用。

5）用户使用移动应用扫描DVR设备下方的条形码进行厂商验证。

6）用户选择摄像头并查看监控视频。

图2-6给出了上述用例的架构图，图中包含了DVR生态系统各组件的详细信息。

图2-6　DVR生态系统架构图

架构图绘制完成后，就需要识别并分析系统所采用的各种技术了。鉴于某些操作系统、协议和底层函数库可能早已存在已知漏洞。因此，为了便于开展进一步分析，并清晰刻画出潜在的威胁用例，将系统中所采用的技术（见表2-4）形成文档非常重要。

表2-4　DVR系统技术应用情况汇总表

步骤3　IoT设备分解

接下来，我们对DVR系统环境中的应用与协议数据流进行分析，定位设备或客户端应用中的漏洞。我们所要搜索的位置可能需要更高权限才能访问，在此过程中需要记录下每个可能的入口点。其中，只需要找到一个能够危害到DVR系统的机密性和完整性的攻击入口点，就能够帮助攻击者赢得攻防中的主动权。

这些入口点根据所使用的平台、技术和协议的区别可能有所不同，在本节中，我们将从一个更高的层次来看待这个问题。同时，我们还需要检查技术和特性之间的各种信任边界。一旦完成了对DVR架构的分解，读者就可以更好地理解攻击面以及针对数据的破坏方式。

图2-7是DVR系统环境中对数据流的分解示意图示例：

图2-7　物联网DVR环境数据流

数据流绘制完成后，表2-5对入口点进行说明。

表2-5　DVR系统入口点汇总表

步骤4　威胁识别

到了这个阶段，我们已经绘制完成了DVR系统的数据流，并确定了都有哪些入口点。现在我们必须判断每个入口点的风险，这些风险同用户、网络和应用以及应用的开发厂商息息相关。从攻击者的视角来看，我们需要识别出影响网络、应用以及主机的威胁，因为其中存在可以被利用的漏洞，进而可能导致以下后果：

·影响大量使用某DVR系统的用户。

·入侵厂商基础设施并造成大规模漏洞利用。

·入侵DVR设备，给用户带来隐私泄露的风险。

·入侵DVR设备，给DVR用户带来功能安全方面的风险。

为了帮助定位威胁并对威胁进行分类，我们采用STRIDE模型对DVR IoT系统进行安全评估。在表2-6中，我们使用一组威胁类型来代替IoT中的安全隐患。表中所列内容可能并不完备，但是在考虑可能对整个DVR系统环境造成的安全威胁时，能够为读者提供一些思路。

表2-6　DVR系统威胁识别表

或者，在这里我们也可以从更高的层面上简单列出可能存在的威胁，后面的章节中我们将对每个组件的威胁进行深入探讨。受知识面所限，有些威胁可能是未知的或者还停留在理论层面，但是对围绕这些威胁开展头脑风暴开拓思维也是很重要的。为了识别出尽可能多的威胁，读者可以找个小伙伴一起练习，或者找到正在尝试入侵你所感兴趣的某套IoT系统的人组团开黑。下面是我们找出的DVR系统高级别威胁示例，攻击者可以执行这些操作：

·远程接管DVR系统。

·在未经认证的情况下，远程查看视频（秘密监视）。

·关闭摄像头的回放功能。

·跟踪某个个人。

·基于所搜集的情报闯入某片区域。

·在DVR设备中植入木马。

·获得物理接触的权限，并破坏视频记录。

·通过发送请求过载DVR系统，使其不能正常工作。

·窃听DVR系统通信数据。

步骤5　威胁建档

接下来，我们将在步骤4中识别出的部分威胁用例形成文档（见表2-7～表2-9），文档中主要包括威胁描述、威胁目标、攻击技术以及可能采用的对抗措施。

威胁1

表2-7　威胁1

威胁2

表2-8　威胁2

威胁3

表2-9　威胁3

步骤6　威胁评级

现在，我们已经识别出了针对DVR系统的威胁并将其形成了文档，下面根据威胁发生的可能性以及可能导致的影响，我们采用DREAD评级系统对威胁进行评级。在本章前文我们已经对DREAD评级系统进行了介绍，也正如前文所指出的那样，用户也可以根据实际情况采用其他评级系统进行威胁评级。DREAD评级系统中每个方面的评级都分为3个等级：3表示高风险；2表示中风险；1表示低风险。

表2-10　风险等级判分表

在DREAD模型中，按照表2-10所示的评级标准确定最终的风险等级。

DVR系统中某威胁用例的威胁评级示例如表2-11所示。

表2-11　威胁风险等级评定表

起初，由于DVR系统用到了众多不同的组件，因此在考虑到所有的威胁用例的情况下，对整个DVR系统进行威胁建模可能会有点儿困难。尽管存在这样或那样的困难，但是一旦建模完成，读者将会发现许多潜在的高风险脆弱点，在渗透测试过程中就可以对这些高风险脆弱点予以重点关注。同时，这一工作也使得我们在对IoT系统开展渗透测试时更容易确定脆弱点的优先级。

[1] 参考http://onlinehelp.microsoft.com/zh-cn/mdop/ff648644.aspx。——译者注

2.4　固件威胁建模

在之前介绍的内容中，我们对DVR系统进行了威胁建模并对威胁用例进行了评级，这有助于对测试中所要针对的脆弱点进行优先级排序。在本节中，我们将对同一DVR系统中的固件进行威胁建模。

2.4.1　准备工作

在针对固件的威胁建模演练中，我们将使用免费在线绘图软件https://draw.io刻画固件中各组件的关系。该软件是一款Chrome应用，存储绘制的图表时需要同第三方服务绑定，例如Google Drive或GitHub。借助该软件可以绘制出重叠的关系和过程，而在微软的威胁建模工具Threat Modeling Tool则难以做到这一点。其实，任何能够有效刻画出目标设备或软件之间关系架构的工具都可以满足威胁建模的需求。

在开始绘制图表之前，需要完成以下操作：

1）选择“创建新图表”（Create New Diagram）。

2）选择“软件设计”（Software Design）。

3）选择部署图2-8中所示的图表模板。

图2-8　选择部署图模板

4）删除模板中所有未用到的图表，仅为固件及其内部组件保留一个方框。

5）将资产拖放到图表中，刻画出资产之间的关系。

2.4.2　测试流程

对于固件而言，我们能够通过设备封装情况、基本的端口探测或者各种在线资源来识别其所运行的操作系统类型。现在，我们应该对固件如何在嵌入式IoT设备中运行已经具备了一定的认识，这些内容在第1章中已经有所提及。本节不再像前面的章节一样进行细节的深入讨论，但是我们需要依据对固件的了解情况对固件的组件加以刻画，进而识别出潜在威胁并开展渗透测试。简单起见，后面将会对部分威胁建模步骤加以合并。

步骤1　资产识别

根据对DVR固件及其所提供服务的了解，我们对固件资产进行整理，如表2-12所示。

表2-12　DVR固件资产清单

步骤2及步骤3　架构概况构建及分解

现在我们已经对DVR系统服务所用到的固件组件以及库文件有了一个大致了解。下面绘制设备、固件内容以及文件系统内容之间的关系，形成概况图，如图2-9所示。

图2-9　DVR设备固件组成概况图

步骤4　威胁识别

基于概况图和对固件内容的了解我们可以将威胁形成文档。需要记住的是，当前阶段我们还没有对固件镜像进行反汇编，也尚未定位其具体位置。图表中的内容是基于DVR系统宣称其所提供的服务和在线文档得到的。下面列出针对固件的潜在威胁，攻击者可以基于所列出的威胁尝试开展漏洞利用：

·针对网络服务实施远程代码执行攻击。

·获取文件系统的管理员访问权限，并对局域网发起攻击。

·拦截网络通信。

·通过SSH访问文件系统资源。

·篡改DNS配置信息，将流量重定向到被攻击者的网络/计算机。

·访问固件中的Web配置信息和敏感信息。

·在DVR设备中安装恶意固件或应用。

·跟踪用户活动。

·篡改摄像头视频和内容。

·篡改审计日志信息。

·毁瘫DVR设备。

·拦截所有向DVR设备发起的网络连接。

步骤5　威胁建档

接下来，我们将挑选一些威胁用例，并依据威胁描述、威胁目标、攻击技术以及可能采用的对抗措施的形成文档（见表2-13～表2-15），进而对威胁风险进行评估。

威胁1

表2-13　威胁1

威胁2

表2-14　威胁2

威胁3

表2-15　威胁3

步骤6　威胁评级

正如我们之前所做的那样，这里我们仍然采用DREAD评级系统对每个威胁进行评级。我们将使用表2-16评定威胁的风险等级，评级过程中首先选择某种威胁，然后找出其对应的风险等级即可。

表2-16　威胁风险等级评定表

大多数嵌入式设备的操作系统通常以root或admin权限运行。这意味着任何针对固件的漏洞利用无须提权即可获得最高访问权限。对于很多受监管行业而言可能还需要开展进一步研究，但是如果读者正在对消费级设备进行测试，那么如果固件已经能够以root权限运行了，则攻击成功的可能性会显著提高。

2.5　IoT Web应用威胁建模

接下来继续介绍针对DVR系统的威胁建模演练，下一步我们将分解Web应用。DVR系统包含两种类型的Web应用。一种是嵌入式Web应用，在DVR设备内部运行。另一种是由厂商提供的SaaS应用，用于远程访问DVR系统和视频。

SaaS应用能够实现对局域网内嵌入式DVR设备的访问。然而，本文我们主要关注DVR系统中运行的本地嵌入式Web应用，而非厂商的SaaS应用。在本章开头，我们曾简单提到了部分厂商Web应用所采用的技术，但是目前除此之外难以开展更深入的了解。下面，我们将绘制嵌入式Web应用的架构，其中在威胁部分涉及厂商SaaS应用，但是由于不知道其采用的架构，所以无法绘制其架构图。

测试流程

现在，我们应该对如何从头开始构建威胁模型已经能够在脑海中形成大体的思路了。了解了这些内容后，我们就可以忽略威胁建模过程中的部分步骤，而将重心放在更加重要的方面。

步骤1　架构概况创建及分解

下面我们将基于对嵌入式Web应用的了解绘制架构概况图，然后在架构的数据流中识别威胁并进行评估。图2-10展示了嵌入式Web应用的部分基本功能。

图2-10　DVR系统嵌入式Web应用数据流分解示意图

由于只有局域网中的流量，没有公网流量，所以应用的数据流比较简单。因此，识别嵌入式应用中的威胁不算太难。

步骤2　威胁识别

嵌入式Web应用中的数据流比较简单，所以将威胁用例形成文档本应轻而易举，但是考虑到还有厂商基于SaaS的Web应用，因此我们还需要再添加一些额外的场景。

攻击者针对DVR嵌入式Web应用和厂商SaaS应用开展漏洞利用能够实现以下操作：

·劫持用户会话查看摄像头监控视频和配置。

·监视API调用。

·通过命令注入漏洞执行操作系统命令。

·泄露敏感用户信息。

·采用SQL注入漏洞转储数据库中的数据（拖库）。

·任意脚本执行。

·获取其他用户账户的访问权限。

·伪造已登录用户的请求（CSRF）。

·修改DVR配置，将流量重定向到未经授权的用户或网络。

·追踪用户。

·泄露摄像头回放视频。

·删除摄像头回放视频。

·对厂商的Web服务器或应用服务器开展漏洞利用。

·阻止正常用户的访问。

步骤3　威胁建档

接下来，同之前工作类似，我们选择部分典型威胁用例形成文档（见表2-17～表2-19），文档中包括威胁描述、威胁目标、攻击技术以及可能采用的对抗措施，并对其风险进行评级。

威胁1

表2-17　威胁1

威胁2

表2-18　威胁2

威胁3

表2-19　威胁3

步骤4　威胁评级

我们将使用表2-20评定威胁的风险等级，选择某个威胁之后，即可确定其对应的风险评级。

表2-20　威胁风险等级评定表

显然，对于攻击者而言，针对厂商SaaS应用开展漏洞利用能够取得更理想的效果，因为其中保存了大量的用户信息以及其他内容。但是，希望读者一定要在法律许可的范围内开展测试，并提前获得甲方授权。话又说回来，针对嵌入式Web应用开展渗透测试，虽然可能不一定会取得同针对厂商SaaS应用开展渗透测试一样的评价，但如果充分分析设备的在线资料了解其用法，进而挖掘出一个可以远程利用的漏洞，那么肯定也会大有收获。

2.6　IoT移动应用威胁建模

在下一个威胁建模演练中，我们将对DVR系统中的IoT移动应用进行分析。代理商和不同的OEM为DVR系统（和IoT中的其他系统一样）开发了多套移动应用。出于演示的目的，我们只分别选择了一款Android应用和一款iOS应用进行威胁建模。

测试流程

在前面的章节中，我们已经绘制了很多数据流图，本节中我们将继续使用微软威胁建模工具Threat Modeling Tool进行图表绘制。

步骤1　架构概况构建与分解

与之前绘制图表的步骤类似，这里我们直接展示构建完成的数据流图，其中包括了移动应用中的所有已知资产。图2-11是移动应用的数据流图。

可以看到，应用每次查看账户信息和摄像头视频时，都需要与第三方厂商的云平台建立连接，即使用户与DVR系统处于同一网络中。而远程访问DVR系统所需的用户名和口令就存储在移动设备中。在这里，我们尚不清楚同应用厂商后台系统通信时如何存储或发送这些数据。带着这些疑问，我们开展下一步工作，进行威胁识别。

图2-11　DVR系统移动应用数据流分解示意图

步骤2　威胁识别

攻击者可以利用移动应用进行以下操作：

·监视API调用。

·访问移动设备中的本地资源。

·泄露用户敏感信息。

·定位在移动设备中以明文存储的用户敏感信息。

·通过SQL(ite)注入漏洞转储数据库中的数据。

·通过WebView控件的JavaScript接口实现任意脚本执行。

·获取其他用户账户的访问权限。

·在厂商的云平台环境中追踪用户。

·访问存储在设备上的摄像头回放视频。

·删除摄像头回放视频。

·篡改用户信息。

·在未经认证的情况下为摄像头添加共享用户。

·建立永久会话，该会话具有持久访问权限不会过期。

·截屏并发送给第三方。

步骤3　威胁建档

接下来，同之前的工作类似，我们将选取部分威胁用例并形成文档，评估其风险等级，见表2-21～表2-23。

威胁1

表2-21　威胁1

威胁2

表2-22　威胁2

威胁3

表2-23　威胁3

步骤4　威胁评级

从表2-24中选择某种威胁并评估其风险等级。

表2-24　威胁风险等级评定表

在移动领域中，常见威胁都与数据以及数据的存储和传输方式有关。因此，除非该漏洞能够对大量用户造成影响，或者导致泄露大量用户数据，否则移动应用漏洞风险一般相对较低。在对移动应用的测试过程中，移动应用的漏洞基本不会导致攻击者获取服务器或者移动设备的shell。

2.7　IoT设备硬件威胁建模

现在，我们开始分析目标DVR系统的硬件威胁。大多数消费级DVR设备很容易拆解，因此攻击者可以很方便地对其各个输入源以及外设进行分析。而之所以出现这种情况，一方面可能是为了便于设备将来扩展存储空间，另一方面也可能是因为设备在设计之初就没有被设计为具备防篡改保护等安全功能的产品，举个例子，如果在设计时采用了硬件安全模块（Hardware Security Module，HSM），那么设备会具备一定的防篡改能力。

测试流程

在本节的演练中，我们使用https://draw.io提供的工具绘制硬件输入图。

步骤1　架构概况构建及分解

图2-12是DVR设备硬件示意图。

图2-12　DVR设备硬件示意图

从图中可以看到，DVR设备对外连接的接口包括8个用于连接摄像头的BNC连接器、2个USB接口、1个以太网口、1个电源接口、1个VGA接口以及1个HDMI端口。同时，DVR设备中还内置了多款芯片，其中包括1块EEPROM存储芯片，以及PCB中UART接口的多个疑似输入源。

步骤2　威胁识别

攻击者对DVR硬件输入点开展漏洞利用可以完成以下操作：

·通过UART接口获取Console口的访问权限。

·转储EEPROM存储芯片中机密信息。

·利用USB栈中的漏洞控制DVR设备。

·插入恶意USB设备造成破坏。

·短路DVR设备电源。

·攻击DVR bootloader获取Console口的访问权限。

·通过USB接口安装恶意软件。

步骤3　威胁建档

接下来，我们将挑选与之前类似的威胁案例，并对其各自风险进行评级，见表2-25～表2-27。

威胁1

表2-25　威胁1

威胁2

表2-26　威胁2

威胁3

表2-27　威胁3

步骤4　威胁评级

我们使用表2-28进行威胁评级，从中选择一个威胁并找到其对应的风险等级即可。

表2-28　威胁风险等级评定表

2.8　IoT无线电通信威胁建模

下面，我们开始对无线电/无线通信的威胁建模，除了从客户端应用或摄像头传输到DVR设备的数据之外，DVR系统中并没有太多涉及无线电通信的内容。虽然大多数IoT设备和运行环境会使用不同的协议、在不同的频率上进行无线电通信广播，但幸运的是，在这里我们只需要考虑DVR系统中的Wi-Fi协议和手机厂商的入口点。

测试流程

对于无线电通信威胁建模演练，我们只需要对之前绘制的图表进行简单更新，反映出设备和应用之间的无线电通信过程即可。

步骤1　架构概况构建及分解

DVR系统中无线电通信的示例架构概况如图2-13所示。

正如读者所了解的那样，无线通信仅限于用户通过客户端设备访问DVR设备，其中客户端设备包括浏览器、应用，也包括无线网络摄像头。需要注意的是，当前概况图是根据之前的概况图迭代得到的，因为在前面的威胁建模过程中我们已经获取到了很多信息。

步骤2　威胁识别

攻击者可以利用无线通信进行以下操作：

·远程访问DVR网络。

·窃听DVR系统无线通信。

·阻塞DVR系统通信。

图2-13　DVR系统无线通信数据流分解示意图

·从DVR系统中移除网络摄像头。

·建立虚假接入点连接摄像头。

·窃听手机通信。

·搭建全球移动通信系统（Global System for Mobile Communication，GSM）伪基站。

·构造请求欺骗客户端应用。

·添加虚假网络摄像头。

·通过流氓客户端应用访问DVR系统。

步骤3　威胁建档

接下来，我们将挑选与之前类似的威胁用例，并将其形成文档对其风险进行评级，见表2-29～表2-31。

威胁1

表2-29　威胁1

威胁2

表2-30　威胁2

威胁3

表2-31　威胁3

步骤4　威胁评级

我们将使用表2-32选择拟评级的威胁并评估其风险等级。

表2-32　威胁风险等级评定表

无线中间人攻击技术较为常见，采用该技术，攻击者可以轻而易举地向DVR系统实施无线攻击。而其他威胁（例如添加虚假网络摄像头）实现起来则可能要困难一些，因此，对于急于想要扩大战果的攻击者来说不值得在上面花费过多时间。

第3章　固件分析与漏洞利用

本章将主要讨论以下主题：

·固件分析方法。

·固件提取。

·固件分析。

·文件系统分析。

·基于固件仿真的动态分析。

·ARM与MIPS架构下二进制文件的分析入门。

·MIPS架构下的漏洞利用。

3.1　简介

到目前为止，我们已经介绍了IoT生态系统中的所有基本原理，并且通过威胁建模确定了各种威胁对应的风险，这些内容对于我们开展渗透测试大有帮助。虽然单纯借助当前普遍应用的漏洞扫描技术，有些漏洞和威胁识别起来可能会更简单一些，但是，在本章中，我们将把注意力聚焦在固件的逆向分析上，希望通过对固件内容的分析实现运行时对固件的操作。我们需要撸起袖子讨论如何对固件进行反汇编，如何使用常见的固件工具分析固件内容与固件架构，以及如何修改固件用于攻击。同其他软件逆向分析方法类似，固件分析也绝对是一门艺术。读者将会了解到有很多工具都可以用来帮助自己挖掘常见的漏洞，但是，针对固件二进制镜像的安全性分析仍需要大量的手工分析。

在我们开始固件分析之前，重要的是讨论固件提取的通用方法，以及分析勾勒出哪些数据较为重要。在之前介绍的轻量级固件威胁建模演练过程中，这一内容已经讨论过了，但是这里我们依然从讨论固件分析的目标开始接下来的内容。

3.2　固件分析方法

固件是控制IoT设备的核心，这也是我们在分析IoT设备的其他组件之前，希望从固件分析开始的原因。根据IoT设备所面向的行业，提取固件镜像并且对其内容进行反汇编的过程可能非常简单。与之类似，对于某些行业的垂直细分领域而言，其采取了专用保护措施，而这些保护措施可能会导致逆向分析过程更加困难或更加耗时。尽管如此，固件分析时还是存在一些通用模式的。通常，测试人员在固件分析时最关注的内容主要包括：

·口令。

·API Token。

·API Endpoint（URL）。

·存在漏洞的服务。

·后门账户。

·配置文件。

·源代码。

·私钥。

·数据的存储方式。

在后面的章节中，进行固件分析时我们也会重点关注这些内容。本节将向读者概要介绍固件正向分析与逆向分析的方法。

下面列出了IoT固件分析时所用到的基本方法：

1）固件提取。

2）固件分析。

3）文件系统提取。

4）文件系统加载。

5）文件系统分析。

6）基于固件仿真的动态分析。

3.3　固件提取

在对固件内容进行分析前，我们首先需要获取固件的二进制文件。本节将会对目标设备固件提取所涉及的各种技术进行介绍。

3.3.1　准备工作

提取固件的过程中我们会用到多个工具。由于Kali Linux中已经默认安装了所需要的大多数工具，因此在这里将主要使用Kali Linux系统。下面是需要用到的工具：

·Kali Linux：Kali Linux可以从网站https://www.kali.org/downloads/直接下载。如果读者使用VMware或者VirtualBox虚拟机，那么建议从链接https://www.offensive-security.com/kali-linux-vmware-virtualbox-imagedownload/下载Kali的虚拟镜像。

·Ettercap：虽然Kali Linux中已经默认安装了Ettercap，但是也可以从链接https://ettercap.github.io/ettercap/downloads.html下载。

·Wireshark：Wireshark也默认包含在Kali Linux中，也可以从链接http://www.wire-shark.org下载。

·SSLstrip：Kali Linux中已经默认安装了SSLstrip，也可以从链接https://github.com/moxie0/sslstrip下载。

·Flashrom：Kali Linux中并未默认安装Flashrom，但是可以执行以下命令方便地安装该工具：

此外，还可以通过链接https://www.flashrom.org/Downloads下载Flashrom。

3.3.2　测试流程

目前，从IoT设备中提取固件的方法有很多。我们将在本节中对其中的大部分方法进行介绍。固件镜像的获取方法主要包括：

·从厂商网站下载。

·代理或镜像设备更新时的流量。

·直接从设备转储固件。

·通过Google搜索引擎搜索/科研渠道。

·反编译与之相关的移动应用。

1.从厂商网站下载

获取固件最简单的方法就是从厂商网站下载固件。

图3-1～图3-5中的截图展示了如何从厂商网站获取固件：

1）进入目标厂商的网站。

2）在搜索栏中输入目标设备，如图3-1所示。

3）选择Support选项卡，如图3-2所示。

4）单击Drivers&Tools按钮，如图3-3所示。

5）单击下载链接，如图3-4所示。

6）用户也可以选择Copy Link Address，在测试主机上直接执行wget（wget<http://URL.com>）命令进行文件下载，如图3-5所示。

图　3-1

图　3-2

图　3-3

图　3-4

图　3-5

2.代理或镜像设备更新时的流量

有时候厂商网站可能并不支持固件下载，此时读者可以选择第2种方法（即在设备固件更新过程中，代理转发设备更新时的流量），或者选择第3种方法（直接从设备转储固件）。为了在设备更新过程中实现对固件更新流量的代理转发，读者必须在更新期间实施中间人（Man-In-The-Middile，MITM）攻击或者镜像设备流量。或者，读者也可以代理转发Web或移动应用的流量，从中提取出固件下载的URL地址。

众所周知，厂商会对固件下载请求中的user-agent字段进行验证，所以读者可能还需要调整数据包首部中的user-agent字段。以下是针对IoT设备实施MITM攻击进而监控设备流量的基本步骤，用到的工具包括Kali Linux、Ettercap、Wireshark和SSLstrip。其中Kali Linux中已经安装了本节中需要用到的所有工具。

当前有多种方法和工具可以对目标设备发起MITM攻击，进而实现流量转发。下面介绍的就是其中一种捕获设备流量的方法。

1）启用IP转发功能：

2）配置iptables，将目的端口80的流量重定向至SSLstrip监听的端口10000。

3）启动SSLstrip：

4）启动Ettercap GUI：

5）图3-6展示了上述操作的运行结果。

图　3-6

6）单击菜单栏中的Sniff菜单，再单击Unified sniffing选项，如图3-7所示。

图　3-7

7）选择所要监听的网卡，如图3-8所示。

图　3-8

8）选择Scan for hosts选项，如图3-9所示。

图　3-9

9）此时即启动Wireshark程序，可以看到部分接口有流量通过，如图3-10所示。

10）单击Start capturing packets按钮开始捕获目标设备的网络流量，如图3-11所示。

图　3-10

图　3-11

11）根据实际需求过滤出所关注的网络报文。在本例中，目标设备的IP地址为192.168.1.137，如图3-12所示。

图　3-12

3.直接从设备转储固件

如果通过厂商网站或者流量代理的方法均无法获取固件，还可以尝试通过UART、SPI或者JTAG接口直接转储固件。直接进行固件转储需要拿到物理设备，并拆解设备找到其中的闪存芯片。找到闪存芯片之后，读者可以直接通过UART接口也可以使用SOIC8测试夹来连接芯片进而转储固件，其中用到了工具Flashrom以及支持SPI的硬件开发板，例如Shikra[1]。图3-13展示了如何使用SOIC测试夹和Shikra连接设备。

图　3-13

图片来源：http://www.xipiter.com/uploads/2/4/4/8/24485815/9936671_orig.jpg562

将固件内容转储为bin文件的命令如下所示：

使用Flashrom或者前面介绍的某种方法提取到了设备固件之后，分析人员就可以开始对固件的二进制文件进行分析了。

4.Google搜索

如果出于某些原因，我们难以借助前面介绍的方法提取出固件镜像，那么最后的选择就是求助于Google搜索。可以直接在Google中输入想要查找的固件名称，搜索是否存在目标固件的下载链接，也可以搜索一下其他人的工作成果，看看是否已经有人对该设备的固件进行了研究。此外，设备厂商在岗或者离职的工作人员也可能会将固件文件上传到其个人的存储空间或Web服务器上。无论哪种情况，都可以使用Google dorking技术缩小指定目标设备的搜索范围。我们还可以通过链接https://www.exploit-db.com/google-hacking-database利用Google Hacking数据库来搜索固件或设备。

[1] Shikra是一款用于固件分析的硬件设备，用户借助Shikra可以与不同的底层数据接口（通过USB接口）进行交互。——译者注

3.3.3　测试分析

在本节中，我们简要介绍了如何通过厂商站点、部署MITM测试环境捕获设备流量、直接从设备转储固件以及Google搜索等方法来获取固件。现在，我们来解释下为什么需要通过这些方法获取固件，难道不是直接从厂商网站下载就行了吗？

当从厂商网站下载固件时，通常情况下，用户可以通过厂商提供的服务链接、文件共享或社区论坛下载到需要的固件。但有时厂商在下载固件前要求用户提供口令，或者将固件打包为需要口令才能解压的ZIP文件。如果碰到了这种情况，为了节省时间我们就可以直接采用其他方法获取固件。

接下来，我们简要介绍了如何使用Kali Linux、SSLstrip、Ettercap和Wireshark搭建MITM测试环境，以在设备更新期间捕获设备流量。

3.4　固件分析

一旦我们提取到了固件，接下来的主要工作就是对固件进行分析。其中涉及如何深入固件内部，发现尽可能多的安全隐患，这也正是本节中我们所要做的主要工作。

3.4.1　准备工作

在本节中，我们将会了解提取出固件二进制文件后如何开展固件分析。在这一过程中，有多种固件分析方法供我们选择，帮助我们找到固件中的安全隐患。

正如前面提过的，固件中包含了很多渗透测试人员感兴趣的内容，如API key、私有证书、硬编码的认证信息以及后门等。

3.4.2　测试流程

为了分析固件，我们将对其逆向以查看其内部组件。固件中的内部组件包括boot-loader、内核、文件系统以及其他内容。其中我们最感兴趣的是文件系统，因为文件系统中保存了我们需要的所有信息。显然，读者也可以分析bootloader并查看其中包含的内容，还可以篡改固件并构建新的固件（我们将在接下来的章节中讨论），但是现在我们只关心如何对固件进行逆向分析以及从中提取出文件系统。

正如之前已经介绍过的，固件是一个二进制文件压缩包，而文件系统只是其中的一个组件，存储在二进制文件的特定偏移地址中，且具有一定的尺寸。然而，此时我们还不知道关于固件中文件系统的任何信息，包括其偏移量和尺寸。为了找到这些信息，需要使用hexdump和grep等工具来搜索我们所关注内容的特征信息。下面以Squashfs文件系统为例进行介绍：

1）如果想要查找Squashfs文件系统，可以使用grep命令在hexdump的执行结果中查找“hsqs”字符串[1]，如图3-14所示。

图　3-14

2）读者可以看到，我们在地址0x000e20c0处发现了Squashfs文件系统。获得了这些信息之后，就可以使用dd命令将从该地址开始到文件末尾的内容全部转储下来，如图3-15所示。

图　3-15

3）一旦获得了从固件二进制文件中截取出来的Squashfs文件系统，就可以运行unsquashfs等命令来查看整个文件系统，这一过程非常简单。

接下来使用unsquashfs命令来看一下我们是否能够提取出整个文件系统，如图3-16所示。

图　3-16

4）正如在前面的截图中所看到的，我们提取出了Squashfs文件系统镜像。读者可以忽略图3-16中的警告和错误，这只是在提示我们没有以root用户权限运行该命令。一旦我们提取出了文件系统，就可以浏览文件系统中的各个目录，对其中的各个文件分别进行分析来挖掘漏洞。图3-17是对整个文件系统目录的截图。

图　3-17

上面就是对固件进行逆向分析并从固件二进制镜像中提取文件系统的方法。我们还可以采用Binwalk等工具自动执行前面的所有操作。Binwalk由Craig Heffner开发，借助Binwalk我们只需要一条命令就能够从固件二进制镜像中提取文件系统。

5）为了安装Binwalk，首先需要从位于https://github.com/devttys0/binwalk.git的Git-Hub代码库中克隆Binwalk代码，命令如下：

6）然后运行./deps.sh命令安装Binwalk需要的所有依赖文件和二进制文件。

7）Binwalk安装成功后，读者可以在命令行中敲入Binwalk命令并按回车键来确认安装是否成功。如果安装成功，此时命令行窗口会显示出Binwalk的帮助菜单，如图3-18所示。

8）下面我们使用Binwalk命令从相同的固件中提取出文件系统。这里在执行提取操作时将用到-e参数：

9）接下来窗口中会显示出固件中的所有分段，并提取出固件内容，如图3-19所示。

图　3-18

图　3-19

10）参数-t和-vv可以采用可读性更强以及更加详细的方式打印出命令执行结果。Binwalk执行完毕之后，会生成名为_[firmwarename].extracted的文件夹，该文件夹中保存了Binwalk提取出的整个文件系统，如图3-20所示。

以上就是采用手工和自动两种方式从固件的二进制文件中提取文件系统的过程。

[1] Squashfs文件系统的头部特征字符串较多，目前已知的有7种：标准固件大端序模式为sqsh，标准固件小端序模式为hsqs，LZMA压缩下的大端序模式为sqlz，3.3版本的Squashfs文件系统在LZMA压缩下的大端序模式为qshs，部分非标准固件小端序模式为shsq（多为D-Link固件），DD-WRT固件小端序模式为hsqt，DD-WRT固件大端序模式为tqsh。——译者序

3.4.3　测试分析

本例中的文件系统提取方法同我们之前采用的方法相同，均是首先使用magic字节以及首部特征字符串（例如Squashfs文件系统中的sqsh字符串等）检测文件系统以及其他组件的偏移。在下面的URL链接中可以查看Binwalk所能识别的文件系统类型：

https://github.com/devttys0/binwalk/blob/62e9caa164305a18d7d1f037ab27d14ac933d3cf/src/binwalk/magic/filesystems。

图　3-20

读者还可以在Binwalk中手工添加更多特征，然后重新编译Binwalk源代码，从而实现对其他文件系统的识别。

3.4.4　拓展学习

除了提取文件系统，读者还可以使用Binwalk进行一系列其他操作，例如针对某个特定固件镜像进行熵分析，该操作能够帮助读者判断固件镜像是否进行了压缩或者加密。熵分析需要在运行Binwalk时带上-E参数，之后再跟固件名，操作命令如图3-21所示。

图　3-21

从上面的截图中可以看出，该固件并未加密，因为加密的固件镜像熵值会出现大幅波动。

3.4.5　延伸阅读

想了解更多关于固件分析与逆向分析的内容，可以访问Binwalk开发者Craig Heffner的博客。读者可以从博文中了解到不同的固件镜像会如何变化，以及可能存在哪些漏洞。Craig Heffner的博客链接为http://www.devttys0.com/。

3.5　文件系统分析

现在我们已经知道如何逆向固件并从中提取出文件系统了，在本节中将关注文件系统中的内容并对其开展漏洞分析。这部分内容能够帮助读者更加深入地了解如何从固件镜像中挖掘漏洞并加以利用，进而入侵IoT设备。

3.5.1　准备工作

针对文件系统内容的分析主要包括两种方法：

·手工分析。

·自动化工具和脚本。

1.手工分析

采用手工方法挖掘固件文件系统漏洞时，需要对文件系统中的各个文件与文件夹进行分析。分析内容包括查看配置文件、Web目录、口令文件以及查找后门等。手工分析方法是在指定固件中挖掘漏洞的理想方法，本节我们也将主要关注这种方法。

2.自动化工具和脚本

本书出版时，除了部分自动化分析脚本，尚没有一套完整的框架或者工具能够帮助我们挖掘固件漏洞。因此，如果读者对Web应用安全或者网络安全比较熟悉，那么应该了解目前在固件安全分析领域也没有类似于Arachni、w3af、Metasploit之类的工具。

3.5.2　测试流程

我们首先从固件分析开始，看看是否能够发现敏感信息或者后门。

在这个练习中我们使用的是路由器D-Link DWR 932B的固件，版本号为DWR-932_fw_revB_2_02_eu_en_20150709。安全研究员Gianni Carabelli和Pierre Kim已经在这款固件中挖掘出了漏洞：

1）第一步是从固件中提取文件系统。但是，本例中的固件为经过加密的ZIP文件。因此，在本例中首先使用fcrackzip工具进行口令破解，破解出的口令是beUT9Z。运行结果如图3-22所示。

图　3-22

2）获取了固件镜像之后，可以采用Binwalk从固件的ZIP文件中提取出yaffs2格式的文件系统。接下来，读者可以使用针对yaffs2格式的工具解压文件系统，也可以直接通过Binwalk来完成提取工作。

3）在yaffs2-root文件夹中，我们提取得到了完整的文件系统，如图3-23所示。

图　3-23

4）从这里开始，我们开始遍历文件系统中不同的目录，并从安全视角查找其中可能存在漏洞的文件。我们需要做的第一件事是查找所有配置文件，这可以通过运行find命令查找所有后缀为.conf的文件来实现，搜索结果如图3-24所示。

5）接着查看配置文件的内容。举个例子，图3-25所示为配置文件wpa-supplicant.conf中的内容。

6）接下来查看其他配置文件，例如inadyn-mt.conf，如图3-26所示。

图　3-24

图　3-25

图　3-26

出乎意料的是，该文件中包含了大量敏感信息，而这些信息本不应该被其他人访问到。正如我们在前面的截图中看到的，文件inadyn-mt.conf中存储了路由器的no-IP配置信息[1]，包括用于访问网站https://www.no-ip.com的用户名和口令。

这就是我们在固件中查找隐藏敏感信息的方法。显然，读者可以在固件的文件系统中进行更加全面的查找，从而发现更多的敏感信息。

现在我们已经知道了如何对固件进行手工分析，接下来将介绍如何采用自动化的方式来挖掘漏洞。为此，我们将用到Craig Smith开发的工具Firmwalker，该工具通过静态分析来识别固件中可能包含的常见敏感信息。

1）克隆GitHub代码库中的Firmwalker代码并完成部署，命令如下：

2）Firmwalker代码库克隆完成后，我们以提取出的文件系统位置为参数，运行./firm-walker.sh脚本：

3）Firmwalker脚本能够识别出多种敏感信息，包括二进制文件、证书、IP地址、私钥等，同时将输出结果都保存在firmwalker.txt文件之中（用户也可指定存储文件）。如图3-27所示。

图　3-27

拿到Firmwalker生成的报告之后，我们就可以分别查看报告中所列出的各个文件并对其开展进一步分析了。在某些情况下，读者还需要对基于ARM和MIPS架构的二进制文件进行逆向分析，以便更好地了解文件执行流程进而挖掘出漏洞。

[1] 提供动态域名服务。——译者注

3.5.3　测试分析

分析并理解文件系统及其中的内容取决于攻击者的手工分析技巧。而这正是能否挖掘出漏洞的关键。即使采用了各种自动化工具，读者也会意识到分析过程最终都会转化为针对二进制文件的手工分析与漏洞挖掘。

3.5.4　拓展学习

为了更加深入地对固件的文件系统开展分析，读者还可以使用诸如firmware diffing之类的技术，即将固件同之前的固件版本进行比较，进而查找出两者之间的差异。通过比较，读者能够了解新版本中所做的安全修复和改动，甚至发现之前版本中未公开的安全漏洞。

我们还可以基于固件文件系统开展另一项工作，就是查看系统使用的库文件和组件，并判断这些组件是否是早期存在漏洞的版本。

3.5.5　延伸阅读

在分析固件文件系统中的内容时，最好多了解一些关于二进制分析和逆向分析的相关知识，并且熟悉Linux二进制文件分析、调试以及针对ARM和MIPS等平台的反汇编技术。

3.6　基于固件仿真的动态分析

通常，开展IoT设备分析会受到这样或那样的限制，其中一个就是我们难以在没有实体设备的情况下开展大量测试并进行漏洞利用。但是在本节中，我们将讨论固件仿真方法，读者可以同仿真设备进行交互，就如同和网络中的实体设备交互一样。

3.6.1　准备工作

为了进行固件仿真，我们将用到由本书作者开发的脚本Firmware Analysis Toolkit（FAT）。FAT采用Firmadyne工具实现固件镜像的仿真。

Firmadyne工具底层基于QEMU虚拟机，这使得用户能够对整个系统架构进行仿真并在该架构之上运行固件，其中还用到了工具开发者编写的其他脚本，例如NVRAM仿真器，该仿真器可以从地址https://github.com/firmadyne/libnvram下载。同时还使用了类似于Binwalk之类的工具，在前面的章节中我们对Binwalk已经进行了介绍，借助该工具能够从固件中提取出文件系统，继而开展固件仿真。

接下来从GitHub中克隆FAT的代码库，并部署固件仿真实验环境。我们强烈建议读者在Ubuntu系统上进行操作，这样可以避免在仿真过程中出现各种奇奇怪怪的问题。

3.6.2　测试流程

固件仿真步骤如下：

1）从链接https://github.com/attify/firmware-analysis-toolkit/处克隆FAT代码库，然后安装：

安装过程中将为Firmadyne创建数据库，将关于固件的信息存储起来并进行管理。数据库密码默认设置为firmadyne。

全部设置完毕之后，下一步就是选择固件并对其进行仿真，下面来看看我们能够针对仿真固件开展哪些工作。

在本节练习中，我们将以D-Link固件DWP2360b为例进行演示，D-Link公司出品的PoE供电无线接入点采用了该固件。

2）此时，我们要做的第一件事就是运行./fat.py，该脚本运行后会请求用户输入固件名称和固件镜像的品牌。输入固件镜像品牌的作用主要在于创建数据库，这样我们就可以在需要时搜索数据库，查看我们已经对哪些品牌的固件进行了仿真。运行后的执行结果如图3-28所示。

图　3-28

3）接下来工具会多次请求用户输入数据库的口令，在本例中我们将口令设置为fir-madyne。程序完成初始化、镜像创建、网络配置并分配IP地址之后，FAT将会在命令行窗口中显示其IP地址，并提示用户已经完成了固件仿真，如图3-29所示。

4）获得了IP地址之后，我们就可以在浏览器中输入该IP地址，之后就可以打开仿真路由器的登录页面了，本例中设备的登录页面如图3-30所示。

以上就是在没有物理设备的情况下如何借助FAT实现固件仿真的过程。

图　3-29

图　3-30

3.6.3　测试分析

前面的仿真实验主要基于QEMU和NVRAM仿真器。NVRAM是非易失性随机访问存储器，固件能够访问该存储器获取设备信息。然而，由于没有物理设备，固件需要访问该存储器时就会导致服务运行出错或崩溃，而这正是NVRAM仿真器发挥作用的地方。使用Firmadyne工具集还能对固件进行修改，以便让用户访问Console口以进行调试。

以下是FAT脚本能够执行的操作：

1）从固件中提取文件系统。

2）获取固件架构。

3）制作所需的镜像。

4）网络设置。

5）镜像仿真。

上述所有操作均可手工完成，但是利用FAT之类的脚本可以帮助我们快速完成操作。

3.6.4　拓展学习

另一种仿真方法是手工下载目标架构的Debian镜像文件，然后将镜像文件从固件中复制到新创建的Debian实例中，再使用chroot命令运行Web服务器（或是其他需要测试的组件）。读者可以从链接https://people.debian.org/~aurel32/qemu/下载最新的Debian镜像。

3.7　ARM与MIPS架构下二进制文件的分析入门

现在我们知道了如何进行固件仿真并开展基本的分析，但是读者会发现在现实工作中经常会遇到不同架构的二进制文件，对此需要开展进一步分析。由于我们难以在一本书中涵盖嵌入式设备用到的所有架构，因此在这里我们主要关注两款流行架构——ARM和MIPS。

然而，在这里我们将只介绍针对MIPS架构下的漏洞利用，并对ARM架构下的二进制文件逆向分析进行简单介绍。从漏洞利用的角度来看，ARM架构和MIPS架构非常相似，只要分析其中一个架构同样也有助于读者了解其他架构。

3.7.1　准备工作

现在开始我们的二进制分析之旅，首先从基本分析开始，看看如何从D-Link固件中发现后门。这个后门是由Pierre Kim首先发现的。为了验证这个后门的存在，要求读者对基于ARM架构的二进制文件逆向分析具备一定的基础。尽管我们不会深入分析寄存器和架构（因为我们将在MIPS架构中介绍这些内容），但是本节内容将帮助读者了解二进制文件的分析过程以及如何发现较为简单的漏洞。

本例中我们将要使用的固件是D-Link设备的固件DWR 932B。使用Binwalk提取出固件后，可以注意到其中包含一个名为appmgr的二进制文件，这正是我们感兴趣的文件。

在分析过程中，我们可以使用读者熟悉的所有反汇编工具，例如Radare2、IDA、Hopper等。本例中我们使用Hopper来对二进制文件appmgr进行逆向分析，这是一个基于ARM架构的小端序（Little Endian）二进制文件。

3.7.2　测试流程

可以使用Hopper的伪代码生成功能来更好地理解二进制文件。步骤如下：

1）在Hopper中加载目标二进制文件进行分析，如图3-31所示。

2）文件加载成功后，搜索telnet字符串，然后就可以看到telnet字符串在样本代码中的位置，如图3-32所示。

图　3-31

图3-32　在字符串中找到telnet字符串

3）为了找到该字符串的调用位置，可以右键单击该字符串并选择References to address选项，然后将展示出字符串的调用位置和调用指令。在本例中，如果执行References to address操作，我们会发现调用该字符串的内存地址为0x13048，如图3-33所示。

图　3-33

4）双击该内存地址跳转到引用该字符串的地址，在本例中即0x13048地址处。跳转到该地址之后，就可以看到所有的反汇编代码了，单击Pseudo-code mode按钮会生成伪代码，如图3-34所示。

图3-34　由反汇编代码生成伪代码

5）伪代码生成功能对于我们的分析工作而言非常有用，因为如果用户对反汇编不是太熟悉的话，借助伪代码就可以把一段反汇编指令看作一个逻辑上相对独立完整的程序，这样理解起来更为容易。本例中的伪代码如图3-35所示。

图　3-35

正如我们从前面的截图中看到的那样，程序调用了strncmp函数，参数为字符串HELODBG。我们知道，strncmp函数用于字符串比较，在本例中的作用是在运行Telnet前对二进制文件的输入字符串进行检查，上述操作在图3-35中以高亮方框的形式进行了标记。

因此我们可以肯定，appmgr文件中存在后门，程序查找字符串HELODBG，一旦接收到该字符串，它就会使用bin/sh shell启动Telnet服务。

上面的内容就是我们对ARM架构下二进制文件进行的分析，所采用的方法也是对二进制文件进行分析以查找敏感信息、挖掘漏洞与后门的基本方法。

3.7.3　拓展学习

既然读者已经知道了对ARM架构二进制文件开展分析的基本方法，我们建议对ARM汇编语言以及架构进行更加深入的了解。对汇编指令和底层架构的了解能够帮助读者更好地理解反汇编代码，即使在不借助伪代码的情况下也能够开展二进制文件的分析。

3.8　MIPS架构下的漏洞利用

现在我们已经掌握了逆向二进制文件的基本方法，那么是时候深入了解如何对IoT设备所采用的主要平台架构开展漏洞利用了。由于本节内容只是帮助读者了解二进制文件漏洞利用的基础知识，所以在这里我们只关注MIPS架构，但是强烈建议读者采用相同的方法自行针对基于ARM的架构开展漏洞利用练习。

3.8.1　准备工作

为了开展MIPS架构下的漏洞利用，在这里我们主要使用QEMU仿真器和chroot命令，这些内容我们在本章开头已经进行了简要介绍。现在将研究如何在MIPS二进制文件中进行缓冲区溢出漏洞利用，并改变程序的执行流程使其跳转到我们想要执行的内容，而不是程序原本应该执行的代码。为了简化漏洞利用过程，在这里我们不会涉及诸如面向返回的编程（Return Oriented Programming，ROP）之类的内容，这样可以使利用过程尽量简单一些。

3.8.2　测试流程

在这个练习中需要用到以下工具：

·路由器漏洞攻防演练靶机（Damn Vulnerable Router Firmware，DVRF）——该靶机可以从GitHub下载

·GDB-Multiarch

·GDB Enhanced Features（GEF脚本）

·QEMU

·chroot

·IDA Pro/Radare2（可选）

下面我们将对上述工具及其安装部署方式进行逐一介绍。首先从下面的URL链接下载DVRF固件：

https://github.com/praetorian-inc/DVRF/tree/master/Firmware

DVRF是由b1ack0wl专门为MIPS平台开发的固件。尽管该固件原本用于Linksys E1550设备，但其也可以在基于QEMU的仿真环境中运行，我们随后开展的漏洞利用也在该环境中加以演示：

1）现在我们已经拿到了固件，为了便于漏洞利用过程中的调试，接下来安装GDB（GNU调试器）和GEF：

同时还要确保已经在系统中安装了所需的QEMU软件包。现在我们已经准备就绪了，接下来利用QEMU提供的二进制仿真功能运行其中的二进制文件。

2）仿真之前，首先需要使用Binwalk工具从固件中提取出文件系统，操作命令如图3-36所示。

图　3-36

3）提取出文件系统后，就可以将对应架构下的QEMU二进制文件复制到文件系统的根目录下，在本例中是squashfs-root文件夹，如图3-37所示。但是在此之前需要确认目标二进制文件是基于MIPS架构的，通过readelf命令可以查看目标二进制文件的架构信息。

图　3-37

4）根据图3-37所示，目标二进制文件需要运行在小端的MIPS架构上，如图3-38所示。

图　3-38

5）此时将针对小端MIPS（mipsel）架构的QEMU二进制文件复制到squashfs-root文件夹下：

6）将qemu-mipsel-static文件复制到当前文件夹下后，再使用chroot命令和QEMU虚拟机仿真运行目标二进制文件，同时使二进制文件认为其根目录就是当前我们执行命令的目录。上述操作命令如下：

7）运行结果如图3-39所示，即使某个二进制文件最初是针对其他架构开发的，我们依然能够运行该文件。基于QEMU虚拟机对目标系统的仿真，再通过chroot命令对根目录进行调整，上述操作是可能实现的。

图　3-39

8）正如我们在命令输出结果所看到的那样（如图3-39所示），该二进制文件在运行时需要输入参数。此外，如果我们查看目标二进制文件的源代码，会发现该文件存在栈溢出漏洞。图3-40是二进制文件stack_bof_01的源代码。

图　3-40

从源代码中不难发现，变量buf在栈中的缓冲区容易遭受缓冲区溢出攻击，而实施溢出攻击的目的则在于修改程序执行流程，使其指向dat_shell的地址，这样我们就可以利用该漏洞来获得shell。

9）现在开始调试程序，运行QEMU和chroot命令，运行chroot命令时使用参数-g把调试器GDB附加到进程之上：

10）如图3-41所示，此时程序暂停执行，等待调试器的连接。

图　3-41

11）程序暂停运行后，我们即可以启动GDB调试器，使用之前分配的端口连接目标进程进行远程调试。另外我们还需要将架构设置为MIPS以确保能够正确地反汇编二进制文件，如图3-42所示。

图　3-42

12）当我们连接上目标进程时，会发现进程已经暂停，此时可以输入字符c让进程继续执行。

13）我们还可以输入info functions命令在屏幕上打印出二进制文件中可用函数的列表，如图3-43所示，这样可以帮助分析人员从渗透测试的角度查找可能存在漏洞的函数。

图　3-43

14）接下来输入disass main命令反汇编main函数查看函数内部结构。

15）disass main命令的执行结果如图3-44所示，此时得到main函数的反汇编代码。

图　3-44

如果读者熟悉反汇编结果中的某些指令，会发现这些指令非常有用。反汇编结果中依次指示了指令地址、指令和操作数。

MIPS架构中共包含32个通用寄存器，分别是$zero、$at、$v0～$v1、$a0～$a3、$t0～$t9、$s0～$s7、$k0、$k1、$gp、$sp、$fp和$ra。在这些寄存器中，$a0～$a3寄存器的作用是存放函数参数，$t0～$t9寄存器用于临时数据存储，$gp寄存器存放全局指针（在利用过程中尽量不要修改$gp寄存器的值），$sp寄存器存放栈指针，$fp寄存器存放帧指针，$ra寄存器存放返回地址。另外还有一个专用寄存器即程序计数器（Program Counter，PC），其作用是存储下一条指令的内存地址，也就是当前正在执行指令的下一条指令。

为了控制基于MIPS架构的二进制代码执行流程，我们主要关注2个寄存器，即RA寄存器和PC寄存器。在处理MIPS架构下的二进制文件时，读者可能已经意识到相对于RA寄存器而言，控制PC寄存器中的内容更加复杂。因此，为了简单起见，在本练习中我们将主要关注如何控制RA寄存器中的内容。

16）由于我们已经知道了当前分析的二进制文件stack_bof_01中存在栈溢出漏洞，因此在程序运行时可以尝试带上一个非常长的参数。我们将使用GEF的模式字符串创建功能生成该参数，运行结果如图3-45所示。

图　3-45

17）生成了测试用的模式字符串后，我们就可以将其作为程序stack_bof_01的参数运行程序，看看执行过程中是否会导致RA寄存器溢出。本例中，我们使用GEF生成了300个字符长的字符串，以该字符串为参数，程序stack_bof_01后的执行情况如图3-46所示。

图　3-46

18）正如我们所预期的一样，由于在命令中使用了-g参数，命令执行后二进制文件处于暂停状态，等待调试器附加进来。现在打开GEF终端窗口敲入target命令，命令执行结果如图3-47所示。

图　3-47

19）使用target命令完成远程主机IP与端口的设置后，我们输入命令c，程序将继续执行直到出现以下三种情况之一，即运行完成、命中断点或者出现异常。本例中，程序在执行过程中出现了SIGSEGV错误，如图3-48所示。

图　3-48

GEF还显示出了捕获异常时栈和寄存器的全部状态。在本例中，我们可以看到RA寄存器中的值被覆盖为0x63616162，这正是字符串baac的十六进制形式。

了解了上述信息后，可以使用模式搜索功能找到覆盖RA寄存器的字节的偏移。取得了偏移之后，我们就找到了放置恶意地址的位置，进而能够控制程序的执行流程。

20）我们可以使用命令pattern search RA-overflown-bytes-in-hex实现模式字符串的搜索工作，搜索命令如图3-49所示。

图　3-49

根据命令执行结果，我们找到了导致寄存器RA溢出的字符串的偏移，在本例中该偏移为204。这意味着访问到RA寄存器之前需要填充204字节的垃圾字节，而接下来的4个字节就是填充RA寄存器的值。

21）如果读者还记得本次练习的目的在于更改程序的执行流程，并调用在程序正常流程中原本不会调用的dat_shell函数，那么下一步工作就是确定dat_shell函数的地址。为了找到dat_shell函数的地址，我们要么打印出dat_shell函数的地址，要么通过反汇编查找dat_shell函数的起始地址。这可以通过命令disass function-name来完成，执行结果如图3-50所示。

图　3-50

从在上面的截图中我们可以看到，dat_shell函数的起始地址为0x00400950。然而，前3条指令中用到了全局指针（GP寄存器），而我们并不希望在这个时候使用该指针，这就是我们跳转到0x0040095c而不是0x00400950的原因。

22）接下来在地址0x0040095c后填充204个垃圾字符后，继续运行二进制文件，这次我们去掉了参数-g，执行如下命令：

在图3-51中可见，二进制文件现在已经执行了我们想要执行的dat_shell函数。上述内容就是如何在MIPS架构下开展栈溢出漏洞利用的过程。

3.8.3　测试分析

缓冲区溢出漏洞的基本思路是在缓冲区中放入超过程序预期长度的字符串，这样就可以控制栈中的寄存器。而控制了栈中的寄存器就可以跳转到shellcode的位置或系统的libc库来执行其他载荷。

图　3-51

3.8.4　拓展学习

尽管在实验环境中我们成功对存在漏洞的二进制文件实现了漏洞利用，但通常在现实情况中遇到的场景更为复杂。其中一种情况是我们希望利用的函数在现实二进制文件中却并不存在，此时攻击者就需要跳转到system函数来执行bin/sh，或者创建ROP链执行自己的shellcode。

3.9　使用firmware-mod-kit（FMK）在固件中添加后门

在漏洞利用过程中，经常需要用到的一种方法就是篡改固件。也就是从固件中提取文件系统，对其内容进行修改，然后再将其重新打包成新的固件，随后攻击者可以将这个新打包的固件刷进设备。

3.9.1　准备工作

固件篡改的过程会用到工具FMK，该工具由Jeremy Collake和Craig Heffner开发。FMK不仅可以利用Binwalk或其他工具从固件中提取出文件系统，还具有将篡改后的文件系统重新打包成新固件的功能。

FMK可以从https://github.com/brianpow/firmware-mod-kit/下载，如果读者之前从GitHub中克隆了FAT代码，那么该工具应该已经存在于读者的系统中了。下载完该工具后，接下来我们就可以找一个固件一试身手了。出于简单起见，同时让本书的读者在无须投入资金购买硬件的情况下也能够复现以下步骤，我们主要以能够采用FAT进行仿真的固件为例进行介绍。

3.9.2　测试流程

篡改固件的步骤如下：

1）在本例中我们使用的固件来自D-Link DIR-300路由器。在这里我们使用FMK目录下的extract-firmware.sh脚本从固件中提取文件系统，而未使用Binwalk。操作命令如图3-52所示。

图　3-52

提取出固件后，脚本会生成一个新目录，其中包括rootfs、image_part和logs等文件夹。由于攻击者的目的大多是添加后门和修改固件，因此这里我们只关心rootfs文件夹。

rootfs文件夹中包含了固件中的整套文件系统。而我们所要做的工作就是在固件中添加后门，然后找到固件启动后自动调用后门的方法。

2）首先查看固件所基于的架构。对固件中任一文件执行readelf命令就可以查看其架构，以BusyBox文件为例，命令执行结果如图3-53所示。

图　3-53

3）正如我们从图3-53中看到的，固件是基于MIPS小端架构的。这意味着我们需要开发符合MIPS小端架构的后门并进行编译。下面是我们将要使用的后门源码，该后门由Osanda Malith开发编写：

代码写好后，我们就可以使用针对MIPSEL架构的Buildroot，并使用该Buildroot构建的交叉编译器编译代码。这里不对安装配置Buildroot的过程进行过多介绍，因为这个过程非常简单，并且在Buildroot的说明文档中已经进行了详细说明。

4）为MIPSEL架构创建了交叉编译器后，我们接下来将bindshell.c编译为能够植入文件系统的二进制文件bindshell：

下一步是在文件系统中寻找可以放置该二进制文件的地方，以及如何在启动过程中将其设置为自启动。这里我们的思路是分析在启动过程中自动调用的脚本，看看是否能够实现自启动。

5）在文件系统中，我们可以在etc/templates/目录中放入后门的二进制文件，然后在system.sh脚本中调用该二进制文件，其中system.sh脚本位于/etc/scripts/目录下，脚本编写如图3-54所示。

图　3-54

6）接下来使用build-firmware.sh脚本将修改后的文件系统重新打包为新的固件，打包过程如图3-55所示。

图　3-55

执行完成后，会在目录firmware-name/中生成新的固件，新固件名为new-firmware.bin。

7）此时就创建完成了新的固件镜像，我们可以将新固件复制到FAT目录中，并通过仿真来验证新添加的后门是否能够正常运行。这里同之前固件仿真的步骤相同。操作步骤如图3-56所示。

图　3-56

如图3-56所示，固件仿真时获得的IP地址为192.168.0.1，此时可以尝试访问该地址。但我们更关注在固件中添加的后门bindshell是否已经成功启动。

8）现在尝试运行Netcat连接目标IP的9999端口，检查后门是否成功启动，如图3-57所示。

图　3-57

根据执行结果，可以看到我们已经对固件进行了修改并成功植入了后门，因此此时成功获得了设备中具有root权限的shell。而获得拥有root权限的shell之后，用户还可以修改设备的其他配置，或者将其作为跳板远程访问其他植入恶意固件的设备。

3.9.3　测试分析

固件篡改的功能强大，对于攻击者而言是梦寐以求的目标。这是因为，如果能够实现对固件的篡改，那么攻击者就能够实现绕过保护机制、移除安全防护措施等操作。而利用本章介绍的FMK等工具，攻击者可以很容易地将自己开发的恶意软件或后门植入到任意IoT设备固件中，这样攻击者就可以在全球任何地方通过后门访问IoT设备了。

正是由于固件篡改在攻击者手中具有如此强大的威力，所以如果能够对固件进行签名和校验值验证，那么对于防止恶意修改固件的攻击而言将具有非常重要的意义。

第4章　嵌入式Web应用漏洞利用

本章将主要介绍以下主题：

·Web应用安全测试。

·Burp Suite的用法。

·OWASP ZAP的用法。

·命令注入漏洞利用。

·XSS漏洞利用。

·CSRF漏洞利用。

4.1　简介

人们通常采用Web应用与Web服务实现对设备的远程访问并对设备进行管理。IoT设备的Web应用功能也非常强大，攻击者借助IoT设备的Web应用就能够实现对设备的远程控制。而存在远程执行漏洞的产品则可能会对用户的人身安全产生影响，例如网联汽车、智能门锁等。因此，当对上述类型的IoT产品进行测试时，如何定位高风险漏洞以及评估对用户的影响是我们首先需要关注的问题。本章中，我们将会介绍如何选择Web应用测试方法、部署Web测试工具集，以及如何挖掘嵌入式Web应用常见的漏洞并开展利用。

4.2　Web应用的安全测试

现代互联网大多运行于Web应用之上，而这些Web应用往往又以数以百计的Web页面、其他Web应用以及数据库服务器为后台支撑。互联网已经从单纯的静态HTML页面演进到了需要更多运算资源的高级异步应用。虽然互联网已经发生了很大变化，但是其中部分最常见的安全问题却没有太大变化。漏洞最先出现于20世纪90年代，但是时至今日依然存在，并且被攻击者广泛利用。在IoT产品中，最常见的漏洞包括：跨站脚本（Cross-Site Scripting，XSS）、目录遍历、认证绕过、会话劫持、XML外部实体（XML External Entity，XXE）、跨站请求伪造（Cross-Site Request Forgery，CSRF）以及其他业务逻辑漏洞。在本章中，我们提出了一种Web应用测试方法，采用该方法可以挖掘IoT Web应用以及Web服务的漏洞并进行利用。

测试流程

评估Web应用的安全性，方法很重要，找到窍门后有时甚至只需要一张检查清单（checklist）就可以开展评估工作了。其中，了解所采用渗透测试方法的特点，以及现实环境下Web应用所面临风险，是绕过安全控制措施成功实施渗透的关键。在本章，提出针对目标应用的测试方法之后，我们将对Web测试环境与工具集进行配置，继而开始针对Web应用的安全测试。

1.Web渗透测试方法

开展Web渗透测试有多种方法可供选择。这些方法自身并没有所谓的“正确”或者“错误”之分，但是，如何能够找到一种适合自身的方法针对Web应用开展渗透测试，对于成功挖掘出软件的漏洞而言至关重要。最常见的方法是渗透测试执行标准（Penetration Testing Execution Standard，PTES）以及OWASP提出的Web应用渗透测试方法。OWASP（Open Web Application Security Project）是一个非营利性的公益组织，该组织致力于安全工具开发、安全文档编制，以及在国际范围内倡导推广软件安全。如果读者之前开展过针对应用的安全测试，或者修复过软件漏洞，那么可能已经对OWASP发布的工具与文档比较熟悉了。而如果读者之前开展过渗透测试，那么在测试过程中很可能也接触过PTES标准了。PTES标准的主要作用在于为渗透测试工作提供工作基线。在PTES标准中，将渗透测试分为了7个阶段，分别是：

1）前期交互。

2）情报搜集。

3）威胁建模。

4）漏洞分析。

5）渗透测试。

6）后渗透测试利用。

7）报告编制。

虽然PTES标准适用于所有的信息安全测试场景，但是大多应用于面向网络的渗透测试。其中只有一小部分内容同Web安全有关，目前来说这些内容还不足以支撑开展一次全面到位的安全评估。但是，PTES标准针对渗透测试过程中的每个阶段均提供了详细且易于上手的实例，还包括了工具用法示例，这也是PTES标准的优势所在。而另一方面，OWASP提出的Web应用渗透测试方法则完全针对Web应用渗透测试而设计，共包括以下12个类别：

·简介及目标。

·信息搜集。

·配置管理与部署管理测试。

·身份管理测试。

·认证测试。

·授权测试。

·会话管理测试。

·输入验证测试。

·错误处理。

·密码学。

·业务逻辑测试。

·客户端测试。

同PTES标准类似，OWASP提出的测试方法在每个阶段均提供了大量实例，其中既包括截图，也包括测试过程中所用到的工具及工具的使用说明。当读者在某一领域的经验还比较匮乏时，了解同目标测试应用有关的实例大有帮助。OWASP测试方法中最棒的一点在于，能够根据某种测试方法的现实环境选择测试用例以及测试角度，例如黑盒测试或者灰盒测试。OWASP被看作是应用安全指南与测试的权威组织，所以如果在测试过程中有什么不确定的地方，我们建议读者可以查阅OWASP测试指南或者在其编制的各种备忘录中寻求帮助。

2.测试工具选择

在对Web应用进行测试时，有很多工具可以用来帮助测试人员开展测试。构建适合自己的Web安全评估工具集可以从选择浏览器着手，同时测试人员还可以根据测试需求对其配置进行定制。在众多浏览器中，Firefox浏览器提供了很多用于测试的插件，所以Firefox浏览器也成了很多测试人员的上上之选。当然，其他浏览器在针对某些应用开展测试时也会用到，例如对于用到了ActiveX或者Silverlight控件的应用而言，就需要使用IE浏览器进行测试。有些浏览器提供了部分插件来简化测试过程，同时使得测试过程更加高效，这些插件包括：

·FoxyProxy：该插件可用于管理Chrome以及Firefox浏览器的代理配置。测试过程中，有时测试人员会存在同时运行多个代理、并且在两个代理之间进行切换的需求。借助FoxyProxy插件，用户就无须再单击一系列浏览器配置按钮即可变更浏览器的代理配置。FoxyProxy插件可以从以下链接中下载：

https://addons.mozilla.org/en-us/firefox/addon/foxyproxy-standard/。

·Cookie Manager+：借助Cookie Manager+插件，用户能够实现对cookie值的编辑并查看cookie中的各项属性。Firefox和Chrome浏览器提供了很多可用的cookie编辑插件。在Firefox浏览器中常用的cookie编辑工具就是Cookie Manager+。Cookie Manager+可以从以下链接下载：

https://addons.mozilla.org/en-US/firefox/addon/cookies-manager-plus/。

·Wappalyzer：为了更好地分析目标应用，借助Wappalyzer插件能够帮助用户澄清应用采用了哪些组件。Wappalyzer插件可以用于分析应用所采用的技术，包括Web服务器、框架以及JavaScript库函数等。Firefox和Chrome浏览器的Wappalyzer插件可以从以下链接下载得到：

https://wappalyzer.com/download。

选择出适合开展渗透测试的浏览器之后，为了能够在Web应用代理工具中查看应用的请求与响应报文，还必须对浏览器的代理配置进行设置。在下面的章节中，我们将介绍如何对浏览器的代理配置以及Web应用代理工具进行设置。

4.3　Burp Suite的用法

Burp Suite是对Web应用进行安全评估时最常用到的Web代理工具。Burp Suite采用Java编写，可以实现跨平台运行。借助Burp Suite，测试人员可以实施中间人攻击来篡改http请求与响应报文，并对应用操作进行监控。此外，测试人员还可以使用Burp Suite爬取Web页面，发起针对脆弱点的主动扫描、被动扫描以及fuzzing测试。

4.3.1　准备工作

在本书中实验所用到的虚拟机中已经预先安装了Burp Suite，但是，用户还可以从链接https://portswigger.net/burp/下载该工具。

Burp Suite分为免费版与专业版两个版本。功能完善的专业版售价为349美元，这一价格并不算高，此外，Burp Suite还提供有专业试用版，试用期限为2周。其中，免费版能够实现http请求与响应报文的代理转发，并且可以从BApp应用商店中下载插件。而专业版则具有更多高级功能，并且可以使用专业的扩展插件。

4.3.2　测试流程

接下来，在开始对嵌入式Web应用开展渗透测试之前，我们首先对Burp Suite的基本用法进行一个简单介绍。下面的实例中我们主要采用Burp Suite专业版进行测试，但是设置步骤对于免费版同样适用：

1）首先将Burp Suite的Proxy模块中监听器的监听地址设置为127.0.0.1，端口为8080，如图4-1所示。

图　4-1

2）采用FoxyProxy插件设置浏览器代理，将代理地址设置为前一步骤中设置的Burp Suite监听地址，如图4-2所示。

图　4-2

3）选择完成配置的代理，将所有流量路由至Burp Suite监听器，如图4-3所示。

图　4-3

4）接下来，访问链接http://burp/cert下载安装Burp Suite的CA证书，将证书保存在本地文件夹中，之后将证书导入浏览器的证书管理器。只有导入Burp Suite的CA证书后，浏览器才能够代理转发采用httpS协议连接的流量，便于后续的测试工作，如图4-4所示。

图　4-4

5）在Firefox浏览器中访问about：preferences#advanced页面，选择Certificates（证书）及Authorities（证书颁发机构），如图4-5所示。

图　4-5

6）单击Import...按钮，选择本地保存的Burp Suite CA证书，如图4-6所示。

图　4-6

此时，我们就可以查看http/httpS协议的请求与响应报文了。

7）完成对浏览器与Burp Suite中与代理相关的基本设置后，访问目标Web应用页面，在目标应用地址上单击鼠标右键选择Add to scope选项，可以将目标Web应用的链接添加到扫描范围中，如图4-7所示。

图　4-7

8）选定扫描范围之后，在测试报文上单击鼠标右键，选择Do an active scan选项，即可启动Burp Suite扫描引擎发送扫描请求报文，如图4-8所示。

9）进入Scan queue选项卡可以查看扫描结果，如图4-9所示。

10）有时测试人员需要观察应用响应报文，有时则需要对数据包载荷进行篡改，那么此时就需要使用Repeater模块来重放请求报文。操作过程为在目标请求报文上单击鼠标右键，将其发送到Repeater模块，随后即可对目标报文进行篡改。图4-10显示了对数据包载荷中alias参数进行篡改的情况。

11）对于篡改后的数据包载荷，我们还可以借助Burp Suite的Decoder模块对特定字符进行编码或解码，以保证载荷能够被服务端执行。图4-11中展示了某字符串（窗口上部）的URL编码结果（窗口下部）。

图　4-8

图　4-9

图　4-10

12）针对特定载荷的参数开展fuzzing测试需要渗透测试人员更多的人工参与，这一工作可以借助Burp Suite的Intruder模块来实现。其中，首先需要指明fuzzing测试的目标参数。在本例中，我们将alias参数作为测试对象，如图4-12所示。

13）接下来，选择所要使用的攻击载荷（本例中选择Fuzzing-XSS），然后单击Start attack按钮开始测试，如图4-13所示。

图　4-11

图　4-12

图　4-13

随后将新弹出一个窗口显示攻击结果，如图4-14所示。

图　4-14

4.3.3　测试分析

在部署步骤中，我们对Burp Suite代理以及浏览器配置进行了设置，了解了采用Burp Suite开展渗透测试的基本用法。接下来，介绍了如何使用FoxyProxy设置浏览器代理，安装Burp Suite CA证书，发送请求报文进行扫描，然后展示了如何使用Burp Suite中的各个模块针对特定目标实施攻击，所涉及的模块包括Repeater、Decoder以及Intruder等。

了解了上述内容后，我们就可以使用Burp Suite对目标设备中的嵌入式Web应用开展脆弱性评估了。

4.3.4　拓展学习

在Burp Suite背后有一个强大的社区为其提供技术支持。当一种新型攻击技术出现之后，社区就会开发出一系列插件。Burp Suite自身的开发演进同样如此。为了保证Burp Suite时刻站在技术前沿，PortSwigger公司开展了大量工作来保证Burp Suite的持续更新。对Burp Suite的版本改进，读者可以通过发布记录进行了解（http://releases.portswigger.net/）。

有效的入侵载荷

当使用Intruder模块时，测试人员最好准备一组有针对性的载荷用作fuzzing测试参数。在更具针对性的攻击测试中，可以采用SecList项目提供的密码字典以及fuzzing载荷[1]。基于社区提供的支持，该项目定期更新，通过链接https://github.com/danielmiessler/SecLists/可以下载SecList项目。

[1] SecLists项目搜集了在开展安全评估过程中可能用到的各种类型数据的字典，包括用户名、口令、URL、敏感数据模式、fuzzing载荷、web shell等。——译者注

4.3.5　延伸阅读

针对部分特定测试需求，读者如果需要在Burp Suite中创建宏或者开发新的插件，可以在链接https://portswigger.net/burp/extender/中查阅Burp Suite的扩展API。

4.4　OWASP ZAP的用法

OWASP开发的Zed Attack Proxy（ZAP）是一套免费的跨平台Web代理测试工具，主要用于挖掘Web应用中的漏洞。在Web应用代理测试工具的选择中，ZAP仅次于Burp Suite，当用户预算有限无法购买Burp Suite专业版授权时，ZAP更是不二选择。ZAP专为具有丰富安全经验的人员设计，但对于开发人员、功能测试人员等对渗透测试不甚了解的人而言也是一款理想的工具。借助ZAP提供的API，用户可以实现自动化扫描，也可以将ZAP直接融入开发人员的工作流，在产品发布之前开展扫描。ZAP扫描引擎功能强大，拥有很多功能各异的插件，引擎中还包含验证测试工具，例如Dirbuster和SQLmap。此外，ZAP还支持图形化脚本语言ZEST，该语言类似于宏，用于对请求报文进行记录与重放。本节主要对ZAP开展Web应用安全测试的基本功能进行介绍。

4.4.1　准备工作

在本书中实验所用到的虚拟机中已经预先安装了ZAP（注：原书误写为Burpsuite），但是，还可以从链接处https://github.com/zaproxy/zaproxy/wiki/Downloads下载。

ZAP的下载页面中还包含Docker镜像，以及ZAP的周更新版本，其中周更新版本中包含了官方发布版本中尚未加入的新特性。ZAP每周发布的周更新版本也非常稳定，如果读者想使用更多的功能，建议读者尝试一下。

4.4.2　测试流程

下面介绍ZAP的安装部署与基本用法：

1）首先单击ZAP主界面中的Tools按钮，选择Options选项，对ZAP监听器进行设置。设置内容包括输入ZAP监听的IP地址与端口信息，如图4-15所示。

图　4-15

2）然后通过Dynamic SSL Certificate选项生成ZAP的CA证书，并在浏览器中安装该证书，这一步同在Burp Suite中所做的工作类似，如图4-16所示。

图　4-16

3）接下来，选择证书保存路径，如图4-17所示。

图　4-17

4）在针对Web的主动、被动渗透测试中，用户需要安装部分测试插件，这些插件大大方便了测试过程。其中，可能用到的插件包括Advanced SQLInjection Scanner、Active scanner rules（alpha版）、DOM XSS Active scanner rule、Passive scanner rules（alpha版），以及用于识别网站技术的Wappalyzer等。ZAP会对插件的成熟度进行评级，但是即便是alpha版本的插件也不会导致什么不良后果。本例中用到的插件如图4-18所示。

图　4-18

5）安装完所需插件之后，用户可以通过Analyse、Scan Policy Manager选项对扫描策略进行配置，也可以选择导入策略或者导出策略。针对XSS漏洞的扫描策略配置示例如图4-19所示。

图　4-19

用户还可以设置ZAP扫描策略的阈值与强度。其中，阈值同警报置信度有关，也就是ZAP以多高的概率会对疑似漏洞进行报警，强度则同ZAP发起的攻击数量有关。这些信息可以在ZAP的用户指南中查阅，用户指南在工具中或者链接https://github.com/zaproxy/zap-core-help/wiki中都可以找到。

6）完成对扫描配置的设置后，我们可以在目标站点上单击鼠标右键将其添加到扫描范围当中，如图4-20所示。这一步骤类似于Burp Suite的Add to Scope选项。

图　4-20

7）此时，就将目标站点加入到了扫描范围当中，如图4-21所示。

图　4-21

8）右键单击想要测试的请求报文，选择拟采用的扫描策略，再单击Start Scan按钮即可以发送请求报文开始扫描了，如图4-22所示。

图　4-22

本例中选择了XSS扫描策略，启动扫描后扫描结果将显示在ZAP的Active Scan标签页中，如图4-23所示。

图　4-23

9）利用ZAP的fuzzing功能，用户还可以实现针对性更强的主动扫描，类似于Burp Suite中的Intruder模块。用户右键单击请求报文，选择打算进行fuzzing测试的位置与载荷即可启动fuzzing测试，设置过程如图4-24所示。

图　4-24

10）字符的解码与编码对于代码能否执行而言至关重要。ZAP中的Tool菜单提供了Encoder和Decoder按钮，可以实现类似于Burp Suite中Decoder模块的功能，操作界面如图4-25所示。

4.4.3　拓展学习

用户可以实现对ZAP的高度定制化并进行扩展，但是，受篇幅所限，在本节的最后我们仅仅介绍了ZAP用于Web应用安全测试的基本用法。想了解ZAP更多的用法以及如何对其进行定制化开发的内容，读者可以通过下面的链接访问ZAP的博客与wiki百科，分别是https://zaproxy.blogspot.com/和https://github.com/zaproxy/zaproxy/wiki。

此外，如果读者想借助ZAP或者Burp Suite不断提高Web应用测试水平，可以查阅OWASP的Web应用漏洞目录项目（Vulnerable Web Application Directory Project），链接为：https://www.owasp.org/index.php/OWASP_Vulnerable_Web_Applications_Directory_Project。

图　4-25

4.5　命令注入漏洞利用

在嵌入式系统中，OS命令注入漏洞多见于固件开发过程中遗留下的Web接口或者调试页面之中，其后果可能导致攻击者执行任意操作系统命令。为了执行操作系统命令，攻击者可以通过Web接口在Web服务参数中提交操作系统命令。如果Web页面中的参数可以动态设置，并且未经适当过滤，那么极有可能导致命令注入漏洞被攻击者利用。如果攻击者能够执行操作系统命令，那么接下来攻击者就可能上传恶意固件、更改配置信息、实现对设备的持久控制、获取口令，攻击网络中的其他设备，甚至锁定账户使合法用户不能正常登录设备。在本节中，我们将会对如何利用命令注入漏洞获取设备shell权限的过程进行介绍。

4.5.1　准备工作

对于本节内容，我们将会用到tcpdump、Burp Suite等工具，并以存在漏洞的IHOME-CAM ICAM-608网络摄像头为目标开展测试。在大多数*Nix操作系统中都会包含tcpd-ump工具，此外，Wireshark也可以用于捕获数据包，这些工具在测试中都可能会用到。

4.5.2　测试流程

在嵌入式Web应用中查找命令注入漏洞的过程相当烦琐。其中，我们首先需要重点关注的是诊断页面，因为诊断页面通常会用到诸如ping或者traceroute之类的系统命令，此外还需要分析系统服务的配置页面，例如SMB、PPTP或者FTP等服务的配置页面。而如果我们已经提取到了固件或者能够访问目标设备的Console口，那么通常做法是首先对设备中可能存在漏洞的脚本以及功能进行静态分析，然后再采用动态分析方法对静态分析过程中发现的可疑点进行动态验证。下面通过实例进行说明：

1）首先查看目标网络摄像头的配置页面设置情况，从中定位可能存在漏洞的页面，如图4-26所示。

图　4-26

2）其实可供选择的页面并不算多，我们很容易地就从中发现了邮件服务和FTP服务的配置页面。这些页面均可能会向操作系统发送系统命令。我们首先分析FTP服务的配置页面，并尝试使用Burp Suite更改系统命令中的参数值，如图4-27所示。

3）当尝试向pwd参数发送载荷$(ping%20192.168.1.184)时，可以发现应用过滤掉了某些字符，报文内容如图4-28所示。

4）测试过程中，建议测试人员在载荷中使用诸如ping之类的基本命令，如果命令在目标设备中执行，则目标设备会向测试人员指定的主机发送请求报文，进而指示载荷中的命令已经成功执行。为了观察ping命令是否已经执行，测试人员可以启动tcpdump程序监听来自目标网络摄像头的ICMP数据包，命令如下：

图　4-27

图　4-28

5）借助Burp Suite的Repeater模块，我们能够更改报文中某些字段的值，从而绕过网络摄像头对客户端的验证。以下面的这段请求报文为例，发送下面的请求报文之后，我们会发现应用接收了更改后的报文，同时根据服务端向浏览器返回的http响应报文，可以看到浏览器会刷新ftp.htm页面。

6）而刷新ftp.htm页面时，在嗅探工具中可以观察到有ICMP报文发往我们指定的主机：

7）根据上面进行的测试，此时我们就可以确认pwd参数存在命令注入漏洞了，下一项工作是获取目标设备的shell权限。我们已经知道该网络摄像头启用了FTP服务，所以存在相关的系统服务，并且还可能启用了Telnet服务器。接下来，我们在25端口上尝试运行Telnet服务，这样攻击者可以在没有用户名和口令的情况下通过Telnet连接目标设备就可以获得目标设备的shell，用到的载荷如下：

8）我们还已经知道了应用要求通过刷新ftp.htm页面来保存设置，通过查看页面源代码，可以发现页面调用了一个名为ftptest.cgi的CGI程序来执行载荷。下面就是ftp.htm页面中执行之前所发送载荷的代码片段：

9）接下来，可以在GET请求报文中尝试直接调用ftptest.cgi程序来保存设置，请求报文如下：

10）此时，Telnet服务就已经运行在目标设备的25端口了，建立同目标设备的Telnet连接就能够获得root权限的shell：

11）获得设备的shell后，测试人员就可以在设备所处的局域网中采用各种后渗透测试技术开展后续攻击了。在本节中的内容不会涉及后渗透测试技术，但是，我们可以将命令注入漏洞载荷写入脚本，以方便下次使用，bash脚本如下：

在本节中，我们初步了解了IHOMECAM ICAM-608网络摄像头中命令注入漏洞的挖掘与利用过程。最终，我们获得了设备的shell，并编写了命令注入漏洞的自动化利用脚本。

4.5.3　延伸阅读

想了解更多关于命令注入漏洞挖掘与防护方面的内容，可以查阅OWASP中有关命令注入的wiki页面（https://www.owasp.org/index.php/Command_Injection）以及OWASP嵌入式应用安全项目（https://www.owasp.org/index.php/OWASP_Embedded_Application_Security）。

4.6　XSS漏洞利用

XSS是一种在可信网站中找到不可信的输入源，然后执行并注入任意JavaScript脚本的攻击技术。当攻击者发现在Web应用中存在动态输入的参数且未经验证，或者在将内容返回给用户之前未对输出进行编码，那么该Web应用就可能存在XSS漏洞。浏览器认为其所传输的代码都是可信的，而XSS攻击正是利用了浏览器的这种特性来传递攻击载荷。XSS漏洞主要包括三种类型，分别是反射型（最为常见）、存储型以及DOM型。直接复制参数内容并写入应用响应报文，而未对参数内容进行过滤时，可能导致反射型XSS。当应用允许将输入数据作为参数存储在应用的数据库中以备后用时可能导致存储型XSS。当参数数据能够通过JavaScript函数导入到某个DOM元素时可能导致DOM型XSS。

攻击者成功利用XSS漏洞后可以进行以下操作：

·植入键盘记录器。

·攻击被攻击者所在的局域网。

·代理转发流经被攻击者的所有Web流量，即实施中间人攻击。

·窃取或篡改应用cookie用于会话劫持。

·更改被攻击者Web应用的显示内容。

·绕过CSRF安全防护措施。

为了成功向被攻击者发起攻击，攻击者需要利用社会工程学技术让用户执行恶意请求。XSS攻击中常用的社会工程学方法包括：

·创建包含恶意JavaScript代码的虚假网站以及到该网站页面的链接。

·发送嵌入恶意Web URL的电子邮件。

·使用URL短码隐蔽真实URL。

在上述每种场景中，初始URL都将链接到被攻击者所信任的站点，同时会在用户不知情的情况下异步执行恶意JavaScript代码。在本节中，我们将对如何挖掘并利用反射型XSS漏洞进行简要介绍，进而获取被攻击者浏览器的控制权限。

4.6.1　准备工作

本节中，我们将会用到OWASP ZAP、BeEF（Browser Exploitation Framework）等工具以及存在漏洞的RT-N12 ASUS路由器。通过链接http://beefproject.com可以安装BeEF，在Kali Linux虚拟机中也已经默认安装了该软件。

4.6.2　测试流程

尝试挖掘反射型XSS漏洞时，我们首先从观察针对参数输入的处理方式入手，判断数据是否能够被反射给用户。诸如OWASP ZAP以及Burp Suite之类的Web代理工具也都提供了扫描引擎实现自动化挖掘：

1）访问应用页面，挖掘可能存在漏洞的反射字段。通常探测的页面主要包括诊断页面、报错页面，以及可以对运行在嵌入式设备中的应用服务或者系统服务进行改动的配置页面。可以从图4-29所示的页面开始Web漏洞的挖掘。

2）在ZAP中代理转发请求图4-29中所示页面的http请求报文，同时对页面中的配置参数进行更改。读者可以观察到POST报文体中的参数，如图4-30所示。

图　4-29

图　4-30

3）审查start_apply.htm页面的源代码，可以发现其中存在部分可以动态修改的变量，通过拼接JavaScript代码就可以实现对这些动态变量的控制。这些变量是采用POST方式提交的请求报文中的参数，但是也可以采用GET方式发送请求报文。举个例子，以start_apply.htm页面中的next_page参数为例，该参数可能存在注入漏洞，代码片段如下所示：

借助XSS载荷中的fuzzing参数，我们可以采用手工注入XSS载荷并观察响应报文的方式进行漏洞挖掘，此外还可以将字典同已知XSS载荷相结合来提高漏洞挖掘速度，例如SecLists项目就提供了很多种类型的字典。

4）基于ZAP的fuzzing测试结果，我们在http响应报文中发现了很多可以用于反射攻击的参数，如图4-31所示。

图　4-31

5）可以看到其中next_page参数反射了fuzzing测试的输入值(<script>(document.head.childNodes[3].text)</script>)，在图4-32中的http响应报文的片段中可以看到这一点。

图　4-32

6）下面在浏览器中手工输入该反射参数的值<script>(document.head.childNodes[3].text)</script>，并进一步观察响应报文，如图4-33所示。

根据响应报文结果，看起来该输入影响了部分JavaScript代码的执行。这可能同载荷的编码形式或者可能的长度有关。此时，我们需要对字符编码进行调整，并审查Java-Script代码，进而确保我们的代码能够启动或者能够终止一个正在使用的功能。

图　4-33

7）漏洞挖掘过程中可以将警告代码作为XSS载荷，例如弹出一个警告框，在start_apply.html页面的源代码中，参数值形式如下所示：

8）使用ZAP的Encoder与Decoder工具对上述XSS载荷进行编码和解码，编码结果如图4-34所示。

图　4-34

9）通过Web接口将采用URL编码的值放入可能存在漏洞的参数，此时弹出警告框的代码成功执行。在研究更加复杂的XSS载荷之前，通常最好尝试运行一个只需显示数字的警告框，来判断我们的载荷是否能够正常执行，如图4-35所示。

图　4-35

10）现在我们更进一步，通过下面的载荷在警告框中显示出任意cookie值：

11）此时我们可以看到，使用基本的XSS载荷alert(document.cookie)能够在浏览器返回cookie值IoTCookbook=1234567890，执行结果如图4-36所示。

图　4-36

棒极了！现在我们已经能够运行一些基本的XSS载荷了。幸运的是，我们目前还没有遇到任何针对字符串的限制的情况，也没有遇到基于过滤的防护措施。接下来我们看一看，如果在存在漏洞的参数中插入BeEF钩取载荷，是否会导致更大的危害。毕竟，警告框能够导致什么风险呢？

1.BeEF XSS载荷用法简介

BeEF是一套在被攻击者环境中，对Web浏览器以及对客户端攻击向量开展漏洞利用的工具，工具在利用过程中主要涉及存在漏洞的应用中的参数，同时还会用到部分社会工程学技术。当被攻击者执行BeEF载荷后，BeEF会钩取一个或多个Web浏览器，而在随后的利用过程中，攻击者还可以使用一系列命令控制模块开展后渗透测试利用。下一节中，将以已挖掘出的XSS漏洞为例，尝试利用该漏洞执行BeEF钩子，同时介绍所涉及的BeEF基本用法。

BeEF功能强大，可以全面展示出XSS载荷能够造成的影响：

1）我们已经介绍了基本XSS载荷的执行方式，下面可以尝试使用一下BeEF载荷，在GET请求报文中采用与下文类似的方式进行编码：

2）发送该GET请求报文，此时浏览器返回了未正常执行的响应页面，如图4-37所示。

图　4-37

3）可以看到，输入再次影响了页面中某些JavaScipt代码的执行，导致浏览器无法执行外部位于BeEF服务端的JavaScript代码。此时，我们需要结束原先的JavaScript代码，再重新使用<script>标签请求执行外部BeEF服务端的JavaScirp代码。这时我们可以尝试在将参数包含在使用<script>标签封装的括号中，并带上引号，然后尝试下面的GET请求报文调用BeEF钩取载荷：

4）上述GET请求报文发送后，观察浏览器响应报文，会发现输出了相同的页面，JavaScript代码依旧无法正常执行；但是，如果我们查看ZAP，会发现浏览器向BeEF服务端发送了请求报文，如图4-38所示。

图　4-38

5）ZAP History标签页中的BeEF钩取请求如图4-39所示。

图　4-39

6）而此时在BeEF服务端，我们看到借助上述载荷已经成功钩取到了浏览器，如图4-40所示。

图　4-40

2.钩取被攻击者浏览器时BeEF的基本用法

当钩取到被攻击者浏览器后，接下来可以使用BeEF进行下面的操作：

1）一旦钩取到被攻击者的浏览器，BeEF可以快速枚举被攻击者计算机中的信息。

BeEF抓取得到的信息如图4-41所示。

图　4-41

2）除了主机信息，BeEF还可以在被攻击主机上应用多个漏洞利用模块，如图4-42所示。

图　4-42

3）其中，网络类别中的一个模块可以对被攻击主机的开放端口进行扫描，这些信息在后渗透测试阶段都会发挥作用，如图4-43所示。

图　4-43

通过被攻击者的浏览器代理转发流量

BeEF最吸引人的特性之一还在于能够将被攻击者的浏览器用作代理，以用户的身份发送伪造的请求报文：

1）操作起来非常简单，右键单击钩取到的用作代理的被攻击者浏览器，然后打开Rider选项卡，再选中Forge Request选项，如图4-44所示。

图　4-44

2）将想要伪造的http请求报文复制到标签页中，例如创建或更改管理员用户口令的请求，该报文会通过被攻击者的浏览器发送，如图4-45所示。

图　4-45

3）在History选项卡中可以查看之前发送的伪造请求报文，如图4-46所示。

图　4-46

4）双击伪造的请求报文，此时将打开一个新的选项卡，新选项卡的名字为该伪造请求报文的访问路径，同时会显示出对该报文的http响应报文，如图4-47所示。

在本节中，我们介绍了如何定位存在XSS漏洞的参数，考虑了编码因素，分析了JavaScript代码，讨论了基本XSS载荷的用法，并以BeEF钩取脚本为载荷对XSS漏洞进行了利用。当BeEF框架钩取到被攻击者浏览器时，分析人员还可以采用多种漏洞利用技术开展后续工作。

4.6.3　拓展学习

关于BeEF框架及其高级功能的更多介绍，可以查阅BeEF在GitHub中的Wiki主页：https://github.com/beefproject/beef/wiki。

4.6.4　延伸阅读

当不满足于基本的警告框且尝试利用XSS漏洞实现其他功能时，还有很多地方需要读者加以留意。通常，由于字符限制，需要对编码进行调整以绕过过滤器或者缩减载荷尺寸。为了绕过过滤器，最好查阅下OWASP为XSS漏洞撰写的wiki页面，链接为https://www.owasp.org/index.php/Cross-site_Scripting_(XSS)。在XSS漏洞的wiki页面中还提供了其他XSS测试指南文档的链接，其中有链接对如何绕过过滤器进行了专门介绍[1]。

图　4-47

[1] https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet。——译者注

4.7　CSRF漏洞利用

CSRF攻击能够诱使被攻击主机采用其自身身份与权限提交恶意请求，执行恶意功能。对于大多数应用而言，浏览器会自动包含所有与之相关的会话信息，例如用户的会话cookie、token、IP地址，有时还会包含Windows域中NTLM的散列值。如果被攻击用户通过了网站的认证，网站则无法区分被攻击用户发送的伪造请求报文与正常请求报文。

CSRF可以针对目标应用中能够改变服务端状态的功能发起攻击，例如更改被攻击主机的电子邮件地址、口令或者其他应用配置。如果攻击成功，只有被攻击者会收到响应，而攻击者不会接收到响应信息。而且，针对状态变更配置请求报文的CSRF攻击通常采用自动化攻击方式。鉴于保持anit-CSRF token状态所需的硬件计算复杂性，一般来说嵌入式IoT设备极易遭受CSRF攻击。有些安全防护设计模式虽然不要求获取服务端状态，但是要求应用对http协议中的referrer与origin字段进行验证，然而这些都不是有效的解决方案。

很多针对IoT设备的恶意代码已经具备了采用CSRF漏洞发起攻击的能力，家用路由器能够将被攻击设备的流量重定向到攻击者控制的DNS服务器，进而实现控制互联网流量或者发起DDoS攻击的目的。类似的恶意代码族包括SOHO Pharming（https://www.team-cymru.com/ReadingRoom/Whitepapers/2013/TeamCymruSOHOPharming.pdf）和DNSChanger（https://www.proofpoint.com/us/threat-insight/post/home-routers-under-attack-malvertising-windows-android-devices）等。在本节中，我们将会介绍如何在目标设备中开展CSRF漏洞利用。

4.7.1　准备工作

在利用CSRF漏洞的过程中，我们会用到Burp Suite工具，测试中以存在漏洞的IHOMECAM ICAM-608网络摄像头为例进行说明。

4.7.2　测试流程

开始测试后的第一步是观察请求报文中的参数以及HTML表单中的字段，通过判断这些值是否能够更改应用状态，来挖掘应用中是否存在CSRF漏洞。如果在报文中各个参数或者HTML表单中硬编码令牌发送时未发送随机令牌，那么该应用就很可能存在CSRF漏洞。这里我们主要关注两方面内容，一方面，是否能够更改敏感配置信息，这对于攻击者而言能够发挥巨大的作用，另一方面，是否能够在设备中持久驻留，例如添加用户：

1）我们首先查看目标网络摄像头的用户配置页面及其源代码，如图4-48所示。

2）用户配置页面的源代码中似乎未包含anit-CSRF token，而且也未对页面URL中随意输入的参数进行验证，如图4-49所示。

基于上述分析，我们认为该页面存在CSRF漏洞。此时我们就可以编写对CSRF漏洞进行利用的PoC（Proof of Concept）脚本了，PoC的作用是以被攻击者的身份创建3个用户。

3）首先，在Burp Suite的Proxy模块中，右键单击可能存在漏洞的http请求报文，然后选择Generate CSRF PoC，如图4-50所示。

图　4-48

图　4-49

图　4-50

4）此时，Burp Suite将会生成用作PoC的HTML页面，我们可以结合自身需求对该页面加以改造。由于我们希望实现的目的是以被攻击者的身份创建3个用户，因此下一步工作是更改管理员用户的配置信息，然后通过硬编码输入值添加两个新用户。从图4-51中可以看到，在用作PoC的HTML页面中添加了IoTCookbookUserAdmin、IoTCookbook-User1以及IoTCookbookUser23个用户。

图　4-51

5）选择Test in browser按钮，会弹出图4-52的对话框。

图　4-52

6）将该链接复制到读者的浏览器中，如图4-53所示。

图　4-53

7）在读者的浏览器中刷新该链接后，在Burp Suite中观察其代理的http历史请求，判断在PoC HTML页面中是否包含向网络摄像头添加用户硬编码，如图4-54所示。

图　4-54

8）刷新网络摄像头的用户配置页面，查看改动是否生效，如图4-55所示。

图　4-55

从图4-55中我们可以看到，同之前的截图相比，我们已经在网络摄像头添加了用户，这表示我们成功对CSRF漏洞进行了利用。

向被攻击者发送CSRF PoC页面时，也可以采用同前面提到的恶意代码相类似的方法与技术。之后会以自动化的方式创建管理员与用户账号，攻击者也就可以基于被攻击者的身份开展未经授权的操作了。

4.7.3　延伸阅读

为挖掘CSRF漏洞而进行的代码审查的指导以及CSRF挖掘与防护的更多内容，可以参看OWASP编制的关于CSRF漏洞的wiki页面：https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)。

第5章　IoT移动应用漏洞利用

本章将主要探讨以下主题：

·获取IoT移动应用。

·反编译Android应用。

·解密iOS应用。

·基于MobSF框架的静态分析。

·基于idb的iOS数据存储分析。

·Android数据存储分析。

·动态分析测试。

对于消费级以及部分商用IoT设备来说，通常都会提供与设备配套的移动应用来实现某些操作功能。例如，在车辆管理基础设施中，可以通过移动应用向服务器提交分析数据，也可以授权移动应用启动汽车引擎。在这些情况下，数据一般都会存储在移动应用当中，这就可能导致数据被攻击者利用继而执行非法操作。本书第3章中提及的方法也同样适用于针对移动应用的漏洞挖掘和逆向分析。在开始针对移动应用的分析之前，测试人员首先需要获得该应用，随后才可以着手对其进行静态分析或者动态分析，如果条件具备的话，还可以重新将应用打包。本章将重点关注移动应用中常见漏洞的利用，进而评估IoT设备移动应用的安全性。

5.1　简介

针对移动应用的安全性测试可以分为以下4个阶段：

·应用映射（application mapping）：应用映射主要涉及应用逻辑与应用的业务功能。可以将应用映射看作是针对应用的信息搜集，搜集到的信息在下一阶段中将会用到。

·客户端攻击（client-side attack）：客户端攻击主要涉及存储在应用中的数据，以及如何从客户端对应用中存储的数据进行操作。

·网络攻击（network attack）：网络攻击则主要同网络层的安全隐患有关，例如是否采用了SSL/TLS协议，是否泄露了XMPP协议数据等。

·服务端攻击（server attack）：服务端攻击指的是在API测试中暴露出的API漏洞以及后端服务器配置错误。

根据白盒测试、黑盒测试等测试角度的不同，测试方法可能还会有所变动。但无论是白盒测试还是黑盒测试，都涉及移动应用安全验证标准（Mobile Application Security Verification Standard，MASVS）。该标准旨在建立一套安全要求框架，涵盖基于iOS和Android移动应用的设计、开发和测试等各个阶段（https://www.owasp.org/images/f/fe/MASVS_v0.9.3.pdf）。此外，MASVS标准中还提出了影响Android和iOS应用安全的常见漏洞的演进趋势和模式，并据此拟制了检查清单（checklist）。在对应用进行安全性评估时，测试人员和开发人员可以依照检查清单开展安全评估（https://www.owasp.org/images/1/1b/Mobile_App_Security_Checklist_0.9.3.xlsx）。这份检查清单中还包括了OWASP移动测试指南的链接，虽然该指南还在不断补充完善，但已经较为完备，可以在现实测试中应用了。MASVS标准和检查清单指出了许多潜在的漏洞，同时也提出了漏洞缓解措施，其中具体到IoT领域，常见漏洞包括：

·硬编码的敏感信息。

·冗余的日志信息。

·会话管理漏洞。

·敏感数据缓存。

·不安全的数据存储。

·数据泄露。

·API通信。

这些常见漏洞固然同应用类型（本地应用或混合应用）有关，也有可能是采用了不安全的编码方式所导致。在本章中，我们将在Android和iOS平台下对上面提及的大多数常见漏洞展开介绍。虽然如何应用这些测试方法和检查清单已经超出了本书的范围，但是在对IoT设备开展渗透测试时，以上述内容为参考不失为一个好的思路。为简单起见，本章首先介绍移动应用的静态分析，之后介绍移动应用运行期间的动态分析。而在对IoT移动应用开展测试之前，首先需要获得该移动应用的二进制文件。

虽然本章将重点放在静态分析和动态分析上，但也会涉及运行时分析，其中包括目标应用的代码插装和断点设置。

5.2　获取IoT移动应用

对IoT设备移动应用开展安全评估的第一步是获取目标平台的移动应用并安装该应用。如果一款设备支持Android应用，那么通常来说也会支持iOS应用。Android应用可以从Google Play Store中下载，其中也会包含对应用基本信息的介绍。iOS应用则需要从苹果的App Store中下载，再安装到苹果设备。但是，对于应用的原始二进制文件而言，通常都难以获取，也无法通过Play Store或者App Store下载。在Android平台中，二进制文件或者程序包（package）一般称之为Android包或APK文件，而iOS平台中的二进制文件则称之为IPA（iOS App Store Package Archive）文件。如果读者有机会从白盒测试角度对应用开展测试，那么甲方会直接将应用的原始二进制文件交给测试人员，此时测试人员也就没有必要绞尽脑汁来获取应用的二进制文件了。而如果读者出于研究目的从黑盒测试角度开展测试，那么就要好好想想怎样才能获取到应用的二进制文件了。

测试流程

接下来，对如何获取Android和iOS应用的二进制文件进行介绍。

1）Android平台有大量的第三方应用商店提供APK的下载。然而从这些第三方应用商店下载应用时有些地方需要特别留意。这些应用商店有时提供的并非是最新版本的应用，甚至其所提供下载的实际应用版本同标识版本还可能不同。所以在安装Play Store提供的应用之前，建议用户对应用的散列值、版本以及内容进行验证。还有些第三方应用商店声称提供了用户搜索的应用，但是最后提供的却是间谍软件，目的是获取用户移动设备的某些高级别权限。但是，以第三方应用商店下载Android应用时比较吸引人的地方主要在于，能够让用户下载之前版本的应用并查阅应用的历史更新记录。如果需要下载Android应用，用户只需要选择一个第三方应用商店，例如https://apps.evozi.com或者https://apkpure.com都可以，然后搜索目标应用，接着下载其APK文件即可，如图5-1所示。

图　5-1

图5-2显示了从网站https://app.evozi.com下载Subaru这款应用的方法。

图　5-2

2）而对于iOS系统，获得开展黑盒测试所需的IPA文件就没那么简单了。同Android应用相比，iOS应用没有类似的第三方应用商店可供选择。这是因为iOS应用均采用了苹果的FairPlay DRM算法进行加密。而如果没有解密工具，分析工作将具有一定的难度。所以在后面的章节中将会提供详细的iOS应用解密攻略。如果读者只关注iOS系统应用的测试，那么可以直接跳到5.4节。

5.3　反编译Android应用

在获得了目标IoT应用的APK文件之后，就可以对其进行反编译查看文件内容了。对于Android应用而言，这个过程可能只需要几分钟就可以完成。稍后，我们将详细地介绍针对应用的自动化静态分析技术。对应用进行反编译是攻击者对应用开展逆向分析进而实现功能篡改的第一步。篡改完成后，攻击者还可以对应用进行重新编译并打包，但是这些内容已经超出了本书的范围。

5.3.1　准备工作

本节将会用到Enjarify和JD-GUI两款工具对Android应用进行反编译。Enjarify能够将Dalvik字节码转换为Java字节码，随后采用JD-GUI对Java字节码开展进一步分析。JD-GUI是一款用于分析Java代码的Java反编译器。以上两款工具均可在附带的虚拟机中找到：

·Enjarify可以从GitHub代码库中下载：https://github.com/google/enjarify。

Enjarify的运行需要安装Python3。

·JD-GUI也可以从GitHub代码库中下载：https://github.com/java-decompiler/jd-gui/releases。

5.3.2　测试流程

1）首先，进入Enjarify文件夹，以目标APK文件为参数运行Enjarify脚本。本例中，所要分析的目标APK文件和Enjarify脚本均位于同一个路径下：

2）打开JD-GUI，将Enjarify运行后生成的JAR文件拖进工作区，如图5-3所示。

图　5-3

3）经JD-GUI处理后，Java类就转换成了便于读取和理解的形式，方便了进一步的分析。以图5-4为例，由于rawQuery方法的作用是将数据保存到SQLite数据库，因此可以在代码中使用rawQuery方法，进而检测SQL注入攻击。其他搜索时经常用到的关键字还包括*keys*、execSQL以及*password*等。

4）这一方法也可以用来定位应用硬编码的敏感信息，下面我们以苹果iOS系统中的iBeacon值为例进行说明。在某次国际消费类电子产品展览会（Consumer Electronics Show，CES）展出的一款寻宝游戏中就包含了iBeacon值[1]，如图5-5所示（http://www.ibeacon.com/the-beacons-at-ces-were-hacked/）。

图　5-4

图　5-5

5）如果获得了该移动应用中的硬编码的iBeacon值，那么任何人都可以在无须亲自跑到拉斯维加斯（CES在此召开）的情况下参与该游戏了，对不对？相对于smali/baksmali代码，Java伪代码阅读起来要容易得多。但如果应用采用了某种代码混淆，或者应用使用C/C++语言进行编码，那情况就不一样了，对此需要针对具体应用展开分析。如果想了解应用的运行机制，这时就需要采用运行时或动态分析方法进行测试和验证了。

[1] iBeacon是苹果公司在2013年WWDC大会上推出的一项基于蓝牙4.0的精准微定位技术。之后很多厂商都开发出了兼容iBeacon的硬件设备，称为beacons，也就是能够向周围移动设备广播自己ID的低功耗蓝牙（BLE）设备。

5.3.3　延伸阅读

OWASP的移动安全测试指南中详细介绍了关于Android应用的逆向分析和篡改技术的细节（https://github.com/OWASP/owasp-mstg/blob/master/Document/0x05b-Basic-Security_Testing.md和https://github.com/OWASP/owasp-mstg/blob/master/Document/0x05c-Reverse-Engineering-and-Tampering.md）。

5.4　解密iOS应用

由于iOS应用均采用苹果FairPlay DRM数字版权保护技术进行了加密，通过第三方应用商店无法下载到未加密的版本，因此，为了分析iOS应用的代码，首先必须对应用进行解密从中提取出加密内容。虽然可以从iTunes直接下载到加密后的IPA文件，但是采用otool、lldb和dd等工具对应用解密却需要手工操作来实现。幸好解密过程也可以借助一款名为Clutch2的工具来实现自动化。

读者还可以借助工具Dumpdecrypted进行解密，该工具可将解密后的iOS应用转储到文件中，但本章节将不再赘述该工具的使用。读者可以自行从GitHub代码库https://github.com/stefanesser/dumpdecrypted中下载Dumpdecrypted。

5.4.1　准备工作

本节主要对otool进行介绍，otool包含在XCode自带的命令行工具中。在OS X终端中执行下列命令即可完成XCode命令行工具的安装：

工具Clutch2主要用于应用解密，可从GitHub代码库https://github.com/KJCracks/Clutch中下载得到，也可以通过越狱设备中的Cydia[1]进行安装。在Cydia中添加链接http://cydia.iphonecake.com作为源，然后搜索Clutch 2.0即可找到该工具，如图5-6所示。

[1] Cydia的主要目的是为越狱的iOS用户提供一个图形界面前端以安装不被App Store接受的程序。它也是一个软件仓库的聚合器，带有几个被社区信任的源以避免对某个服务器的过度依赖。大部分软件包的稳定版本都可以在这些源中找到；不过，用户也可以很容易地添加源。这使得iOS开发可以尽量开放，任何有服务器的人都可以设置、储存、管理和更新他自己的软件仓库并和社区分享。不过大部分的社区源是接受提交软件包的，相比起独立的源，这样也可以帮助软件获得更多关注。——译者注

5.4.2　测试流程

1）为了判断某一应用是否进行了加密，必须将IPA文件重命名为ZIP文件，并且应用的二进制文件必须位于重命名文件解压出的文件夹中。举例来说，对应用二进制文件运行以下命令即能检测出该应用是否进行了加密，这里需要注意的是操作对象并非IPA文件。在运行结果中，如果cryptid的值为1，那么就意味着该应用已加密。

图　5-6

根据命令执行结果可以确定该应用进行了加密。如何对其进行手工解密超出了本书的讲解范畴，这里我们采用Clutch2进行自动解密。运行Clutch2时如果不带任何参数，那么会列出所有已安装的应用：

2）接着，使用参数-d和想要解密的应用对应的编号就可以对目标应用进行解密与转储。在本例中，要进行解密转储的应用编号为1：

3）此时，应用即解密完成。接下来可以使用scp命令将解密后的应用从苹果设备传输到分析主机上来，命令如下所示：

4）在分析主机中，将解密后的IPA文件重新命名为ZIP文件，然后将ZIP文件解压，步骤与之前验证加密应用的步骤类似：

5）进入Payload/STARLINK.app目录，在该目录下即存放着应用的二进制文件：

6）为了开展进一步分析，可以使用Hopper等工具对应用的二进制文件进行反汇编。分析人员采用class-dump命令转储应用中的类信息，并采用反汇编器开展进一步分析。例如，如果要分析应用在saveCredentialsToKeychain类中如何存储认证信息，那么就可以使用Hopper反汇编得到其反汇编代码，如图5-7所示。

图　5-7

有了对应用中类和方法的了解，就可以通过动态或运行时分析对应用的功能进行篡改与测试。本章稍后将介绍动态测试的方法。

5.4.3　延伸阅读

OWASP的移动安全测试指南提供了关于解密iOS应用的更多细节（https://github.com/OWASP/owasp-mstg/blob/master/Document/0x06b-Basic-Security-Testing.md）。

5.5　基于MobSF框架的静态分析

在获得了Android平台和iOS平台下应用的二进制文件后，我们可以采用自动化方法对其开展进一步的分析。此时会用到移动安全测试框架（MobSF），MobSF是一款可以用于分析Android和iOS应用的开源工具，该工具采用Python语言开发。MobSF提供了很多自动化分析功能，尤其适用于Android应用。接下来本节将介绍如何采用MobSF对Android和iOS应用进行自动化静态分析。静态分析往往会用到应用的源代码，虽然源代码通常难以获取，但是通过反编译Android和iOS应用，我们可以得到接近于原始源代码的伪代码。

5.5.1　准备工作

在附带的虚拟机中可以找到MobSF，版本为0.9.5.2 beta。由于MobSF会持续进行更新，所以也可以通过链接https://github.com/MobSF/Mobile-Security-Framework-MobSF下载最新版本。同时还需要安装在MobSF文档中列出的依赖库。

在开始分析之前，请读者确保已经获得了目标应用的APK文件和已解密的iOS IPA文件。MobSF不会自动对iOS应用进行解密。在分析时，MobSF要求其分析对象须是已经解密完成的IPA文件，而不是将已解密IPA文件重命名ZIP文件后，再进行解压后在Payload文件夹中生成的解密二进制文件，因为MobSF会自动完成对已解密IPA文件的重命名与解压操作（由于MobSF是一款开源工具，所以也可以将其修改为直接使用原始二进制文件而不是IPA文件）。在iOS设备中，Clutch2使用参数-d时即可以转储IPA文件。

5.5.2　测试流程

（1）在终端运行以下命令启动MobSF：

（2）此时浏览器会出现MobSF的Web界面，地址为127.0.0.1：8000，如图5-8所示。

图　5-8

1.Android静态分析

1）我们首先展开对Android应用的分析。将目标应用的APK文件拖到MobSF的Web界面中，此时MobSF会自动对应用反编译并分析其中内容。界面中列出了Android的核心组件（ACTIVITIES、SERVICES、RECEIVERS和PROVIDERS）以及相关的元数据，如图5-9所示。

图　5-9

MobSF具有较高的灵活性，可使用不同的Java反编译器和Dex2JAR转换工具。如果想修改这些设置，可以找到MobSF/settings.py文件进行修改。

2）当读者向下滚动页面时，MobSF会显示所分析应用的权限、Android API的用法、browsable Activitie（浏览器在特定条件下可以打开的Activity），以及很多其他有用的静态分析特性。本书重点关注的、可能也是最有用的内容是代码分析（Code Analysis）部分。如图5-10所示，MobSF已经将不安全的编码实践和存在潜在漏洞的代码片段标记了出来。

3）其中一个使用和查找起来最方便的项是Files may contain hardcoded sensitive infor-mation like usernames，passwords，keys etc，即可能包含有硬编码敏感信息（如用户名、口令、密钥等）的文件。图5-11是MobSF的一个标记示例，MobSF标记出了应用中可能包含硬编码数据的Java类。

4）在移动应用中，常常会找到硬编码的OAuth属性值client_secret和云服务提供商API账户的认证信息。前文中也有一个类似的例子，即CES应用中的硬编码iBeacon。当选中在MobSF中标记的一个Java类时，就会显示出与之对应的Java伪代码，其中包含了硬编码的字段值，如图5-12所示。

图　5-10

图　5-11

2016年三星公司曾因此而蒙受过损失，在其移动应用SmartThings中，client_secret字段的值采用了硬编码形式，从而导致攻击者能够获取令牌继而打开智能门锁。相关事件的细节可在链接https://web.eecs.umich.edu/~earlence/assets/papers/smartthings_sp16.pdf中找到。

图　5-12

5）有了MobSF框架，对Android应用的测试就变得轻松多了。而对于iOS应用的静态分析而言，则不像基于MobSF的Android应用静态分析那样有迹可循。

2.iOS静态分析

1）MobSF框架也能够为iOS应用的静态分析提供很多实用的功能。和Android一样，首先需将解密的iOS IPA文件拖动到MobSF框架的Web界面。MobSF随后会将IPA文件重命名为ZIP文件、提取文件内容、分析plist文件、检查应用请求的权限、转储应用中的类信息，并执行一些其他操作。图5-13展示的是将解密后的iOS IPA文件拖动到MobSF的Web界面后显示的处理页面。MobSF提供了三个主要选项，分别包括查看Info.plist、查看字符串及查看类转储信息。

用户需要确保在MobSF的配置文件中调整了class-dump-z工具的路径，通过位于MobSF/settings.py中的CLASSDUMPZ_BINARY变量可以对该工具的路径加以设置。在本例中，class-dump-z工具的路径为/opt/iOSOpenDev/bin/class-dump-z，但是使用常规的class-dump工具也是可以的，其路径为/opt/iOSOpenDev/bin/class-dump。

图　5-13

2）首先需要查看的是Info.plist文件。Info.plist文件中包含了同应用有关的基本信息，如权限、IPC URL scheme以及应用传输安全配置等，MobSF会提取出这些基本信息并显示在界面上。图5-14展示的即为MobSF提取出的Info.plist文件。

3）接着，选择View Strings按钮，将会显示出在该二进制文件中的字符串，如图5-15所示。

4）这时，我们注意到其中有一个字符串CONSUMERSECRET，在Android版本的应用中该字符串也出现过。通常来讲，如果一个版本的应用里包含硬编码值，那么在另外的版本中很可能也是如此。通过查看MobSF转储的类信息，很快就可以确认这一点。单击View Class Dump按钮就可以查看应用中类的有关信息。如果读者已经正确地对类转储进行了设置，则会打开一个单独的选项卡并显示出类的编码，如图5-16所示。

5）获得了类的详细信息之后，我们就可以定位到应用中的具体功能并开始深入分析了。例如，我们可以搜索包含口令字符串的类，然后使用Hopper等反汇编器对该类进行分析。图5-17中显示，应用中与之相关的类为addBasicAuthenticationHeaderWithUsername：

6）然后，使用反汇编器Hopper对类addBasicAuthenticationHeaderWithUsername开展进一步的分析，该类的伪代码如图5-18所示。只需在string选项卡中搜索类addBasic-AuthenticationHeaderWithUsername就可以查看该类中的内容。

图　5-14

图　5-15

图　5-16

7）由于我们当前采用的是Hopper反汇编器，并且在前面的步骤中已经定位出了字符串CONSUMERSECRET的位置，那么现在可以尝试在iOS应用中搜索该字符串，判断其在iOS应用中是否也采用了硬编码。下图所展示的是在iOS应用中的硬编码值，可以看到该值同Android应用中的硬编码值相同。其中一个硬编码的敏感信息以c4d5结尾，在截图中以高亮显示，如图5-19所示。

8）在应用中定位出这些硬编码值后，下一步通常是通过动态分析验证硬编码值可能导致的后果。动态分析测试将在本章后面进行介绍。

图　5-17

图5-18　在string选项卡中查看类中的内容

图5-19　硬编码secret值

5.5.3　拓展学习

本节介绍了Android和iOS应用的静态分析。由于运行时分析测试需要在应用运行时hook到应用的类和方法，因此运行时分析测试在本节并未涉及。同时，读者根据自身能够在移动应用安全测试中投入的时间和精力，也可以选择是否将这部分内容纳入测试范围之中。但是，对于绕过PIN码锁屏或暴力登录等客户端安全控制措施的测试而言，非常适合采用运行时分析进行验证。OWASP测试指南对Android和iOS应用的运行时分析技术进行了详细介绍，更多内容可以参考以下链接：

·Android：https://github.com/OWASP/owasp-mstg/blob/master/Document/0x05c-Reverse-Engineering-and-Tampering.md。

·iOS：https://github.com/OWASP/owasp-mstg/blob/master/Document/0x06c-Reverse-Engineering-and-Tampering.md。

5.6　基于idb的iOS数据存储分析

遗憾的是，iOS开发者往往会忽略苹果设备所提供的针对数据存储API的控制措施。而其结果就是导致数据泄露，数据泄露的位置包括明文数据库（含realm数据库）、plist文件（属性列表）、缓存、键盘以及其他存储位置。有时，出于性能方面的考虑，应用所采用的混合框架往往也会鼓励用户忽略对数据存储API的控制措施，但是却没有考虑这种行为可能导致的安全后果。对于混合框架和某些定制模块而言，可能还需要插件来清空缓存等位置存储的数据，这就增加了开发人员的工作复杂性。在本节中，我们将重点分析IoT iOS应用的数据存储。

5.6.1　准备工作

在开始本节的分析之前，首先需要准备好一台越狱的苹果设备及工具idb。idb是一款可以在OS X以及Ubuntu系统中运行的免费工具，用于简化常见的iOS应用安全评估工作。在配套的虚拟机中已经安装了idb，当然读者也可以访问idb主页http://www.idbtool.com/手动安装该工具。如果读者使用gem来管理Ruby组件，还可以通过执行gem install idb命令来实现idb的安装。

在撰写本书时，idb已不再提供对iOS 10应用的支持。

如要需要查看SQLite数据库条目，可以通过链接http://sqlitebrowser.org下载并安装sqlitebrowser。在本书提供的虚拟机中，已经安装了sqlitebrowser。

5.6.2　测试流程

1）在终端启动idb，只需执行idb命令就会出现用户界面，如图5-20所示。

图　5-20

2）接着，选择Connect to USB/SSH device，如图5-21所示。

图　5-21

3）如果读者是第一次使用idb，那么在越狱设备上还需要再安装几个软件包。如果idb通过USB或SSH协议访问设备，那么idb会自动安装这些软件包。所需的软件包如图5-22所示。

苹果设备越狱后的默认用户和口令是alpine。

图　5-22

4）所有软件包安装完成后，在App Selection菜单中选择一款应用，本例选取的是com.skybell.doorbell应用，如图5-23所示。

图　5-23

5）选中SkyBell应用之后，接下来我们将重点关注应用的内容以及数据的存储方式。MobSF中的很多功能都可以用来实现对iOS应用的自动化安全评估，但本节中我们主要使用针对数据存储的分析功能。首先选择Storage选项卡，再选择plists选项卡，最后单击Refresh按钮，就可以开始对应用数据存储的分析了，如图5-24所示。

图　5-24

6）此时界面中会出现很多文件，但大多数文件同本次测试都是无关的。分析过程中，首先需要分析的是bundle目录中的Info.plist文件，以及应用在运行时创建的所有preference文件。本例中的preference文件为com.skybell.doorbell.plist。在明文plist文件中，我们想要寻找的是同组织或用户相关的个人信息或敏感数据。双击打开preference文件，会发现OAuth中的access_tokens令牌和refresh_tokens令牌在存储时未采取任何保护措施（CVE-2017-6082）。下图显示了这些令牌以明文形式进行存储。通常来说，应用中会持久保存access_token令牌以改善用户体验，这样用户每次打开应用时就无须都进行一遍登录操作了，如图5-25所示。

7）当会话令牌以明文形式存放时，那么在很多区域存储的数据可能都不安全。如果要查找存储在磁盘上的敏感数据，通常是查看应用中所有类型的数据库，以及应用启动时在data目录下生成的文件。而idb则能够对所有这些区域进行分析。接下来我们查看Cache.dbs选项卡，看看会有什么发现。

前往Cache.db选项卡，选择Refresh按钮，双击进入Cache.db条目，如图5-26所示。

图　5-25

图　5-26

8）如图5-27所示，可以看到在SQLite数据库中包含了很多张表。

图　5-27

9）这些表中包含了BLOB类型的数据，可以以文本格式查看这些数据。从运行结果中可以看出，应用对所有请求和响应报文均进行了缓存，其中就包括了个人信息和令牌数据（CVE-2017-6084），如图5-28所示。

通过在idb设置（例如~/.idb/settings.yml）中指定编辑器路径，可以使用自定义的SQLite编辑器。

图　5-28

攻击者可以采取两种方法窃取上面提到的数据。一种是在目标用户手机开启自动备份功能的情况下，将其连接到iTunes。此时，攻击者只需要插入一台测试用苹果设备，然后将目标用户手机的备份恢复到测试用苹果设备即可。另一种方法就是使用iFunbox（http://www.i-funbox.com/）[1]等工具，获取对未越狱设备文件系统的访问授权。借助iFunbox，攻击者可以将应用的Cache.db、plist和SQLite数据库传输到设备外部，从而获得会话令牌和其他个人账户信息的访问权限。在这种情况下，通过调整摄像头运动设置或者将视频共享到外部账户，攻击者就可以查看可视门铃中的视频并更改其配置了。

了解了上述方法后，攻击者就可以在无须对连接进行代理转发的情况下查看会话管理控制措施和API数据。同时，还可以依据前面提到的移动应用安全检查清单开展会话超时和随机数、随机令牌测试。此外，攻击者还可以篡改plist文件或Cache.db中的数据并上传回设备，进而观察应用同这些文件之间的信任关系。

[1] iFunbox是iPhone以及苹果其他产品的通用文件管理软件。以类似Windows资源管理器的窗口方式浏览和管理iPhone、iPad、iPod touch上的文件和目录，使苹果各类设备得以共享彼此的资源，让用户可以轻松上传电影、音乐、电子书、桌面、照片以及应用程序。——译者注

5.6.3　拓展学习

本节中未曾提及但仍需进一步分析的其他数据存储位置还包括，密钥链、本地存储、realm数据库、日志、BinaryCookie等。在OWASP的移动安全测试指南中，对iOS应用中的数据存储漏洞测试技术进行了详细介绍，链接如下：https://github.com/OWASP/owasp-mstg/blob/master/Document/0x06d-Testing-Data-Storage.md。

5.6.4　延伸阅读

如果想了解更多idb的功能，可以查阅http://www.idbtool.com/documentation/中提供的文档。

5.7　Android数据存储分析

针对Android的数据存储开展运行时测试可以采用多种方法。而且，无论是免费的还是商业版工具都可以自动浏览常见数据存储位置，并且还可以调整浏览时的数据存储位置。在手工分析中，我们主要对以下应用运行时常见的存储位置予以重点关注：

·/data/data/<package_name>/

·/data/data/<package_name>/databases

·/data/data/<package_name>/shared_prefs

·/data/data<package_name>/files/<dbfilename>.realm

■需要Realm数据库管理工具（Realm Browser）（https://itunes.apple.com/us/app/realm-browser/id100745727?）

·/data/data/<package name>/app_webview/

■Cookies

■本地存储

■Web数据

·/sdcard/Android/data/<package_name>

对于Android应用来说，应用中的文件结构不会发生变化，这一点使得手工分析的难度得以降低。本节中，就来探讨如何对IoT Android应用中的数据存储开展分析。

5.7.1　准备工作

本节的准备工作如下：

·已获得root权限的Android设备（启用USB调试模式）或已获得root权限的Android仿真器。

·Android debug bridge（ADB）：可以在配套的虚拟机中找到ADB，也可以通过URL链接https://developer.android.com/studio/releases/platform-tools.html手工安装。

5.7.2　测试流程

1）输入下列命令，确保分析主机已同Android测试设备或仿真器建立了连接：

2）连接Android测试设备的Console口，并使用以下adb命令切换到root用户模式：

3）进入目标应用目录，如下所示：

4）首先，分析shared_prefs目录，枚举出所有文件，并查看preferences文件，如图5-29所示。

图　5-29

从显示结果中可以看到，文件中似乎包含了一串特别的编码字符串。我们知道应用运行时需要用到同登录时认证信息有关的字符串，而该字符串正是电子邮件账户的用户名。

5）接下来，我们分析文件com.skybell.app.networking.oauth.oauth_shared_preferences_key.xml，如图5-30所示。

图　5-30

6）看起来账户的OAuth令牌似乎以明文形式进行存储，这一点同在iOS应用中看到的情况相类似。应用中存在一个files目录，其中可能包含有Realm数据库文件。下面，切换到file目录并枚举出目录下的所有文件，如图5-31所示。

图　5-31

7）从枚举出的文件名可以看出，应用采用了Realm数据库。注意Realm数据库所在的路径，使用以下adb命令将文件传输至分析主机中：

在本书撰写时，在OS X系统中只能使用Realm Browser查看Realm数据库，其中Realm Browser可以从APP Store中下载。Android和iOS平台下还可以使用非官方的Realm Browser，但需要用户从源代码开始编译。有关Realm数据库的更多细节可以访问链接http://news.realm.io/news/realm-browser-tutorial/。

8）双击default.realm文件，在Realm Browser中打开Realm数据库，如图5-32所示。

图　5-32

无论设备是否在线，DeviceRecord模型都会报告可视门铃的名称和状态，而Device-RecordActivity模型则会列出事件、与事件相关的时间戳和缩略图。这其实就是一种数据泄露，有两种方法可以对这种形式的数据泄露加以利用。一种方法是将Android设备中的数据备份到主机上再进行恢复，就像之前在iPhone设备上的操作一样，另一种方法是如果存在ADB工具的话，可以采用与前面同样的方式通过ADB获取数据。糟糕的是，应用并没有在AndroidManifest.xml文件中设置标记[android：allowBackup=false]，不然就可以缓解上述安全威胁，但是以这种方式存储数据始终是一种非常糟糕的做法，可能给用户带来隐私泄露的风险。

5.7.3　延伸阅读

更多Android应用数据存储漏洞测试的技术细节，可以查看OWASP移动安全测试指南：https://github.com/OWASP/owasp-mstg/blob/master/Document/0x05d-Testing-Data-Storage.md。

5.8　动态分析测试

到目前为止，本书已经对示例IoT移动应用中的数据存储方式进行了静态分析，并对其安全性进行了评估。但是我们还未分析应用和服务器之间的API流量。在应用运行时查看和篡改其通信报文的过程称之为动态分析。动态分析测试主要关注应用执行时的评估，既可以在移动平台层上进行分析，也可以针对移动应用的后端服务和API进行分析，而在针对后端服务和API的分析中，主要是对请求和响应报文进行分析。本节将通过部分测试用例介绍如何部署iOS的动态分析测试环境。

5.8.1　准备工作

本节中将采用Burp Suite和OWASP ZAP来对应用的通信流量进行分析。在开展测试时，首先需要获得苹果设备和安卓设备的访问权限。分析应用通信过程相对来说比较方便的一点是，苹果设备和安卓设备无须越狱或root。本节主要以iOS应用为例进行介绍，但以下步骤对于iOS和Android平台都是适用的。

5.8.2　测试流程

1）就像配置Web应用测试环境一样，为了代理转发httpS的请求报文，在越狱设备中也需要安装ZAP和Burp Suite的CA证书。代理设置可以通过更改移动设备的Wi-Fi代理配置，使其指向Burp Suite监听器的IP和端口来完成。设置内容如图5-33所示。

图5-34展示的是为苹果设备设置代理，使其指向Burp Suite代理监听器的操作。本例中，Burp Suite代理正在监听IP地址192.168.2.183的8080端口。

2）接下来，以Burp Suite的IP地址、端口以及/cert作为URL路径，访问该URL将Burp CA证书添加到设备。在本例中，Burp Suite证书的地址为http://192.168.2.183:8080/cert，如图5-35所示。

图　5-33

图　5-34

图　5-35

3）执行完成后，iOS会询问用户是否想为Burp Suite的CA证书安装一个profile配置文件，如图5-36所示。单击Install按钮，此时就可以采用Burp Suite来分析基于httpS协议的流量了。

图5-37显示了经过Burp Suite代理转发的所有从移动设备发出的httpS请求报文。

4）Android设备也可以采取类似的设置步骤。下面我们演示一下如何设置ZAP的CA证书。首先，逐级选择Tools|Options|Dynamic SSL Certificates选项导出ZAP的CA证书。接着，选择路径保存该证书，随后将其传输到Android设备中，如图5-38所示。

5）将ZAP的CA证书传输到Android设备中的方法有很多，其中一个又快又实用的方法就是采用Python的SimplehttpServer模块来搭建服务器进行文件传输。如果使用的是基于*Nix的系统，那么可以在证书所在的目录下运行以下命令：

图　5-36

图5-37　经过Burp Suite代理的httpS请求

图　5-38

6）执行上述命令后，会在1111端口上运行Web服务器。此时，在Android设备上打开一个浏览器，访问该Web服务器即可看到打算下载的CA证书。在本例中，地址为http://192.168.2.186:1111，在浏览器中输入该URL后，页面如图5-39所示。

图　5-39

7）接着，就可以将证书下载到Android设备了。此时，在Android设备中，访问存储设备中的Settings|Security|Install目录，会看到Download文件夹，而Download文件夹中包含了ZAP的CA证书，如图5-40所示。

图　5-40

8）选择ZAP的CA证书，并将其重命名，如图5-41所示。

9）进入Wireless配置界面，将代理配置修改为ZAP代理监听器的地址，如图5-42所示。

10）进入目标IoT移动应用并执行操作，此时就可以在ZAP的History选项卡下看到基于httpS协议的请求和响应报文了，如图5-43所示。

11）无论是Android设备还是苹果设备都可以对其进行设置，使其代理转发应用的请求报文和响应报文。获取到请求报文和响应报文后，可以对参数进行fuzzing测试以验证注入漏洞（前提是获得开展渗透测试的授权），也可以挖掘其中的业务逻辑漏洞。举例来说，在查看目标可视门铃中存储的视频时，通过代理转发其请求和响应报文，发现MP4视频文件的GET请求报文中包含了一个URL参数access_token（CVE-2017-6085）。如果将该GET请求报文复制到剪贴板再粘贴到浏览器中后，就可以在无须用户名或口令的情况下下载MP4视频，其中access_token的值如图5-44所示。

图　5-41

图　5-42

图　5-43

图　5-44

12）然后，将该请求报文复制到剪贴板，如图5-45所示。

图　5-45

13）将复制的URL粘贴到浏览器中，即可观察到可视门铃在本地主机中的自动下载操作，如图5-46所示。

图　5-46

在浏览器中将复制的URL作为请求报文发送后，浏览器会自动询问在本地主机中保存下载视频的位置，如图5-47所示。

图　5-47

视频以.mp4格式下载，用户可以采用图5-48所示方式查看。

图　5-48

14）需要注意的是，我们无须输入任何用户名或口令，就可以下载和观看视频。这表明，可视门铃存在用户访问控制安全问题，同时也说明该产品可能还存在其他漏洞。对于可视门铃来说，没有证书就能访问视频，无论从安全还是隐私的角度来说都存在风险。仅仅上面的案例中就发现了多个漏洞，这些漏洞包括了在GET请求报文中包含会话令牌、无令牌过期期限和访问控制措施不完善等问题。基于上述漏洞，攻击者可以通过社会工程学或MITM技术获得所需的access_token。作为后续拓展，测试人员还可以采用用户账户开展其他针对访问控制安全措施的测试。

5.8.3　延伸阅读

·对于部分Android应用而言，MobSF在仿真器、虚拟机甚至物理设备中均可以对应用开展动态测试。Android应用的动态测试还包括针对intent和activity的测试。在MobSF的wiki百科中列出了部分需要注意的事项：https://github.com/MobSF/Mobile-Security-Framework-MobSF/wiki/2.-Configure-MobSF-Dynamic-Analysis-Environment-in-your-Android-Device-or-VM。

如果正在测试的应用需要访问硬件，例如摄像头或其他采用无线协议（即蓝牙、ZigBee或Z-Wave）的设备，那么建议读者拿到物理设备后再开展手工测试。

·了解更多Android和iOS应用安全测试的相关内容，可查阅OWASP的移动安全测试指南，链接为https://github.com/OWASP/owasp-mstg/。

第6章　IoT设备攻击技术

本章将主要讨论以下主题：

·硬件漏洞利用与软件漏洞利用。

·硬件攻击方法。

·硬件分析技术。

·电子技术基础。

·总线与接口识别。

·嵌入式设备的串行接口。

·NAND噪声干扰。

·JTAG接口的调试与漏洞利用。

6.1　简介

任何IoT解决方案的关键核心组件都是嵌入式设备。同物理环境进行交互的是嵌入式设备，同Web终端及其周边设备进行通信的也是嵌入式设备。因此，如何对这些硬件设备开展漏洞利用对于IoT设备的渗透测试而言至关重要。

各IoT解决方案使用的设备类型各不相同。在某些方案中，硬件设备可以是网关，借助网关，不同的设备可以进行交互，也可以同Web服务端点进行通信，在另一些方案中，硬件设备可以是医疗设备，其功能可能仅仅是收集患者病情数据，并在智能手机上加以展示。

但是，这些方案中可能都存在着某些特定的安全隐患，这些安全隐患对任何一款设备都可能造成影响，而无论这款设备属于哪种类型。这正是本章所关注的重点，即抛开设备类型，对IoT设备中可能存在的各种安全隐患展开深入分析，并介绍如何发现设备中存在的安全隐患，如何对其加以利用。但是，在开始学习硬件漏洞利用之前，首先需要了解一下硬件漏洞利用同传统的软件漏洞利用存在哪些区别。

6.2　硬件漏洞利用与软件漏洞利用

硬件漏洞利用同软件漏洞利用之间的区别非常之大，其中硬件漏洞的挖掘与利用同其他漏洞利用之间最重要的区别在于，读者需要拥有一套物理设备。这意味着除非读者拥有两套或者更多套的物理设备，否则对IoT设备开展渗透测试的过程会相当复杂。

导致硬件安全分析复杂度较高的另一个因素在于，围绕硬件安全从公开渠道可以获取到的资源数量是有限的。与之形成对比的是，在对软件进行安全评估时，无论是在软件当前所使用的某个组件中发现的已知漏洞，还是已研究的同类型软件中的通用漏洞，测试人员都可以拿来开展软件的测试评估。然而，同软件漏洞利用的对比并不意味着硬件漏洞利用的难度更大，而仅仅意味着读者在着手开展硬件漏洞利用时，由于对硬件组件缺乏深度了解，不熟悉其中隐藏的安全隐患，因此同之前针对软件开展漏洞利用的经历相比，对硬件开展漏洞利用的复杂度比较高。

还需要注意的一点是，基于硬件的漏洞修复起来更加困难，甚至在某些情况下，如果不对终端用户的设备进行完全替换，那么硬件漏洞的修复就是一项不可能的任务。这意味着如果某套硬件设备公开发行之后才发现自身存在着严重的安全隐患，那么厂商唯一所能采取的补救措施就是召回设备，然后使用安全性更高的设备替换原有设备。

最后，对渗透测试人员而言最显著的区别在于，在硬件漏洞利用过程中，为了有效地对终端设备的安全性进行评估并开展漏洞利用，需要用到诸多硬件工具与设备。

但是，读者也无须畏葸不前，认为硬件漏洞利用好难。在本章中，我们围绕硬件漏洞利用将会介绍一系列工具和技术，这些知识能够帮助读者完成硬件攻击的快速入门。

6.3　硬件攻击方法

硬件攻击方法主要涉及以下步骤：

·信息搜集与分析。

·设备的外部分析与内部分析。

·通信接口识别。

·采用硬件通信技术获取数据。

·基于硬件漏洞利用方法的软件漏洞利用。

·后门植入（可选）。

下面将逐一对上述内容进行介绍与深入分析。

6.3.1　信息搜集与分析

嵌入式设备攻击的第一步是针对我们所关注的目标设备搜集尽可能多的信息。这句话说起来很简单，但是对于嵌入式设备而言，现实情况可能比我们想象的要复杂一些。因为如果要获取关于设备的大量信息，首先需要拿到物理设备，所以在尚未拿到物理设备的情况下，渗透测试人员所能获取的关于目标设备的信息通常是较为有限的。

但是在拿到物理设备之前，对于某一特定目标设备而言，渗透测试人员仍然可以通过一系列方法获取关于目标设备的信息。此时的信息来源既包括可以公开查阅到的信息，也包括从客户手里或者其他渠道获取的文档。

本阶段可能涉及的信息主要包括：

·嵌入式设备基于哪种架构？

·该设备运行于何种操作系统上？

·设备支持哪些外设？

·设备采用了哪种芯片组？

·设备所采用的存储与内存的实现方面的细节。

·关于设备的其他相关技术信息。

一旦获取这些信息，就可以开始进行下一个步骤，也就是分别从内部和外部对设备开展分析。

6.3.2　设备的外部分析与内部分析

读者从上一步骤中获取设备信息后，下一步就是针对设备自身开展分析工作。这一步的目的在于从攻击者的视角来观察设备，并从外部和内部进行观察，获取尽可能多的信息。

外部分析比较简单，只需要查看设备的外观，搞清楚观察到的每个组件的作用。在这里，读者可以思考以下问题：

·设备都有哪些不同的接口，是否提供了USB接口、SD卡槽或者以太网口？

·设备如何供电，是通过电池、PoE供电还是电源适配器供电？

·设备上是否有标签？如果有的话，标签中都包含哪些信息？

完成外部分析后，下一步就是对设备进行内部分析。这就需要打开设备外壳，然后观察设备的印制电路板（PCB）了。在这一步骤中，我们需要识别出设备所采用的各种芯片组，继而在芯片数据手册中查找对应的芯片组，了解每个组件的功能，同时将芯片数据手册中找到的各种信息做好记录。

在这一阶段，我喜欢将设备中不同组件之间的各种连通关系绘制成基本框图，这样有助于对整套设备的内部结构形成更为清晰的认识。

6.3.3　通信接口识别

查看PCB并分析出足够多的关于电路整体结构以及各个组件的信息之后，下一步就是查找出能够同设备进行交互的所有接口。

有些情况下，通信接口显而易见，读者可以轻松识别，但是另外一些情况下，通信接口可能会分布在整块PCB的不同位置，所以识别起来可能要困难一些，还有些情况下，读者可能需要直接连接到芯片组的引脚排针才能识别出接口类型。

6.3.4　采用硬件通信技术获取数据

识别出设备采用的通信协议与接口之后，我们就可以借助专用工具通过特定协议与目标设备进行通信，并且与目标设备进行交互或者读/写特定芯片的信息了。

对接口进行了细致的分析后，有多种方法可以用来同设备建立连接进而获取渗透测试所需要的数据。测试过程中最常用到的接口包括UART、JTAG、SPI、I2C以及1-Wire等。

6.3.5　基于硬件漏洞利用方法的软件漏洞利用

如果我们能够通过特定硬件接口访问目标设备，下一步就是通过对硬件的漏洞利用实现软件漏洞利用，这其中主要牵涉固件转储、向特定内存区域写入内容、篡改运行进程等工作。

根据前面的介绍，读者现在应该已经了解到了，大多数基于硬件技术的漏洞利用都可能使攻击者获得敏感资源的访问权限，而攻击者可以采用多种方式对这些资源加以利用。

到目前为止，我们已经了解了硬件渗透测试方法的脉络，下面对硬件设备的分析进行更加深入的介绍。

6.4　硬件分析技术

除了观察硬件的外观，分析过程还包括两个步骤，分别是打开设备外壳查看内部的各种芯片，以及从芯片数据手册中查找芯片有关信息，下面逐个展开介绍。

6.4.1　打开设备

硬件分析过程中的第一步是打开设备。根据设备的不同，这一过程的复杂性跨度相当大。

在某些设备中，读者可能发现螺丝隐藏在设备支架的橡胶垫下，而在其他设备中，螺丝可能直接暴露在设备外部，还有些情况，设备的各个组成部分可能直接焊在了一起。

根据设备的组装方式，需要选取合适的拆解工具。建议读者在开展硬件漏洞利用时准备一套多功能工具箱，因为不同的设备可能会用到各种型号的螺丝，这时工具箱中的螺丝批头就能派上用场了。

6.4.2　芯片分析

读者打开设备外壳之后，下一步就是查看PCB并识别出板上所有的芯片。查看芯片标签时，可以将芯片稍微倾斜一下，然后使用USB电子显微镜或者智能手机的闪光灯查看标签上的信息。这里建议测试人员在查看芯片上的信息时可以安装一个支架，以保证在读取芯片信息时设备稳定。

如果读者识别出了芯片型号，可以在Google搜索引擎中输入该芯片的制造商，之后再加上芯片型号以及“datasheet”（芯片数据手册），尝试搜索该型号芯片的数据手册。这也是在本章后半部分所要做的事情。

获得芯片数据手册之后，读者就可以使用手册中的信息识别出目标芯片的所有特性了，其中也包括引脚定义，这些信息早已被证明在硬件漏洞利用过程中能够发挥相当大的作用。

现在我们已经知道了如何针对目标设备开展信息搜集，那么此时就可以深入开展硬件的漏洞利用了。但是，为了确保对目标具有足够的了解，进而确保硬件攻击的成功开展，我们还需要具备一定的电子技术基础，这些内容对于深入了解硬件漏洞利用技术大有帮助。

6.5　电子技术基础

正如前文所提到的，读者如果想要学习硬件攻击技术，那么电子技术则是必须要了解的重要基础知识之一。虽然在即便不具备电子技术相关基础的情况下，读者也可能发现硬件设备中部分简单的漏洞。但是，为了熟练掌握硬件设备的漏洞挖掘技术，读者就需要了解设备所执行的操作，以及如何才能对一个特定组件进行漏洞利用。在本节中，我们将会对电子技术的基本概念进行介绍，当读者开始深入学习嵌入式设备时，这些内容能够帮助读者增强信心，同时更好地理解相关内容。

本节内容对于部分读者而言可能都是基本知识。但是，也可以将这部分内容看作电子技术基础的参考手册，当读者开始学习嵌入式设备时，可以随时翻阅本节内容。

6.5.1　电阻

电阻是一种阻挡电流流动的电子元件，或者从更深的层次上来说其功能是阻拦电子的流动。电阻通常用字符R表示，是一种被动元件[1]，这也就意味着电阻自身不会产生任何电能，而是以发热的方式消耗能量，进而降低电压与电流。

电阻的计量单位是欧姆（Ω），制作材料通常是碳或者金属丝。读者可能会发现电阻上一般带有彩色的标识条码，这里彩色条码的作用就是表示电阻所能提供的电阻值。

电阻的外形如图6-1所示。

图　6-1

现在读者已经了解了电阻的作用，但是还需要注意电阻有两种不同类型，即固定电阻与可变电阻。顾名思义，固定电阻的电阻值是固定的，不可更改，而可变电阻，可使用特定技术更改电阻值。可变电阻最常见的实例就是电位计（potentiometer）。

[1] 被动元件（passive component）是中国台湾电子行业对某些电子元器件的叫法，区别于主动元件（active component）。在中国大陆则称为无源器件和有源器件，目前一般也沿用被动元件（电容、电阻、电感），以及主动元件（集成电路）的叫法。——译者注

6.5.2　电压

电子技术中的电压是两个不同计量点之间的势能差。在大多数情况下，测量特定位置电压的参考点通常选择地（Frou ND，GND），或者是电池、供电设备的负极。现实生活中，如果读者使用9V的电池，那么这意味着电池正负极两点之间的势能差值为9V。

从更深层次来说，在铜线等导体的两端，一端会汇聚大量的电子（负电荷），而在另一端则会汇聚大量质子（正电荷）。这就意味着在两点之间存在势差并最终会形成电流。

我们使用电压表（voltmeter）测量电压，即电压表所相连两点之间的势差。例如，9V电池的正极电压为+9V，电池负极的电压为-9V。

6.5.3　电流

正如前面所讨论的，当存在电势差时，就会产生电流（在前面的例子中，导体为铜线），直到导体两端拥有等量的电子与质子。

电流可以分为交流（Alternating Current，AC）与直流（Direct Current，DC）两种类型，如果电流以恒定速率流动，那么就是直流电，例如电池，反之如果电流随着时间而变化，则是交流电，在美国，通常电源插座提供120V、60Hz的交流电。

电流的计量单位为安培（A），在公式中采用字符I标记。测量电流的设备称为电流表（ammeter）。

读者看到这里可能会认为电流、电压、电阻三者之间存在一定的关联。综合考虑就是，电压会导致电流的流动，而电阻则会阻碍电流流动。

而事实也确实如此，电流、电压、电阻三者之间的关系即欧姆定律，即：

电流（I）＝电压（V）/电阻（R）

这也证明了电流同电压成正比，同电阻成反比。

6.5.4　电容

电容也是所有嵌入式设备中最常见的电子元件之一。顾名思义，电容的主要功能是以电荷的形式储存电量。

电容由两块极性相反的电极板构成，当连接到电源时即开始储存电荷。电容的其他用法还包括用作过滤器、降低影响设备中其他芯片的电子噪声、分隔交流电与直流电组件（避免交流耦合）等。

电容的计量单位是法拉，用字母F表示，计算公式如下：

C＝Q/V

其中，C表示电容，Q表示电量，V表示电压。

公式中的所有数值分别采用其标准单位进行表示，即法拉（F）、库伦（C）以及伏特（V）。

6.5.5　晶体管

晶体管也是一种电子元器件，主要用作开关与放大器。

如果用作放大器，晶体管可以接收小电流并将其放大，然后输出大电流。这种用法的一种实例是麦克风的扬声器，麦克风接收低音量输入，当声音通过扬声器后，放大生成高音量的输出。

与之类似，如果将晶体管用作开关，则可以将小电流作为输入，通过触发新的电流使得更大的电流得以通过。

晶体管的外形如图6-2所示。

图　6-2

图6-3是NPN型三极管（另一种类型是PNP型三极管，箭头从基极向上指），其电路图如图6-3所示。

图　6-3

6.5.6　存储器类型

嵌入式设备中最重要的电子元件同数据存储有关，数据存储元件在嵌入式设备中具有多种用途。类似于固件以及API key之类的内容都可以在数据存储元件中找到。嵌入式设备中三种主要的存储器类型以及它们的细分类型如下所示：

·随机存储器（Random Access Memory，RAM）

■静态RAM（Static RAM，SRAM）

■动态RAM（Dynamic RAM，DRAM）

·只读存储器（Read Only Memory，ROM）

■可编程ROM（Programmable ROM，PROM）

■可擦写可编程ROM（Erasable Programmable ROM，EPROM）

·混合型存储器

■电可擦写可编程ROM（Electrically Erasable Programmable ROM，EEPROM）

■闪存（Flash）

不同类型的存储器之间的区别由很多因素决定，包括数据存储能力、数据存储时间、数据擦除及覆写的方式，以及数据覆写的过程等。

例如，SRAM只有当加电时才保存数据，而DRAM则将每一位数据均保存在单独的电容内。此外，由于DRAM存在刷新周期（因为电容最终要放电），所以SRAM与DRAM相比，存储速度要快一些。

与之类似，对于ROM而言，基于数据可以写入的次数，可以分为PROM和EPROM。对于PROM而言，一旦写入数据，就不可修改，而对于EPROM而言，则可以使用紫外线（Ultra Violet，UV）擦除数据，紫外线穿过一个透明小窗照射芯片，通过重置或者复位芯片中存储的数据来实现芯片擦除。

其中，我们将要分析的最重要的两种存储器类型是EEPROM和闪存（NOR和NAND），两者之间的区别在于读、写以及擦除周期，而这取决于是否能够立即对整个存储块实施操作（闪存），还是能够立即对某单个比特进行操作（EEPROM）。

6.5.7　串行通信与并行通信

现在我们已经对部分电子元器件有了一个初步的了解，下面将介绍嵌入式设备所采用的不同类型的通信方式。

嵌入式设备通常采用两种数据通信方式，即串行通信和并行通信。顾名思义，串行通信在每次通信时顺序地逐个发送比特数据。这意味着，如果需要发送8比特数据，那么串行通信会一个比特接着一个比特发送，只有当所有8比特数据均接收到后，数据传输才算完成。

但是，在并行通信中，可以同时传输多个比特，因此同串行通信相比，并行通信的数据传输过程更快。

看到这里，读者可能会认为由于并行通信具有更快的数据传输速率，因此并行通信方式性能更优，在现实中的应用肯定也更为广泛。但是，现实并非如此，因为我们并未考虑实现并行通信电路板时所需基板面的数量。

嵌入式设备在物理空间布局上相当紧凑。而考虑到现实中并行数据传输同串行数据传输相比需要更多的数据信道，通信成本也更高，因此对于数据传输而言，更快的传输速率通常并不是最优选项。

并行数据传输的实例包括PCI和ATA接口，而串行通信的实例包括USB、UART与SPI接口。

由于在读者遇到的几乎所有硬件设备中都会采用串行通信，因此在本书中，我们主要关注串行通信的相关内容。

6.5.8　拓展学习

现在，读者可以随便找一块嵌入式设备的电路板，试着识别电路板所采用的元件，以及它们所采用的通信方式。

6.6　总线与接口识别

认识了嵌入式设备中的各种元器件之后，接下来介绍如何识别设备中不同的总线与接口。

识别过程的第一步是打开设备外壳查看PCB。注意在本节中，我们仅仅关注识别特定引脚、插座或者芯片的作用，而非同其建立连接，建立连接的相关内容主要在下一节中进行介绍。

6.6.1　测试流程

我们首先从识别UART接口开始，这是攻击者连接设备时最喜欢使用的接口。首先查看UART接口的内部构造，然后识别引脚定义，最后了解如何建立同目标设备的连接。

1.UART接口识别

在分析嵌入式设备时，我们首先需要分析的对象是UART（Universal Asynchronous Receiver Transmitter）接口。UART是嵌入式设备最常用的通信协议之一。UART接口能够将接收到的并行数据转换为串行数据比特流，从而更加便于数据交互。

由于采用UART协议的串行通信主要关注减少信号线的数量，因此UART接口没有设置时钟信号线。UART接口采用波特率（baud rate）表示数据的传输速率，通信过程中双方对波特率进行协商，以确保接收方能够以正确的格式接收数据。

此外，在基于UART协议的通信过程中，会在通信数据中添加校验位（parity bit）以便于错误校验。因此，典型的UART通信过程顺序包含以下比特：

·起始位（start bit）：用于指示基于UART协议通信的起始位置。

·数据位（data bit）：需要传输的实际数据。

·校验位（parity bit）：用于错误校验。

·停止位（stop bit）：用于指示UART数据流的结束位置。

如果读者自己想尝试验证这些比特以便更好地理解UART数据流，可以使用逻辑分析仪连接UART接口（这部分内容稍后我们将进行介绍），然后在逻辑分析软件中查看结果。最常用的逻辑分析仪是Salae Logic，包含8通道和16通道两种型号。

图6-4展示了数据在逻辑分析仪中的表示形式。

图　6-4

接着来看看现实设备中UART接口到底长什么样子。图6-5是设备中UART接口的实例。需要注意的是，当使用UART接口通信时，有两个引脚是必须要用到的，一个用于数据传输（Tx），一个用于数据接收（Rx）。此外，在大多数情况下还会用到另外两个引脚，一个用于接地（GND），一个用于供电（Vcc）。

在图6-5中可以看到，有4个紧挨着的引脚，这4个引脚就是UART引脚。下一节将主要介绍如何同串行通信接口进行交互，其中我们主要关注如何准确识别引脚定义，哪些引脚分别对应于Tx、Rx以及GND引脚，以及如何同这些引脚/接口进行交互以访问设备。

2.SPI接口与I2C接口识别

SPI接口与I2C接口的识别同之前提到的UART接口的识别相类似，也可以使用逻辑分析仪观察通信过程中传输的比特来进行SPI接口或I2C接口的识别。

图　6-5

SPI与I2C接口都属于串行通信方式，通常用在闪存以及EEPROM之中。为了准确识别出芯片所采用的串行通信协议以及相关信息，可以查看芯片型号，从芯片数据手册中获取所需要的信息。

SPI闪存芯片的外形如图6-6所示。

图　6-6

图片链接：https://cdn-shop.adafruit.com/1200x900/1564-00.jpg

图6-6中闪存芯片的标签信息为Winbond W25Q80BV，因此即便不知道该芯片是SPI闪存芯片，也可以查阅该型号芯片的数据手册，进而识别出该芯片的所有特性。

如果在Google中搜索该芯片型号，搜索结果如图6-7所示。

接下来在搜索结果中打开任意一份芯片数据手册。在数据手册的开始位置就可以发现如图6-8所示的信息。

图　6-7

图　6-8

图6-8的意思是该芯片是一枚存储容量为8MB的SPI闪存芯片。继续查阅数据手册，可以找到该SPI闪存芯片准确的引脚定义，如图6-9所示。

至此，我们就正确识别出了该芯片的用途、基本功能及其引脚定义。

获取到上述信息之后，我们就可以使用Attify Badge连接SPI闪存芯片了，Attify Badge能够同多种硬件协议与标准进行交互，例如UART、JTAG、SPI以及I2C等。或者，我们也可以使用FTDI MPSSE电缆连接SPI闪存芯片。

图　6-9

将SPI闪存芯片的数据输出（Data Out，DO）与数据输入（Data In，DI）引脚分别连接到Attify Badge的MOSI和MISO引脚，如果读者使用FTDI电缆的话，那么可以将芯片中的DI引脚连接到FTDI电缆的DO（黄色）信号线，将芯片的DO引脚连接到FTDI电缆的DI（绿色）信号线。此外，还要将电缆的Vcc、GND、WP和CS信号线连接到芯片的相应引脚。

图6-10中的表格可以帮助读者完成上述连接过程。

图　6-10

连接完成后，此时所要做的就是运行LibMPSSE库中的spiflash.py脚本，LibMPSSE库可以从链接https://github.com/devttys0/libmpsse处下载，执行结果如图6-11所示。

前面命令中参数-s后面跟着的参数值可以从闪存芯片的数据手册中获得，然后将闪存芯片中的所有内容均存储至名为new.bin的文件。

此时，读者可以找到自己感兴趣的设备查看SPI闪存芯片，确定其引脚定义，转储芯片中的数据，根据所分析设备的类型，这些数据中可能包括固件、硬编码数据，也可能是其他敏感信息。

3.JTAG接口识别

在设备中，我们还需要关注的开放接口是JTAG（Joint Test Action Group，JTAG）接口。

图　6-11

同之前提到的颇为棘手的测试方式相比，通过JTAG接口对引脚进行测试与调试相对简单。设备开发人员和测试人员可以借助JTAG接口确保设备中各个芯片上的每个引脚都能够正常工作、连通，并且能够按照预期工作。

对于渗透测试人员而言，JTAG接口也具有多种作用，包括读/写数据、调试运行进程以及修改程序执行流等。

JTAG中4个最重要的引脚分别是测试数据输入（Test Data in，TDI）、测试数据输出（Test Data Out，TDO）、测试时钟输入（Test Clock，TCK）以及测试模式选择（Test Mode Select，TMS）等引脚。但是，在识别出这些引脚定义之前，需要首先找到设备中JTAG插座的位置。

简单说来，JTAG提供多套接口标准，例如13针、14针、20针等。现实中设备的JTAG接口的外观如图6-12所示。

图6-13是Experia v8 Box设备中焊接上插座的JTAG接口。

需要注意的是，即便在某些现实设备中的JTAG接口以标准插座形式摆放，读者也可能会发现JTAG引脚分布在整块电路板中，而不是位于同一块区域。在这种情况下，就需要通过焊接插座或跳线，将引脚连接到JTAGulator，才能够识别出测试的引脚是否符合JTAG的引脚定义，以及各个引脚分别对应于JTAG的哪个引脚。

图　6-12

图片来源：https://www.dd-wrt.com/wiki/images/thumb/9/99/DLINK-DIR632_Board.png/500px-DLINK-DIR632_Board.png

图　6-13

6.6.2　拓展学习

除了之前提到的接口和协议，目标设备还可能会用到其他硬件通信协议。其他的主流通信协议还包括CAN、PCI、1-Wire等。建议读者多了解硬件通信协议，从而才能够深刻理解分析协议所用到的方法。

6.7　嵌入式设备的串行接口

在之前的章节中已经对UART接口的基础知识进行了介绍，下面让我们来了解如何同UART接口进行交互。

6.7.1　准备工作

当找到设备中的UART引脚后，下面就是识别出各个引脚的作用。

我们关注的引脚主要有4个，分别是：

·Tx

·Rx

·GND

·Vcc

对此，需要使用万用表测量电压和电流。由于该设备既可以用作电压计，也可以用作电流表，因此称之为万用表。

万用表的外观如图6-14所示。采用图中所示方式连接探针。

图　6-14

6.7.2　测试流程

连接完成后，采取以下步骤开始分析UART不同引脚的定义。

1）将万用表中的指针指向喇叭符号，如图6-15所示。

分析时需要关闭测试设备，然后将黑色探针放至地面，或者设备上的任意金属面。

2）将红色探针分别放至可能是UART接口的4个焊盘的任意一个之上，并对其他焊盘重复相同操作，直到听到哗哗或者嗡嗡的声音。

图　6-15

3）听到哗哗声的引脚即设备的GND引脚。该测试也被称为导通性测试（continuity test），正如刚刚对两个GND引脚之间的导通性进行了检测，一个是已知的GND引脚[1]，另一个是未知的GND引脚。

现在我们已经识别出了GND引脚，接着将继续识别其他引脚。

4）将万用表指针指向-20V的位置开始测试电压。保持黑色探针接地，将红色探针逐个接触UART接口的其他引脚（除了GND引脚）。

此时，给设备加电并启动设备，可以看到持续保持高电压的引脚，即Vcc引脚。

5）接下来，重启设备，并测量剩余焊盘同GND引脚（除了在之前步骤中识别出的Vcc和GND引脚）之间的电压。由于在设备重新引导时会进行大量的数据传输，因此在初始的10～15s期间，其中一个引脚的电压值会出现较大幅度的摆动。该引脚即Tx引脚。

6）电压波动最小的引脚即Rx引脚，并且在整个测试过程中，该引脚的电压值也是最低的。

至此，我们就识别出了UART通信过程中的所有引脚，即Tx、Rx以及GND和Vcc引脚。

7）在识别出设备的引脚之后，下一步是将设备的UART引脚连接到Attify Badge。这里除了Attify Badge之外，读者也可以使用其他设备，例如USB-TTL转接线或者Adafruit FT232H。

此时我们所关心的Attify Badge引脚为D0和D1，分别对应于数据传输与数据接收。

将目标设备的传输（Tx）引脚连接至Attify Badge的Rx（D0）引脚，将目标设备的Rx引脚连接至Attify Badge的Tx（D1）引脚，目标设备的GND引脚则连接至Attify Badge的GND引脚。

完成上述所有连接后，下一步就是确定设备运行的波特率。将Attify Badge连接到系统，并将目标设备加电。

在确定波特率的过程中我们会用到baudrate.py脚本，该脚本可以从链接https://github.com/devttys0/baudrate/blob/master/baudrate.py下载。

8）脚本运行命令如下：

9）脚本运行结束后，屏幕显示如图6-16所示，读者可以使用向上键或者向下键调整波特率。直到屏幕显示出具有意义的字符，此时的波特率即目标设备所采用的波特率。操作过程如图6-16所示。

图　6-16

10）接下来按下Ctrl+C键，会依据识别出的波特率等配置信息启动minicom工具。如果目标设备为UART接口提供了shell访问权限，那么只需单击回车键，用户就会获得shell权限，如图6-17所示。

图　6-17

至此，我们就实现了对UART接口的漏洞利用，找到了该接口的引脚定义并同其进行交互，并最终获得了root shell。

[1] 即地面或设备上的任意金属面。——译者注

6.7.3　延伸阅读

如果用户已经获得了目标设备UART接口的访问权限，那么用户就可以使用其他漏洞利用技术了，例如后门植入或者通过TFTP协议进行整个文件系统的转储。但是，根据设备的不同，并且依据被攻击设备所能获得的当前权限，所能实现的操作也有所区别。

6.8　NAND噪声干扰

绕过嵌入式设备安全防护措施（例如不允许在UART控制台执行root shell）的方法之一是实施噪声干扰攻击。

6.8.1　准备工作

顾名思义，噪声干扰就是在测试的系统中引入错误。这一过程可以通过多种方式完成，并且已经有专门的论著以及研究文章对这一主题进行了探讨。

现在，我们对基于噪声干扰的攻击方法进行简单的了解。噪声干扰的目的在于访问bootloader，更改引导参数等敏感参数，在引导参数中我们可以自己定义参数以通知系统使用登录提示符或shell来启动UART控制台，或者进入单用户模式[1]引导系统，上述两种操作均可以用来绕过验证。

[1] Linux提供了单用户模式（类似Windows安全模式），可以在最小环境中进行系统维护。在单用户模式（运行级别1）中，Linux引导进入root shell，网络被禁用，只有少数进程可以运行。单用户模式可以用来执行修改文件系统、还原配置文件、移动用户数据等操作。——译者注

6.8.2　测试流程

1）本书研究的噪声主要是NAND噪声（NAND glitching），这里将设备中NAND闪存的一个I/O引脚同GND引脚短路。需要注意的是，短路操作的执行时机需要控制在bootloader已经引导且正要对内核进行引导时。

最后，如果短路成功，内核则会引导失败，用户进入到默认的bootloader命令行界面，提示用户输入命令，这时用户就能够修改bootloader的参数了。

2）下面以一个实例来介绍获得bootloader访问权限后用户所能执行的操作，在引导参数中添加single参数后，用户即进入单用户模式，从而绕过部分系统所要求的认证过程。这一过程如图6-18所示。

图　6-18

图片来源：http://console-cowboys.blogspot.com/2013/01/swann-song-dvr-insecurity.html

3）与之类似，对Wink Hub设备进行相同的NAND噪声干扰也可能导致用户进入bootloader的命令行界面，提示用户输入命令（该漏洞由Exploitee.rs的团队发现），此时用户可以对引导参数进行更改，操作过程如图6-19所示。

图　6-19

4）对引导参数完成修改后，就可以在下一次引导过程中通过UART接口获取root shell的权限了，执行结果如图6-20所示。

图　6-20

图片来源：http://www.brettlischalk.com/assets/WinkHack/WinkRootShell.png

6.8.3　延伸阅读

NAND噪声仅是噪声干扰攻击技术中的一种。读者也可以使用电流与电压噪声干扰攻击来实现口令绕过等操作。

之前提到的部分参考资料的链接如下：

·https://www2.cs.arizona.edu/~collberg/Teaching/466-566/2012/Resources/presentations/2012/topic1-final/report.pdf

·https://www.cl.cam.ac.uk/~sps32/ECRYPT2011_1.pdf

·https://www.blackhat.com/docs/eu-15/materials/eu-15-GillerImplementing-Electrical-Glitching-Attacks.pdf

6.9　JTAG接口的调试与漏洞利用

前面已经对硬件设备中的各种漏洞利用技术进行了介绍，现在介绍设备攻击中最重要的一种攻击方式：JTAG。在之前的介绍中，我们已经知道了JTAG接口的作用，并认识了JTAG引脚的外观。

6.9.1　准备工作

首先需要识别出特定目标设备中的JTAG引脚定义。对此，可以使用JTAGulator工具，该工具是由Joe Grande开发的专门用于识别JTAG引脚的硬件工具。

6.9.2　测试流程

将JTAGulator的所有信道均连接到目标设备上的JTAG引脚之后，还需要将GND连接到GND引脚。

1）使用如下代码启动显示屏：

2）然后，用户可以看到JTAGulator的命令提示行，提示用户输入命令，如图6-21所示。

3）接下来要做的第一件事是设置目标设备的电压，在本例中我们将电压设置为3.3 V。操作过程是：首先输入命令V，紧接着输入3.3，操作过程如图6-22所示。

4）目标电压设置完成后，输入命令B执行旁路扫描，识别出当前连接的JTAG引脚，如图6-23所示。

此时可以看到，JTAGulator识别出了JTAG的引脚，并指示出了各引脚所对应的作用。

5）既然我们已经识别出了引脚定义，下一步就是将引脚连接至Attify Badge（或者FTDI C232HM MPSSE电缆），连接方式如下所示：

图　6-21

图　6-22

图　6-23

①将目标设备的TDI引脚连接至Attify Badge的D1（TDI）引脚（或者FTDI电缆中的黄色信号线）。

②将目标设备的TDO引脚连接至Attify Badge的D2（TDO）引脚（或者FTDI电缆中的绿色信号线）。

③将目标设备的TMS引脚连接至Attify Badge的D3（TMS）引脚（或者FTDI电缆中的棕色信号线）。

④将目标设备的TCK引脚连接至Attify Badge的D0（TCK）引脚（或者FTDI电缆中的橙色信号线）。

6）完成上述连接后，下一步是使用为Attify Badge（或者FTDI C232HM MPSSE电缆）准备的配置文件以及目标设备的芯片来运行OpenOCD。在OpenOCD安装完成后，配置文件可以从位于openocd/tcl/target的OpenOCD目录中获取。

7）OpenOCD的运行效果如图6-24所示。

图　6-24

8）如图6-24所示，OpenOCD识别出了与之连接的设备，并且在4444端口启动了Telnet服务，此时用户就可以建立到该端口的Telnet连接了，执行结果如图6-25所示。

图　6-25

到了这一步，用户不仅可以执行OpenOCD中的各种命令，还可以执行针对特定芯片的命令，从而实现对设备的攻击。

6.9.3　延伸阅读

此时通过JTAG接口可以使用mdw命令从特定内存位置中读取数据，命令执行结果如图6-26所示。

另一个实例是建立同GDB调试器之间的连接，通过3333端口对当前运行进程进行调试，然后可以使用前面章节介绍的技术开展ARM/MIPS架构下的漏洞利用。

图　6-26

第7章　无线电攻击技术

本章将主要探讨以下主题：

·SDR入门。

·SDR工具。

·ZigBee漏洞利用。

·Z-Wave深入分析。

·BLE分析及漏洞利用。

7.1　简介

在当前的应用场景中，几乎所有的IoT设备都会同其他设备进行交互并做出响应。因此，为了有效地对IoT设备开展渗透测试，有必要了解IoT设备所使用的无线协议及其相关的安全问题。

无线通信或无线电其实就是一种以空气为媒介，利用电磁波将数据从数据源传输到目的地的通信方法。无线电信号与常见设备中采用的微波、可见光和红外线等信号类似，只不过这些信号的波长和频率不一样而已。在无线通信中，首先会利用电位差和天线位置将数据转换成电信号，然后由载波进行传输，最后在另一端进行解调获得由数据源发送的实际数据。对于电磁概念以及数据转换成电信号的原理本章将不再赘述。

根据产品需求和设备厂商的特点，IoT设备可以采用蜂窝网络、Wi-Fi等多种无线通信协议。然而仅在一章或一本书中，是不可能涵盖所有无线通信协议的，因此本章将重点放在通用渗透测试方法的研究之上，并主要涉及两种最常见的无线协议的安全研究——ZigBee和低能耗蓝牙（BLE）。

不同的无线协议有其不同的用途，也有各自的优缺点。每个协议都以特定的频率（或在某一频率范围内）工作，因此渗透测试人员需要部署不同的软硬件测试环境来实现对通信协议数据包的分析。

在介绍无线协议之前，首先需要深入了解软件无线电（Software Defined Radio，SDR）的概念。在谈及IoT设备的无线电逆向和攻击时，这是一个非常重要的概念。同时，为了帮助读者更好地理解无线电攻击和SDR，下面将对各种基本概念进行简单介绍。

7.2　SDR入门

SDR是一项非常有用的技术，借助SDR技术我们可以改变无线电设备的用途。顾名思义，软件无线电即指基于软件定义的无线电通信协议而非通过硬连线实现的无线电通信技术，这意味着无线电的功能或者所执行的操作可以根据用户需求进行改变和调整。这一点与传统无线电不同，传统无线电基于其内置的硬件设计，其功能往往是固定单一的。

SDR的这一特点为用户提供了很多可操作的空间，用户可以利用SDR，并不断改变其用途以满足多样的需求。这里举例说明改变用途的意思，比如说我们现在需要分析FM频谱，那么可以使用设备开展FM频谱分析，随后，如果我们又需要分析某台IoT设备以433 MHz频率发送的数据，那么我们还可以使用相同的设备来接收和处理数据，并从数据中提取出发送的文本信息。

此时，读者应该对SDR的概念及其功能有了一个大致的了解。在开始使用SDR进行实操练习、对不同的设备开展分析之前，读者还需要熟悉一些基本概念和术语。当读者深入了解无线电攻击和SDR相关技术时，总会接触到这些概念和术语的。

无线电的关键术语

下面让我们简要了解一下在SDR中经常遇到的术语。

一套基本的无线电系统通常由以下部分组成，分别是发射器、接收器、载波和介质。这些内容大家可能已经比较熟悉了。发射器就是指发送信号的部件，接收器则是通过传输介质接收发射器所发送信号的部件。

在大多数现实场景下，原始数据调制成载波的形式，然后发送到接收器，载波再被解调，恢复出原始数据波。

调制技术包括多种方式，例如调频、调幅和调相等。此外，还有多种数字调制方式，如开关键控（On-Off Keying，OOK）、相移键控（Phase-Shift Keying，PSK）、频移键控（Frequency-Shift Keying，FSK）以及幅移键控（Amplitude-Shift Keying，ASK）。

在使用无线电系统时，经常会遇到以下术语：

·波长（wavelength）：在无线电系统中，波长指波形中两个相邻波峰（高点）或两个相邻波谷（低点）之间的距离。

·频率（frequency）：顾名思义，表征某件事情发生的频繁程度。

·增益（gain）：处理后信号的信噪比同原始信号的信噪比的比值。

·滤波器（filter）：滤波器能够移除无线电信号中不必要或不需要的部分。滤波器可分为多种不同类型，如高通滤波器（只允许超过特定阈值的信号通过滤波器）、低通滤波器（只允许低于特定阈值的信号通过滤波器）以及带通滤波器（只允许特定频率范围的信号通过滤波器）。

·采样（sampling）：采样能够将一个连续信号转换成具有许多独立值的离散时间信号。如果采样率不正确，信号就会显得不完整或失真，进而导致计算错误。

·奈奎斯特定理（Nyquist’s theorem）：如果采样频率至少是信号带宽的两倍，那么所有信号均可以采用离散采样序列加以表示。

·模数转换器（Analog-to-Digital Converter，ADC）/数模转换器（Digital-to-Analog Converter，DAC）：将模拟信号转换成数字信号，反之亦然。

了解了这些无线电术语之后，下面再来看一看同SDR相关的部分工具以及如何利用这些工具开展安全研究。

7.3　SDR工具

本节将讨论SDR和无线电信号分析中常用到的工具。首先从最基本的工具开始介绍，然后讨论如何利用这些工具从无线电数据包中提取信息。

7.3.1　准备工作

要开展基于SDR的安全研究，需要做好以下准备：

·硬件：

■RTL-SDR

·软件：

■GQRX

■GNU Radio Companion

在上述工具的部署过程中，各自代码库中均包含了安装指导，为工具的部署提供帮助。

建议读者下载源码重新编译安装GNU Raido companion，这里不推荐使用apt-get命令直接安装，这样在对SDR开展相关分析时能够获得更好的用户体验。

SDR安全研究同样也依赖于系统性能。进行测试时，需要确保分配给虚拟机足够的RAM来执行任务。如果可能的话，建议使用Ubuntu作为主机来获得更好的体验。

7.3.2　测试流程

开始接触SDR领域时，RTL-SDR可以说是最理想的入门设备之一。RTL-SDR最初只是一个搭载Realtek芯片组的电视调谐器，其中的Realtek芯片组可用于实现多种无线电操作。RTL-SDR设备的生产厂家为了使自己的芯片能够一次投产、多次使用以便于销售，会将芯片设计得能够覆盖较宽的频段，而后根据用户需求和政策要求在不同的产品中开启特定频段，因此RTL-SDR设备的频率各不相同，通常在22 MHz～1.7 GHz的范围之间。

1.FM分析

1）开始对SDR的分析之前，首先使用RTL-SDR查看频谱。这将使我们更好地了解SDR的工作原理，进而开始对SDR设备的研究。

2）然后将RTL-SDR插入系统。如果用户正在使用虚拟机，请确保RTL-SDR已连接到虚拟机。

3）接下来，打开GQRX软件[1]，在初始启动菜单中选择RTL-SDR设备。可以看到界面中包含了多个分区，如图7-1所示。

图　7-1

在界面顶部，用户可以使用上下箭头键来设置频率，也可以直接输入想要RTL-SDR接收的频率。

频率部分往下是频谱，当读者使用基于无线电的IoT设备时，可从这里看到哪些频段最为活跃，同时观察到波峰。后续会详细探讨这部分内容。

再往下看是瀑布图，即信号-时间坐标轴。在这里可以观察到过去几秒内哪些频段进行了通信。

界面的右半部分是接收器选项（Receiver Options）、输入控制（Input controls）和FFT设置面板（FFT Settings），进行不同配置有助于用户开展数据分析。但是，为了简单起见，本章将不对配置开展具体讨论。所有的选项卡都可以根据需要进行调整和定制。

第一个练习，看下如何利用GQRX调谐接收一个本地FM广播电台。

4）首先在接收器选项面板中将模式（Mode）设定为Wide FM stereo，如图7-2所示。

图　7-2

5）设定完成之后，将频率切换到本地FM广播电台的频率范围，如图7-3所示。

图　7-3

6）单击Capture按钮之后，读者会看到一段频谱，其中包含了多个波峰，频谱中的每个波峰都代表了该频率范围内的通信信号，如图7-4所示。

调谐到一个FM广播电台后，再去听扬声器里的声音，会发现扬声器中的声音正对应于频谱中的波峰，此时就可以收听该频率的FM广播了。

图　7-4

2.基于RTL-SDR的GSM分析

读者还可以将RTL-SDR用于许多其他用途，其中一种用法是进行蜂窝网络分析，下面我们将对这种用法进行介绍。借助RTL-SDR，我们能够准确查看不同手机用户的定位信息。在测试过程中，使用单向天线有助于扩大范围并且提高所收集的信息量。

1）首先从链接https://github.com/ptrkrysik/gr-gsm/下载安装grgsm_livemon，其作用是实时监控用户指定的GSM信道，grgsm_livemon的启动界面如图7-5所示。

图　7-5

2）打开grgsm_livemon界面之后，读者可以通过调整增益和频率的方式来查看频谱，如图7-6所示。

图　7-6

那么，如何获得某蜂窝网络中通信的频率呢？对此，我们需要用到工具Kalibrate，Kalibrate是一款GSM频率识别器，可从链接https://github.com/ttsou/kalibrate下载。

3）获得Kalibrate后，接着指定需要扫描的频段。在本例中，我们扫描的是GSM900 MHZ频段，同时将增益设置为40.0 dB，如图7-7所示。

图　7-7

4）根据扫描结果可以看到，在956.4 MHz+9.829 kHz频率处存在大量流量。然后启动GQRX对该频率进行分析，如图7-8所示。

5）同之前预测的一样，在该频率中确实存在大量通信信号。此时，我们就发现了想要寻找的频率，再回到GRGSM界面将监听频率设置为该频率，继而开始分析，设置内容如图7-9所示。

图　7-8

图　7-9

6）我们也可以查看GRGSM中的流量。为了对其开展进一步分析，我们可以使用Wireshark查看本地回环网卡lo接口中的流量。不出所料，在这里我们发现了一些有趣的信息。使用gsmtap滤波器可以过滤出我们关心的信息，如图7-10所示。

图　7-10

7）从图7-10中我们可以识别出移动设备国家代码（Mobile Country Code，MCC）、移动设备网络代码（Mobile Network Code，MNC）和位置区码（Location Area Code，LAC）。利用这些信息，再配合类似于CellidFinder这样的工具，就可以在地图上定位出目标手机的位置。使用CellidFinder可以在地图上找到离手机最近的基站，如图7-11所示。

图　7-11

以上就是对RTL-SDR几种用法的介绍，其中分析对象既包括了常见的FM广播流量，也包括了蜂窝移动通信流量。

3.GNU Radio的用法

之前的实例更多的只是关注频率分析，但是分析并不深入。假设现在有一台IoT设备正在通过无线电传输数据，如果我们想知道这背后的原理，并获取到实际的传输数据，那么需要开展哪些操作呢？

为了实现上述目的，我们将会用到工具GNU Radio-companion，借助GNU Radio-companion我们可以构建无线模块来处理分析多种无线电信号。首先选择一个输入源（例如RTL-SDR、Osmocom、HackRF，也可以采用信号发生器），接着使用相应的无线模块对输入源进行处理，最后可以将输出内容存储为wav文件，也可以将其在图中绘制出来。

在本练习中，我们以一个气象站为研究对象，使用RTL-SDR来捕获气象站发送的数据，然后对捕获到的数据执行解调与时钟恢复操作，进而发现气象站发送的实际数据。

为了找出设备运行的频率，我们可以使用GQRX查找数据传输时的波峰。或者，我们也可以查找设备的FCC ID编码，根据FCC ID编码找到设备的运行频率。FCC ID是厂商在美国销售设备所需的强制性认证，FCC ID编码由申请人代码（grantee code）和产品代码（product code）两部分组成，一般印在设备标签上。

找到FCC ID编码后，访问网站fccid.io，然后输入FCC-ID编码，就可以获得设备所使用的准确频率了，如图7-12所示。

图　7-12

找到设备运行的频率之后，输入gnuradio-companion即可进入GNU Radio-companion操作界面，然后就可以创建工作流来处理气象站发送的数据了。本节不会对GNU Radio-companion及其各种属性进行深入介绍，但是还是强烈建议读者自行了解GNU Radio-companion的用法，并尝试使用它来捕获无线电信号。

以下是需要添加的无线模块（如图7-13所示）：

·Osmocom source：该模块帮助用户从RTL-SDR设备中获取无线电数据包，并将数据包传递到以下无线模块。

·Complex to Mag^2：在不考虑诸如相位角等当前无关紧要的因素时，该模块用来帮助用户将复数类型数据转换成实数类型。

·Multiply Const：由于接收到的原始输出数据信号可能非常微弱，因此该模块的作用为帮助用户提高接收到的输出数据信号强度。通常来说，5或10是比较理想的值。

·File sink：该模块可以帮助用户将输出数据保存为文件，然后在信号分析软件audacity中进行分析。

模块添加完成之后，执行以下操作：

双击osmocom Source模块更改其属性，将其设置为先前识别出的频率。

图　7-13

再双击Wav File Sink模块，命名输出文件。

现在就可以执行编辑好的工作流了，运行之后会生成一个名为monitor.wav的新文件。将该文件作为原始文件导入audacity分析软件。导入后，发现信号波形看起来与OOK（开关键控）信号类似，此时需要将这些信号转换成便于理解的实际数据，其中一种方法是将短脉冲间隔表示为数字0，将长脉冲间隔表示为数字1，如图7-14所示。

图　7-14

对转换得到的数据开展进一步分析，就会提取出气象站发送的气象数据，测试人员可以发现在数据中包含了温度、湿度等信息，如图7-15所示。

图　7-15

[1] 一款开源的SDR接收器软件，基于GNU Radio与Qt图形工具集开发。GQRX支持多种SDR硬件，包括Airspy、Funcube Dongles、rtl-sdr、HackRF以及USRP等设备。——译者注

7.3.3　拓展学习

开展SDR渗透测试，还有许多其他围绕RTL-SDR构建的工具能够实现多种功能。例如，可以实时追踪飞行记录的ADS-B系统、能够处理433 MHz信号的RTL-433，还有对遥控钥匙等设备开展漏洞利用的工具等。

7.4　ZigBee漏洞利用

基于ZigBee能够构建Mesh网络以及功耗低、耗损低的特点，ZigBee成了IoT设备中最为常见的无线协议之一。该协议还被广泛应用于智能家居、工业控制系统（Industrial Control Systems，ICS）、智能楼宇等领域。在很多国家，ZigBee协议的运行频率为2.4 GHz，而在美国和澳大利亚的运行频率则是902～928 MHz，在欧洲为868～868.6 MHz。

本节将重点讨论如何识别周边的ZigBee设备，并对其信号进行嗅探和重放以发现其中的安全隐患。

7.4.1　准备工作

研究ZigBee设备的安全隐患，需做好以下准备：

·硬件：刷有KillerBee固件的Atmel RzRaven USB设备。

·软件：KillerBee。

KillerBee的安装非常简单，可按照官方GitHub代码库提供的说明直接下载安装，官方GitHub代码库的链接为https://github.com/riverloopsec/killerbee。

安装完成后，将RzRaven USB设备连接系统，此时会看到设备上的LED灯闪烁琥珀色光。倘若LED灯闪烁蓝光，则说明RzRaven USB设备未刷上KillerBee固件。本节中不再对如何刷入KillerBee固件的过程进行赘述，感兴趣的读者可以通过GitHub进行了解。此外，测试人员还可以选择网上购买已经预先刷好KillerBee固件的RzRaven USB设备。

7.4.2　测试流程

下面将对如何着手分析周围的ZigBee设备进行具体探讨，并通过RzRaven和Killer-Bee来嗅探ZigBee流量。

1）首先查看周围的ZigBee设备。这一步可以通过zbid工具来实现，操作命令如图7-16所示。

图　7-16

2）我们已经将下面的程序刷入了Arduino开发板。该段程序能够让Arduino开发板与XBee模块[1]进行交互，并通过XBee模块发送信息：5e87bb4a6cdef053fde67ea9711d51f3，其中Arduino开发板与XBee模块是通过串口的引脚2和引脚3进行连接的。XBee模块发送数据的信道取决于XBee模块的编程设置，用户可以使用XCTU软件对自己的XBee模块进行编程并指定通信信道：

3）接下来，将Xbee模块和Arduino开发板都部署在Xbee Shield扩展板上，部署之后如图7-17所示。

图　7-17

4）给Xbee Shield扩展板加电并运行Zbstumbler，执行结果如图7-18所示。

图　7-18

我们可以看到所有在信道12上进行广播的设备。

5）下一步，嗅探信道12的流量，并查看其中是否包含敏感信息。这一步中将会用到zbwireshark工具，操作命令如下所示，该命令将自动打开Wireshark，并在命令中指定的信道上嗅探ZigBee协议流量：

6）同之前的预期一样，我们可以在Wireshark的界面中观察到所有的流量，以及对Arduino开发板编程时所用到的敏感字符串，在Wireshark中截获到的数据包如图7-19所示。

图　7-19

[1] XBee模块是美国DIGI公司出品的系列模块。目前已形成XBee生态圈，支持的协议包含Zigbee 3.0、Digimesh、802.15.4、3G、4G、NB-IOT等。——译者注

7.4.3　拓展学习

读者也可以尝试实施其他攻击，例如利用KillerBee工具套件中的Zbreplay工具对捕捉到的流量进行重放。

7.5　Z-Wave深入分析

Z-Wave协议是无线传感器网络和智慧家庭中较为常见的协议。Z-Wave协议在美国的运行频率为908.42 MHz，在欧洲为868.42 MHz。像ZigBee一样，Z-Wave也支持Mesh网络，这使得它可以有效应对节点故障之类的问题。

Z-Wave由Sigma Systems公司设计开发，同ZigBee以及其他协议不同的是，Z-Wave是一套封闭协议。因此，相较于其他常见的IoT协议，安全社区针对Z-Wave协议所开展的安全研究不太活跃。还有机构设计了Z-Wave协议的开源替代方案，例如OpenZWave等。然而这些项目都还处于初期阶段。

但是就像其他典型的无线电通信协议一样，Z-Wave设备也会面临同样的安全隐患。其中最常见的隐患之一就是未对通信过程加密，这一点极易导致设备中明文传输的敏感信息泄露，或者使得设备遭受重放攻击。然而，还需要特别指出的是，S2 Security公司针对Z-Wave设备所提出的解决方案可以极大地提高设备中Z-Wave实现的安全性，保护设备免遭针对密钥交换和设备认证的攻击。

测试流程

开展针对Z-Wave的攻击，常用到框架EZ-Wave（https://github.com/AFITWiSec/EZ-Wave），该框架由Joe Hall和Ben Ramsey开发，使用Hack RF硬件来对采用Z-Wave协议的设备实施攻击。

EZ-Wave工具集中包含3款工具，分别是：

·设备发现与枚举工具——EZStumbler。

·已发现设备的分析工具——EZRecon。

·漏洞利用工具——EZFingerprint。

通过捕获基于Z-Wave协议的传输过程中的数据包，进而查找其中以明文传输的敏感信息，可以对Z-Wave协议的安全性进行评估，如图7-20所示。

使用之前在GNU Radio-companion中介绍的模块，最终的构建工作流图如图7-21所示。

工作流图构建完成后，可以根据我们的预期目标选择直接重放数据包，或者对数据包进行修改之后再重放该数据包。其他针对Z-Wave系统的攻击还包括针对网络中Z-Wave设备节点的Disjoining/Unpairing攻击、欺骗攻击、无线电干扰攻击和拒绝服务攻击等。

图　7-20

图　7-21

图片来源：http://oldsmokingjoe.blogspot.in/2016/04/z-wave-protocol-analysis-using-ez-wave.html

7.6　BLE分析及漏洞利用

在智能家居、医疗设备，甚至是运动手环和可穿戴设备等一系列智能设备中，低功耗蓝牙（Bluetooth Low Energy，BLE）是最常见的平台之一。其受欢迎程度越来越高的原因在于我们今天使用的几乎所有智能手机都能支持BLE，从而大大降低了同基于BLE的IoT设备进行交互的难度。

BLE是为那些资源和功耗存在限制的设备设计的，通过提供短脉冲进行远程无线连接，可以有效地解决资源与功耗有限的问题，从而大大降低了电池的消耗。

BLE首先在蓝牙4.0规范中引入，主要针对采用极低功耗通信模式的设备，其声称仅靠一粒纽扣电池就可以维持几个月甚至是几年的电量。

根据BLE设备的当前连接和操作状态，BLE设备可以以4种模式运行：

·中心设备与外围设备：在这种分类中，扫描广播数据包并初始化连接的设备称为中心设备，而在连接时对自身进行广播的设备称为外围设备。举个例子，智能手机就是一个中心设备，而运动手环则是一个外围设备。

·广播者与观察者：顾名思义，广播者是指用来广播数据的设备，而观察者是指扫描广播数据包的设备。然而，与之前分类最大的区别在于，广播者是不可连接的，而观察者不能初始化连接。举个例子，气象站就是广播者，它会持续发送温度数据，而接收广播并在屏幕上显示的显示器则是一个观察者。

BLE由40个不同的信道组成——包括3个广播信道和37个数据信道，如图7-22所示。

图　7-22

图片来源：http://www.connectblue.com/press/articles/shaping-the-wireless-future-with-low-energy-applictions-and-systems/

使用BLE还能实现跳频扩频通信，这意味着它会在每个事件中不断地改变信道。但接下来我们在下面小节中使用的工具能够通过跃点跟踪设备，并嗅探BLE通信过程中的数据。

图7-23所示为BLE协议栈，方便读者更好地深入了解低功耗蓝牙的基本概念。

图　7-23

图片来源：http://www.embetronicx.com/

如图7-23所示，BLE协议栈主要分为三层，即应用层、主机层和控制器层。此外，主机层和控制器层通过主机控制器接口（Host Controller Interface，HCI）进行交互。

控制器层又包含链路层（Link Layer，LL）和LE物理层（LE Physical Layer，PHY）。其中物理层主要负责信号调制和解调，并计算连接过程中设备的跳频模式。链路层则负责包括管理设备的蓝牙地址、加密和连接启动以及处理广播数据包等在内的多项工作。

主机层所包含的部分最为重要，这部分内容在对BLE进行漏洞利用时会直接用到，包括通用访问配置文件（Generic Access Profile，GAP）和通用属性配置文件（Generic ATTribute profile，GATT）。

GAP负责控制大部分的广播和连接初始化，并定义通信过程中出现的各种设备的角色。

GATT位于ATT（属性协议）的顶部，而ATT是负责主从设备数据交换的组件，并执行读、写和错误处理等操作。GATT在ATT之上增加了一个总体数据组织层，使之更容易理解。在GATT中，所有数据均按照图7-24所示方式加以组织。

图　7-24

从图7-24中可以看到，总体数据由最小元素特征（Characteristic）组成，每个特征中又包含一个值（Value）和描述符（Descriptor）。举个例子，心率（heart-beats-per-minute）即是特征的一个实例，心率值就储存在特征当中。特征具有唯一的UUID，该UUID可以从蓝牙SIG（Special Interest Group，SIG）的数据库中找到，蓝牙SIG数据库特征UUID列表的链接为https://www.bluetooth.com/specifications/gatt/characteristics。

接着，多个相似的特征会包含在同一个服务当中。以心率服务（heart-rate-service）为例，该服务就包含心率、不规则心率（irregular-heart-heats）和急性焦虑（panic-attack）等特征。每个服务均会包含一个16比特的UUID，这些UUID也可以从蓝牙SIG数据库的服务UUID列表中找到，蓝牙SIG数据库的服务UUID列表的链接为https://www.bluetooth.com/specifications/gatt/services。

再接下来，整个服务又包含在一个配置文件（Profile）中，该配置文件是一个通用配置文件。以之前介绍的心脏健康配置文件为例，该文件中就包含了多项服务，如心率服务和心脏含氧量服务（heart-oxygen-service）。

如前文所述，嗅探的目标是找到正在被读取和写入的特征值。这些特征通常也称为句柄，捕获到相关流量时就会看到句柄值。

继续往下看，BLE协议栈的另一个重要的组成部分是L2CAP。L2CAP表示逻辑链路控制与适配协议层，主要负责从其他层获取数据，并将数据以BLE报文结构进行封装。

以上就是在开始针对BLE进行漏洞利用之前所需掌握的基本知识。接下来，让我们开始实际操作吧。

7.6.1　准备工作

在开始进行BLE漏洞利用之前，需要准备好以下工具：

·软件：

■Blue Hydra或HCI Utils

■Ubertooth相关软件

■Gattacker

·硬件：

■BLE适配器

■Ubertooth或类似的BLE嗅探器

在研究BLE时我们采取以下方法，首先找出目标设备的地址，然后在对目标BLE设备进行操作时嗅探该地址的流量。

这样就能够找到写入设备以执行特定动作的BLE句柄了。那什么是BLE句柄呢？简单来说，BLE句柄就是对BLE特征所具有的多种属性的引用。

在本节中，我们首先需要完成实验环境的部署，部署步骤如下。

将蓝牙适配器连接到虚拟机，随后读者可以看到hci接口，接口信息如图7-25所示。

图　7-25

紧接着，从官方GitHub代码库中下载以下工具：

·Blue Hydra（用于BLE设备的初期侦测）：https://github.com/pwnieexpress/blue_hydra。

·Ubertooth（针对BLE设备进行数据包嗅探和捕获操作）：https://github.com/great-scottgadgets/ubertooth。

·Wireshark（数据包分析工具，兼容BLE）：https://www.wireshark.org/download.html。

安装配置完成之后，我们就可以开始对身边的BLE设备进行测试了。

7.6.2　测试流程

1）首先，查找附近的BLE设备并确定它们的蓝牙地址，进而同BLE设备进行交互。操作命令如下所示：

2）这一步用到了Hcitool的lescan（低功耗扫描）功能，搜索附近所有的BLE广播，执行结果如图7-26所示。

正如读者所看到的，运行结果显示工具识别出了周围的设备以及它们的地址，接下来可以使用Ubertooth来嗅探某台特定设备的流量。

图　7-26

Ubertooth One是由Michael Ossman开发的一款设备，作用是评估蓝牙设备的安全性，Michael Ossman来自开源硬件组织Great Scott Gadgets。Ubertooth One由一个CC24002.4 GHz的RF收发器和一个带有USB接口的NXP LPC1756微控制器组成。

对于安全研究人员和渗透测试人员来说，Ubertooth One可以用来帮助发现包括明文数据传输在内的很多安全隐患，还可以用来识别网络通信中正在写入和读取的句柄。

3）可以通过以下命令来运行Ubertooth，嗅探某台特定设备的流量：

4）在前面的命令中，可以将[address]替换为之前步骤中获得的设备地址。

如果我们想进行主动流量拦截的话，[capture-output]可以是一个文件，也可以是一个管道。

下面，我们以管道/tmp/pipe作为流量捕获接口，该管道的一端接收来自Ubertooth的输入信息，另外一端在Wireshark显示数据。

5）新打开一个终端窗口，输入mkfifo/tmp/pipe。完成操作后，找到Wireshark|Cap-ture Interfaces|Manage Interface|New Interface|Pipes，添加新建管道/tmp/pipe并保存。

6）接着，在Wireshark中对新建的/tmp/pipe接口进行嗅探。根据用户执行的操作以及目标设备的类型，就可以在Wireshark中观察到BLE流量了，如图7-27所示。

在图中所示的数据包捕获过程中，我们已经设置了过滤器btl2cap.cid==0x004，作用是对蓝牙中的L2CAP协议进行过滤，确保捕获到的数据包中包含对我们有用的数据。在图7-27中，还可以看到有许多读写请求报文，请求报文中包含了句柄的详细信息和写入该特定句柄的值。本例中，可以看到句柄0x0037的值为1，对应于基于BLE的智能锁处于开锁状态。

既然已经知道了句柄中同执行某一特定操作所对应的值，那么现在就可以直接将该值写入句柄，而无须再借助Ubertooth工具。在这一过程中，我们将会用到BLE适配器和一款叫作gatttool的工具。

7）首先启动gatttool，如下所示，同时使用-b和-I参数，参数的作用分别是提供蓝牙地址，以及进入gattool的interactive模式对蓝牙设备进行控制：

图　7-27

8）接着，需要向目标设备发送一个写入请求，指明想要写入句柄的值，如图7-28所示。

图　7-28

更改完成后就实现了智能锁的解锁。因为智能锁检测到句柄0x0037的当前值为01，这表示智能锁当前处于解锁状态。

这就是用户同基于BLE的IoT设备的交互方式，首先找出需要重新写入的句柄，然后再自行写入句柄值。

9）读者也可以通过查看所有服务的句柄值来查看设备的其他属性，如图7-29所示。

图　7-29

10）同样，对特征也可以执行类似的操作，如图7-30所示。

图　7-30

7.6.3　拓展学习

为了有效地嗅探BLE流量，在BLE的3个广播信道中，识别出目标设备采用的广播信道非常重要。因此，需要部署3套Ubertooth设备，仅仅1套设备是不够用的。

此外，读者还可以尝试选择其他工具开展测试：

·btlejuice：如果想要在Web GUI界面上对BLE通信流量发起MITM攻击，该工具将会是一个实用的工具。

·Gattacker：和btlejuice类似的工具，但是没有GUI。

·BLEah：用于BLE信息采集。

第8章　固件安全最佳实践

本章将探讨以下主题：

·内存崩溃漏洞防护。

·注入攻击防护。

·固件更新保护。

·敏感信息保护。

·嵌入式框架加固。

·第三方代码及组件的保护。

8.1　简介

尽管嵌入式开发人员和IoT设备厂商往往并未对嵌入式应用的安全给予足够的重视，但是嵌入式软件依然被视作IoT的核心。而究其缺乏重视的原因，可能源自开发人员安全编码知识的匮乏，也可能源自代码开发团队之外的因素。抛开安全编码方面的问题，ODM的供应链、有限的内存存储空间、尺寸较小的堆栈以及如何将固件更新安全地推送到终端等问题对于开发人员而言都可能构成安全隐患。本章主要对嵌入式固件应用的最佳实践进行介绍，根据OWASP嵌入式应用安全项目（https://www.owasp.org/index.php/OWASP_Embedded_Application_Security），嵌入式应用最佳实践包括：

·缓冲区和堆栈溢出防护。

·注入攻击防护。

·固件更新保护。

·敏感信息保护。

·身份管理控制措施。

·嵌入式框架和基于C语言的工具链加固。

·调试代码和接口的用法。

·设备通信保护。

·信息搜集和存储的用法。

·第三方代码保护。

·威胁建模。

下面，本节将以POSIX环境为例重点对上述最佳实践进行介绍，但是原理对于其他平台也是适用的。

8.2　内存崩溃漏洞防护

当使用C语言等低级语言时，如果开发人员未对边界进行检查和验证，很容易导致内存崩溃漏洞。而通过禁止使用已知的危险函数和API调用则有助于防范固件中可能存在的内存崩溃漏洞。举例来说，已知的不安全的C函数包括（但不限于）：strcat、strcpy、sprintf、scanf和gets等。常见的内存崩溃漏洞，如缓冲区溢出或堆溢出漏洞都是由内存栈溢出或堆溢出所导致的。对内存崩溃漏洞进行利用所造成的影响根据操作系统的不同也有所区别。以商用RTOS平台QNX Neutrino为例，该系统会将系统中每个进程及进程堆栈同文件系统相隔离，从而减少攻击面。然而，普通的嵌入式Linux操作系统则并未采取与QNX Neutrino操作系统相同的处理方式。所以，嵌入式Linux操作系统中的缓冲区溢出漏洞就可能导致恶意代码的执行，并允许攻击者对操作系统进行篡改。在本节中，我们将展示如何使用工具来帮助检测存在漏洞的C函数，并介绍内存崩溃漏洞防护的安全控制措施以及最佳实践。

8.2.1　准备工作

本节中将会用到以下工具：

·flawfinder：flawfinder是一款免费的C/C++静态代码分析工具，能够帮助分析人员发现潜在的安全漏洞。

8.2.2　测试流程

虽然在防护内存崩溃漏洞方面，除了开发人员常用的IDE插件，有些商业源码分析工具可以取得更加理想的防护效果。但是，一些常见的Linux工具就可以用于在C/C++代码文件中进行搜索。在这里，出于展示的目的，将介绍如何使用grep和flawfinder两款工具在代码文件中进行搜索，进而查找预先定义的可能存在漏洞的函数调用和规则。

1）有很多种方法可以用来查找文件中不安全的C函数。其中，最简单的方法是使用以正则表达式为参数的grep命令，类似下面的例子：

用户在使用时可以对命令中的正则表达式进一步加以调整，或者也可以将命令封装在脚本中，每次程序编译之前执行该脚本，或者根据需要随时执行该脚本来查找文件中不安全的C函数。

2）除了grep命令，用户还可以使用flawfinder等免费工具搜索可能存在漏洞的函数，操作时直接调用flawfinder程序，并以所要分析的代码片段的路径为参数即可，操作命令如下所示：

3）如果发现了可能存在漏洞的C函数，读者必须准备好安全的替代方案。举个例子，下面的示例代码中使用了不安全的gets()函数，而该函数并未检查缓冲区长度，因此存在安全隐患：

4）对于上面的示例代码，任意超过8个字符的字符串都会超过字符串userid的长度，例如缓冲区溢出漏洞利用（BoE）代码，攻击者通常会通过漏洞利用代码来实现自定义的功能。为了缓解缓冲区溢出漏洞，开发人员可以使用fgets()函数作为安全的替代方案。以下示例代码展示了如何安全地使用fgets()函数，并正确地分配内存：

其他能够实现漏洞缓解的安全替代函数还包括snprintf()、strlcpy()和strlcat()等。根据操作系统平台的差异，某些安全替代函数可能并不适用于所有平台。所以对于读者而言，根据自身架构和平台的特点，研究找到适合自己的安全替代方案非常重要。英特尔公司就自己开发了一套名为safestringlib的开源跨平台库函数，用来帮助开发人员使用安全的替代函数，而避免使用存在安全隐患的禁用函数。更多有关safestringlib库函数的细节，可以访问GitHub代码库链接https://github.com/01org/safestringlib。

还有其他一些内存安全控制措施也可以用于防止内存崩溃漏洞的出现，例如：

·使用安全的编译参数，例如-fPIE、-fstack-protector-all、-Wl、-z、noexecstack、-Wl、-z、noexecheap，以及其他依赖于特定编译器版本的参数。

·优先选择包含内存管理单元（MMU）的片上系统（System-on-Chip，SoC）和微控制器（MCU）。如果出现针对内存的漏洞利用情况，MMU就会隔离线程和进程以减少攻击面。

·优先选择包含内存保护单元（MPU）的片上系统和微控制器。MPU能够确保强制执行内存和独立进程的访问控制规则及特权规则。

·如果MMU或MPU都未采用，则可以使用特定比特来监视堆栈，通过计算有多少堆栈已不再包含特定比特来监控堆栈的消耗情况。

·要注意缓冲区中存放的内容，并在使用后清空缓冲区。

如果系统采用了地址空间布局随机化（ASLR）以及其他堆栈保护措施，那么对于攻击者而言针对这类系统的内存漏洞利用就比较棘手了，需要花费较多的精力和时间。但是，即使用户采用了堆栈保护措施，在某些情况下攻击者也可能成功实施攻击。对此，读者也不要沮丧，只要确保所开发的代码能够抵御攻击，同时采用纵深防御方法对内存中的数据加以保护，都还是有助于提高嵌入式设备安全性的。

8.2.3　延伸阅读

可以参考卡内基梅隆大学发布的C语言安全编程规范，了解更多内存安全管理方面的指导：https://www.securecoding.cert.org/confluence/display/c/SEI+CERT+C+Coding+Standard。

可以参考卡内基梅隆大学发布的C++语言安全编程规范，该规范也提供了很多内存安全管理方面的指导：https://www.securecoding.cert.org/confluence/pages/viewpage.action?pageId=637。

8.3　注入攻击防护

注入攻击是Web应用中最常见的漏洞之一，特别是在IoT系统中。事实上自2010年以来，在OWASP排名前10的漏洞中，注入攻击一直位居前2名。注入攻击的类型很多，如操作系统（OS）命令注入、跨站脚本注入（如JavaScript）、SQL注入、日志注入，以及表达式注入等。在IoT和嵌入式系统中，最常见的注入攻击是OS命令注入和跨站脚本注入（XSS），其中命令注入就是当某一应用在未对输入进行验证或者未对输入进行正确的转码时，接收了不可信的用户输入，并将该输入传递至应用后台执行shell命令。本节将向读者展示，如何对所有不可信数据和用户输入采取验证、过滤或者其他安全控制措施，从而缓解命令注入攻击。

8.3.1　测试流程

当IoT设备运行时，采用动态或静态方法开展针对命令注入漏洞的测试其实并不难。固件可以调用system()、exec()以及上述命令的变体来执行OS命令，也可以调用外部脚本来执行，其中在外部脚本中执行OS调用时可能用到Lua以及与之类似的解释语言。命令注入漏洞也可能是由缓冲区溢出导致的。下面，我们以存在命令注入漏洞的代码为例，介绍如何缓解命令注入攻击。随后，我们将列出常用的安全控制措施来阻止常见的注入攻击。

1）在下面的代码片段中，可以看到代码中调用了C函数system()来删除home目录中的.cfg文件。如果攻击者能够控制该函数，那么在后面串接shell命令就可以执行未经授权的操作。此外，攻击者还可以篡改函数参数，删除所有以.cfg结尾的文件：

2）这里，为了缓解前面存在漏洞的代码所可能造成的影响，我们建议使用unlink()函数而非system()函数。因为相较于system()函数，unlink()函数更不易遭受符号链接和命令注入攻击。unlink()函数的作用是移除符号链接，而不会对由符号链接内容所指定的文件或目录产生影响。然而，虽然这一工作原理降低了unlink()函数遭受符号链接攻击的可能性，却并不能完全阻止符号链接攻击，因为如果对目录以相同的名称进行重命名，那么该目录也是可以被删除的。不过unlink()函数确实能够阻止命令注入攻击，但需要注意同相关函数配合使用，而非直接执行该系统调用：

此外，还有其他几种方法也可以用于缓解注入攻击。下面是阻止注入攻击的常用的最佳实践和控制措施：

·尽可能避免直接进行OS调用。

·如果需要的话，建立可接收命令的白名单，并在命令执行之前对所接收的输入加以验证。

·如果用户输入的字符串可能传递给操作系统，那么可以“采用编号-命令字符串”的方式对用户输入进行映射，例如{1：ping-c 5}。

·对代码进行静态分析，当代码用到os.system()等OS命令时需格外留意。

·默认所有的用户输入都是不可信的，并将返回给用户的数据以转义字符的形式进行输出。（例如，将&转义为&amp，将<转义为&lt，将>转义为&gt等）。

·针对XSS漏洞，使用X-XSS-Protection和Content-Security-Policy等http响应报头，并采用适当的方式对其加以配置。

·确保在量产的固件版本中禁用了带有命令执行功能的调试接口（例如http://example.com/command.php）。

在将固件部署到生产环境之前，通常要求根据上述提到的这些控制方式对固件进行测试。因为，注入攻击可能导致设备和用户面临被攻击者和流氓设备接管的风险。这并非危言耸听，在2017年Reaper和Persirai等IoT僵尸网络发起的攻击中，我们已经看到了此类事件的发生。而需要注意的是，这还仅仅是一个开始。

8.3.2　延伸阅读

更多注入攻击预防指南和注意事项，可参考OWASP的嵌入式应用程序安全项目（https://www.owasp.org/index.php/OWASP_Embedded_Application_Security）和OWASP XSS防欺骗指南（https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet）。

8.4　固件更新保护

根据行业的不同，通常只有来自制造商、供应商或企业授权的固件才能够刷进设备。为了确保刷入设备的固件经过了授权，在下载固件或者更新第三方软件或库文件时必须采用健壮的更新机制。因此，所有固件都应采用加密签名，以便对固件进行验证，从而确保，开发人员创建固件并对其签名之后，该文件未经改动或篡改。签名和验证过程采用的是公钥加密，在未获得私钥的情况下，很难伪造数字签名（例如PGP签名）。当使用公钥加密技术时，必须确保私钥存储安全，无关用户无法获取私钥。而如果私钥泄露，软件开发人员必须撤销泄露的密钥，并采用新的私钥对所有之前的固件版本重新进行签名。有些IoT设备商要求用户将设备寄回或送到售后服务站，因此固件更新对于设备商而言一直是一个令人头疼的问题。固件更新保护的实现细节会根据IoT设备部署行业的不同而有所区别。例如，有些产品可能具备无线（Over The Air，OTA）更新功能，而另一些产品可能需要通过USB接口或加载新固件镜像的界面进行手动更新。对于消费级IoT设备来说，选择何种更新方式可能不会有太大影响，但是对于工业级IoT设备而言，如果更新方式选择不慎，则可能导致未经授权的恶意固件被加载到网联汽车或医疗设备中，进而导致人身伤亡、经济损失等严重后果。在本节中，我们将对固件更新的保护机制进行介绍。

测试流程

在为嵌入式IoT设备构建安全的更新系统时，需要考虑许多变量和因素。受各种条件的限制，某些架构、SoC或者bootloader可能难以应用具备抗攻击能力的固件更新系统。鉴于安全更新系统实现的复杂性和多样性，本节将主要介绍制造商在固件更新设计中应该加以集成的高级控制措施。为简单起见，我们使用嵌入式Linux作为测试平台，并提出了实现安全更新系统所需的必要条件。不过，下面所提出的必要条件也未必都适用，但重要的是，对于设备厂商来说，在采用安全更新系统时需要承担起属于自己的责任并了解相关的风险。下面列出了为实现安全固件更新可以采用的安全控制措施和要求。

1）实现bootloader的安全引导或者对引导过程加以验证。

2）使用安全硬件芯片（例如TPM、HSM、安全元件等）对启动密钥加以保护。

3）确保更新机制在进行功能更新时采用了密码签名的固件镜像。

4）固件镜像在下载后以及刷进设备之前必须进行验证。

5）确保更新可以通过最新的TLS协议版本进行下载（截止本文撰写时TLS协议的最新版本为TLS 1.2）：

·确保更新过程会对公钥进行验证，并对更新服务器链进行认证。

6）包含固件自动更新功能，可以设置计划任务进行更新：

·对存在高危漏洞的固件版本进行强制更新。

·对于医疗设备等设备，应考虑将固件更新推送列入计划任务，避免强制更新导致安全隐患。

7）确保能够清晰地显示固件版本。

8）确保固件更新中包含更新日志，并对安全相关的漏洞进行说明。

9）通过电子邮件、应用通知或登录界面，通知用户存在可用的新版本的固件更新。

10）确保设备采用了反降级保护（反回滚）机制，使设备无法恢复到存在漏洞的固件版本。

11）考虑构建完整性度量架构（Integrity Measurement Architecture，IMA），该架构能够帮助内核通过对存储的或者计算得到的散列值（称作标签）进行验证来检查文件是否已被篡改。制造商还可以使用扩展验证模块（Extended Verification Module，EVM）检查文件属性（包括扩展属性）。

其中标签有两种类型：

·不可变的和已签署的标签。

·简单的标签。

12）考虑实现只读根文件系统，可以为有本地持久化需求的目录创建覆盖层。

安全更新系统高度依赖于公钥加密技术对固件镜像的签名和验证。这就需要基础设施和管理机制对设备签名和密钥验证进行全生命周期的维护。当密钥泄露或者需要进行更新时，应该在生产部署之前进行测试，以防止设备瘫痪。即便如此，还可以采用第三方公司提供的无线固件（FOTA）更新服务，从而将安全责任转移到服务提供商。但是如果选择无线固件更新服务，对于像网联汽车这样的产品来说成本可能非常昂贵，因为制造商必须为网络数据买单。在选择更新机制时，可以考虑采用多种框架，例如Update Framework更新系统（https://theupdateframework.github.io/）以及网联汽车适用的Uptane更新系统（https://uptane.github.io/）。

8.5　敏感信息保护

由于IoT设备存储空间有限且利润微薄，所以敏感数据的保护对于IoT设备而言是一个难题。通常，敏感数据会存储在客户端应用或设备中，这样即便在IoT设备不联网的情况下也能够提供服务。保护设备中的敏感数据时，需要遵循下面提出的安全原则。首先，永远不要在发布的固件中包含硬编码的敏感信息，例如口令、用户名、令牌、私钥等类似的数据，也不要在磁盘中存储敏感数据。这是因为攻击者可以通过提取固件文件系统，或者在运行时访问操作系统的方式获取这些数据。如果设备采用了安全元件（Security Element，SE）或可信执行环境（Trusted Execution Environment，TEE）等硬件，那么建议在运行时使用这些硬件来存储敏感数据。否则的话，可以借助服务器端的计算资源，使用强度较高的密码来保护数据，从而弥补硬件的不足。

如果可能的话，所有明文形式的敏感数据应当均为临时数据，并且只存储在易失性存储器中。本节将向读者展示部分场景，这些场景中的数据均未被安全使用，并向读者介绍如何在IoT设备中缓解不安全C代码所带来的安全威胁。

8.5.1　测试流程

下面我们将通过代码实例对不安全的数据存储方式加以展示，并对如何修复存储方式中的脆弱点进行介绍。

1）下面的例子中，敏感信息存储在变量key中，变量key的存储空间通过动态分配得到，其中内容继而被复制到了动态分配的缓冲区new_key中，随后进行处理，最终调用free()函数回收内存空间。但是，敏感信息的这种存储方式并不安全。因为内存中的内容并未被完全清除，而这部分内存可能被重新分配给程序的其他变量，从而可能导致存储在new_key中的信息意外泄露：

2）为了防止上述敏感信息泄露事件的出现，包含敏感信息的动态内存应该在释放之前进行擦除。擦除过程通常可以采用写入“\0”字符来覆盖之前分配的内存空间，这一过程也称为归零。

在设备未采用安全硬件芯片对操作系统进程和内存空间进行隔离的情况下，可以直接使用上面的代码示例。如果确实没有安全硬件芯片（例如TPM或SE），对于ARM架构而言则是未采用TEE环境，嵌入式设备将很难实现数据的安全存储。有时，开发人员会选择将敏感数据存储在操作系统无法读取的分区中，但这也并非安全的存储位置。因为攻击者可以从PCB上移除闪存芯片，将其置于离线环境中进行分析或者进行数据提取。

当前产业界已经提出了部分新的框架和操作系统平台，这些新框架和新系统的涌现有助于解决敏感数据的存储问题。例如，ARM Mbed操作系统包含了一个名为uVisor的系统设备安全层，通过硬件安全特性限制对内存的访问实现了对代码块的隔离。尽管Mbed操作系统还处于开发初期，但其已经得到了许多大型半导体公司的强力支持，此外，ARM不仅提供了操作系统运行的平台，而且还提供了与之相关的云服务。

8.5.2　延伸阅读

·关于uVisor的更多细节可以访问以下链接：https://www.mbed.com/en/technologies/security/uvisor/。

·uVisor的示例代码在GitHub代码库中的下载链接如下：https://github.com/ARMmbed/mbed-os-example-uvisor-number-store。

·有关Mbed操作系统的更多信息，可访问以下链接：https://www.mbed.com/en/。

8.6　嵌入式框架加固

嵌入式固件的设计和构建非常复杂，不仅因为固件的依赖项众多，还因为纷繁复杂的makefile文件可能已经十余年没有人碰过了。鉴于这种复杂性，在这里我们首先从平台和工具链的加固开始安全软件的构建。许多嵌入式Linux设备都会用到BusyBox，因为其中包含了很多常用的GNU工具。使用前，需要对BusyBox进行专门配置，并进行更新。除了BusyBox之外，还需要对嵌入式框架和工具链进行调整，确保固件构建时只用到需要的库文件和功能。RTOS系统通常提供符合POSIX标准的工具，不过多是由SoC、MCU和芯片厂商进行配置。至于工具链环境部署和配置，一般由Buildroot、Yocto等嵌入式Linux构建系统来完成。这里，我们建议移除不安全的库文件、不采用Telnet等不安全的协议，这样不仅可以减少固件构建中攻击的入口点，还形成了一套安全的设计方法来构建软件，可以规避潜在的安全威胁。在本节中，我们将对Buildroot如何选择和禁用某些网络服务和配置的操作进行介绍。

8.6.1　准备工作

在本节中，我们以Buildroot为例来展示加固过程。

Buildroot是一款简单、高效、易用的交叉编译工具，主要用于实现嵌入式Linux系统的自动化构建。Buildroot能够生成交叉编译链、根文件系统、Linux内核以及目标架构的bootloader。用户可以对Buildroot中的配置选项进行任意组合，其源代码可以通过以下链接下载：https://buildroot.uclibc.org/download.html。

8.6.2　测试流程

我们从Buildroot的用法开始介绍，首先打开Buildroot菜单选项进行配置。

1）Buildroot下载完成后，在Buildroot文件夹下执行以下命令，此时屏幕上会显示出Buildroot的配置选项：

用户也可以根据自己习惯，选择其他用户配置界面，如xconfig和gconfig。更多相关细节，可查看Buildroot的用户手册：https://buildroot.uclibc.org/downloads/manual/manual.html。

2）配置界面如图8-1所示。

图　8-1

3）在这里可以对Linux固件镜像进行配置。本节中，我们主要关注如何选择安全的系统服务以及如何进行安全的默认设置。

4）接下来，进入Toolchain菜单，启用堆栈保护选项Enable stack protection support，即在构建时使用-fstack-protector-all参数，如图8-2所示。

图　8-2

5）来到主菜单屏幕并进入System configuration菜单。选择Password encoding再选择sha-512加密算法，如图8-3所示。

图　8-3

6）同样在System configuration菜单中，还可以进入Root password选项为固件镜像创建根口令。这里使用一个包含有字母和数字的长字符串作为口令，如图8-4所示。

图　8-4

7）退出System configuration菜单进入到Target packages菜单。在Target packages菜单中可以将指定工具、库文件、系统服务和第三方代码纳入进固件镜像中。根据设备的不同，用户可以有许多种选择，此处只举其中一个例子。如图8-5所示，这里选择了openssh系统服务，但是未选择Telnet系统服务。

在启用FTP服务时需要采用TLS协议。以Pure-FTPd为例，即意味着在编译时需要传入./configure--with-tls参数。

图　8-5

8）回到Target packages菜单并选择Shell and utilities子菜单。这里需要确保只选择了一个shell解释器，因为只选择一个shell解释器有助于减少攻击面，如图8-6所示。

所有选项选择完毕之后，保存配置并选择退出配置菜单。然后在Buildroot文件夹下输入make就可以来构建属于自己的配置和工具链了。

图　8-6

使用Yocto构建系统时也可以采取类似的步骤，但是需要确保使用所要求的代码包对所涉及的recipes方法进行更新与配置。此外，还可以选择其他配置选项来加固Linux构建环境，包括：

1）移除未用到的解释器，如Perl、Python和Lua等。

2）删除库函数中的无用代码。

3）移除环境中不安全的系统服务，包括但不限于Telnet、FTP和TFTP等服务。

4）将未用到的shell工具从Busybox中删除，例如grep、awk、wget、curl和sed等。

5）对库文件或服务进行加固以支持加密。

6）确保构建时所选择的所有包和库文件均为最新版本。

7）使用最新的Linux内核。

8）禁用IPv4转发。

9）禁用IP源路由。

10）禁用ICMP协议。

11）忽略所有广播报文。

12）禁用IPv6协议。

13）启用TCP SYN Cookie保护措施。

14）使用Linux安全模块（包括SELinux）。

15）使用Lynis等免费工具来获取构建完成后的加固建议（https://raw.githubusercontent.com/CISOfy/lynis/master/lynis）。

前面提到的对嵌入式框架进行加固的做法肯定还不完整。如果能够协同开发人员及相关人员一起对嵌入式设备中的软件开展威胁建模迭代，则有助于避免一些常见的安全风险，例如不在嵌入式设备中选用某些软件存在漏洞的早期版本，就能够避免很多安全风险的引入。

8.7　第三方代码及组件的保护

在工具链部署完成并且IoT设备投入量产后，确保软件包和第三方库文件始终是最新的版本才能够有效应对公开的已知漏洞。对照漏洞数据库及其更新日志，可以采用黑盒测试方法对RomPager、NetUSB等第三方软件和Buildroot等嵌入式构建工具进行检查，来决定何时以及是否需要更新。而使用上游BSP驱动也不是一件简单的事。开发团队在发布构建之前应该对库文件和上游BSP驱动所做出的的改动进行测试，因为对库文件的改动可能会导致不可预见的依赖性问题。

嵌入式项目和应用需要维护一份物料清单（Bill Of Material，BOM），清单中涵盖了固件镜像中所包含的第三方库文件和开源软件。维护这份清单有时是世界上某些管制地区和GPL明确提出的要求，但该清单的维护也的确有助于改善对资产以及库文件的管理。同时，研发人员或者安全人员需要依据清单开展核查，确保其中所有第三方软件中不存在未修补的漏洞或已知的安全隐患。有关最新的漏洞信息，可以从美国国家漏洞数据库（National Vulnerability Database，NVD）、Open Hub等第三方网站获得。

在将固件交付给市场部门之前，开发人员需要确保已经删除了所有不必要的前期构建代码、无用的和未用到的应用代码。这些代码包括但不限于原始设计制造商（ODM）、供应商和第三方承包商出于测试或售后支持等目的所遗留的潜在后门代码和root特权账户。一般来说，这属于原始设备制造商（OEM）的职责范畴，OEM可以采用本书第3章所描述的方法，对二进制文件进行逆向分析来查找可能隐藏的后门。为了降低OEM额外的人力成本，ODM应该签署总服务协议（Master Service Agreement，MSA），确保提交的代码不包含隐藏后门或特权账户，且全部代码均经过了安全审计，并且让第三方开发公司为在市场中大规模部署的设备承担相应的责任。此外，还要考虑建立安全管理制度，要求ODM设置信息安全岗位，签署服务级别协议（Service Level Agreement，SLA）确保关键安全漏洞的修复。在本节中，主要就如何使用免费工具来确保第三方代码和组件的安全来向读者展开介绍。

8.7.1　准备工作

本节中需要用到以下工具：

·RetireJS：RetireJS用于检测包含已知漏洞的JavaScript库的使用情况。该工具可以通过GitHub代码库下载（https://github.com/RetireJS/retire.js）或使用npm命令下载，操作命令如下：

·Node Security Platform（NSP）：NSP用于检测项目中存在已知漏洞的NodeJS包的使用情况。该工具可以从GitHub代码库下载（https://github.com/nodesecurity/nsp）或使用npm命令下载，操作命令如下：

·LibScanner：LibScanner是一款免费工具，作用是依据NVD漏洞数据库对Yocto构建环境中使用的RPM或SWID包列表进行解析。LibScanner可以从GitHub代码库中下载，链接为https://github.com/DanBeard/LibScanner。

8.7.2　测试流程

很多IoT设备都会通过各种形式的JavaScript代码来缓解对硬件资源的消耗。有时，当需要将IoT设备在某些场景中用作服务器时，这些JavaScript代码也会在该设备上运行。有很多工具都可以用来扫描项目目录，查找项目中存在已知漏洞的JavaScript脚本。下面，我们首先来讨论RetireJS的用法。

1）运行RetireJS，只需输入retire命令并指定JavaScript目录即可，执行结果如下所示：

在上面的扫描结果中，我们发现项目用到了两个存在漏洞的jQuery库文件，同时还打印出了对存在漏洞的jQuery库文件的一些补充说明和解释。这些暴露出来的安全隐患可能导致设备遭受攻击，但如果能在设备量产之前就发现这些安全隐患，则能够大大降低解决这些安全隐患的成本。

2）NSP是一款非常不错的NodeJS漏洞扫描器。同RetireJS类似，NSP可以通过执行nsp命令，以NodeJS项目目录或packages.json的路径为参数来运行扫描器。运行结果如下所示：

在执行结果中可以看到，NSP发现了一个存在漏洞的库文件，它可能会导致设备遭受命令注入攻击，这也是在IoT设备中很常见的漏洞。

3）如果IoT设备使用的是Yocto构建系统，那么就可以使用免费工具LibScanner在NVD漏洞数据库中查询存在已知漏洞的库文件，查看存在已知漏洞的库文件是否出现在了项目安装包的文件列表之中。使用LibScanner时，需要运行以下命令更新漏洞数据库：

4）NVD漏洞数据库更新完成之后，根据Yocto中文档installed-packages.txt中的指示要求运行LibScanner，操作命令如下所示：

5）执行完成后可以查看cve_results.xml文件，该文件中不仅包含存在漏洞的库文件的扫描结果，还包含了以xUnit格式显示的单元测试结果：

还有一些工具可以在设备构建之前进行静态分析，或者在设备构建后及设备运行时开展动态分析。在之前的章节中，我们已经对部分动态测试工具进行了介绍，例如用于Web应用测试的OWASP ZAP与Lynis等工具，这些工具可以直接在设备的命令行界面中运行。所有这些工具的应用都有助于增强设备的安全性，进而将针对设备成功实施攻击的可能性降到最低。

本章主要对在构建和编写固件过程中的最佳实践进行了讨论，同时我们也建议读者结合自己的操作系统平台（也就是嵌入式Linux、RTOS、Windows IoT等操作系统）开展研究，了解IoT设备所采用的安全控制措施。

第9章　移动安全最佳实践

本章将主要探讨以下主题：

·数据存储安全。

·认证控制措施的实现。

·数据传输安全。

·Android与iOS平台下组件的使用安全。

·第三方代码与组件安全。

·针对逆向分析的保护措施。

9.1　简介

通常，移动应用是控制消费级IoT设备的关键。无论是智能家居设备还是网联汽车，移动应用向来都是发起攻击的理想目标，同时也是安全防护的重点。本书第5章从攻击的角度对移动应用的漏洞利用进行了介绍，而本章将讨论的是针对常见的攻击向量，移动应用可以采取的安全防护控制措施。其中需要重点指出的是，同众多专注于移动安全最佳实践的专著相比，本章中对移动安全最佳实践的介绍难以面面俱到。因此，强烈建议读者查阅延伸阅读中的内容，以便更加深入地了解本章中介绍的安全控制措施和最佳实践。结合对最佳实践的介绍，本章中将提供相关的Android和iOS实例。根据OWASP提出的移动安全项目（https://www.owasp.org/index.php/Projects/OWASP_Mobile_Security_Project_-_Top_Ten_Mobile_Controls），排名前十的移动安全控制措施包括：

1）敏感数据识别与保护。

2）认证信息保护。

3）数据传输保护。

4）用户身份认证、授权和会话管理的正确实现。

5）后端API（服务）与平台（服务器）的安全保障。

6）同第三方服务与应用之间的数据集成安全。

7）搜集和使用用户数据时，需要特别关注是否获得了用户对数据搜集和存储的许可。

8）对付费资源实施控制措施防止未经授权的访问。

9）移动应用的安全分发与安全交付。

10）代码运行时解释的错误检测。

在本章中，将重点选取同常见IoT应用实例相关的若干种移动安全控制措施进行介绍。

9.2　数据存储安全

移动应用中的敏感数据会根据IoT设备的类型而有所区别。许多设备都会存储并收集诸如患者健康信息（Patient Health Information，PHI）、信用卡信息之类的个人数据，同时还会在移动设备中存储账户认证信息以便对IoT设备进行身份认证。对于智能门锁和网联汽车来说，泄露的认证信息或长期会话令牌（session token）可能导致后果非常严重的影响，因此需要采取适当的控制和验证方法才能确保这些敏感数据的安全。很多时候，敏感数据会因操作系统中的进程间通信（IPC）机制在不经意中暴露给运行于移动设备之上的第三方应用。此外，移动设备丢失、在旅行途中被窃或者被他人接触的情况也不少见。在这些情况下，移动应用也应当采取适当的安全控制措施来保护敏感数据，提高数据的获取难度。在本节中，我们将重点探讨敏感数据的安全存储方法。

9.2.1　准备工作

本节中将采用SQLCipher加密工具来演示数据库的安全存储方法。SQLCipher可以从以下链接下载得到：https://www.zetetic.net/sqlcipher/。

9.2.2　测试流程

无论是Android还是iOS平台都提供了敏感数据安全存储的原生方法。对于Android来说，敏感数据存储在KeyStore文件中；而对于iOS而言，敏感数据则存储在Keychain文件中。需要注意的是，如果设备已被root或越狱，那么Android平台下KeyStore文件和iOS平台下Keychain文件的内容都可以被转储。而如果某台Android设备拥有可信执行环境或者采用了安全元件（SE），那么操作系统则无法直接访问KeyStore文件，从而也就无法访问其中保存的数据。除了可以采用原生平台API之外，数据的安全存储还可以通过第三方工具对磁盘中的数据或者整个SQLite数据库进行加密来实现，就比如SQLCipher加密工具。如果IoT设备采用了SQLite数据库，那么Android和iOS平台就可以采用SQL-Cipher对数据加密来实现数据的安全存储。

1）要在Android应用中使用SQLCipher，我们首先需要创建一个activity来初始化SQLCipher数据库，并在数据库中选取适当的表和字段保存数据，示例代码如下所示：

2）上面示例代码中并未包含创建PRAGMA key的步骤，该步骤非常重要。PRAGMA key是SQLCipher加密工具中数据库的加密密钥，是在应用初始化期间为每个用户和设备在运行时生成的。PRAGMA key应具有足够高的熵值，且不应当硬编码到应用中，也不应当存储在没有硬件保护（例如安全元件）的存储位置。

Android系统开发人员通常会在SharedPreferences.xml文件中存储配置信息，但是这一存储位置并不安全。除非采用第三方封装代码对preferences的值进行加密，不然存储在SharedPreferences.xml中的数据都能以明文形式进行读取。

对于iOS系统而言，数据不应存储在应用容器内的文件中，也不应在plist文件中以明文形式存储。根据用户应用运行时环境，所有认证信息和令牌数据均应存储在Keychain中，同时在调用Keychain API时需要选取适当的属性。举个例子，如果应用不需要后台运行，那么建议使用最严格的属性，例如kSecAttrAccessibleWhenUnlockedThisDeviceOnly属性（只有在设备被用户解锁后才能够访问Keychain条目中的数据，但仅限此设备，该属性可以防止Keychain文件中的内容被iTunes备份，如果在不同的设备上恢复数据备份，那么具有该属性的相关条目不会恢复）或者kSecAttrAccessibleWhenUnlocked属性（只有在设备被用户解锁后才能够访问Keychain条目中的数据，当使用加密备份时，具有该属性的条目可以迁移到新设备上）。如果应用需要前台运行，那么建议使用kSecAttrAccessible-WhenPasscodeSetThisDeviceOnly属性（Keychain条目中的数据只有在启用设备密码验证后才能够被访问，但仅限此设备。具有该属性的数据不会迁移到新设备。当在新设备中恢复数据备份时，具有该属性的数据会全部丢失）。

3）数据存储过程中，适用于Android和iOS的最佳实践通常包括：

①尽可能不要存储敏感数据。

②只存储实现应用功能所需的数据。

③避免在缓存、外部存储器（SD卡）或临时文件中存储敏感数据。

④不要将敏感数据写入磁盘，也不要在控制台中显示敏感数据。

⑤对于敏感输入字段禁用键盘缓存。

⑥限制对应用数据的备份。

⑦如果需要将敏感数据存储在磁盘上则需要对其进行加密，同时数据的存储位置需要具备防篡改能力，例如可以将敏感数据存储在安全元件当中。

⑧敏感数据用完后且之后不再用到该数据时，需确保应用会将敏感数据从内存中清除。

⑨确保对敏感文本字段禁用剪贴板。

有时，针对KeyStore和Keychain等文件进行操作的安全API可能并不足以确保敏感数据的机密性与完整性。在这些情况下，建议采用应用级加密增强对敏感数据的保护，然后将加密数据存储在平台的安全存储位置中，从而实现敏感数据的安全存储。

9.2.3　延伸阅读

·有关Keychain的更多细节，可参考苹果公司提供的Keychain服务编程指南（https://developer.apple.com/library/content/documentation/Security/Conceptual/keychainServ-Concepts/01introduction/introduction.html#/）。

·有关KeyStore的更多细节，可参考Android开发者文档（https://developer.android.com/training/articles/keystore.html）。

·有关SQLCipher的更多细节，可参考SQLCipher的API开发者文档（https://www.zetetic.net/sqlcipher/sqlcipher-api/）。

9.3　认证控制措施的实现

移动应用既可以在服务端进行身份认证，也可以在客户端进行身份认证。在IoT移动应用中，这两种设计模式都是可行的，但是在生产过程中需要分别考量两种设计模式所面临的风险。本节中将对其所涉及的风险进行讨论，并介绍实现服务端和客户端身份认证的最佳实践。

9.3.1　测试流程

用户安全认证的通用原则也同样适用于移动应用。OWASP提出的Authentication Cheat Sheet是一份非常有价值的参考资料（https://www.owasp.org/index.php/Authentication_Cheat_Sheet）。常用的认证控制措施和最佳实践包括：

·选取适当的口令强度控制措施。

■口令长度。

◆10个字符或以上长度。

■口令复杂度策略。

◆包括1个大写字符、1个小写字符、1个数字、1个特殊字符，且不允许连续出现2个或2个以上相同的字符，例如222。

■强制控制历史口令的使用。

◆禁用最近三个使用过的口令（口令重用）。

·采用加密通信（TLS）方式传输认证信息。

■在http POST报文体中发送认证信息。

·对执行敏感操作的用户进行二次认证。

■更改口令。

■更改账户PIN码。

■更改安全问题。

■共享摄像头视频。

■车辆解锁。

·确保认证报错信息不存在泄露敏感数据的可能。

■正确的错误响应如下所示，即“无效的用户名和/或口令（invalid username and/or password）”。

·确保认证过程进行了日志记录，能够检测到登录失败的情况。

·能够防止自动化的暴力破解攻击。

■采用校验码或类似方法。

■对可疑登录的登录频率加以限制。

■登录频率或登录失败次数达到预定阈值后临时锁定账户，并向指定账户邮箱发送邮件。

·采用多因子认证，并在登录时与资源访问时的加强认证中强制采用多因子认证方式。其中，双因子认证方式包括：

■除口令之外，再加上一个只有用户自己知道的值。

■采用一次一密（One-Time Password，OTP）方法，或者通过电子邮件或短信发送编码。

■除用户口令之外，配合使用基于OTP方法实现的物理令牌。

上述内容不仅适用于Web应用，也适用于混合移动应用，甚至是原生移动应用。以下内容是可在应用中实现的针对移动应用认证的最佳实践：

·如果采用生物识别技术，需确保使用KeyStore和Keychain文件存储认证信息而非基于事件的认证机制。

·服务端会话无效。

·在应用中列出最后的登录操作，并允许用户屏蔽设备。

·避免使用设备的UUID、IP地址、MAC地址和IMEI进行身份认证或授权操作。

·在移动应用之外使用第三方OTP应用（例如，Google或Salesforce身份认证器）

针对Android开展认证的最佳实践内容包括：

·当使用Android中的FingerprintManager类时（https://developer.android.com/refer-ence/android/hardware/fingerprint/FingerprintManager.html），需要使用KeyGenerator类生成非对称密钥对。非对称密钥对的应用实例可参考链接https://github.com/googlesamples/android-AsymmetricFingerprintDialog。

·使用在Android Nougat API 24版本中引入的setInvalidatedByBiometricEnrollment(boo-lean invalidateKey)方法，该方法能够使得在移动设备中新录入指纹创建的密钥无效。

·采用SaftyNet reCAPTCHA API对认证过程加以保护，避免遭受基于僵尸节点的暴力破解攻击。

若要使用SaftyNet reCAPTCHA API，需要遵循以下步骤：

1）访问链接https://www.google.com/recaptcha/admin#androidsignup注册reCAPTCHA密钥对，如图9-1所示。

图　9-1

2）如果还未进行配置，则需添加SafetyNet API依赖项和Google Play服务。例如，在用于项目自动化构建的gradle文件中包含编译内容com.google.android.gms：play-services-safetynet：11.4.2，如下所示：

3）必须使用verifyWithRecaptcha()方法发送验证请求（https://developers.google.com/android/reference/com/google/android/gms/safetynet/SafetyNetClient#verifyWithRecaptcha(java.lang.String)）。验证请求中必须以站点API key作为参数，并且必须重载onSuccess()和onFailure()方法。以下代码片段展示了如何调用verifyWithRecaptcha()方法，这段代码源自于Android开发者指南（https://developer.android.com/training/safetynet/recaptcha.html#send-request）：

4）通过SafetyNetApi.RecaptchaTokenResult.getTokenResult()方法验证响应令牌。JSON风格的http响应代码示例如下：

5）接下来，添加逻辑代码来处理故障和错误。SafetyNet reCAPTCHA API共用到了7个状态码，分别是：

①RECAPTCHA_INVALID_SITEKEY

②RECAPTCHA_INVALID_KEYTYPE

③RECAPTCHA_INVALID_PACKAGE_NAME

④UNSUPPORTED_SDK_VERSION

⑤TIMEOUT

⑥NETWORK_ERROR

⑦ERROR

读者可以访问下面的链接来了解每个状态码的细节信息：https://developers.google.com/android/reference/com/google/android/gms/safetynet/SafetyNetStatusCodes。

针对iOS进行认证的最佳实践内容包括：

·将应用的敏感信息存储在应用中的访问控制的Keychain文件当中。在苹果开发者文档中可以找到使用Keychain和Touch ID的示例代码：https://developer.apple.com/library/archive/samplecode/KeychainTouchID/Listings/KeychainTouchID_AAPLKey-chainTestsViewController_m.html。

·确保应用会读取LAContext.evaluatedPolicyDomainState属性值，并检查evaluated-PolicyDomainState值是否发生了变化，如果该值发生变化则表明已注册的Touch ID指纹已经发生了改变。

·除非应用明确要求，否则通过kSecAttrSynchronizable属性值禁止将Keychain同步到iCloud。

Touch ID是用户认证的常用方法；但是，仍然有部分方法和工具可以用来绕过只使用本地认证框架的应用。这种情况下，借助前文提到过的Keychain访问控制机制，用户可以防止攻击者在程序运行时或者对自身打补丁时覆盖LAContextevaluatePolicy：localized-Reason：reply方法。

9.3.2　延伸阅读

·关于iOS Keychain服务的更多信息，可参考Keychain服务编程指南：https://developer.apple.com/library/content/documentation/Security/Conceptual/keychainServ-Concepts/02concepts/concepts.html。

·关于使用Fingerprint API对远程服务器进行身份认证的更多内容，可访问Android开发者博客：https://android-developers.googleblog.com/2015/10/new-in-android-samples-authenticating.html。

·了解关于SafetyNet reCAPTCHA API的更多内容，可访问下面的Android开发者页面：https://developer.android.com/training/safetynet/recaptcha.html。

9.4　数据传输安全

对于IoT移动应用来说，确保端到端之间的通信安全是个颇为棘手的难题。通常来说，数据的泄露往往源于移动应用采用了http或UDP（SIP）等明文协议，这些协议主要用来向移动应用传输音视频数据。有时，我们发现IoT设备厂商会向第三方泄露数据，因为在内容识别或崩溃报告分析等分析服务中，第三方通常只采用http协议与IoT设备通信，或者采用的加密配置安全性不高。而数据传输安全的目标正在于确保移动应用、IoT设备和API endpoint之间数据交互的机密性和完整性。采用TLS协议并对密码学套件进行适当配置，移动应用就可以建立起一个安全的加密信道进行网络通信。对于智能门锁或网联汽车这样的设备来说，则必须采用上述做法。在本节中，我们将对IoT移动应用中安全数据传输的最佳实践进行介绍。

9.4.1　测试流程

为了确保数据在移动应用传输过程中的安全，当前已经有机构制订出了部分通用要求和最佳实践供开发人员借鉴遵循。确保数据传输安全的最佳实践包括但不限于以下内容：

·使用平台所能够支持的最新TLS协议和密码学套件。

·验证服务端X.509证书。

■确保证书中的主机名有效。

·只接受可信CA签署的证书，包括公共CA和内部可信CA。

■禁用自签名证书。

·只绑定可信证书和可信公钥的链接。

Android平台与iOS平台下的最佳实践在实现上会略有不同。两个平台均提供原生加密API可以调用，也都有第三方封装库，但是其中未必包含证书绑定之类的功能。

1.Android

在接下来的例子中我们会看到，Android应用利用CA（可信证书）创建了KeyStore，再由KeyStore初始化TrustManager对象，而TrustManager对象负责对KeyStore中的证书进行验证：

1）创建线程安全（使用public static synchronized进行定义）的KeyPinStore类：

2）加载位于应用资产目录下的CA：

3）使用指定的可信CA创建KeyStore对象：

4）创建TrustManager对象验证KeyStore对象中的CA：

5）创建SSLContext对象，并使用当前的TrustManager对其进行初始化：

6）在与应用API endpoint进行通信时，使用指定证书的SSLContext创建httpsURL-Connection对象：

Google发布了一款名为nogotofail的工具，帮助用户进行TLS/SSL配置。nogotofail工具不仅会对配置进行检查，还能够确保未使用存在漏洞的TLS/SSL协议，同时该工具借助MITM技术实现了对客户端设备所发送数据的分析。关于nogotofail的更多信息，可访问该项目的GitHub代码库链接：https://github.com/google/nogotofail。

2.iOS

类似的操作也可以用于iOS中证书和公钥指纹的绑定。绑定操作一般会用到NSURL-ConnectionDelegate类，其中必须实现connection：didReceiveAuthenticationChallenge：和connection：canAuthenticateAgainstProtectionSpace：方法，在connection：didReceiveAuthenti-cationChallenge：方法中，还需要调用SecTrustEvaluate方法进行X509有效性检查。在应用中进行X509有效性检查时，可以参考OWASP提供的iOS应用绑定示例代码，示例代码的下载链接如下所示：https://www.owasp.org/images/9/9a/Pubkey-pin-ios.zip。

除了所有应用采用TLS协议时均应遵循的通用最佳实践之外，iOS还为开发者提供了一个新的功能，将来，在开发者向苹果应用商店提交应用时必须使用该功能（https://developer.apple.com/news/?id=12212016b）。这一功能即在iOS 9中引入并默认启用的应用传输安全（App Transport Security，ATS）。ATS要求应用必须基于httpS协议进行通信，并且在TLSv1.2中支持完全正向保密（Perfect Forward Secrecy，PFS）和专用密码学套件。如果应用不满足最低要求，就不允许同iOS应用建立连接。这对于所有的IoT设备固然是好的，有助于保障IoT设备的安全，但是仍然存在很多方法可以绕过ATS。具体来说，开发人员可以通过使用Info.plist文件中的NSAllowsArbitraryLoads属性配置来禁用ATS，如图9-2所示。

图　9-2

糟糕的是，由于密码学和PKI相关知识的匮乏，这种情况在IoT应用中非常常见。此外，开发者可以为一个或多个域名单独配置ATS，也可以在全局范围内配置ATS，因此实际应用中无须一股脑地禁用ATS功能。在配置过程中可能出现的例外情况包括：

·禁用PFS（NSExceptionRequiresForwardSecrecy）。

·对媒体禁用ATS（NSAllowsArbitraryLoadsForMedia）。

·允许建立基于http的不安全连接（NSExceptionAllowsInsecurehttpLoads）。

·降低可以采用的最小TLS版本号（NSExceptionMinimumTLSVersion）。

·允许建立同本地域名之间的连接（NSAllowsLocalNetworking）。

对此，苹果提供了一款工具nscurl，用来检查应用的传输安全问题，使用nscurl工具的命令如下所示：

当前，苹果公司正在做出一些积极的改变来影响开发者，以确保数据在传输过程中的安全。举个例子，前面我们就提到过的这样一项措施，即所有提交给App Store的应用在发布的时候均需要提供对ATS的支持。

9.4.2　延伸阅读

·OWASP提供了Android平台下公钥绑定的示例代码，可以通过以下链接下载：https://www.owasp.org/images/1/1f/Pubkey-pin-android.zip。

·读者可以参考下面的苹果开发者指南，了解更多关于ATS的要求：https://developer.apple.com/library/content/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW57。

9.5　Android与iOS平台下组件的使用安全

当IoT移动应用从第三方应用程序执行或提取命令时，可以采用内部平台的API进行进程间通信（Inter Process Communication，IPC）。采用IPC机制可以整合多款应用程序，根据调用情况向导航应用、IFTTT等第三方服务应用或者类似于亚马逊Alexa的个人助理进行收费。Android以及类似的平台提供了丰富的IPC机制，而iOS平台仅提供了若干个选项。大多数IoT应用都会利用平台和硬件特性同现实世界进行交互，而这反过来又使得攻击者成功实现漏洞利用的影响得以进一步扩大。在本节中，我们将探讨如何围绕IPC机制采取安全控制措施，以及如何以安全的方式调用平台API。

测试流程

借助移动平台同第三方应用进行命令交互是个非常强大的功能，但是如果未采用适当的方式对交互过程加以保护，未经授权的移动应用就有可能劫持交互命令并访问第三方应用中存储的数据，而非预期用户原本并不能接触到这些数据。在使用平台提供的API时，应该考虑采用以下安全实践：

·除非采取了适当的保护机制，否则不要通过IPC导出敏感数据。

·必要时应对来自外部和用户的输入进行验证和过滤。其中输入源包括用户界面、IPC（例如intents）、自定义的URL处理程序以及通过网络接收到的数据。

·应对WebView进行配置，只采用httpS等必需的协议，禁用其他容易遭受攻击的协议处理程序，如file：//、tel：//、sms：//以及app-id：//等。

·建立可信应用白名单，对IPC调用加以限制。

·在本地或远程加载基于白名单的Web页面和URL处理程序。

·只请求实现应用功能所需的最小权限。

·应对WebView中暴露出的原生方法进行验证，以确保只提交应用沙箱中的Java-Script脚本。

·除非明确要求开启，否则WebView应禁用JavaScript脚本。

·只使用安全序列化API，并应当采用密码签名。

上述大部分最佳实践都可以应用到Android和iOS平台当中；但是，还需要根据应用功能对Android权限、自定义权限和保护级别等内容反复斟酌。

下面以自定义权限IOT_COOKBOOK_ACTIVITY为例展开介绍，在AndroidMani-fest.xml文件中注册MAIN_ACTIVITY，启动该Activity时要求具备该权限。

1）第一个代码块定义了新的权限，其中包含标签和对Activity的描述。接下来，根据所赋予的权限类型设置保护级别。定义了权限之后，在应用的AndroidManifest.xml文件中设置uses-permission标签，强制组件以该权限执行。第二个代码块是采用新定义权限加以限制的组件，通过在代码中添加android：permission属性来强制实现对组件的权限限制：

2）新权限IOT_COOKBOOK_ACTIVTY即创建完成，应用可以使用AndroidMani-fest.xml文件中的uses-permission标签请求使用该权限。在这种情况下，只有采用同一证书签署的应用才可以启动MAIN_ACTIVITY：

在引入自定义权限和保护级别时，建议读者多多参考Android的开发者文档。所有Android权限都可以在文档https://developer.android.com/guide/topics/permissions/request-ing.html中找到。

对于iOS应用而言，鉴于iOS生态系统的封闭性，权限定义并不适用。但是，iOS和Android均采用了WebView组件，该组件的作用是在应用内部加载Web页面。像在其他Web应用中一样，恶意代码也可以在Web浏览器中运行，同样恶意代码也可以在Web-View组件中运行。这一点在减少IoT应用的攻击面时，需要着重考虑。

3）以下代码片段展示了如何在iOS应用的WKWebViews控件中禁用JavaScript脚本：

4）对于Android应用，可以通过配置WebView中的WebSettings属性来禁用Java-Script脚本，代码如下所示。此外，如果应用不需要某些功能的话，还需要完成一系列其他配置，例如禁用文件系统访问、关闭插件和关闭地理定位等：

考虑到最小权限和纵深防御原则，应用应当只采用并开放实现业务操作所需的平台组件。一般来说，所有从第三方应用发送和接收的数据都应被看作是不可信的，用户应当采取措施对其加以验证。

9.6　第三方代码与组件安全

与所有软件一样，移动应用也大量使用第三方库文件和封装类来实现发送http请求或对象加密等功能。但这些第三方库文件也有可能在应用中引入漏洞、泄露敏感信息或者破坏应用自身的完整性。考虑到这一点，应当对第三方代码进行审查以查找其中可能存在的漏洞，并及时予以更新，如果条件允许的话还需要进行测试。对于基于第三方混合框架和库文件执行数据发送、接收和保存等操作的混合应用来说尤其如此。在本节中，将对如何避免第三方代码在IoT应用中引入漏洞进行介绍。

9.6.1　测试流程

本书在第8章中已经探讨了采用NSP和RetireJS扫描JavaScript库文件的方法，该方法同样适用于移动应用。为确保第三方代码不会在移动应用中引入安全漏洞，可以考虑以下建议：

·采用NSP、RetireJS和dependency-check等工具，持续汇总库文件、框架的版本及其依赖关系（https://github.com/jeremylong/DependencyCheck）。

■创建清单，汇总移动应用中用到的所有组件和第三方软件。

·持续监控NVD等漏洞数据库，避免使用存在漏洞的组件，并采用分析工具实现监控过程自动化。

·分析第三方库文件，确保应用运行时会用到应用中所包含的所有第三方库文件，移除应用正常运行过程中未用到的功能。

·确保使用了最新版本的混合框架。

■监控混合框架的发布信息和博客，确保未使用存在已知漏洞的组件。

■如果框架开发人员未采用新版本的库文件，那么应当为存在漏洞的库文件打上补丁。

·监控所采用开源代码中的安全问题与隐患。

·确保在使用混合框架插件前对其进行安全漏洞审查。

·采用最新Android版本的API进行开发，并采用新加入的功能特性（苹果会强制iOS更新）。

·查看Android和iOS的安全公告，了解平台最新漏洞和新加入的安全特性。

Apache Cordova是一款常见的移动混合框架。在iOS和Android系统中，可以通过以下命令更新Cordova框架：

Cordova框架为大家所知源于安全研究人员对该框架给予了很高的关注，并且在Android和iOS平台发布的新版本中经常包含安全更新的相关内容。可以在博客https://cordova.apache.org/blog/中查看到Cordova的发布信息。如果想要查寻尚未发布的漏洞，可以重点关注框架的漏洞跟踪系统，例如Cordova的漏洞跟踪系统（https://issues.apache.org/jira/projects/CB/summary）。读者会发现漏洞跟踪系统中包含了大量已修复[1]、已提交和已关闭[2]的漏洞。另一个常用的混合框架是Xamarin。但是，由于Xamarin的认证信息管理器使用了一个硬编码的Android KeyStore口令，所以从2014年4月起，该框架下用户的账户认证信息就一直存在风险，直到2016年年底才被修复。关于该安全隐患的相关内容具体可查阅该项目的GitHub代码库：https://github.com/xamarin/Xamarin.Auth/issues/55。

[1] 经研发人员确认是BUG修复后的状态，修改还没有验证，由开发人员来设置。——译者注

[2] 测试人员认为问题已经修改，通过验证，由测试人员设置。——译者注

9.6.2　延伸阅读

·谷歌简要分析了Google Play中使用的设备版本，并将这些数据发布到一张饼状图中，可以帮助开发者在选择支持的不同设备版本时确定优先级（https://developer.android.com/about/dashboards/index.html）。

·每个月谷歌都会发布Android安全公告，公告内容包含通告、CVE漏洞及其严重程度和缓解方法。可以在链接https://source.android.com/security/bulletin/中查看Android安全公告。

·苹果公司每年都会发布一份iOS安全指南，详细介绍平台的安全特性和新版iOS的安全控制措施。iOS的安全指南链接地址为https://www.apple.com/business/docs/iOS_Security_Guide.pdf。

9.7　针对逆向分析的保护措施

当内部团队与外包团队共同负责用户体验（User eXperience，UX）的相关开发时，安全代码的开发具有一定的难度，这时需要确保某些功能特性不会对网络中的IoT设备产生负面影响，这些功能特性包括在应用启动时搜索设备、以适当方式执行所设置规则以及应用更新等。但是，鉴于应用的复杂性，攻击者难免会发现漏洞，也肯定会设法绕过安全控制措施。的确，虽然当攻击者试图针对应用开展分析并窃取应用中所蕴含的知识产权（Intellectual Property，IP）时，可以通过技术手段提高攻击者逆向分析的复杂度，但是任何软件都不可避免会出现漏洞。

面对攻击者采用的各种攻击技术，可以在应用逻辑中融入抗分析技术来防止针对应用运行时的篡改，可以通过混淆应用程序的类来防止针对二进制文件的静态分析，还可以通过数据分段防止其他潜在的攻击。需要注意的是，这里强调的是应用始终需要在内部构建安全控制措施，而不是通过第三方软件保护来取代应用内部的控制措施。本节将对部分能够提高应用抵御攻击能力的最佳实践进行介绍。这些最佳实践不仅能够增强应用的抗分析能力，还可以作为抗滥用系统的一部分，有助于纵深防御的实现。

9.7.1　测试流程

在实现针对逆向分析与代码篡改技术的控制措施时，应当遵循以下最佳实践：

·应用应能够检测出root或越狱设备，并通过提醒用户或终止应用运行等方式做出响应。

·在编译过程中对类和方法进行混淆处理，防止基于动态分析的反混淆。

·相较于混淆，在可能的情况下首选基于硬件的进程隔离措施。

·应用应能够阻断调试，并防止调试器附加在应用之上。

·应用应能够检测到逆向分析工具和分析框架的运行。

·应用应能够检测自身是否运行于仿真环境，并采用适当的方式做出响应。

·应用在编译时应当删除符号。

·应用编译时不应当包含调试代码或调试属性，比如android：debuggable="false"。

·Android应用可以使用SafetyNet Attestation API进行兼容性检测，以确保应用未被篡改。

·应使用SafetyNet Verify Apps API检查设备中是否安装了可能造成威胁的应用（https://developer.android.com/training/safetynet/verify-apps.html）。

iOS应用可以采用基于常用越狱文件的方式进行越狱检测，常用的越狱文件列表如下所示（https://github.com/OWASP/owasp-mstg/blob/master/Document/0x06j-Testing-Resiliency-Against-Reverse-Engineering.md）：

此外，iOS应用还可以尝试执行根用户级系统API调用、通过在应用沙箱之外的文件中写入数据来检查文件权限等方式，检测设备是否越狱。

Android应用也可以采用类似的方法来检查root设备中常见的文件，并尝试以root身份执行命令。检测root设备常用到的root文件和应用列表如下所示（https://github.com/OWASP/owasp-mstg/blob/master/Document/0x05j-Testing-Resiliency-Against-Reverse-Engineering.md）：

此外，检查定制的Android ROM文件也可以用于检测root设备，但这种方法并不可靠。

读者可以采用多种检测和防御方法来提高应用的抗攻击能力。这些检测和防御方法的应用，目标在于确保攻击者不能在代码存储及运行时篡改代码，也不能对应用进行逆向分析，从而避免上述技术的滥用。在应用启动和运行期间，可以考虑将应用的实现逻辑同前面介绍的最佳实践结合起来。当然，用户也可以采用商业解决方案来处理先前的实例，但在集成到应用中之前需要对商业解决方案进行审查。

9.7.2　拓展学习

了解更多移动应用逆向分析和未授权代码篡改的风险，可参考OWASP的逆向分析和代码篡改预防项目（https://www.owasp.org/index.php/OWASP_Reverse_Engineering_and_Code_Modification_Prevention_Project）。该项目中详细介绍了技术和业务风险用例，并提出了风险缓解建议。

9.7.3　延伸阅读

更多关于采用SafetyNet API进行兼容性检查的信息，可查阅Android开发者链接https://developer.android.com/training/safetynet/attestation.html#cts-check。

第10章　硬件安全保障

本章将主要探讨以下主题：

·硬件最佳实践。

·非通用的螺丝类型。

·防篡改和硬件保护机制。

·侧信道攻击防护。

·暴露的接口。

·通信数据加密与TPM。

10.1　简介

如今市面上大多数的IoT设备，在硬件安全方面往往存在着这样或那样的隐患，也就是说，大多数IoT设备并不能很好地保护硬件免遭攻击者的入侵。无论是网络摄像头、婴儿监视器、医疗设备、企业物联网、智能可穿戴设备，还是智能电视，只要读者对上述设备的安全性进行审查，就会发现即便是技术水平很普通的攻击者也可以轻松地拆开设备外壳（因为设备几乎没有或很少采用物理防护措施）、查看芯片型号、获取芯片数据手册（由于没有隐藏芯片型号），进而提取芯片中的数据（如果未采用芯片访问保护机制），或通过不同的接口与设备进行交互（缺乏对暴露接口的保护）。

本章将对各种硬件保护的方法和步骤进行介绍，而设备开发人员和厂商可以采取本章所介绍的保护措施来对IoT设备中使用的嵌入式设备硬件实施保护。尽管难以确保设备完全安全，但本章提到的方法将有助于改善设备整体的安全状况，可大大提高攻击者的攻击难度。

10.2　硬件最佳实践

在深入探讨各种硬件安全保护的本质之前，首先简单讨论一下都有哪些方法措施可以用来确保嵌入式设备的安全。

在开发嵌入式设备时，首先需要明确这样一个事实：一旦产品已经进入市场，那么大多数硬件漏洞都是无法修复的。这意味着在刚开始构建硬件时就必须慎之又慎。

在为物联网解决方案设计硬件设备时需要时刻留意的另一件事是，如果攻击者能够拿到硬件设备，那他就可以接触到硬件设备中的所有硬件资源。也就是说，如果攻击者能够打开IoT设备并查看PCB，那么攻击者就能够识别出IoT设备所采用的所有组件。更进一步，如果攻击者能够通过shell访问硬件接口，那么此时攻击者又会做什么呢？

上述内容都是在构建嵌入式设备时应该考虑的事情。

以下是嵌入式设备的硬件设计和开发过程中应该遵循的部分最佳实践，包括：

·确保设备采取了防篡改和硬件保护机制。

·使用非通用的螺丝或者其他方式将硬件中的各个部分加以封装，从而提高逆向分析的复杂度。

·确保攻击者同硬件交互的所有常用接口（例如UART或JTAG接口）均未暴露在外或并未采用。

·采用基于可信模块（TPM）的保护措施，确保设备安全性得到进一步加强。

10.3　非通用的螺丝类型

硬件攻击者实施攻击的第一步就是拆开设备，查看PCB上的芯片和各种暴露在外的接口。对此，我们可以使用非通用螺丝对设备加以保护，提高设备外壳的拆解难度，或者也可以使用超声波焊接或高温胶水之类的材料将多个硬件外壳密封在一起。

部分常用的螺丝类型如图10-1所示。

如果设备厂商使用的螺丝类型较为独特且比较少见，那么攻击者将难以打开设备外壳，而如果想要打开这样的设备，大多数情况下的唯一选择只能采取暴力手段。此外，无论是暴力拆解还是正常拆解都可以通过添加专用部件的方式来进行防护，这些专用部件可以感知并检测到设备外壳的开启，下一节将对这部分内容进行讨论。

10.4　防篡改和硬件保护机制

防篡改指的是使用专用部件来防止设备遭受篡改。在设备中添加篡改检测开关、传感器或电路是一种常见且有效的防篡改方法，能够有效增强设备硬件的安全性。这些部件不仅可以检测到设备的正常拆解，还可以检测到设备的暴力拆解，并且还可以根据预先设定采取清除闪存或使设备无法正常使用等操作，从而达到硬件保护的目的。

除此之外，强烈建议厂商使用去除芯片标记、采用环氧树脂隐藏标记，或者采用金属外壳封装芯片等方式保护敏感的芯片和部件。

图　10-1

图片来源：http://thecraftsmanblog.com/wp-content/uploads/2013/09/Screw-Drive-Types.png

其他可以实现硬件防篡改的技术还包括：密封线路、采用安全螺丝、加固金属外壳等，所有这些防护措施都会使得对设备的篡改变得极其困难，如图10-2所示。

图10-2　电源插座上的安全螺丝

然而，大多数设备厂商采取的防篡改保护措施并非都是有效的。图10-3是一台TP-Link MR3020家用路由器的内部结构图片，从图片中可以看到该设备使用胶水来隐藏UART接口，显然，这对于硬件保护而言起不到多大作用。

图　10-3

因为，对于这种情况，攻击者可以很容易地用裁纸刀刮掉胶水，随后PCB上的UART接口就会暴露出来。

10.5　侧信道攻击保护

加密技术也是一种有效的硬件保护机制。然而，由于加密机制可以被绕过，密钥也可能被泄露，因此依然存在遭受攻击的可能。

侧信道攻击是一种高级的硬件漏洞利用技术，攻击者使用不同的信息源提取尽可能多的信息，这些信息源包括能量变化、时序分析、电磁数据变化和声音信息等，这些信息都可以被攻击者用来对目标设备实施攻击。

直接内存攻击（Direct Memory Attack，DMA）就是一种侧信道攻击，攻击者可以在不采用常见访问方式的情况下，实现对特定功能部件的直接访问。以USB设备为例，USB设备连接到控制器集线器（controller hub）/平台控制单元（Platform Controller Hub，PCH），而控制器集线器或平台控制单元则可以通过直接内存访问的方式进行访问。

针对上述攻击的防护方式实现起来比较复杂，但还是可以采取以下措施来抵御这类攻击：

·在设备中使用能够减少向系统外传递信息的部件，无论传播介质是电磁辐射还是声音。

·在执行敏感操作时添加噪声，提高攻击者提取信息的难度。

·确保攻击者不能对非预期组件进行物理访问。

10.6　暴露的接口

确保IoT设备硬件安全最重要的一点是，在设备投放市场之前，禁用或者去除硬件中的UART、JTAG等接口以及其他诊断功能。

另一点需要注意的是，即使没有可见的外露接口，攻击者也可以通过直接连接到芯片的引脚，来访问UART、JTAG等接口。攻击者只需要阅读芯片数据手册，识别出引脚功能，然后进行对应连接即可。还有一种提高攻击者分析复杂度的方式，那就是通过导通孔将接口隐藏在PCB的内层当中，而不是在外部可见的表层上暴露接口。然而，只有当设备开发人员在后续工作中还需要用到接口时，才建议这样做。除此之外，在现实中我们通常建议移除这些接口。另一个值得关注的安全保护措施是提高软硬件融合程度，进而防止芯片读写。

这里需要注意的一点是，切断导线等基本保护机制对于技术水平较高的攻击者而言是无效的。因为，攻击者可以将切断的导线再重新焊接在一起，进而重新启用JTAG接口，再使用其他技术建立同该接口的连接。

10.7　通信数据加密与TPM

即使加密技术已经是固件安全的重要组成部分，但攻击者通常仍然可以实现对在两个不同硬件组件之间传递的数据的嗅探。因此，为了避免敏感信息落入攻击者手中，需要对动态传输和静态存储的数据进行加密。

在嵌入式设备中讨论加密时，还需要考虑实现各种加密功能所需的资源数量。

由于嵌入式设备的资源有限，实现高强度的加密算法通常是不可能的，因此，就需要提前思考如何在加密和可用性之间取舍以取得平衡，并在硬件中加以实现。

如果可能并且芯片也支持的话，可以利用TPM来存储所有加密密钥，TPM还可以提供其他功能，例如采用信任根来防止对启动过程的篡改。大多数TPM都支持硬件随机数生成器，具备在200ms中计算2048位RSA签名的能力。

当基于TPM的安全保护措施难以实现时，替代方案是使用加密狗或硬件安全模块（HSM）来存储加密密钥。这种方式也可以在设备运行时抵御固件修改和后门植入等攻击，从而提高设备的安全性。

第11章　IoT高级漏洞利用与自动化安全防护

本章将主要讨论以下主题：

·ROP gadget搜索。

·Web安全漏洞的组合利用。

·固件持续集成测试配置。

·Web应用持续集成测试配置。

·移动应用持续集成测试配置。

11.1　简介

为了利用IoT设备中的漏洞，并保护设备自身免遭漏洞利用，我们希望采用自动化的方式实现PoC武器化的过程，同时增强安全防护团队的应急处置能力。如果安全团队跟不上代码推送与研发的速度，那么肯定会出现漏洞。此外，安全团队还需要适应开发团队的速度，保证安全测试与代码审查不影响开发团队的进度。本章主要对IoT高级漏洞利用技术与挖掘方法进行介绍，采用自动化方式避免IoT设备出现漏洞。

11.2　ROP gadget搜索

嵌入式设备的漏洞利用过程中最重要的地方在于采用ROP（Return Oriented Pro-gramming）等技术对存在漏洞的二进制文件进行漏洞利用，这也是在本节所要讨论的主要内容。

之所以需要ROP技术是因为在漏洞利用过程中，经常需要拿到目标设备的shell或者在目标设备上执行某个后门程序，从而获取在目标设备上访问更多信息或者敏感资源的访问权限。

在ARM以及MIPS（甚至还包括x86）架构中，ROP的概念都是相同的。但是，根据平台的不同，ROP技术在实际应用过程中还存在部分差异，需要我们特别注意。简单来说，ROP技术就是从系统中不同的位置选择部分特定指令（也就是gadget），然后将这些指令链接在一起构建成一条完整的ROP链，而ROP链中指令的执行能够完成某一特定操作。

11.2.1　准备工作

正如在前面提到过的，为了实现ROP技术，我们需要能够识别出有用的ROP gadget，同时将这些gadget链接在一起来实现某项功能。为了找到这些特定的gadget，我们需要在libc或者其他库文件中进行手工搜索，有时还需要借助自动化工具或脚本来完成这一工作。

简单起见，我们以ARM架构下一个存在漏洞的程序为例进行说明，之后再借助其他实例帮助我们深化对基于ROP的漏洞利用技术的理解。

这一过程中需要用到以下工具：

·GDB-Multiarch：针对不同架构的GDB调试器。

·BuildRoot：用于编译ARM架构下的漏洞程序。

·PwnDbg：辅助开展漏洞利用的GDB插件。

·Ropxx：将各ROP gadget组合起来构建最终ROP链的Python脚本。

目前我们尚未用到任何自动化工具，而是聚焦于手工方法，这样可以更加直观地了解ROP漏洞利用技术的原理。如果读者稍后想要使用自动化工具（其实也建议读者采用自动化工具实现这一工作），那么可以参考延伸阅读中的链接。

11.2.2　测试流程

本节中，我们将从如何利用ARM环境中最普通的栈缓冲区溢出漏洞开始。

1）存在漏洞的代码示例如下所示：

正如读者在前面的代码中所看到的，main函数接收用户输入的参数，然后将参数传递给存在漏洞的函数，而该函数中存在一个名为buff的缓冲区，长度为10字节。如果输入参数的长度远远大于buff的长度，那么将导致缓冲区溢出。

一旦造成buff缓冲区溢出，我们就需要找到一种方法覆盖pc或者lr寄存器，进而接管程序的执行流程。通过在strcpy函数的地址处设置断点，然后分别对复制前后的栈中数据进行分析，不难找到这种方法。

2）接下来使用Qemu仿真ARM架构来运行上面这段代码，如图11-1所示。

图　11-1

也可以使用-q参数将调试器附加到运行实例，本例使用GDB通过端口1234建立同程序之间的连接，在下面的图中可以看到这一信息。

3）本例使用GDB-multiarch调试器，然后指定sysroot与远程对象，操作命令如图11-2所示。

图　11-2

在调试环境中，我们在main函数处设置断点（输入命令b main），然后继续执行程序（输入命令c）。

接下来开始搜索gadget，这也是漏洞利用过程中最有趣的部分。为了找到适用于漏洞利用的gadget，我们需要找到能够设置跳转目的地址的指令，比如说将跳转目的地址设置为system函数的地址（当前场景中），并在跳转时将字符串/bin/sh的地址作为system函数的参数，那么执行后就能够获得shell。

这意味着我们需要将system函数的地址放在pc寄存器或lr寄存器中，并且将/bin/sh的地址放在r0寄存器中，r0寄存器是ARM架构中的第一个寄存器，同时也被用作被调用函数的一个参数。一旦找到了能够实现上述功能的指令，还需要确保该指令之后的指令满足下列两种情况之一，也就是，要么是能够跳转到控制地址的分支跳转指令，要么是pop{pc}或者pop{lr}指令。

4）接下来分析erand48函数的反汇编代码，该函数是libc库文件中的一个函数，分析过程中可以发现该函数中包含有一组特定的指令，这组指令非常有用，能够帮助我们接管执行流程并对寄存器中的值加以设置。erand48函数的反汇编代码片段如图11-3所示。

图　11-3

其中，需要重点关注的三条指令分别是：

①ldm sp，{r0，r1}：该指令将栈中数据装载到r0和r1寄存器。可使用该指令控制r0寄存器，而r0寄存器可以用作所要跳转到的函数（system函数）的参数。

②add sp，sp，#12：该指令将栈指针增加12。

③pop{pc}：该指令从栈中弹出某个值并将该值放入pc寄存器，这表示我们能够接管程序执行流程。

接下来还需要确定两件事情，分别是：

①system函数的地址。

②字符串/bin/sh的地址。

5）我们可以使用print命令或者反汇编工具来查找system函数的地址，操作命令如图11-4所示。

图　11-4

6）现在，生成了一个长度为50个字符的字符串，然后来看一下我们如何溢出缓冲区，使其成功跳转到erand48函数的地址，如图11-5所示。

图　11-5

7）使用生成的字符串作为参数调试漏洞程序，如图11-6所示。

图　11-6

8）在存在漏洞的函数处设置断点并继续执行。执行过程中，GDB调试器会命中断点，调试信息如图11-7所示。

图　11-7

9）在漏洞函数的最后一条指令处设置断点，如图11-8所示。

图　11-8

10）一旦命中断点，即可以开始对栈中数据的分析，如图11-9所示。

其中，高亮显示的指令会从栈中弹出两个dword类型的数据（双字节）分别放入fp和pc寄存器。如果此时我们观察栈中数据，会发现第二个值为0x61616165('eaaa')，这正是将要送至pc寄存器的值。

11）观察该值的偏移量，可以计算出使用特定地址覆盖pc寄存器所需的偏移量。我们可以通过命令cyclic-l 0x61616165来计算该偏移，操作命令如图11-10所示。

12）命令执行结果为16，这意味着我们需要将想要放入pc寄存器的值（erand48函数中的ldm指令）以小端序放在偏移16位置处。

图　11-9

图　11-10

然后，我们使用图11-11中的Python代码生成新的字符串。

图　11-11

13）接下来，将新生成的字符串作为参数来执行程序，执行命令如图11-12所示。

图　11-12

14）跟之前一样在程序上附加GDB调试器，并在漏洞函数的最后一条指令处设置断点，也就是地址0x84e0处，如图11-13所示。

15）此时，我们可以看到pc寄存器中已经装入了erand48函数中目标指令的地址，也就是0x4087b9dc。接着使用ni命令单步执行一条指令即可到达指令ldm，如图11-14所示。

图　11-13

图　11-14

16）在这一步骤中，寄存器r0中装载的内容为0x61616161，r0寄存器也是我们打算放入字符串/bin/sh地址的寄存器，如图11-15所示。

图　11-15

17）因此，有效偏移为16＋4＋0＝20，计算过程如下：

18）在偏移20处，放置字符串/bin/sh的地址，之后该地址将会作为参数传递给system函数。再次单步执行两条指令可以到达pop指令，如图11-16所示。

图　11-16

19）寄存器pc的值为0x61616164，采用之前的方法计算偏移，如图11-17所示。

图　11-17

20）所以，寄存器pc的有效偏移为：

16＋4＋0＋12＝32

这表示在偏移32处，我们需要放置之前计算得到的system函数的地址。

同时，我们将字符串/bin/sh的ASCII码放在偏移36处，并在偏移20处使用该字符串。因此，该字符串地址在栈中的值为0x407fff18。

21）接下来使用模块ropgen生成漏洞利用载荷，生成代码如图11-18所示。

图　11-18

22）继续调试并再次进入单步调试，如图11-19所示。

图　11-19

23）观察此时栈中的数据，字符串/bin/sh的ASCII码位于地址0x407fff38处，这意味着我们需要在代码中进行相应的调整，调整结果如下，如图11-20所示。

图　11-20

24）采用与之前类似的方法进行调试，可以看到此时ASCII码字符串已经装载到了正确地址，如图11-21所示。

25）再次执行到erand48函数地址处，调试信息如图11-22所示。

图　11-21

图　11-22

26）此时寄存器r0存储的正是我们期望的ASCII码字符串的地址。在调试器中输入2遍c命令，执行到函数的最后一条指令处（pop pc），此时栈中数据如图11-23所示。

图　11-23

27）指令pop{pc}将从栈中数据装载系统地址，并将其放入pc寄存器中，随后会和位于r0寄存器中的参数一起进入系统，其中r0寄存器中存储的是字符串/bin/sh的地址。查看寄存器的值可以确认这一点，如图11-24所示。

图　11-24

28）此时输入命令c，即可获得设备shell，执行结果如图11-25所示。

图　11-25

至此，我们利用位于erand48函数中的指令，以期望的字符串作为参数，采用ROP技术跳转到了system函数，最终获得了shell，实现了对栈缓冲区溢出的漏洞利用。

但是，这仅是ARM架构下ROP技术应用的一个简单示例。ROP技术同样适用于MIPS架构，下面将会进行简要介绍。在这里我们需要说明的是如何解决缓存一致性问题，这一问题在现实漏洞利用过程中会经常出现。

29）对于缓存一致性问题，我们以DVRF固件中的socket_bof_01程序为例进行说明。在该例中，我们需要跳转到的第一条指令是sleep，并在参数中指明我们需要sleep的时间。调用sleep函数刷新缓存之后，准备gadget代码以想要执行的命令的地址为参数调用system函数，如图11-26所示。图中展示了第一段gadget的代码示例。

图　11-26

在图11-26中的gadget代码中，除了设置第一个寄存器$a0（类似于ARM指令集中的r0寄存器），我们还可以控制返回地址（Return Address，RA）以及很多其他寄存器，例如$fp、$s7、$s6……$s0等，最终跳转到$ra寄存器。

30）在图11-27中的gadget代码中，则需要准备跳转到以$a0寄存器值为参数的sleep函数，其中寄存器$a0的值已经进行了设置。注意到在这段gadgets代码中，$t9寄存器从$s0寄存器中获取数值，而在之前的gadget代码中我们已经实现了对$s0寄存器的控制。

图　11-27

31）该段gadget设置完成之后，在图11-28中的gadget代码中需要设置system函数的参数（所期望执行的命令字符串的地址），并跳转到system函数。在本例中，函数参数为$sp+24，接着将$s3寄存器中的存储内容转移至$t9寄存器（我们期望将该寄存器设置为system函数的地址），而借助之前提到的第一段gadget代码我们能够实现对$s3寄存器的控制。

图　11-28

32）一旦我们准备好了所有需要用到的gadget代码，那么下一步就是计算各项偏移来确保ROP链能够发挥预期作用。漏洞利用过程中用到的ROP链如图11-29所示。

图　11-29

33）接下来，需要将各个参数放到正确的位置上，运行二进制文件，并从/proc/maps文件中确定libc库文件的地址，如图11-30所示。

图　11-30

34）正确识别出libc的地址并运行程序后，读者就可以看到在运行过程中参数均放入了正确的位置，运行GDB可以对寄存器中存储的内容加以确认，如图11-31所示。

图　11-31

在前面的执行结果中，id正是我们所期望执行的命令。

35）总结一下，本例中的ROP链如图11-32所示。

图　11-32

以上就是基于ROP开展漏洞利用所涉及的所有内容，我们对ARM和MIPS架构下的情况均进行了介绍。在现实中应用的漏洞利用方式与之相同，但是现实场景下的应用程序可能不会只需要几条指令，而是需要多条指令才能完成ROP链的构建。

11.2.3　延伸阅读

对于不同平台下基于ROP技术的漏洞利用，读者可以借助一些自动化工具来简化利用过程。下面列出了部分自动化工具推荐给读者：

·ROPGadget：https://github.com/JonathanSalwan/ROPgadget

·MoneyShot：https://github.com/blasty/moneyshot

11.3　Web安全漏洞的组合利用

当攻击者针对某种类型的IoT设备开展攻击时，在漏洞利用过程中可能会用到多个漏洞。单独来说，这些漏洞中每个漏洞自身的威胁性可能并不高，但是，当这些漏洞组合起来后，漏洞利用的风险可能会比原来大得多。低危漏洞结合起来导致高危漏洞的情况并不鲜见，对于IoT设备而言尤为如此。而只要在IoT设备中发现一个高危漏洞，就可能破坏整套设备的完整性。本节内容主要介绍如何将Web中的安全漏洞结合在一起，在没有遥控钥匙（key fob）、实体钥匙或者其他认证介质的情况下获取到斯巴鲁网联汽车的访问权限。

需要重点指出的是，所有漏洞研究都应当在合规合法的基础上开展。针对MySubaru账户与Subaru服务器所开展的未经授权的测试均是违法行为。所有的测试都应该在受控环境中进行并经过授权。虽然Subaru远程服务不涉及对汽车发动机与动力传动系统的控制，但是其测试结果也不予公开。本节内容所涉及的所有高危漏洞都已经公开报道，并且斯巴鲁公司已经进行了修复。

11.3.1　测试流程

评估过程的第一步是威胁建模。本例中，我们从黑盒测试角度对2017年斯巴鲁公司发布的WRX STi网联汽车进行威胁建模。首先从车辆的入口点识别开始，以这些入口点作为攻击面是之后工作开展的基础。

步骤1　资产及入口点识别

某些型号的车辆同其他型号相比具有更多特性，因此每款型号的汽车都各不相同。从斯巴鲁网联汽车已公开的资料中可以看到，其生产的车辆根据生产年份、型号均具有不同的功能特性。例如，我们知道有些网联汽车可以通过蜂窝4G/LTE连接到互联网，但是有些车辆则是通过手机连接或者其他诸如Wi-Fi的方式连接到互联网。下面，在开展主动攻击之前，我们从连接方式开始，记录下目标车辆的情况并进行分析：

·蜂窝连接：斯巴鲁网联汽车采用AT&T 4G LTE技术连接互联网（http://about.att.com/story/att_subaru_bring_4G_lte_to_select_model_year_vehicles.html）。

·Wi-Fi：目标斯巴鲁网联汽车未提供Wi-Fi连接方式。

·蓝牙：信息娱乐系统通过蓝牙连接设备，访问多媒体影音播放系统、设备联系人簿以及通信系统。

·遥控钥匙：需要遥控钥匙才能够访问并启动特定车辆。遥控钥匙的传输频率范围为314.35～314.35 MHz（https://fccid.io/HYQ14AHC）。

·USB连接：信息娱乐系统采用USB方式连接到多媒体影音播放系统，可以通过USB连接对GPS以及信息娱乐系统进行更新。

·SD卡：信息娱乐系统提供microSD卡插槽，可以插入存储有GPS地图的存储卡。

·OBDⅡ系统：通过OBDⅡ系统可以接入CAN总线进行诊断，并且可以将ECU镜像刷入车辆以优化车辆性能，或者进行其他性能改进。

·CAN总线：每台车辆都拥有一条或者多条CAN总线用于车内通信。而CAN总线自身存在漏洞，借助免费工具就能够嗅探其流量。

·移动应用：斯巴鲁网联汽车采用Starlink互联技术连接到MySubaru应用，用户通过MySubaru应用能够实现远程关锁与解锁、鸣笛及开关车灯、查看车辆健康报告、在地图中定位车辆等操作。为了使用MySubaru应用的各项功能，车主需要购买会员。

·Web应用：除了MySubaru移动应用，斯巴鲁的Starlink互联技术还可以通过Web接口实现远程关锁与解锁、鸣笛及开关车灯、更改用户设置、调度服务、增加授权用户以及在地图上定位车辆等操作。同样，车主也需要购买会员才能够使用这些特性。

在上面的介绍中，我们列出了访问网联汽车的入口点，基于对这些入口点的了解有助于我们在构建防护体系时确定防护目标的优先级。同时，我们也可以结合自身能力以及现实条件对实施攻击所需要付出的代价进行评估。

步骤2　薄弱环节定位

当前，安全研究人员针对信息娱乐系统以及CAN总线的漏洞利用已经开展了大量研究。在蓝牙、Wi-Fi或者遥控钥匙中发现的协议中的脆弱点稍微花些时间就可以转化为类似于0-day的漏洞。在本节中，我们主要将重点放在MySubaru移动应用和Web应用上。借助移动应用以及Web应用，攻击者甚至都不需要来到车辆附近，而只需要订阅STARLINK Safety Plus以及Security Plus功能包、知道支持该功能包的车型以及进入MySubaru账户的认证信息就可以展开攻击了。这可真是太棒了，因为我们可以将工作进行多任务切分，同时在3种应用[1]上进行操作。此外，斯巴鲁还授权移动或者Web应用可以执行解锁、关锁、鸣笛、定位等操作。在本测试中，以1.4.5版本的MySubaru Android应用与iOS应用作为测试目标。在其中所发现的所有应用级漏洞都可能造成重大影响，给斯巴鲁车主带来人身安全隐患。

步骤3　分析

在这里，我们主要关注应用层面的安全隐患，因此需要对前面提到的3种应用类型开展分析。接下来，首先从移动应用开始，然后再分析Web应用。

Android应用

由于反汇编及静态分析相对容易些，因此在开始动态测试之前可以对Android应用进行反汇编及静态分析。虽然对Android应用进行逆向分析时需要耗费些时间精力，但是如果能够发现一些简单的漏洞，那么就可以迅速展开漏洞利用。开展逆向分析需要拿到目标应用的二进制文件，因此，我们首先从第三方软件商店获取MySubaru应用，并验证该版本同Google Play中所获取的版本是否相同。验证完成后，对MySubaru的Android应用开展基线分析，步骤如下：

·采用MobSF或类似工具反汇编APK文件：

■分析类与方法。

■识别第三方库文件。

■判断app是原生应用还是混合应用。

■搜索硬编码值。

■搜索潜在的密钥等敏感信息。

·安装app并监控Android组件：

■activitiy、service以及intent。

·数据存储分析：

■SD卡的使用。

■SharedPreferences.xml。

■缓存。

■SQLite数据库。

·采用Burp Suite或类似工具代理转发从Android app向车辆发送的所有API请求：

■登录/登出。

■解锁/关锁。

■鸣笛。

■开关车灯。

■定位车辆。

■查看车辆健康度报告。

■编辑车辆细节信息。

在这一过程中，Android通信代码在工具中以彩色高亮的方式进行显示。通过彩色高亮的方式对不同的API调用进行标记，在挖掘Android应用以及其他Subaru应用中的漏洞时能够帮助分析人员定位漏洞。

iOS应用

对iOS应用进行逆向分析时，需要花费时间来获取IPA文件并解密，再将应用的二进制文件在主机上解压，对解压得到的文件开始漏洞分析。在这种情况下，我们必须通过App Store下载MySubaru应用，然后将该应用的二进制文件解密并将结果保存到主机中。这一工作完成后，可以按照以下步骤对MySubaru的iOS应用开展基线分析：

·采用Hopper或类似工具对iOS二进制文件进行反汇编：

■分析类与方法（使用Class-dump-z）。

■识别第三方库文件。

■判断App是原生应用还是混合应用。

■搜索硬编码值。

■搜索潜在的密钥等敏感信息。

·安装app并监控iOS组件：

■通过URL模式进行IPC。

·数据存储分析：

■Plist。

■SQLite数据库。

■Cache.db。

■Localstorage。

·采用Burp Suite或类似的工具代理转发从iOS App向车辆发送的所有API请求：

■登录/登出。

■开锁/关锁。

■鸣笛。

■开关车灯。

■定位车辆。

■查看车辆健康度报告。

■编辑车辆细节信息。

此时，需要留意iOS API调用与Android API调用之间的区别。同时，还需要关注存储数据中的个人信息以及认证信息。通过对Android和iOS应用的基线分析，可以发现攻击者发起攻击所面临的潜在技术难题。例如，Android和iOS系统的移动应用均通过POST请求报文进行远程服务调用，请求报文中包含有sessionId参数值，而该值对于每个请求而言都是唯一的。这一特点就可能使得攻击者难以伪造远程服务请求，因为该值是唯一的并且不是某一特定的硬编码值。在iOS应用中还有一个实现细节很关键，那就是iOS应用的所有http协议的请求与响应报文均会在SQLite数据库Cache.db中进行缓存。而Cache.db中的所有数据都以明文形式存储，这些数据包括车辆信息、用户信息、账户令牌以及API请求等。当对iOS设备进行备份或者使用iFunbox等免费工具时，攻击者就有机会窃取到这些信息。

图11-33展示了一个缓存请求的示例，请求的URL中包含了一个handoffToken令牌：

Web应用

接下来，我们来研究MySubaru Web应用，并对应用发送的所有http请求与响应报文进行分析。MySubaru Web应用中包含移动应用所没有的选项，例如添加授权用户或者更改账户PIN码等。对Web应用流量进行代理转发时的步骤与之前相同，但是需要确保对所有可能导致状态变化的报文均进行了分析，例如下面所列出的内容：

图　11-33

·登录/登出。

·开锁/关锁。

·鸣笛。

·开关车灯。

·车辆定位。

·查看车辆健康度报告。

·编辑车辆细节信息。

·增加车辆。

·增加或删除授权用户。

·更改PIN码。

·更改口令。

·更改安全问题。

·更改个人账户信息。

我们需要对Web应用同移动应用之间的所有区别加以注意。到目前为止，Web应用同移动应用之间最大的区别在于远程服务API请求发送至Subaru服务器的方式。对于所有应用而言，API endpoint均是相同的，当发现漏洞并开展利用时这一点非常有用。

在图11-34的截图中采用彩色高亮方式展示了Burp Suite拦截到的所有应用的http历史报文。

图　11-34

步骤4　脆弱点识别

通过Web代理可以识别出应用所有的特征以及API调用，随后我们将开始分析设计过程中的脆弱点，进而测试脆弱点中是否存在逻辑漏洞。我们所关注的脆弱点如下所示：

1）Web应用中的所有远程服务调用均采用GET方式发送，参数包含在URL之中，而移动应用则以POST方式发送远程服务调用请求，参数包含在报文体中。其中，Web应用在进行远程服务调用时不会用到随机生成的sessionId参数。

2）移动应用中不强制要求证书绑定与验证。

3）在iOS应用中会将所有的请求与响应报文进行缓存。

4）在编辑车辆信息或者增加授权用户等账户配置变更操作中，均未包含anti-CSRF token。

5）当添加授权用户时，用户不会收到通知。

6）更新账户PIN码时无须知道之前设置的PIN码。

7）对安全问题的变更无须再次认证，且没有最小字符长度限制，还可以设置为相同的值，例如1。

8）授权用户对Subaru远程服务具有完全的访问权限，对于添加用户的数量也没有限制。

9）所有应用均未设置并发登录策略。

图11-35是PIN码以及安全问题的配置变更页面，其中在对配置进行改动时，并未要求用户进行认证或者输入之前的配置信息。

图　11-35

现在我们更改配置参数，并将用户输入反射到屏幕上。在本例中，由于我们没有权限发送恶意载荷，所有的工作都需手工完成，因此需要通过Burp Suite的Repeater模块来手工输入参数。了解到这一点后，我们可以尝试发送简单的XSS载荷，并观察是否会对载荷进行验证或编码。第一个想到的用来测试反射参数值的位置就是车辆的名称。在车辆名称输入框中输入一段普通的<script>alert(1)</script>脚本，然后查看脚本是否能够在浏览器中执行，验证是否存在漏洞。

下面以一个以授权用户身份执行的跨站脚本攻击（cross-site scripting，XSS）漏洞（Vulnerability#10）为例，展示XSS漏洞的利用情况。该XSS漏洞的利用结果如图11-36所示。

接下来，我们分析API中的逻辑漏洞，例如是否进行了强制限速，或者在未对API请求做出改动的情况下是否可以重放API请求报文。测试步骤为将http请求报文发送给Burp Suite的Repeater模块，然后再重放该请求报文。经过测试发现，进行远程服务调用时（漏洞#11），应用并未采用抗重放或者强制限速等安全控制措施。虽然在测试过程中，发送每个API请求报文时需要间隔5秒，以保证车辆有足够的时间来执行请求。

下一项测试是测试移动应用与Subaru服务器之间的登录过程是否存在逻辑漏洞。Subaru服务器采用POST方式在报文中传输用户的认证信息，经过认证后将用户重定向至其账户的控制面板。在登录过程中，账户认证信息成功验证之后，移动应用会采用GET方式发送请求到Subaru服务器，请求中包含用户名、handoffToken以及其他参数。这些内容同在iOS应用中的Cache.db中找到的http请求中所包含的内容相同，仅仅是令牌值有所区别。可以将GET请求复制粘贴到浏览器中，并在无须用户名、口令的情况下完成MySubaru账户的自动登录（漏洞#12）。此外，handoffToken永不过期，在MySubaru用户退出Web或者移动应用登录后依然有效。甚至口令的变更也不会导致令牌过期。这是一个重大发现，因为我们可以在用户未感知到已遭受入侵的情况下保持对MySubaru账户的访问权限。另一个同handoffToken有关的安全隐患是，新设备以及授权用户登录他们的MySubaru移动应用时会创建新的令牌。例如，某个用户使用2台iPhone设备以及2台Android设备登录MySubaru账户。那么现在对该账户而言就会有4个可用的handoffToken值。这同样适用于授权用户。例如，2个授权用户（carhackingemail@gmail.com和carhackingemail1@gmail.com）分别通过3台设备登录进他们的MySubaru账户。那么此时对于授权用户而言就存在6个存活令牌。这样就实现了MySubaru账户攻击面的扩展。图11-37的示例展示了2个授权用户账户carhackingemail@gmail.com和carhackingemail1@gmail.com，分别采用3台不同的移动设备进行登录的情况，并且获取到了不同的handoffToken值。

图　11-36

图　11-37

步骤5　漏洞利用——将漏洞组合起来加以利用

到现在为止，通过主、被动分析我们已经发现了至少11个漏洞。其中部分漏洞可以直接利用，其他漏洞由于程序逻辑以及设计方面的问题不能直接利用。考虑到我们的目标是在没有遥控钥匙、实体钥匙以及认证信息的情况下能够访问车辆，那么可以说我们已经拿到了我们想要的东西。

回顾已经发现的安全漏洞，我们发现对MySubaru账户以及车辆实施成功的漏洞利用需要用户介入，而用户的介入可以借助多种方式来实现。我们可以尝试构建以下攻击场景，这些场景中均涉及了社会工程学技术：

·制作恶意页面，页面中采用XSS载荷攻击车辆名称字段。

·提取handoffToken以获取有效会话。

·通过CSRF漏洞添加授权用户。

·通过CSRF漏洞伪造目标Subaru车辆的远程服务调用进行解锁。

·更改安全问题。

·更改PIN码。

·金钱收买。

可以用于提取有效handoffToken的其他攻击场景包括：

·被攻击者采用攻击者部署的设备进行登录，而攻击者设备可以从该设备缓存中提取出被攻击者的handoffToken。

·被攻击者将移动设备（Android/iOS）中的内容备份到攻击者的计算机中，攻击者再将被攻击者的备份恢复到测试用移动设备，此时测试用移动设备中即会包含hand-offToken。

·攻击者窃取授权用户而非车主的handoffToken。

·通过Wi-Fi热点或者其他方式对被攻击者发起中间人攻击。

·通过iFunBox（iOS）获取Cache.db。

·审计日志中的URL GET请求会泄露handoffToken，Subaru系统管理员以及负责网络流量与无线热点监控的网络管理员均可以获取该信息。

攻击者不仅能够实现对车辆的未授权访问，还能够对车主进行跟踪定位从而可能对车主的人身安全带来风险。其他有待探索的后渗透测试利用场景还包括：

·从车辆中窃取信息。

·破坏车辆的发动机。

·在能够访问多台车辆的MySubaru账户中持久驻留。

·植入带外跟踪器。

·植入恶意Wi-Fi接入点，通过w/GSM远程连接来实现对邻近访问点或车辆的漏洞利用。

·重放远程服务请求耗尽电池电量，例如车辆的关锁操作。

读者可能已经注意到，前面提到的都是基本的Web安全漏洞，并非新型0-day漏洞。然而，相比于其他系统，对于IoT互联设备与车辆而言这些基本漏洞的危害会更大。

[1] Andorid应用、iOS应用与Web应用。——译者注

11.3.2　延伸阅读

了解本主题的更多研究可以查看以下页面：

·https://www.scmagazine.com/researcher-hacks-subaru-wrx-sti-starlink/article/666460/

·https://www.bitdefender.com/box/blog/iot-news/researcher-finds-basicmistakes-subarus-starlink-service/

·http://www.databreachtoday.com/exclusive-vulnerabilities-could-unlockbrand-new-sub-arus-a-9970

11.4　固件持续集成测试配置

构建采用C/C++语言开发的固件对于已发布的产品而言是个大大的难题，因为其中涉及复杂的Makefile文件。然而，在产品部署前，就应该对所有源代码进行静态分析查找其中可能存在的安全漏洞。本节中将介绍如何在持续集成环境中对固件的C/C++代码开展基本的静态分析。

11.4.1　准备工作

在本节中，我们将会用到以下应用和工具：

·Jenkins：Jenkins是一套开源自动化服务器，可以对其做进一步定制开发，用于代码的安全性分析。通过链接https://jenkins.io/download/可以下载到Jenkins代码。在不同的操作系统中，Jenkins需要采取不同的安装部署方式。对于Debian和Ubuntu系统，可以使用以下命令安装Jenkins：

·然后将以下内容添加到/etc/apt/sources.list源文件中：

接着执行以下命令安装Jenkins：

·Fuzzgoat：Fuzzgoat是一个存在漏洞的C程序，可以通过GitHub代码库https://github.com/packttestaccount/fuzzgoat下载。使用下面的命令可以将fuzzgoat的代码克隆到Jenkins服务器中：

·Flawfinder：Flawfinder是一个挖掘C/C++代码漏洞的工具。Flawfinder可以通过链接https://www.dwheeler.com/flawfinder/flawfinder-2.0.4.tar.gz下载。

通过以下pip命令可以安装Flawfinder：

11.4.2　测试流程

部署固件持续集成测试环境的步骤如下：

1）Jenkins安装[1]完成之后，登录进入主界面并单击New Item选项创建项目，如图11-38所示。

此时，读者需要确保已经对JAVA_HOME环境变量进行了配置。如果系统中存在多套Java版本，则需要在链接http://127.0.0.1:8080/configureTools/对Jenkins中的Global Tool Configuration选项中的JDK进行配置。

2）输入项目名称，选择Freestyle project，如图11-39所示。

3）接着会出现配置页面。此时无须进行任何配置，因为我们完成项目构建之后，会将本地项目加载进Jenkins创建的工作空间。如果构建失败也没关系，因为我们只是想使用Jenkins创建目录，然后将采用C代码编写的项目复制进工作空间。后面的章节中也会采用这一方法创建工作空间，如图11-40所示。

图　11-38

图　11-39

图　11-40

图11-40　（续）

4）单击Save按钮之后，用户会返回至项目页面，在该页面选择Build Now选项：

图　11-41

此时，Jenkins就完成了工作空间的创建，接下来我们可以将代码文件转移至工作空间当中。目录结构根据所使用的操作系统有所区别。对于Ubuntu而言，工作空间中的文件位于/var/lib/jenkins/workspace/目录下，而对于OS X系统而言，工作空间中的文件位于/Users/Shared/Jenkins/Home/workspace/目录下。将fuzzgoat文件发送到新创建的工作空间目录下，其中目录名与项目名相同，在本例中，就是/var/lib/Jenkins/workspace/Packt-TestFirmware/。

在此，需要确保Jenkins*Nix用户具有对应的文件与文件夹操作权限来对工作空间目录中的内容进行扫描。同时，所用到的工具也需要具有相关权限对相关目录进行扫描。

5）现在，fuzzgoat位于Jenkins工作空间目录中，返回Jenkins项目，选择Configure选项再选择Build选项卡，添加构建步骤，在其中选择执行shell命令，即在工作空间目录下执行flawfinder命令，如图11-42所示。

图　11-42

6）再添加一条构建步骤执行另外一条shell命令。这次是在工作目录下执行make命令，其中Makefile文件包含在fuzzgoat的代码库中。随后单击Save按钮，如图11-43所示。

7）在项目页面选择Build Now选项。在Build History中单击历史构建操作前面的固定链接，在其中选择Console Output选项，如图11-44所示。

8）构建完成后会返回构建结果，以及flawfinder的执行结果，页面如图11-45和图11-46所示。

用户可以结合自身情况对构建步骤进行调整定制，提醒项目经理或安全负责人根据输出结果开展应对措施。虽然并非flawfinder提示的所有信息均存在漏洞，但是还是应该对提示信息认真审查，确保代码中确实不存在安全漏洞。这里需要注意的是，flawfinder较为简单，只会实现对C/C++代码最基本的检查，仅能够发现常见的缓冲区溢出漏洞以及其他常见的安全隐患，例如禁用函数的使用等。而商用SAST工具则可以基于依赖图与调用图开展应用数据流依赖性分析，挖掘出存在依赖关系的软件漏洞。此外，很多商用SAST工具还包含了IDE插件，可以实时检测代码中的安全漏洞。OS X上的集成开发环境XCode集成了Clang Static Analyzer工具，其中包含了用于C/C++代码分析的免费IDE插件，但是在OS X环境中进行代码编译时需要对配置进行相应调整。Clang不会对无法编译的文件进行分析。在移动应用的持续集成测试中，我们将会讨论如何使用IDE插件对代码开展静态分析。

图　11-43

图　11-44

图　11-45

图　11-46

[1] Jenkins安装运行步骤如下所示：①下载Jenkins。②打开终端进入下载目录。③运行命令java-jar jenkins.war--httpPort=8080。④使用浏览器访问页面http://localhost:8080。⑤遵循指令完成安装。——译者注

11.4.3　延伸阅读

通过下面的链接可以了解到关于Clang Static Analyzer工具的更多信息：

https://clang-analyzer.llvm.org/

https://help.apple.com/xcode/mac/9.0/#/devb7babe820

如果想了解更多语言的源代码分析工具，可以查看下面的链接：

https://www.owasp.org/index.php/Source_Code_Analysis_Tools

11.5　Web应用持续集成测试配置

无论IoT设备使用Web应用还是Web服务进行消息传递，都应该对代码进行静态分析与动态分析，进而查找其中的软件安全漏洞。在本节中，我们将会对如何在产品部署之前开展Web应用动态扫描进行介绍。

11.5.1　准备工作

本节中，我们使用Jenkins作为自动化构建服务器，使用OWASP ZAP作为动态扫描工具。其中，我们会用到OWASP ZAP Jenkins插件，OWASP ZAP工具可以通过下面的链接下载得到：https://github.com/zaproxy/zaproxy/wiki/Downloads。

11.5.2　测试流程

部署Web应用的续集成测试环境的步骤如下。

1）下载OWASP ZAP插件，这一操作也可以通过Jenkins的插件管理器来完成，在Jenkins菜单中选中Manage Jenkins选项中的插件管理器Manage Plugins，接着在Availble选项卡中的可用插件选中OWASP ZAP Plugin，如图11-47所示。

2）插件安装完成之后Jenkins会随即重启。重新登录Jenkins对ZAP进行配置。在Jenkins中使用ZAP有两种方式。一种是对已加载的会话运行ZAP，另一种是部署Selenium框架执行ZAP并在随后保持会话。这里我们在目标构建项目中对已加载的会话部署ZAP。在本例中，我们首先需要通过链接http://127.0.0.1:8080/对ZAP进行设置并配置环境变量。如图11-48所示，设置ZAP的主机地址以及端口号。

用户可以配置多台ZAP主机，从而开展并发扫描。在项目的构建步骤中，可以对此进行配置以覆盖系统的默认配置。

3）根据当前所使用的操作系统，输入ZAP的默认目录（https://github.com/zaproxy/zaproxy/wiki/FAQconfig）。OS X系统中ZAP的默认目录为~/Library/Application Support/ZAP，如图11-49所示。

图11-47　下载OWASP ZAP插件

图　11-48

图　11-49

如果使用的是ZAP的周更新版本，那么在OS X系统中使用默认目录/Users/<user>/Library/Application\Support/ZAP_D/。

4）现在，像之前章节中的操作一样创建Freestyle project，并对其进行重命名，如图11-50所示。

图　11-50

5）保存项目并选择Build Now选项，此时Jenkins会创建项目的工作空间。

由于我们打算针对已装载的会话采用ZAP进行分析，则必须在项目的工作空间目录中创建一个会话并加以保存。为了做到这一点，需要找到运行中的目标应用，并通过浏览器将应用流量代理转发到ZAP。此时，请确保用户点击了应用中的所有链接，爬取了应用中的所有页面并执行了所有功能。在下面的示例中，我们以The BodgeIT Store应用为例进行介绍，该Web应用运行在8888端口上，可以通过File|Persist Session...选项在项目工作空间中保存会话，如图11-51所示。

图　11-51

6）将会话保存到Jenkins中项目的工作空间目录下。本例中，项目PacktZAPscan在工作空间目录下的保存结果如图11-52所示。

图11-52　将PacktZAPscan项目保存至工作空间目录下

7）在ZAP中，需要配置ZAP的API Key。单击Tools菜单，然后打开Options页面。在Options页面中，选择API选项，在配置选项中插入Jenkins插件提供的默认API key，即ZAPROXY-PLUGIN，操作过程如图11-53所示。

图　11-53

注意，我们可以禁用API key，也可以在构建步骤中通过ZAP插件的命令行参数更改API key。如果API key同Jenkins插件中的API key值不匹配，那么将导致扫描失败。

8）由于之前已经将会话保存在了工作空间中，这里返回项目主菜单并选择Configure选项。接下来进行源代码管理配置、设置构建环境并依据应用架构输入构建脚本。在Build选项中，依次选择Add build step|Execute ZAP，如图11-54所示。

图　11-54

9）此时在弹出的页面中输入ZAP的主机配置信息，并将之前保存的会话填入home目录路径。如果会话未保存在项目工作空间下的文件夹下，那么将不会出现在Load Session下拉菜单中，如图11-55所示。

图　11-55

10）接下来，输入会话属性，例如上下文信息以及认证信息等内容。上下文信息主要指自动化扫描的in-scope与out-of-scope对象。上下文信息必须是唯一的，并且不包含在已加载的会话之中。我们可以使用build ID环境变量对上下文信息进行迭代编号，这样它们就是唯一的了，如图11-56所示。

图　11-56

11）下面是Attack Mode部分。在此处，我们可以指定目标URL、扫描配置以及定制的扫描策略，还可以对扫描策略进行配置并保存在项目工作空间中。在下面的例子中，测试URL是在页面爬取过程中选择的，同时对定制的XSS扫描策略进行了配置。如果未指定定制的扫描策略，那么使用默认策略。攻击设置配置完成后，对生成的报告进行命名，选择Format以及Export Report对报告格式进行设置，然后单击Save按钮，如图11-57所示。

确保对权限进行了适当的设置之后，Jenkins和ZAP就可以对工作空间目录进行扫描了。

12）随后返回至项目页面，单击Build Now按钮，在Build History中单击历史构建操作前面的固定链接，在其中选择Console Output选项，如图11-58所示。之后将展示构建状态以及ZAP的扫描进度。

输出结果与图11-59类似。

13）构建与扫描完成后，在工作空间项目目录的reports文件夹下会生成报告，报告路径与名称如图11-60所示。

14）生成的报告包括XML与HTML两个版本，如图11-61所示。

图　11-57

图　11-58

图11-59　Console口的输出

用户还可以对ZAP的扫描与告警信息进行深度定制，只在报告中显示危险和高危的安全威胁。用户应该针对每款应用开展不同的扫描，这可以通过根据应用架构创建不同的环境细节与扫描策略来实现。例如，对于分别运行在Apache Web服务器、Apache Tomcat应用服务器以及MySQL数据库的应用，需要分别针对不同的架构开发定制不同的扫描策略。对于上述情况不推荐采用默认的扫描策略，因为默认扫描策略中可能会用到无关的攻击，从而导致扫描时间延长，甚至可能耗尽ZAP的内部数据库资源。而扫描器所能够发挥的作用同配置、规则集以及所指定的扫描策略有很大的关系。

自动化扫描能够发现部分简单漏洞，可扩展性方面也非常好，但是自动化扫描永远也无法取代人工Web应用安全评估。因为自动化扫描不能进行上下文业务逻辑测试，也无法定位未公开的漏洞，而人工评估则可以实现这些工作。因此，现实中我们建议测试人员可以将自动化测试与人工测试结合起来使用。

图　11-60

图　11-61

11.5.3　延伸阅读

可以通过以下链接了解更多关于OWASP ZAP Jenkins插件的信息：

https://wiki.jenkins.io/display/JENKINS/zap+plugin

https://wiki.jenkins.io/display/JENKINS/Configure+the+Job#ConfiguretheJob-Configure-theJobtoExecuteZAP

11.6　移动应用持续集成测试配置

与之前各节对自动化分析的介绍类似，本节内容主要介绍，在产品部署之前，如何对Android应用进行依赖性扫描与动态分析配置。

11.6.1　准备工作

在本节中，我们将会用到Jenkins自动化构建服务器以及下列工具：

·Mobile Security Framework（MobSF）：这是一套开源的移动应用静态分析与动态分析工具。MobSF应用广泛，且移动安全社区不断对其加以改进完善。可以从下面的链接下载MobSF：

https://github.com/MobSF/Mobile-Security-Framework-MobSF/archive/master.zip

·OWASP Dependency-Check：该工具可以针对Java、NodeJS、Python、Ruby与Swift等多种编程语言进行分析，检测项目的依赖文件中是否存在已公开的漏洞。其中，我们将用到Jenkins的OWASP Dependency-Check插件，该插件可以通过Jenkins插件管理器下载，如图11-62所示。

图　11-62

·依赖性检测工具也可以作为一个单独的工具下载，链接如下：

https://github.com/jeremylong/DependencyCheck

11.6.2　测试流程

部署移动应用持续集成测试环境的步骤如下：

1）首先启动Jenkins并创建Freestyle project，输入项目名称，如图11-63所示。

2）出于简单起见，跟之前一样，直接单击Save按钮保存项目，随后即创建工作空间。接下来，将用户的Android项目文件复制到Jenkins创建的新的工作空间当中，如图11-64所示。

本实例中的工作空间路径为/Users/Shared/Jenkins/Home/workspace/PacktTestAndroid。

图　11-63

图　11-64

3）接下来，在项目主菜单中单击Configure选项，进行构建配置，如图11-65所示。

4）根据构建环境输入所需要的构建脚本，如图11-66所示。

如果测试目标是一个已存在的项目，读者已经知道构建完成后输出的APK放在什么位置。如果测试目标是一个新项目，则需要确保所构建项目能够编译为APK文件。由于下一步工作是扫描构建完成的APK文件，因此进行构建时了解APK文件存储的位置非常关键。

5）新打开一个终端窗口，并进入MobSF的安装路径，运行如下命令：

6）此时终端命令运行结果如图11-67所示。

需要注意MobSF的API key，因为在Jenkins构建服务器中执行REST API调用时会用到该API key。

使用MobSF提供的clean.sh脚本删除所有扫描结果与MobSF数据库信息时，API key会发生变化。

图　11-65

7）回到Android项目在Jenkins中的Configure选项。添加构建步骤执行shell命令，如图11-68所示。

图　11-66

图　11-67

图　11-68

8）在命令输入框中，我们通过REST API调用向MobSF上传APK文件。在此过程中，用户会用到REST API key，以及APK文件构建完成后的存储位置。以API key与APK文件路径为参数，调用curl命令如下所示：

前面的curl命令会将最新构建完成的APK文件上传到工作空间，然后对该APK文件进行扫描。MobSF会生成上传二进制文件的散列值，在其他API调用引用该二进制文件时会用到该散列值。紧接着，使用awk命令解析MobSF返回的JSON格式的响应数据，并将生成的散列值存储到特定文件，在随后的MobSF API请求中会用到该文件。

9）APK文件上传完成之后，再次添加构建步骤来执行shell命令，这时在curl命令中以APK文件名、API key值为参数开始扫描上传的APK文件：

10）此时MobSF需要几分钟扫描APK文件，因此新建步骤执行shell命令等待扫描结束，即执行Sleep命令：

根据MobSF分析应用所消耗的时间，可以对Sleep命令的参数进行调整。在本例中大概需要2分钟。需要注意的是，MobSF扫描APK文件时，如果用户未等待足够的时间就尝试下载报告，那么下载到的报告内容将是空的。

11）接下来，新建构建步骤生成并下载PDF格式的扫描结果报告。针对不同的API key分别执行以下命令：

读者也可以选择以自己喜欢的方式命名MobSF报告。为了使报告具有唯一性，可以使用build ID环境变量。此时，Jenkins就实现了已构建APK文件的上传、扫描以及MobSF报告的生成与下载等操作。

12）再添加构建步骤来调用Dependency-Check进行依赖性分析，通过依赖性分析可以对项目所依赖的文件进行扫描，进而查找已知漏洞，如图11-69所示。

图　11-69

13）Dependency-Check依赖性分析中的扫描路径Path to scan的内容应该设置为空，这样将会对工作空间目录中的项目文件进行扫描，并在工作空间中输出结果，如图11-70所示。

图　11-70

这里需要确保对权限进行了适当的设置，这样Jenkins以及Dependency-Check依赖性分析插件才能够对工作空间目录进行扫描。

14）项目的构建步骤配置如图11-71所示。

图11-71　项目构建步骤配置

15）接下来，保存项目配置并构建Android应用。用户可以在Android应用项目的控制台查看构建过程。构建过程的第一步是编译应用的APK文件，然后使用MobSF进行扫描，最后使用Dependency-Check分析项目所依赖的文件，如图11-72所示。

图11-72　Console口的输出

16）图11-73展示了第二个与第三个构建步骤中上传以及扫描APK文件的操作。

图11-73　执行构建步骤进行APK的上传与扫描

17）之后是第四步、第五步、第六步的构建步骤，分别是执行Sleep命令、生成MobSF扫描结果的PDF文件、扫描项目的依赖文件，如图11-74所示。

图　11-74

18）如果读者查看项目工作空间，就会发现此时生成了一份MobSF报告以及Depend-ency-Check依赖性分析报告，如图11-75所示。

19）单击MobSF报告以及依赖性分析报告，可以分别以报告各自的格式来打开报告（采用PDF文件方式打开MobSF报告，采用HTML、JSON或者XML格式打开依赖性分析报告），如图11-76所示。

20）图11-77为以HTML格式显示的依赖性分析报告。

用户还可以通过对分析报告进行配置来自动向中心服务器发送，或者在构建过程中发现某些高危漏洞时，执行发送告警邮件或Jira ticket等操作。除了本章中所介绍的内容，用户还可以采用高级特性对Jenkins进行深度定制开发。OWASP组织就提出了一个能够帮助应用安全团队提高速度，并提高安全测试过程自动化程度的项目，即OWASP AppSec Pipeline（https://www.owasp.org/index.php/OWASP_AppSec_Pipeline）。AppSec Pipeline项目对多套工具以及设计模式进行了分析，能够帮助小型安全团队根据代码推送速度高效地开展安全分析，并能够进行功能扩展。

图　11-75

图11-76　扫描结果输出

11.6.3　延伸阅读

·Dependency-Check依赖性分析插件需要用到应用依赖文件的存储路径，同时还会用到OWASP Dependency-Track跟踪应用中存在漏洞的组件。可以在http://JenkinsURL:8080/configure页面中对OWASP Dependency-Track进行配置。了解OWASP Dependency-Track的更多信息，可以查看下面的链接：https://www.owasp.org/index.php/OWASP_Dependency_Track_Project。

·了解更多关于MobSF REST API的内容，可以查看下面链接中的文档：https://github.com/MobSF/Mobile-Security-Framework-MobSF/wiki/3.-RESTAPI-Documentation。

图　11-77