本文翻译自:https://research.checkpoint.com/dji-drone-vulnerability/


最近Check Point研究人员发现大疆无人机漏洞。漏洞如果被利用,攻击者就会被授予访问用户DJI账户的权限。

漏洞是通过DJI论坛访问产生的,论坛主要讨论大疆的产品。当用户登陆DJI论坛,点击刻意植入的而已链接时,攻击者就可以获取其登陆凭证,并访问其他DJI在线资产,包括:

2018年3月,研究人员将该漏洞通报给了大疆,大疆对该漏洞进行了修复。大疆对该漏洞的评级为high risklow probability。也就是说该来的被利用的可能性小。

攻击流图

技术分析

下面解释如何获取DJI web平台、手机APP和FlightHub的敏感飞行数据、敏感用户数据的访问权限。

漏洞

该漏洞位于DJI身份识别过程中。
DJI用cookie来识别用户和创建token/tickets来访问平台,而cookie是攻击者可以获取的。通过使用cookie,攻击者可以劫持任意用户的账户,并完全控制用户的DJI Mobile Apps, Web账户或DJI FlightHub账户。
首先看一些DJI网站登录过程来了解DJI后台是如何识别用户,以及那些参数和cookie对登陆过程非常重要。研究人员分析了客户端与DJI后台的流量。

研究人员注意到DJI对以下子域名使用了该服务:

这些域名之间的登陆使用的是OAuth框架。
研究人员分析发现到URL mobile.php的请求暴露了用户账户的敏感信息,包括username, member_uid, token等。然后研究人员发现这里用来进行用户识别的cookie是meta-key

图1: mobile.php请求

研究人员的目标是获取meta-keycookie,因此必须要找到没有被http-only保护的子域名,因为http-only会防止JS泄露cookie。满足这一要求的域名是forum.dji.com,然后研究人员开始寻找和分析平台的漏洞。

发现漏洞

研究人员发现了这样的请求:
https://forum.dji.com/forum.php?mod=ajax&action=downremoteimg&message=

响应中反映出了消息参数,但是有两个困难:

研究人员认为GET请求的response比较像下面的伪代码:

首先,用后斜杠和单引号来进行函数逃逸:
parent.updateDownImageList(‘ \’ ‘);

然后addslashes会增加一个后斜杠,使后斜杠逃逸,并修改为这样的字符串:
parent.updateDownImageList(‘ \\ ‘ ‘);

然后处理剩下的字符‘)和未定义的函数updateDownImageList

