A look at WeChat security
原文地址:http://blog.emaze.net/2013/09/a-look-at-wechat-security.html
TL;DR: Any (unprivileged) application installed on an Android phone can instruct WeChat to send an hash of your password to an external, attacker-controlled server. If you are a WeChat user, it is probably worth reading the rest of this post :-)
Introduction
Nowadays, instant messaging (IM) has become one of the main applications of mobile phones, with plenty of "apps" available and literally billions of messages exchanged every day. With the widespread diffusion of mobile Internet traffic plans, IM applications are rapidly replacing other forms of mobile communication, such as text messages and, in some situations, even e-mails.
As conversations are rapidly converging to IM applications, it is natural to start asking how secure this communication channel actually is, and if users can really trust IM apps and their back-end infrastructure. We decided to pick one of these applications and look "under the hood", in order to see how the developers tried to ensure the confidentiality of in-transit communications.
After a quick survey of available IM applications, we decided to start with WeChat, a popular mobile IM platform developed by the China-based Tencent company. The choice of this specific application was quite arbitrary and mainly based on the fact that, in this period, WeChat is publicized a lot on the Italian TV.

WeChat is a feature-rich and sophisticated mobile application, which allows users to communicate via text messages, voice calls, to share photos and videos, and much more. The app is available for several mobile platforms, but we focused on the Android version only: according to Google Play, WeChat for Android alone has more than 50 million downloads. Most of the issues discussed in this post should affect Android versions of WeChat up to 4.5.1. On August 5th, 2013, Tencent released version 5.0, which introduced some major changes; we still have to analyze this version in detail.
A glimpse at the network traffic
The most obvious and easy thing to start with was an analysis of the network traffic generated by the application during normal usage. At this aim, we instructed our Android emulator to save all network traffic to file, we installed WeChat, we logged in and sent a couple of text messages. Part of the traffic generated by WeChat is shown below.

