# [Root Me] Python - Server-side Template Injection Introduction (có mở rộng)
## Giới thiệu

Chào mừng bạn đến với thử thách SSTI trong Python! Đây là một bài thử thách đầy thú vị về SSTI, một chủ đề rất hấp dẫn trong lĩnh vực bảo mật web. Nhiệm vụ của bạn là tìm cách RCE và lấy được flag từ máy chủ. Không cần phải lo lắng nếu bạn chưa có kiến thức về SSTI vì bài viết sẽ cung cấp cho bạn những kiến thức cơ bản và hướng dẫn chi tiết về cách khai thác SSTI trong Python bằng Jinja2. Ngoài ra, bài viết cũng sẽ giúp bạn hiểu rõ hơn về cách tận dụng các built-in và class object trong Python để thực hiện RCE. Vậy còn chần chờ gì nữa? Hãy tham gia thử thách và trở thành người giỏi nhất trong lĩnh vực SSTI!
## Mục tiêu và đối tượng
1. Mục tiêu
1. Flag nằm trên máy chủ khi mình RCE được
2. Đối tượng đáng ngờ
1. ô input content
## Triển khai
Vì mình có detect được là ô input content sẽ là nơi mà mình inject thành công

Nên bây giờ mình cứ vọc quanh thằng content thôi
Trang chính ra đề có đưa cho mình tham khảo về những khả năng khai thác đôi với Jinja2
[link jinja2](https://podalirius.net/en/publications/grehack-2021-optimizing-ssti-payloads-for-jinja2/)
Thì mình có nghiên cứu xem qua thằng **TemplateReference** mà trang trên đề cập, thì mình có thể lợi dụng thằng đó để vào built in của global và import lib os để có thể RCE
Có sẵn một vài payload mẫu nên mình sẽ thử dùng payload này
```
{{ self._TemplateReference__context.cycler.__init__.__globals__.os }}
```

Và mình đã import thành công module os, nên mình sẽ tận dụng nó để mình liệt kê với payload sau
```
{{ self._TemplateReference__context.cycler.__init__.__globals__.os.popen('ls -a').read() }}
```

Mình có thể thấy file .passwd là flag của mình nên mình sẽ đọc nó và submit flag thôi

Xong nhưng mình muốn mò xem tại sao họ có thể có được payload như vậy, nên mình sẽ back ngược từ phía self ra nhé (cơ bản mình muốn hiểu rõ tại sao có payload thì mình mới craft được ấy).
## Mở rộng

Ở mình sẽ xem thử thuộc tính của TemplateReference như thế nào bằng __context (cứ đi từ đầu theo người ta để nắm)
> _TemplateReference__context

Mình thấy được có kha khá class ở đây nên mình sẽ thử init qua từng class để xem có gì vọc khong nhé



Như trên ta chia ra hai loại là Function wrapper và Slot wrapper,
## Slot Wrapper
Đối vơi slot wrapper thì mình có thể dùng mro để check xem có class nào, và mình thấy được có class object nên sẽ quay về đó

Khi ta quay về được class object thì ta có thể follow theo cách thức sau
[jinja SSTI](https://book.hacktricks.xyz/pentesting-web/ssti-server-side-template-injection/jinja2-ssti#recovering-less-than-class-object-greater-than)
Ta dùng subclasses để xem hết các class mà ta tận dụng được

Với class object thì theo kinh nghiệm mình sẽ có class Popen ở vị trí 408

Nên mình vẫn có thể tận dụng thằng này RCE theo cách sau

Và ta vẫn lụm được flag dù đi đường dài hơn
Có cách ngắn hơn và tương tự là ta đi từ class str bằng cách tạo một string giả như sau
> ''.\_\_class__.\_\_mro__
Đối với cách này ta cũng sẽ đi được ngược về class object và triển khai tương tự trên
## Function Wrapper
Nhưng quay về với Function wrapper thì ta có thể vọc những gì
Khi ta init các funtion wrapper và go globals thì ta thấy được rất nhiều built in ở đây

Và chắc chắn luon tồn tại builtin os mặc định của python rồi

Nếu dùng os luôn thì sẽ dùng được popen và RCE như bình thường

Tương tự như namespace thì joiner và cycler cũng như vậy

Thì ta vẫn có thể RCE được
## Ngoại lệ

Vì khi này từ self là None nên khi ta init nó và go global ta có thể đi tới các builtin một cách dễ dàng
Nhưng ở builtin này sẽ không có os mà ta phải đi vòng thông qua \_\_import_\_

Và lụm flag

## Tổng kết
Đối với bất kì lỗi SSTI nào của python, ta sẽ làm mọi cách nếu leo được lên builtin hoặc class Object thì hầu như mọi khả năng ta có thể kiểm soát được rồi. Heheh khá thú vị