Penetration Testing Step 3 – Các đòn cơ bản với Server-Side Template Injection

Như đã hứa hẹn cuối nội dung Penetration Testing Step 3 – Nhập môn Server-Side Template Injection – SSTI, kỳ này tôi sẽ chuyển sang phần demo minh họa để làm rõ các chiêu cơ bản với Server-Side Template Injection – SSTI. Cụ thể, tôi sẽ tập trung vào 3 nội dung:

  • SSTI – Đường cơ bản;
  • SSTI – Đường cơ bản với code context;
  • SSTI – Khai thác documentation.

Lưu ý:

#1. Server-Side Template Injection – Đường cơ bản

Không nói nhiều, tôi múc phần demo ngay và luôn. Đầu tiên, tôi truy cập vào mục tiêu và thử kiểm tra chi tiết của một sản phẩm.

Target site
Target site

Quan sát ở Burp Suite Proxy History, tôi thấy request dùng message parameter để render (tạm dịch thô bỉ là “dựng”) cái nội dung “Unfortunately this product is out of stock” như hình minh họa trên.

https://ac571fad1f4bb415c0a609c600a2004f.web-security-academy.net/?message=Unfortunately%20this%20product%20is%20out%20of%20stock

Request with message parameter
Request with message parameter

Nhờ chơi cheatcode (cái này thực tế tôi sẽ phải xắn tay lên mà chạy các phương án thử nghiệm), tôi xác định mục tiêu sử dụng ERB template. Kiểm tra ERB documentation, tôi nhận thấy cái syntax sẽ có dạng <%= someExpression %>. Với thông tin này, tôi có thể dùng payload để test hàng theo kiểu dùng mathematical operation <%= 7*7 %>.

ERB documentation
ERB documentation

Tôi chạy URL-encode cái payload này rồi đút vào làm giá trị cho message parameter theo kiểu:

https://ac571fad1f4bb415c0a609c600a2004f.web-security-academy.net/?message=<%25%3d+7*7+%25>

Lúc này nếu load URL trên browser tôi sẽ hốt được kết quả phép tính “7*7” (49) như sau. Việc này xác nhận cho tôi khả năng “ăn” mục tiêu với SSTI.

Test SSTI
Test SSTI

Tiếp tục mân mê cái Ruby documentation, tôi xác định cái system() method có thể được sử dụng để thực thi operating system command (tức là là lệnh của hệ điều hành) tùy ý. Vậy nên, tôi có thể sáng tác ra một payload để triệt hạ file của nạn nhân Carlos (morale.txt) theo kiểu:

<%= system("rm /home/carlos/morale.txt") %>

Tương tự như trên, tôi dí con hàng này vô giá trị của message parameter theo kiểu như sau để thực hiện ý đồ đen tối.

https://ac571fad1f4bb415c0a609c600a2004f.web-security-academy.net/?message=<%25+system("rm+/home/carlos/morale.txt")+%25>

#2. Server-Side Template Injection – Đường cơ bản với code context

Trong kịch bản này, tôi sẽ bật sẵn Burp Suite rồi login với crendetial được cung cấp và tiến hành post thử một comment vớ vẩn vào bài blog.

Post comment
Post comment

Kiểm tra kỹ vị trí My account, tôi thấy xuất hiện tùy chọn Preferred name để lựa chọn dạng tên (Full name, First name, Nickname) sẽ xuất hiện ở phần comment (ở trên tôi đang dùng Full name tương ứng với tùy chọn Name trong phần Preferred name).

Preferred name setting
Preferred name setting

Nếu thử đổi tùy chọn sang First Name và quay về chỗ comment, tôi sẽ thấy cái cái Full name đã chuyển sang First Name tương ứng.

Preferred name in blog post
Preferred name in blog post

Kiểm tra chỗ Burp Suite Proxy History, tôi quan sát thấy cái POST request thiết lập giá trị tương ứng cho parameter blog-post-author-display (như nói trên, ngoài dạng user.first_name bên dưới, tôi có các lựa chọn user.nameuser.nickname).

Request with blog-post-author-display parameter
Request with blog-post-author-display parameter

Tôi hốt cái request này quăng qua Burp Suite Repeater. Lại nhờ chơi cheatcode, tôi biết được mục tiêu đang sử dụng Tornado template (và một lần nữa, tôi nhắc lại, thực tế tôi sẽ phải bỏ công ra mà xác định thông tin này). Rà qua Tornado documentation, tôi ghi nhận cái template expression sẽ cần “bao bọc” với curly braces theo kiểu {{someExpression}}.

Tornado documentation
Tornado documentation