As can be seen from the figure, most of the traffic travels on TCP port 8080, typically reserved for HTTP connections (previous versions of WeChat were using the standard HTTPS port, tcp/443). However, at a first sight, the payload of these packets looks quite strange; indeed, Wireshark is not even able to dissect the HTTP payload.
Looking more closely, we noticed WeChat developers implemented a custom communication protocol: we were able to recognize an initial packet header, right at the beginning of the payload, that confirms these are actually not HTTP/HTTPS sessions. More precisely, we identified the following header fields:
- Packet length (4 bytes)
- Header length (2 bytes, always equal to 0x0010)
- Protocol version (2 bytes, always equal to 0x0001)
- Opcode (4 bytes, specifies the actual command encapsulated in this packet)
- Sequence number (4 bytes)
This initial header is followed by an opcode-dependent message body, usually in encrypted form. Briefly, the first message is encrypted by the application using RSA, with an hard-coded public key; next messages are encrypted in AES. In WeChat versions up to 4.3.5 we identified several vulnerabilities which allow an attacker who can intercept the traffic to quickly decrypt the message body, thus being able to access the messages sent and received by the user. More recent versions seems to be immune to these attacks, but we still have to perform a more in-depth analysis of the encryption scheme implemented in the latest WeChat releases.
Debugging
Here we come to the interesting part :-) WeChat includes an undocumented debugging infrastructure, probably used by developers for testing purposes. However, this infrastructure can also be abused by attackers to steal sensitive information concerning a WeChat user account.
In detail, WeChat reads debug settings from an Android ContentProvider, identified by URI "com.tencent.mm.coolassist.debugprovider/config". This ContentProvider is used by the application as a centralized source of debug configuration parameters, and can be employed to specify which debug messages should be logged to the Android console (adb logcat), to save log messages to the sdcard, and even configure a remote logger.
From a security perspective, the remote logging feature is surely the most interesting one. By exploiting this functionality, an attacker can develop a malicious application which exposes the aforementionedContentProvider and, through specially-crafted debug settings, makes WeChat to send logs to an external, attacker-controlled, server. Such a malicious application would not require any special Android permission.
It is worth considering that logged messages disclose sensitive information about the users, including the user ID, password hash and other details. As an example, here is an excerpt from a remote log session:
- :: V/MicroMsg.MMBuiltInIP <-- data-blogger-escaped-br="" data-blogger-escaped-dump="" data-blogger-escaped-end="" data-blogger-escaped-mmbuiltinip=""> 09-09 14:32:51 626 D/MicroMsg.AccInfo update session info: session=, uin=-1893467821
- :: I/MicroMsg.AutoAuth sending remote request, network.active=false
- :: I/MicroMsg.AutoAuth.SceneInfoQueue inQueue: netid=
- :: V/MicroMsg.SDK.SyncTask sync task done, return=, cost=(wait=, run=)
- :: V/MicroMsg.NetStatWatchDog dkreport status: nowCount: ret:
- :: D/MicroMsg.AutoAuth account info updated:AccInfo:
|-uin =-
|-user =ukcd_ao03gex3y2731v
|-session =
|-pass =5f4dcc3b5aa765d61d8327deb882cf99
|-pass2 =5f4dcc3b5aa765d61d8327deb882cf99
`-cookie =(null)
- :: D/MicroMsg.NetStatWatchDog item.toByteArray() :
- :: D/MicroMsg.GYNet encoding, type=, key=, time=
- :: I/MicroMsg.GYNet sendImp reqData.len:
- :: D/MicroMsg.NetStatusUtil activeNetInfo extra=internet, type=
As can be seen from these logs, the application forwards to the remote server the user name (ukcd_ao03gex3y2731v), another user identifier (uin, with value -1893467821), and even the user's password hash (5f4dcc3b5aa765d61d8327deb882cf99). It should be noted the hash value is a plain MD5 of the user's password, sent to the server for the authentication. Obviously some parameters in the above logs have been edited to prevent readers from hacking our account but, yes,5f4dcc3b5aa765d61d8327deb882cf99 is the MD5 for string "password" and this was really our account's password :-)
The next section details the communication protocol used by WeChat to interact with the remote log server.
Remote logging protocol
Remote logging can be enabled by configuring the following debug keys:
- .com.tencent.mm.debug.log.level = 0
- .com.tencent.mm.debug.log.mmlog.url.mm.log = <ip1>:<port1>
- .com.tencent.mm.debug.log.mmlog.url.push.log = <ip2>:<port2>
The first key defines the log level ("0" simply means to log everything), while others are used to set the log server address for the two main WeChat application modules (mm and push).
WeChat developers implemented a trivial key derivation scheme to allow the application and the remote log server to agree on an encryption key to cipher debug logs. In a nutshell, the app reads three ASCII lines from the server and uses these lines to derive a DES key. Before transmitting debug messages, the application encrypts them in DES/ECB using this key.
The key generation function is implemented by the following Python code snippet. Functiongeneratekey() receives in input the three lines sent by the server and returns the corresponding DES key.
import hashlib def mangle(data):
charset = "0123456789abcdef"
r = ""
for c in hashlib.md5(data).digest():
r += charset[(ord(c) >> ) & 0xf]
r += charset[ord(c) & 0xf]
return r def generatekey(line0, line1, line2):
seed = line1[:]
seed += str(int(line2[:]))
seed += "dfdhgc"
key = mangle(seed)[:]
return key
We also implemented a buggy "quick & dirty" Python script that listens for incoming connections, sends out three ASCII lines, computes the key and deciphers incoming messages. The script is available here.
As a final note, we would like to point out that the ".com.tencent.mm.debug.log.mmlog.url.* " configuration keys are not supported by the latest version of WeChat (5.0). However, this version still queries the ContentProvider for debug settings and part of the logging functionalities have been moved to a dedicated JNI library. We plan to investigate these new features in the future, so at the moment we cannot exclude that the remote logging mechanism has simply been moved elsewhere.
Local database encryption
WeChat locally stores application data in an encrypted SQLite database named "EnMicroMsg.db". This database is located in the "MicroMsg" subfolder inside the application's data directory (typically something like "/data/data/com.tencent.mm").
The database is encrypted using SQLCipher, an open source extension for SQLite that provides full database encryption. The encryption password is derived from the "uin" parameter (see previous sections) combined with the device identifier through a custom function. More precisely, the key generation function leverages the mangle() function shown in the previous Python snippet. The actual database encryption key can be generated through the following pseudo-code:
password = mangle(deviceid + uin)[:]
Here deviceid is the value returned by the Android API functionTelephonyManager.getDeviceId(). Follows a sample SQLCipher console session that demonstrate how the EnMicroMsg.db database can be decrypted.
$ sqlcipher EnMicroMsg.db
sqlite> PRAGMA key = 'b60c8e4';
sqlite> PRAGMA cipher_use_hmac = OFF;
sqlite> .schema
CREATE TABLE conversation (unReadCount INTEGER, status INT, ...
CREATE TABLE bottleconversation (unReadCount INTEGER, status INT, ...
CREATE TABLE tcontact (username text PRIMARY KEY, extupdateseq long, ...
...
It is also worth pointing out that, as the key generation algorithm truncates the password to 7 hex characters, it would be not so difficult for motivated attackers who are able to get the encrypted database to brute force the key, even without knowing the uin or the device identifier.
Conclusions
In this post we discussed some security weaknesses that affect Android versions of WeChat up to 4.5.1 (and possibly others). We tried to contact developers to notify our findings, but with no luck: we wrote an e-mail to Tencent technical support both on August 30th and on September 3th, but we got no reply. With the recent widespread diffusion of mobile instant messaging, app developers should take security into more serious considerations, as their application will probably rapidly become an attractive target for attackers.
A look at WeChat security的更多相关文章
- 移动安全初探:窃取微信聊天记录、Hacking Android with Metasploit
在这篇文章中我们将讨论如何获取安卓.苹果设备中的微信聊天记录,并演示如何利用后门通过Metasploit对安卓设备进行控制.文章比较基础.可动手性强,有设备的童鞋不妨边阅读文章边操作,希望能激发大家对 ...
- ZendFramework-2.4 源代码 - 关于配置
$applicationConfig = $serviceManager->setService('ApplicationConfig'); // 获取配置 /data/www/www.doma ...
- 集成 WeChat SDK - 支付篇
作者感言 惯例, 开头都是要说些东西的了, 随着现在的App越来越商业化, 很多公司的App都会集成第三方的支付SDK, 这样子的成本就比较低, 但是呢, 有很多朋友还是不太会集成, 也不太爱看集成文 ...
- “/wechat”应用程序中的服务器错误。
对路径“C:\inetpub\wwwroot3\wechat\img\qrcode\”的访问被拒绝. “/wechat”应用程序中的服务器错误. 对路径“C:\inetpub\wwwroot3\wec ...
- spring security集成cas实现单点登录
spring security集成cas 0.配置本地ssl连接 操作记录如下: =====================1.创建证书文件thekeystore ,并导出为thekeystore.c ...
- Spring Security中实现微信网页授权
微信公众号提供了微信支付.微信优惠券.微信H5红包.微信红包封面等等促销工具来帮助我们的应用拉新保活.但是这些福利要想正确地发放到用户的手里就必须拿到用户特定的(微信应用)微信标识openid甚至是用 ...
- Spring Security OAuth2 微服务认证中心自定义授权模式扩展以及常见登录认证场景下的应用实战
一. 前言 [APP 移动端]Spring Security OAuth2 手机短信验证码模式 [微信小程序]Spring Security OAuth2 微信授权模式 [管理系统]Spring Se ...
- Security Policy:行级安全(Row-Level Security)
行级安全RLS(Row-Level Security)是在数据行级别上控制用户的访问,控制用户只能访问数据库表的特定数据行.断言是逻辑表达式,在SQL Server 2016中,RLS是基于安全断言( ...
- Content Security Policy 入门教程
阮一峰文章:Content Security Policy 入门教程
随机推荐
- 002_更新Nginx证书
全球可信并且唯一免费的HTTPS(SSL)证书颁发机构:StartSSL 1.自行颁发不受浏览器信任的SSL证书: HTTPS的SSL证书可以自行颁发,Linux下的颁发步骤如下: openssl g ...
- 修复 Tween.JS 的 onStop 设置无效
Tween.js 个人认为还是一个比较不错的 缓动动画库,给作为学渣的我实现一些酷酷的动画带来了极大的遍历. 但是,今天突然发现特么设置onStop的回调函数居然没反应...... 作为一个渣渣只能一 ...
- logback.xml 模板
ssm模板 <?xml version="1.0" encoding="UTF-8"?> <!--configuration 根节点,包含下 ...
- java 异常的限制
一. 1.) 在覆盖方法的时候,只能抛出在基类方法的异常说明里列出的那些异常 2.) 在基类构造器声明的异常,在子类必须抛出,子类的构造器可以抛出任何异常,但是必须抛出基类构造器的异常 3.) 在基类 ...
- 如何批量删除word文档中的超级链接?
有时候从网页上copy来的文章中,会带有非常多的链接,这些链接很烦人是吧?如何批量删除(一次性全部删除)word文章中的超链接呢? 有些朋友说,Ctrl+A全选文章,然后点击格式工具栏上的“清除格式” ...
- 【LOJ】#2183. 「SDOI2015」序列统计
题解 这个乘积比较麻烦,转换成原根的指数乘法就相当于指数加和了,可以NTT优化 注意判掉0 代码 #include <bits/stdc++.h> #define fi first #de ...
- MySQL主从检验一致性工具pt-table-checksum报错的案例分析
[问题] 有同事反馈我们改造过的MySQL5.7.23版本,使用pt-table-checksum工具比较主从数据库的一致性时报错 Unsafe statement written to the bi ...
- java 记录对象前后修改的内容(工具类)
有时候业务需要,需记录一条记录的修改历史,但是不能为完成任务而硬编码,不靠谱 这种情况可以使用java反射来完成 对对象属性的描述可以通过自定义注解来完成,读取里面的属性进而记录修改历史. 在对象的属 ...
- JDBC之 大数据内容的传输
JDBC之 大数据内容的传输 什么是大数据内容? 在数据库中,有一条一条的记录,记录中很多字段都是几个字符就够的,假如现在要把一部小说存入数据库,这本小说当然不是几个字符组成,而是由几万字组成,这本小 ...
- jQuery方法实现
children 原生JavaScript中,如果希望找到某个元素的子元素,只能通过Node类型上的children方法一步一步获取.如 let li = document.querySelector ...