# WriteUp NoSandbox IsitDTU
###### tags: ``Prototype Pollution``
Ở challage này cung cấp cho ta source code và một trang web như sau:

Nhìn qua source thì ta sẽ thấy 2 endpoint khác là ``/debug`` và ``/api/submit``
Ở endpoint ``/debug`` sẽ nhận param là ``debug`` và thực hiện check xem có xuất hiện những ký tự trong blacklist không, nếu có sẽ return not allow còn nếu không thì sẽ được đưa vào hàm ``eval`` để thực thi

Còn ở endpoint ``/api/submit`` thì ta phải truy cập qua methods POST.

Để kích hoạt được endpoint này thì ta phải truyền property là ``artist.name`` và set ``Content-Type: application/json``, ta có thể thấy điều này được gợi ý trong file ``/static/js/main.js``

Thử truy cập đến ``/api/submit`` với những điều kiện trên:

Ta để ý 2 dòng code sau của endpoint này:

Nếu ``artitst.name`` là 1 trong 3 admin thì code sẽ thực hiện ghi đề file ``./routes/demo.js`` với nội dung là property ``options.data``. Đến đây mình đặt 1 giả thuyết là nếu ta tìm cách kiểm soát được giá trị của ``options.data`` thi ta hoàn toàn có thể inject bất cứ thứ gì mình muốn vào ``./routes/demo.js`` .
Nhìn kỹ vào đoạn code xử lý ta phát hiện, chall dùng ``unflatten`` để featch API

Và qua vài đường gg ta biết thêm hàm này cho phép ta thực thi được prototype pollution. Từ đây ta sẽ lợi dụng ``unflatten`` thực hiện prototype pollution để thay đổi giá trị của ``option.data``
Gửi payload

Kết quả:

Mình đã có thể inject bất kỳ đoạn code nào muốn vào ``demo.js`` vậy thì bây giờ làm sao để thực thi ?
Hàm ``eval()`` tại ``/debug`` chính là câu trả lời, ta sẽ truyền vào param debug giá trị là: ``/debug?debug=require('./demo.js')`` . Khi đó hàm eval sẽ thực thi ``eval("require('./demo.js')")`` từ đó ta có thể chạy bất kỳ đoạn code nào mà ta mong muốn
Mình sẽ dùng module ``child_process`` để thực hiện exec shell command
Payload:

Truy cập ``demo.js`` để kích hoạt payload:

Code đã thực thi tuy nhiên request.repo của mình không nhận được gói tin nào cả :<<
Sau một hồi debug, mình phát hiện câu lệnh ``eval()`` của mình không trả về gì cả, nghĩa là đoạn payload trong file ``demo.js`` đã không được thực thi đúng

Nếu eval thực thi đúng thì kết quả sẽ trả về ``true``
Sau một hồi đào bới trên gg thì mình phát hiện, trong quá trình runtime thì hàm ``require`` sẽ chỉ execute một lần và lưu vào bộ nhớ ``require cache``

Đây là cơ chế ``cycles`` của hàm require trong nodejs để hạn chế việc require tạo thành một vòng lặp vô tận. Và trong bài trên thì ta đã require ``demo.js`` rồi nên không thể require ``demo.js`` thêm 1 lần nữa được

Trong docs của nodejs đề cặp, để thực thi require nhiều lần thì hãy export một function và tiến hành gọi fuction. Có thể ví dụ như sau:
```
module.exports = function() {
console.log("IMPORTED");
}
```
Thì khi thực hiện require ta sẽ gọi:
```
require("./my_script")();
```
Tuy nhiên khi áp dụng cách trên cho challange thì ta xảy ra lỗi:

Vậy thì còn cách nào khác để bypass hành vi này không?
Câu trả lời nằm trong link này (https://stackoverflow.com/questions/52359789/require-multiple-times
Ta sẽ tiến hành clear cache sau đó gọi đến file ``demo.js``, dùng đoạn code sau để clear cache:
```javascript
delete require.cache[require.resolve('./demo.js')]
```
Giờ chỉ cần thay giá trị của param debug bằng đoạn code trên ta đã có thể thực thi được payload


Giờ thì chỉ cần tìm và đọc flag thôi
#
__Link tham khảo__: https://nodejs.org/api/modules.html#modules_caching