当前位置:WooYun >> 漏洞信息

漏洞概要 关注数(24) 关注此漏洞

缺陷编号:wooyun-2016-0190761

漏洞标题:铁路12306通信加解密破解

相关厂商:12306

漏洞作者: chaoxilab

提交时间:2016-03-30 16:51

修复时间:2016-05-16 16:00

公开时间:2016-05-16 16:00

漏洞类型:账户体系控制不严

危害等级:高

自评Rank:20

漏洞状态:厂商已经确认

漏洞来源: http://www.wooyun.org,如有疑问或需要帮助请联系 [email protected]

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2016-03-30: 细节已通知厂商并且等待厂商处理中
2016-04-01: 厂商已经确认,细节仅向厂商公开
2016-04-11: 细节向核心白帽子及相关领域专家公开
2016-04-21: 细节向普通白帽子公开
2016-05-01: 细节向实习白帽子公开
2016-05-16: 细节向公众公开

简要描述:

详细说明:

信任所有证书极易导致中间人攻击,完全可以控制整个通信内容。业界公认高危漏洞。

漏洞证明:

一、 https未校验证书导致数据被捕获(中间人攻击风险)
客户端虽采用了https,但并未对服务端证书进行校验能够捕获通讯数据,可导致中间人攻击。

1.png


信任所有证书

1.png


1.png


可以正常截获通讯数据
二、通信数据解密
铁路12306通信加解密主要通过checkcode、decheckcode两个函数进行通信加解密,虽然采用加固方式,但是太过依赖于加固技术,从而造成通信接口过于暴露。
dex部分:

1.png


加解密函数代码

1.png


so部分:

Java_com_MobileTicket_CheckCodeUtil_checkcode伪代码非常多,这里就不贴出来了。
Java_com_MobileTicket_CheckCodeUtil_decheckcode伪代码:
int __fastcall Java_com_MobileTicket_CheckCodeUtil_decheckcode(int *a1, int a2, int a3, int a4)
{
int *v4; // r4@1
int v5; // r5@1
void *v6; // r0@1
int v7; // r0@1
int v8; // r3@1
int (__fastcall *v9)(int *, _BYTE *); // r3@2
int *v10; // r0@2
_BYTE *v11; // r1@2
unsigned __int8 *v12; // r0@3
int v13; // r3@3
void (__fastcall **v14)(_BYTE *, int *); // r5@3
_BYTE *i; // r7@8
size_t v16; // r7@11
unsigned int v17; // r7@11
_BYTE *j; // r3@11
int v19; // r0@17
void (__fastcall *v20)(_BYTE *, int *); // r3@17
_BYTE *v22; // [sp+0h] [bp-30h]@11
int v23; // [sp+4h] [bp-2Ch]@5
void *v24; // [sp+8h] [bp-28h]@3
void *ptr; // [sp+Ch] [bp-24h]@1
int v26; // [sp+14h] [bp-1Ch]@17
v4 = a1;
v5 = a4;
v6 = j_j_malloc(0x21u);
ptr = v6;
v7 = verification(v4, v6);
v8 = *v4;
if ( v7 )
{
v12 = (unsigned __int8 *)(*(int (__fastcall **)(int *, int, _DWORD))(v8 + 0x2A4))(v4, v5, 0);
v13 = *v12;
v24 = v12;
v14 = (void (__fastcall **)(_BYTE *, int *))off_24E94;
if ( v13 == 0x46 )
{
v23 = (int)(v12 + 1);
*(_DWORD *)off_24E94 = off_24E9C;
}
else if ( (unsigned __int8)v13 == 0x53 )
{
v23 = (int)(v12 + 1);
*(_DWORD *)off_24E94 = off_24E98;
}
else
{
*(_DWORD *)off_24E94 = off_24E9C;
v23 = (int)v12;
}
for ( i = (_BYTE *)v23; *i; ++i )
;
v16 = (size_t)&i[-v23];
v22 = j_j_malloc(v16);
v17 = (unsigned int)&v22[v16];
for ( j = v22; (unsigned int)j < v17; j += 4 )
{
*j = 0;
if ( v17 <= (unsigned int)(j + 1) )
break;
j[1] = 0;
if ( v17 <= (unsigned int)(j + 2) )
break;
j[2] = 0;
if ( v17 <= (unsigned int)(j + 3) )
break;
j[3] = 0;
}
v19 = base64_decode(v23, v22);
v20 = *v14;
v26 = v19;
v20(v22, &v26);
v22[v26] = 0;
j_j_free(ptr);
j_j_free(v24);
v9 = *(int (__fastcall **)(int *, _BYTE *))(*v4 + 0x29C);
v11 = v22;
v10 = v4;
}
else
{
v9 = *(int (__fastcall **)(int *, _BYTE *))(v8 + 0x29C);
v10 = v4;
v11 = ptr;
}
return v9(v10, v11);
}


这里以解密代码为例:

1.png


调用R3,这里就调用到了aes_decrypt1

1.png


在 aes_decrypt1函数中调用了CWAESCipher::WBACRAES128_DecryptCBC

1.png


在这个循环1中,调用CWAESCipher::WBACRAES_DecryptOneBlock进行解密,解密的顺序为逆序,第一次解密的key为:00 00 00 00 00 00 00 00 00 00 00 00 最后四字节为base64数据长度+1。
解密出来的数据有2个作用:1> 作为下次解密使用的key,2>通过第2个循环修复出真正的解密数据。

1.png


逆序进行数据解密
编写封包解析程序验证登录加密数据和返回数据的解密:

1.png


登录数据中parameters项中para中数据是加密的

1.png


通过编写程序测试,checkcode加密后的数据为para中的内容。
服务器返回数据中respData中的数据为加密内容,解密后的数据:

1.png


手机号、生日、身份证号码、姓名、邮箱、用户名等等信息暴露。
三、数据重放

1.png


登录数据信息

1.png


退出之后登录,仍然可以重放登录数据
解密登录返回数据内容信息:

1.png


重放某人的登录包,可拿到手机号、生日、身份证号码、姓名、邮箱、用户名等等信息

修复方案:

你们更专业!

版权声明:转载请注明来源 chaoxilab@乌云


漏洞回应

厂商回应:

危害等级:中

漏洞Rank:8

确认时间:2016-04-01 15:58

厂商回复:

谢谢!

最新状态:

暂无


漏洞评价:

评价

  1. 2016-03-31 02:05 | 坏男孩-A_A ( 实习白帽子 | Rank:81 漏洞数:23 | 膜拜学习中)

    木人关注?

  2. 2016-04-01 16:17 | Praise ( 路人 | Rank:10 漏洞数:1 | null 开心就要笑得如痴如醉~)

    这么猛?

  3. 2016-04-01 17:50 | Moonight ( 实习白帽子 | Rank:51 漏洞数:7 | 无线安全攻城狮)

    12306的Android?iOS?是的话兄弟很牛逼啊~

  4. 2016-05-16 16:10 | 猪猪侠 认证白帽子 ( 核心白帽子 | Rank:4781 漏洞数:368 | 你都有那么多超级棒棒糖了,还要自由干吗?)

    学习