研究人员加入了一个简单的HTML注释<!–,创建了下面的payload:
parent.updateDownImageList(‘ \'<!– ‘);

为了处理未定义的函数,需要做的就是自己定义该函数。
最终的payload为:
\’ alert(document.cookie); function updateDownImageList (data) {} <!–

图3: 使用payload获取的cookie

攻击者可以创建一个发送meta-keycookie到网站的payload。这类XSS并不会被XSS过滤器过滤,因为不含有任何脚本或事件。

为了触发XSS攻击,攻击者需要做的就是在DJI论坛上发布一个帖子,帖子中需要包含一个链接到payload的链接。因为DJI会限制链接到论坛的内容,所以不能发送这样的链接到恶意站点。

图4: 链接到恶意网站的内容

因为XSS在论坛内,所以可以绕过对链接的限制。而且有成千上万的用户在DJI论坛上交流,因此用户会自己转发消息和链接,不需要用户分析恶意链接。在获取meta-key后,就可以进行登陆测试DJI后台处理登陆的过程。

DJI网站

为了获取DJI网站用户账户的访问权限,就需要其meta-key,也就是子域名account.dji.com中的mck。首先创建DJI账户并登陆,通过分析登陆过程,研究人员发现后台使用OAuth来认证用户和子域名,比如从accounts.dji.com到forum.dji.com,再到dji.com。

每次DJI要认证用户的时候,就发送含有mckcookie的initData.do,然后响应就是一个含有ticket的回调URL。通过导航到该url就可以在没有凭证的情况下认证用户。

因此,为了达到劫持账户的目的,需要:

  1. 以攻击者的身份登陆dji.com,然后点击DJI.COM,会将用户重定向到dji.com;
  2. 用受害者的mck替换initData.do请求中的mckcookie值;
  3. 继续登陆进程,并访问受害者账户。

下面是initData.do请求:

图5: initData.do请求

DJI App

要劫持DJI手机应用的账户,就需要绕过应用中实现的所有缓解措施:
拦截应用和DJI后台的请求数据来分析登陆过程。但研究人员发现应用使用了SSL校验证书绑定(ssl pinning) 技术,这妨碍了研究人员拦截应用流量和分析。因此,研究人员反编译了应用来找出如何绕过SSL pinning机制。但DJI手机应用使用了SecNeo保护,因此反编译过程也失败了。

SecNeo提供了以下保护:

了解了这些之后,研究人员决定使用Frida来绕过这些限制。事实上,研究人员在添加dji.go.v4应用时失败了。然后研究人员分析了添加失败的原因,并用frida-ps –U命令来获取运行的所有进程列表。

运行该命令后,研究人员注意到只有一个dji.go.v4进程,过了几秒钟后,出现了另外一个dji.go.v4进程。

通过查看/proc/11194/status,研究人员发现新出现的进程与第一个进程是有关联的,实际上是在调试这也就是为什么不能用Frida进行调试了,因为已经在调试了。

图6: 新创建的进程在Frida中与第一个dji.go.v4进程关联

研究人员发现第一个开启的进程并不是调试器,而是真实的应用。调试器并没有与真实应用相关联,这也就是说这里存在一个可以利用的竞争条件。

为了实现绕过,首先复制Burp Suit证书到手机APP,并复制DJI应用。这会开始处于挂起模式的应用。然后用以下逻辑创建一个Frida脚本:

  1. 打开Burp Suit证书,并转化为X.509证书;
  2. 加载keystore并将证书放进去;
  3. 创建TrustManagerFactory,并用刚才创建的含有Burp Suit证书的KeyStore初始化;
  4. 重载SSLContext,并用研究人员的TrustManager hook TrustManager。

Hook完成后,研究人员恢复挂起的应用。调试器在完成hook后就可以开始保护了。这样研究人员就成功地绕过了SSL pinning,在Burp Suit中就可以看到拦截的流量了。

图7: 绕过SSL pinning后在Burp Suit看到的流量

绕过SSL pining后,研究人员建立了一个拦截手机应用流量的代理。
在分析了web应用登陆过程后,研究人员发现用户插入凭证后,手机应用就会发送请求到/apis/apprest/v1/email_login。接收到的响应如下:

{“code”:0,”message”:”ok”,”data”:{“nick_name”:”XXXXXXXXX”,”cookie_name”:”_meta_key”,”cookie_key“:”NTUxNjM2ZTXXXXXXXXXXXXXXNmI2NjhmYTQ5NGMz“,”active”:false,”email”:”[email protected]”,”token“:”XXXXXXXXX2139“,”validity”:15275XXXXX,”user_id”:”9629807625XXXXXX”,”register_phone”:””,”area_code”:””,”inner_email”:false,”subscription”:false,”vipLevel”:null,”vipInfos”:[]}}
`

这里有两个重要的参数:

账户劫持过程

劫持账户的过程如下:

  1. 首先攻击者需要meta-keytoken来进行替换。所以需要发送meta-key来黑掉mobile.php并接收对应的token;
  2. 攻击者输入凭证,发送登陆请求;
  3. 接收到第二步的响应后,攻击者需要用受害者的meta-key和来自第1步的token替换对应的meta-key和token;
  4. 攻击者获取受害者账户的完全访问权限。

利用DJI漏洞,攻击者可以获取受害者账户的完全访问权限,还可以访问同步的飞行记录、无人机拍摄的照片等信息。

为了访问飞行日志文件,攻击者需要用手机同步飞行记录,因为所有的飞行记录都手动上传到DJI云服务器了。然后浏览·DJI/dji.go.v4/FlightRecord·就可以看到飞行相关的文件,和相关的用户飞行数据。

DJI-FlightHub

DJI-FlightHub是一个web端的应用程序,可以帮助企业用户对无人机进行管理。DJI-FlightHub允许实时查看无人机的飞行状况,包括飞行地图、实时摄像头画面、以及无人机的准确位置信息等。

DJI-FlightHub有一个桌面应用程序来访问管理控制面板,该web门户位于www.dji-flighthub.com
在DJI-FlightHub中,一共有三个角色,分别是admin, captain和pilot。

也就是说,如果获取了admin或captain账户的访问权限,就可以查看无人机的实时操作和状态。为了劫持DJI的admin或captain账户,需要了解DJI-FlightHub的登陆过程。

图8: DJI-FlightHub登陆页面

研究人员发现点击login,会发送一个initData.do请求,但是响应中并没有ticket。当用户输入凭证时,只接收到login.do响应的ticket。这也之前通过web门户劫持account.dji.com是不同的,因此需要重新考虑如何劫持DJI-FlightHub账户。

研究人员发现DJI-FlightHub的initData.do请求中有一个DJI-FlightHub的appid,这就是为什么在响应中没有获得ticket的原因。因此研究人员替换了appid来获取ticket。接收到ticket后,需要做的就是确定另一个appidticket在这里是否适用。

步骤如下:

  1. 发送含有appId=store和Admin的mckinitdata.do请求,获取响应中的ticket
  2. 登陆FlightHub,拦截请求,修改login.do请求中的mck和对应的inidata.do响应响应中的ticket。然后攻击者会重定向到管理员或受害者账户。

另外,admin不会接收到任何攻击者访问账户的通知。攻击者可以访问飞行数据,下载之前上传到FlightHub平台的飞行记录等。

源链接

Hacking more

...