Như vậy, tôi có thể thử nghiệm trên Burp Suite Repeater phương án escapse out (tạm dịch là thoát) cái expression trước đó (với “}}“) và tuồn cái template syntax tôi muốn kiểm tra {{7*7}} vào như sau.

blog-post-author-display=user.name}}{{7*7}}

Modified request with blog-post-author-display parameter
Modified request with blog-post-author-display parameter

Sau khi send con hàng này đi, tôi quay lại chỗ comment và nhận thấy con số may mắn 49 đã phọt ra cho thấy SSTI vulnerability có thể tồn tại trong code context.

Test SSTI result
Test SSTI result

Thừa thắng xông lên, sau khi xác định có thể thực thi code Python với syntax có dạng {% somePython %}, tôi thử nghiệm import os (operating system) module sau đó gọi system() method để thực system command tùy ý. Ví dụ, để xoá file morale.txt của nạn nhân Carlos, tôi sẽ có thể chơi payload theo kiểu.

{% import os %}

{{os.system('rm /home/carlos/morale.txt')

Ghép cái payload này vào chỗ blog-post-author-display theo kiểu trên và chạy URL-encode, tôi sẽ có kết quả kiểu như sau:

blog-post-author-display=user.name}}{%25+import+os+%25}{{os.system('rm%20/home/carlos/morale.txt')

Công việc tiếp theo không có gì đặc sắc. Tôi dí cái đống phía trên vào cái POST request tương ứng và send. Và kết quả 302 trả về cho biết ý đồ của tôi đã thành công mỹ mãn.

Attack request with blog-post-author-display parameter
Attack request with blog-post-author-display parameter

#3. Server-Side Template Injection – Khai thác documentation

Trong kịch bản này, phương án tấn công sẽ phức tạp hơn khi tôi phải nhờ cậy vào các documentation liên quan. Thực tế, việc nghiên cứu documentation của template engine là yêu cầu bắt buộc trước khi bắt tay vào hành động (chứ không đọc thì sao biết dùng template syntax như thế nào???). Ngoài ra, documentation cũng sẽ có thể cung cấp các “dự báo” quan trọng về các vấn đề bảo mật tiềm ẩn mà người dùng có thể mắc phải từ đó tạo điều kiện cho tôi đâm thọt vào hệ thống.

Thôi không dông dài nữa, tôi vào demo đây. Để bắt đầu, tôi sẽ login vào hệ thống với vai trò content-manager. Sau đó tôi tiến hành chọn một sản phẩm và Edit template.

Edit template
Edit template

Tại đây, tôi thăm dò template engine với syntax kiểu ${test} (thực tế tôi sẽ phải thử nghiệm nhiều kiểu chứ hiếm khi có kiểu đập phát ăn ngay như thế này) rồi save để render result ra check hàng sản phẩm.

Test SSTI
Test SSTI

Quan sát hiện trường vụ án, tôi ghi nhận kết quả cho biết mục tiêu đang sử dụng Freemarker template engine.

 Freemarker template
Freemarker template

Tôi nghiên cứu cái documentation của FreeMarker và phát hiện một thứ hay ho liên quan đến phần bảo mật của việc cho phép người dùng upload template.

Upload template issue
Upload template issue

Soi kèo để coi kỹ hơn về cái new built-in này, tôi ghi nhận.

new built-in issue
new built-in issue

À, đại khái, cái new built in này có thể được sử dụng để tạo một Java object tùy ý từ đó thực thi TemplateModel interface. Mà rồi TemplateModel Interface có gì hot?

Tiếp tục chuyển qua kiểm tra cái TemplateModel class và soi phần liên quan đến “All Known Implementing Classes“, tôi ghi nhận có xuất hiện class execute khá hứa hẹn.

TemplateModel issue
TemplateModel issue

Kiểm tra kỹ cái Class Execute, tôi xác nhận khả năng thực thi command như tôi mong đợi.

Class execute issue
Class execute issue

Và như vậy, tôi có thể triển thử phần khai thác như sau để đưa vào Template.

<#assign ex="freemarker.template.utility.Execute"?new()> ${ ex("pwd") }

Test SSTI
Test SSTI

Lúc này, tôi có thể quan sát được thư mục hiện hành từ command pwd. Ngon rồi, giờ tôi có thể cập nhật payload để thử xóa file của Carlos với command kiểu như sau.

<#assign ex="freemarker.template.utility.Execute"?new()> ${ ex("rm /home/carlos/morale.txt") }

Attack with SSTI
Attack with SSTI

1 thought on “Penetration Testing Step 3 – Các đòn cơ bản với Server-Side Template Injection”

Leave a Reply

Your email address will not be published. Required fields are marked *