Author: ngoithu0
Source: Common Web Attacks
Note
Đôi lời tâm sự: Hôm nay nhân dịp đầu năm mới. Khởi động cho một 2025 đầy năng lượng, mình quyết định tổng hợp tất cả các cuộc tấn công Web nhằm vào cả client-side và server-side. Bạn đọc có thể lấy writeup này như một roadmap nhằm mục đích tra cứu và nâng cấp kỹ năng hacking của mình. Lưu ý tài liệu chỉ nhằm mục đích học tập, mình sẽ không chịu bất kỳ trách nhiệm nào khi các bạn vướng vào vòng lao lý của pháp luật.
Một website hoạt động bằng cách nhận HTML, JS code từ server, sau đó chúng sẽ render lên browser. Thì ý tưởng của XSS vô cùng đơn giản, chỉ cần bạn có thể thao túng được HTML cần render lên bằng cách chèn JS code vào input. Thì khi ấy bạn đã thực hiện XSS thành công.
Lưu ý XSS là một cuộc tấn công client-side, tức là nó hoàn toàn không ảnh hưởng đến server. Những tác động mà XSS có thể mang lại bao gồm trải nghiệm người dùng, thông tin cá nhân cùng với các lợi ích của người dùng.
Có ba loại XSS, bao gồm:
Về cơ bản thì cả Store XSS và Reflected XSS đều có thể chèn JS code thông qua tag <script>maliciouscode</script>. Đôi khi tag script bị filering, vậy có thể thử với các middle call như onerror, onload,…
Tuy nhiên thì DOM XSS lại không giống như thế, bởi vì lý do bảo mật nên các hàm viết DOM và JQuery như:
không cho phép thực hiện chèn script tag. Vậy nên phải thông qua các middle function như onerror, onload,…
Ví dụ như <img src="" onerror=alert(window.origin)>.
Về cơ bản, ý tưởng của XSS khá đơn giả. Tuy nhiên thì cùng với sự phát triển nhanh chóng của xã hội hiện đại, đi với đó là các ký thuật tấn công ngày càng đa dạng. XSS trở thành một trong những lỗ hổng phổ biến nhất hiện nay. Vì vậy các biến thể của XSS là vô cùng đa dạng, bao gồm các kỹ thuật như:
XSS cùng các biến thể của nó là vô cùng rộng lớn bao quát rất nhiều chủ đề. Vì vậy mình sẽ dành riêng một bài chỉ để nói về XSS tại đây.
Để thực hiện mô phỏng cho XSS, mình lấy 2 ví dụ. Cái đầu tiên sẽ là assessment của module XSS hackthebox. Và ví dụ thứ hai sẽ dựa trên report Twitter XSS.
Đầu tiên, khi truy cập vào browser, có thể thấy một form với tựa đề Post and Comment. Các bạn có thể tìm XSS ở bất cứ đâu, miễn là nơi đó cho phép đưa dữ liệu người dùng nhập vào. Vì vậy, ở đây mình thực hiện thử alert(1) với tất cả các trường dữ liệu có thể nhập.
Sau khi post comment và nhận được kết quả trả về của server. Mình nhận được "Your comment is awaiting moderation…". Nói tóm lại rằng những gì mình post sẽ được render lên browser của admin trước khi có thể hiển thị cho người dùng khác. Lợi dụng điều này, mình có thể thực hiện XSS lên browser của admin. Từ đó thực hiện các hành vi như Defacing, Session Hijacking (với điều kiện httpOnly=false).
Để thực hiện kiểm tra vấn đề trên, mình cần xác nhận rằng browser của admin có thực sự tồn tại Blind XSS không. Và bằng cách fuzzing các payload để request một file JS từ browser của admin tới máy mình, khi đó mình có thể xác nhận được rằng: browser của admin thực sự tồn tại một Blind XSS.
Đầu tiên, mình sẽ khởi chạy một server bằng python.
Tiếp theo, thực hiện thử tất cả các payload thu nhặt được từ PayloadOfThings và Hacktricks. Nếu thử từng cái một thủ công, chắc mình không sống nổi với cái lưng mình quá. Vì vậy bên dưới là một số payload điển hình và python script mình dùng để gửi các payload đó đến browser của admin.
Sau khi chạy lệnh bên dưới, mình nhận thấy rằng có một vài python server nhận được một vài request đến từ target server. Có nghĩa là không phải tất cả các payload đều thành công. Nhưng mình không quan tâm đến điều đó, chỉ cần một payload hoạt động là quá đủ.
Vì vậy, mình tiếp tục thực hiện request một file JS như bên dưới (chứa code ăn cắp cookie) từ browser của admin để thực hiện Session Hijacking.
Khi admin truy cập vào browser, comment chứa JS code ngay lập tức request đến python server và thực thi stealing cookie code.
Đúng như những gì mình dự đoán, ở đây có thể thấy cookie admin với định dạng flag của hackthebox hiển thị phía python server như hình bên dưới. Vậy là chúng ta đã get được flag rồi ^^
Các bạn có thể trực tiếp chèn code vào các trường thông tin của Post Comment như bên dưới. Kết quả vẫn sẽ hoạt động mượt mà và không cần phức tạp hóa quá trình như mình. Tuy nhiên ở bối cảnh thực tế, khi không xác định được Blind XSS có tồn tại hay không, và server thực hiện filter những payloads hay characters như thế nào. Cá nhân mình khuyến cáo mọi người thu nhặt payload và thực hiện fuzzing trước. từ đó xác định sự tồn tại của lỗ hổng và tiến hành các bước tiếp theo.
Ngoài ra thì các bạn có thể đọc thêm blog XSS Hacktricks để hiểu thêm về XSS cũng như tác động của nó với bối cảnh thực tế. Đồng thời góp nhặt kinh nghiệm viết script và nắm bắt được quy trình bypass cũng như các lỗ hổng đã outdate.
Để ngăn chặn XSS, chúng ta phải thực hiện validation, sanitization ở cả phía client và server. Thực hiện encode output trước khi render lên browser như HTML entity. Đồng thời cấu hình các cơ chế bảo vệ như:
Ngoài ra thì biện pháp tốt hơn cả là áp dụng WAF.
CSRF (Cross-Site Request Forgery) là một kiểu tấn công khai thác lòng tin của server vào xác thực của người dùng. Cụ thể, kẻ tấn công đánh lừa người dùng thực hiện một hành động trái phép trên trình duyệt của họ, thường thông qua việc truy cập một đường link hoặc thực thi một yêu cầu độc hại. Cuộc tấn công lợi dụng các cơ chế xác thực, như cookie hoặc token, mà server sử dụng để nhận diện người dùng hợp lệ, khiến server hiểu nhầm rằng hành động được thực hiện bởi ý muốn của người dùng. Ví dụ:
Khi người dùng nhấp vào hình ảnh để xem rõ hơn, trình duyệt của người dùng sẽ lấy thông tin xác thực đã lưu và gửi yêu cầu đến server bank.com. Từ đó trực tiếp chuyển một số tiền 500000 đến tài khoản của attacker.
Đại khái mình thấy nó khá giống với XSS, tuy nhiên thì CSRF không thực hiện chèn JS code. Ý TƯỞNG CỦA NÓ CHỈ ĐƠN GIẢN LÀ THỰC THI HÀNH ĐỘNG KHÔNG MONG MUỐN. Vì vậy có thể kết hợp CSRF và XSS để có tác động mạnh hơn.
XSRFProbe
(Tuy nhiên thì mình khuyến khích code chay. Vì ý tưởng của CSRF tuy đơn giản, nhưng mỗi trang web có các endpoint và api khác nhau. Vì vậy cách tốt nhất là đọc source code, fuzzing và tìm ra các endpoint thích hợp.)
Mô phỏng cho CSRF, mình sẽ thực hiện lại Session Security Assessment của hackthbox. Mình sẽ trình bày theo 2 cách. Đầu tiên sẽ là hướng dẫn exploit challenge, các cách thứ 2 sẽ được nghĩ khác đi để phù hợp với bối cảnh CSRF hơn.
Đăng nhập bằng tài khoản hackthebox cung cấp, mình có thể thấy được thông tin của Julie Rogers. Ở giao diện này có một form thông tin mà mình có thể sửa đổi được.
Lợi dụng các trường thông tin, mình chèn script vào để thử xem XSS có tồn tại hay không. Thì kết quả cho thấy rằng có một XSS ở trường Country thuộc endpoint /profile?email=example@gmail.com. Với mục tiêu của mình là lấy được thông tin từ profile của admin. Lợi dụng XSS trên, mình có thể chèn script vào profile để trình duyệt của admin leak thông tin cho mình.
Nghĩ là làm, mình chỉ cần get được cookie của admin rồi thực hiện Session Hijacking là challenge được giải thôi. Với đoạn script cơ bản như bên dưới, mình đã thực sự làm được điều đó.
Quá đơn giản đúng không
Thì ở assessment của hackthebox có 2 câu hỏi, đáp án cho câu hỏi đầu tiên có thể lấy được khi thay đổi cookie phía trên và login như admin. Còn ở câu hỏi thứ 2 yêu cầu lấy flag từ file pcap. Chỉ cần lấy string rồi grep là được.
Theo mình nghĩ, thì cách phía trên là nhanh gọn và tối ưu nhất rồi. Tuy nhiên, ở các trường hợp thực tế, không phải lúc nào mọi thứ cũng thuận lợi như vậy. Đôi khi httpOnly được bật hoặc server có các cơ chế bảo vệ như SOP, CORS. Khi đó cookie sẽ không dễ dàng bị lấy như vậy. Vậy nên ở cách này, mình muốn đào sâu vào chi tiết hơn để chúng ta cùng hiểu rõ quy trình kiểm thử.
Với cả, mình đang viết về CSRF, nhưng cách một lại chỉ toàn về XSS. Vậy nên ở cách 2 này mình sẽ thực hiện cả XSS và CSRF.
Ý tưởng ở phần này của mình sẽ bao gồm:
Đầu tiên là việc tìm cách lấy được thông tin của admin. Mình nhận thấy rằng endpoint /api/userinfo sẽ trả về thông tin của một user dựa trên session cookie trong http header. Vậy nên mình có thể thực hiện CSRF bằng cách yêu cầu browser của admin thực hiện request đến endpoint này. từ đó gửi trả email nhận được về máy mình.
Với đoạn script sau, mình thực hiện chèn vào Country của Julie và sử dụng enpoint /submit-solution?url=… được cung cấp bởi hackthebox để thực hiện truy cập vào profile của Julie từ phía admin.
Và kết quả là mình đã dễ dàng lấy được email của admin như bên dưới mà không cần đụng đến cookie của họ.
Sau khi thành công lấy được email của admin, mình thử truy cập vào profile thì lại bị chuyển hướng về /app. Vấn đề ở đây nằm chỗ, visibility của admin có lẽ đang là private. Vì vậy Julie không có quyền truy cập vào đó.
Vì thế nên bây giờ mình lại tiếp tục chèn một đoạn script khác để thực hiện CSRF. Với mục đích sửa đổi visibility của admin thành public. Với endpoint /app/change-visibility như bên dưới, mình thực hiện lấy csrf token từ gói get và chèn vào gói post. Nhờ thế mà thay đổi được visibility.
Sau khi thay đổi visibility, mình có thể dễ dàng truy cập profile của Super Admin từ chính tài khoản của người dùng bình thường như Julie mà không cần phải có cookie.
Phần lớn các web/app hiện đại đều sử dụng CSDL để lưu trữ dữ liệu. Vì vậy các cuộc tấn công SQLi là vô cùng phổ biến. Có thể gây thất thoát dữ liệu và ảnh hưởng lớn đến uy tín của doanh nghiệp.
Kẻ tấn công có thể thực hiện SQLi khi back-end server thực hiện đưa input người dùng vào câu lệnh truy vấn. Ví dụ lệnh truy vấn của một chương trình PHP như sau:
Bằng cách inject findUser, kẻ tấn công có thể thực hiện truy vấn CSDL một cách tùy ý:
http://example.com/user?findUser=1'+or+username='admin'–+- thì khi đó câu lệnh truy vấn sẽ trở thành select * from logins where username like '%1' or username='admin'– -'. Dù cho có như nào thì user admin sẽ luôn được trả về.
Có tổng cộng 5 loại SQLi, bao gồm:
Ở bài viết này, mình sẽ tập trung vào MYSQL. Tuy nhiên thì các hệ quản trị cơ sở dữ liệu khác cũng có chung ý tưởng. Chỉ là cú pháp và một vài tính năng sẽ hơi khác một tí. Các bạn có thể hiểu mindset, rồi đọc thêm Hacktricks và PayloadOfThings để khai thác CSDL mong muốn.
SQLMap
Thực sự mà nói thì mình nghĩ trong các trường hợp thực tế, SQLMap chỉ hữu dụng khi chúng ta exploit SQLi thành công. Khi đó sử dụng SQLMap theo success payload để dump dữ liệu một cách nhanh chóng.
Tiếp tục mô phỏng cho một lỗ hổng lớn và nhiều tác động như SQLi, mình sẽ thực hiện lại 2 assessments của hackthebox bao gồm: SQL Injection Assessment và SQLMap Assessment.
Đầu tiên khi truy cập vào server được cung cấp bởi hackthebox, mình thấy một login form bao gồm username và password, được gửi đi theo định dạng url encode với POST method.
Bởi vì mình không được cung cấp thông tin đăng nhập, đồng thời khi login fail cũng chỉ trả về một kết quả chung chung nên mình tạm thời chưa thể bruteforce username. Vậy chỉ còn cách SQLi vào cả 2 trường username và password. Để làm được điều đó, mình phải giả lập một câu lệnh query bên phía server, truy vấn đó có thể như sau:
Vậy một trong 2 trường có thể injected (ở đây là username). Nhưng để chắc chắn thì các bạn nên thử ở tất cả các input. Mình thực hiện truy vấn khớp với tất cả username có trong CSDL và limit lại 1. Và câu lệnh truy vấn của mình như sau:
Sau khi thực hiện login thành công bởi lệnh truy vấn phía trên. Mình lại được điều hướng đến endpoint /dashboard/dashboard.php với một input tìm kiếm payment theo "month". Vì vậy mình dự đoán lệnh truy vấn được áp dụng ở đây là:
Nhận thấy rằng ở đây có thể tồn tại UNION-based SQLi. Mình thực hiện inject với order by để tìm ra số cột của bảng "purchases" (lưu ý tên bảng là mình đặt tượng trưng, không thực sự biểu diễn cho table_name trong CSDL của server).
Sau khi có được số cột là 5, mình thực hiện get thông tin từ CSDL với các payload như sau (các bạn có thể tự viết, hoặc chưa quen thì lên PayloadOfThings để tìm kiếm payload phù hợp).
Hoặc sau khi đã có các thông tin cơ bản như schema_name, table_name, loại hình dbms. Cũng có thể sử dụng sqlmap để dump dữ liệu một cách nhanh chóng hơn.
Tóm lại thì phần phía trên mình chỉ thực hiện để làm rõ các nhìn về việc trích xuất dữ liệu từ database, chứ không thực sự liên quan đến đề bài được hackthebox đặt ra. hackthebox yêu cầu thực hiện RCE và đọc flag ở thư mục '/'. Để làm được điều đó, chúng ta cần biết chính xác rằng secure-file-priv có được bật hay không. Chỉ khi cờ được bật thì chúng ta mới có quyền thực hiện đọc và viết file.
Và thử đọc file /etc/passwd. Kết quả trả về thành công giúp mình khẳng định được rằng chúng ta đang có quyền đọc và viết file.
Bây giờ, nhiệm vụ tiếp theo của mình là tìm được nơi để tạo một webshell. Thông thường các root path của web server sẽ được đặt ở /var/www/html/. Vì vậy mình thực hiện đọc file dashboard.php theo đường dẫn như payload bên dưới. Kết quả quá okela giúp mình định hình được vị trí để đặt một webshell.
Mình thực hiện tạo một webshell với file shell.php -> RCE và get được flag như hình bên dưới.
Yêu cầu được đặt ra ở hackthebox là, tìm nội dung của table final_flag.
Truy cập vào trang web, sau một hồi mày mò thì mình cũng tìm được endpoint để thực hiện SQLi nằm ở việc bấm "Add to Cart".
Một gói json post sẽ được gửi đi theo endpoint action.php với nội dung {"id": 1} như hình bên dưới.
Vậy là đủ dữ kiện rồi, giờ đến lượt SQLMap phát huy tác dụng của nó. Mình chưa vội phân tích câu lệnh truy vấn ở phía back-end. Mọi việc thì thả cho sqlmap thực hiện. Lưu ý khi sử dụng sqlmap mà chưa giả lập được câu lệnh truy vấn và kết quả trả về ra sao. Các bạn nên nhìn ở chế độ -v 6 để xem rõ ràng responses. Từ đó hình dung nên câu lệnh truy vấn ở backend.
So sánh các phản hồi, có thể thấy rõ ràng server trả về lỗi của câu lệnh truy vấn. Vì vậy có khả năng rất cao đây là một SQLi error-based.
Sau một hồi quan sát các phản hồi, mình nhận thấy rằng id là một con số (int). Vì vậy các payload có prefix ' hoặc " nhằm vào string là hoàn toàn vô dụng. Biết là vậy nhưng mình cũng không tìm ra cách để sqlmap bypass những payload này, đây là một điểm mình không thích ở sqlmap khi nó tiêu tốn rất nhiều thời gian. Chỉ có thể coi điểm này như một dữ kiện phục vụ cho việc custom payload thôi.
Phân tích thêm một cách kỹ càng hơn, thì server thực hiện filter các dấu <> để phòng tránh XSS. Bằng chứng là các dấu tương ứng đã bị lọc đi mất ở các phản hồi.
Vì vậy, mình chỉ đơn giản là sử dụng tamper between để thực hiện thay thế <> thành between thôi.
Ở trên mình dự đoán rằng nó là một error-based SQLi, tuy nhiên thì sau quá trình thử với tất cả các payload error-based mà không thu được gì. Mình bắt đầu thử với các loại kỹ thuật khác, thì phát hiện được rằng lỗ hổng nằm ở time-based như hình dưới kèm với payload:
Lưu ý rằng time-based thực hiện bruteforce theo mệnh đề LIKE '%', vì vậy nên thời gian nó truy xuất kết quả là rất lâu. Để tiết kiệm thời gian, khuyến cáo mọi người tập trung vào yêu cầu của đề bài. Đó là dump nội dung của table final_flag thôi. Và dưới đây là kết quả:
👉 Kết luận
SQLi là một lỗ hổng cực kỳ phổ biến, nó được xếp vào Injection, đứng hàng thứ 2 trong TOP 10 OWASP. Vì vậy thành thạo exploit SQLi là một điều rất rất cần thiết.
Thực sự thì mình rất ngại khi phải đụng đến time-based SQLi. Vì thời gian chờ đợi SQLMap bruteforce rất lâu. Cũng may cuối cùng cũng xong rồi 🥹.
Command Injection tương tự với SQLi. Tuy nhiên khi SQLi thuộc về ngữ cảnh inject một câu lệnh truy vấn, thì Command Injection thực hiện inject vào một lệnh hệ thống. Ví như ở back-end có đoạn code sau:
Dễ dàng thấy được, filename không được sanization mà đưa trực tiếp vào system(). Điều này tạo điều kiện cho kẻ tấn công thực hiện inject và thực thi hành vi độc hại.
Có một số ký tự đặc biệt thường xuyên được sử dụng trong Command Injection:
Ký tự | Các biến thể có thể sử dụng thay thế |
---|---|
\n | %0a |
\t | %09 |
; | %3a - ${LS_COLORS:10:1} - tr${IFS}'!-}'${IFS}'"-~'<<<: |
& | %7c - tr${IFS}'!-}'${IFS}'"-~'<<<{ |
&& | %26%26 |
| | %7c - tr${IFS}'!-}'${IFS}'"-~'<<<{ |
|| | %7c%7c |
`` | %60%60 |
$() | %24%28%29 |
/ | %2f - {PATH:0:1} |
Ngoài ra còn có các ký tự thường được sử dụng bởi các cuộc tấn công Injection như hình sau:
Có thể vào PayloadOfThings để thu nhặt thêm các hình thức bypass trên nhiều nền tảng và hệ điều hành khác nhau.
Khi truy cập vào trang web, có 2 chức năng của trang web có thể giúp mình khai thác Command Injection. Một là copy file và cái còn lại là move file. Tuy nhiên thì qua quá trình thử nghiệm. Mình nhận thấy back-end server đang thực hiện filter input. Mà chức năng copy lại không in ra lỗi cụ thể khiến mình mất phương hướng. Ngược lại thì move file lại in ra lỗi của command. Từ đó giúp mình lần mò ra được các ký tự bị filter.
Theo mình nghĩ thì câu lệnh move file có lẽ trông như thế này. Nếu thực sự là định dạng như vậy, có lẽ mình có thể dễ dàng inject vào và thực thi lệnh tùy ý. Vấn đề khó khăn còn lại là mình chẳng biết back-end filter như thế nào.
Và sau khi thử với một inject đơn giản, mình nhận ra rằng lỗi của command được trả về phía browser -> error-based injection.
Căn bản của một error-based injection là phải thực thi sub-command. Nghĩ là làm, sau một hồi fuzzing các ký tự có thể xài để thực thi một sub-command. Mình nhận thấy cả "\t" lẫn ${IFS} đều cho các kết quả khả quan.
À bởi vì code được render lên browser quá dài, quá trình tìm kiếm error-based trở nên khó khăn và mất nhiều thời gian. Vậy nên mình bỏ qua zaproxy để code một đoạn python ngắn thực hiện filter error bằng regex.
Sau khi trực quan hóa exploit, mình tiếp tục thử với các câu lệnh để tìm ra những gì server filter. Có thể thấy ở hình dưới mình dễ dàng bypass bằng cách thêm ngoặc kép.
Thực hiện quá trình một cách tuần tự, mình có thể liệt kê được các ký tự bị filter bao gồm: "/, \n, ;, &, |" cùng rất nhiều command.
Nhờ nắm bắt được thông tin, mình có thể dễ dàng viết payload để đọc file /flag.txt.
Hoặc bạn có thể copy nó sang web folder để đọc bằng browser-))
Là một lỗ hổng nằm trong TOP 10 OWASP. SSRF xảy ra khi ứng dụng web lấy dữ liệu từ xa nhờ vào input của người dùng. Ví dụ mạng nội bộ của một công ty đang chạy một dịch vụ API ở domain api.business.com. Tuy nhiên thì API này được cấu hình không tiếp nhận truy cập của bất cứ ai ngoài business.com. Ứng dụng web của business.com bị kiểm soát bởi người dùng. Từ đó cho phép kẻ tấn công bypass firewall và xâm nhập vào máy chủ API.
Một số cách thức exploit thông qua SSRF:
Một ví dụ đơn giản về SSRF:
Tạm thời mình chưa tìm được ví dụ về SSRF, phần này sẽ được update trong thời gian tới. Ngoài ra thì các bạn có thể tham khảo assessment của SSTI, ở đây tồn tại một SSRF trong gadget chain.
SSTI là một lỗ hổng thuộc về template framework. Khi server không thực hiện filter input của người dùng, đồng thời thư viện cũng không có các cơ chế bảo vệ. Từ đó cho phép kẻ tấn công thực hiện inject template code để thực thi các hành vi không mong muốn.
Ví dụ có một back-end server đang chạy một chương trình python cùng với django template như sau:
Qua đoạn code trên, kẻ tấn công có thể dễ dàng inject template để thực hiện RCE:
👉 Có rất nhiều template dễ dàng bị inject, có thể tìm thêm payload cho từng loại template ở PayloadOfThings.
Đây là một challenge ngớ ngẫn và hết sức đơn giản. Đồng thời cũng quá phi thực tế.
Đầu tiên, khi vào website thì nó tự động POST một gói tin với content bao gồm api=http://truckapi.htb?id=…. Nhờ đến mình biết ngay đây là một SSRF. Tuy nhiên thứ mình để ý hơn cả là những gì mình nhập vào sẽ trả nguyên si mà không hề filter hay làm bất cứ một điều gì cả.
Điều này khiến chắc chắn trang web tồn tại XSS, đồng thời có thể có cả một số lỗ hổng server-side như SSTI, SSI.
Vì mục tiêu của mình là đọc tạo RCE để đọc flag phía server-side. Vì vậy mình bỏ qua XSS, đồng thời tập trung vào SSTI, bởi vì mình phát hiện sự tồn tại của nó sau khi nhập {{7*7}}.
Tuy nhiên thì ở đây mình chưa biết back-end server được code bởi ngôn ngữ nào, và sử dụng loại hình template ra sao. Và, sau quá trình fuzzing extension, mình nhận ra back-end server đang chạy PHP.
Sau khi biết ngôn ngữ, mình thực hiện tìm kiếm các template framework của PHP thông qua PayloadOfThings.
Và sau quá trình thử nghiệm với cú pháp của từng loại, mình xác định được framework đang được sử dụng là Twig.
Nhờ thế mà mình có thể viết payload RCE SSTI một cách dễ dàng (vì server không thực hiện filter bất cứ điều gì).
Sau quá trình tìm ra flag quá sức dễ dàng, mình tra google tìm kiếm hints của các cách thức khác để làm giàu kỹ năng exploit. Và ở forum của hackthebox có một comment như sau:
Tuy nhiên thì mình đã thử fuzzing tất cả các wrapper trước khi đọc hint này. Và nhận ra server không cho phép các wrapper đó. Vậy nên mình chẳng hiểu tại sao người ta có thể đọc flag được nữa.
SSI (Server Side Includes) là một kỹ thuật được sử dụng trong phát triển web để nhúng các nội dung động vào trong các trang HTML tĩnh. Từ đây, nếu kẻ tấn công có thể kiểm soát được SSI thông qua inject user input -> thực thi các hành vi độc hại.
Trên đây là một vài ví dụ về payload cho SSI Injection. Nhìn chung đây là một lỗ hổng injection khá đơn giản.
Có thể sử dụng tools của các lỗ hổng injection khác.
Tạm thời mình chưa tìm được ví dụ về SSI Injection, phần này sẽ được update trong thời gian tới.
eXtensible Stylesheet Language Transformation (XSLT) là một ngôn ngữ cho phép chuyển đổi cấu trúc XML.
Kẻ tấn công có thể lợi dụng XSLT để lấy thông tin nhạy cảm của server. Ví dụ:
Upload File là một tính năng đã quá thông dụng với các chương trình hiện nay. Nhưng không phải chương trình nào cũng thực hiện lọc đúng và đầy đủ các cách thức để chấp nhận upload file. .
Một số hệ lụy có thể kể đến như:
Có một số trường thông tin cần đặc biệt lưu ý khi thực hiện File Upload:
fuxploider
Burp Upload Scanner
ZAP File Upload
Mô phỏng cho File Upload, mình tiếp tục thực hiện lại một assessment của hackthebox.
Đầu tiên, khi truy cập website, mình thấy được một yêu cầu upload ảnh cho các bài post được gửi về server. Sau khi review qua source code ở front-end. Mình nhận thấy các extension bị filter (chỉ cho phép ảnh). Tuy nhiên thì vì thực hiện gửi request qua zaproxy, nên mình không quan tâm đến chúng.
Ở response, mình nhận thấy ảnh được render dưới dạng base64 của tag <img>. Đồng thời request được gửi đi theo XMLHttpRequest. Vì vậy mình thử sửa đổi body thành định dạng XML với XXE payload. Và đúng như mình nghĩ, ở đây tồn tại một XXE.
Vậy nên ở đây, mình thực hiện đọc source code của upload.php.
Cùng mình phân tích một chút về source code của upload.php:
Đôi khi, điều kiện có thể kiểm tra thêm magic bytes, vì vậy các bạn nên tập thói quen giả mạo magic bytes cho các file được upload.
Và, như những điều kiện ở trên. Mình có thể đoán được rằng một file phar với đuôi mở rộng jpg (hoặc png, jpeg,…).
À nói thêm, trong các trường hợp thực tế, không phải khi nào chúng ta cũng có thể đọc được source code back-end. Vì vậy tốt nhất nên học cách tự tạo wordlist và thực hiện fuzzing, từ đó nhận ra các extension được cho phép như bên dưới.
Thực hiện chèn PHP webshell vào một file ảnh bằng exiftools với tên file là shell.phar.jpg (nhớ lưu ý mime type). Từ đó mình upload lên server và đạt được RCE.
File Inclusion là một lỗ hổng xảy ra khi back-end server thực hiện include một file (có thể là cục bộ hoặc từ xa). Khi đó, nếu kẻ tấn công có thể kiểm soát được nội dung của file cần include -> LFI, RFI.
Nói dông nói dài không bằng một vài ví dụ. Cụ thể ở đây, mình có một đoạn code JS nhỏ:
Ở đây trực tiếp lấy parameter language vào file include. Nếu mình thực hiện thay đổi language một tí, ví dụ như:
Từ đó có thể lấy nội dung của file này rồi ^^.
Đương nhiên File Inclusion không chỉ có như thế, mà nó còn có tác động mạnh mẽ như sử dụng wrappers, remote code execution thông qua log file, file upload,…
Lưu ý: Cần phải phân biệt rõ File Inclusion và Path Traversal. Trong khi Path Traversal chỉ có thể được dùng để thu thập thông tin, thì File Inclusion có thể thực hiện RCE.
Mình thực hiện module File Inclusion Assessment của hackthebox để mô phỏng cho lỗ hổng này.
Đầu tiên, khi truy cập vào trang web, mình nhận thấy endpoint index.php với tham số page đang render một sub-html.
Và, theo như hiểu biết của mình, một sub-html được render bằng cách sử dụng template engine, hoặc include một file nối chuỗi thủ công. Ví dụ như render('$_GET["page"].".php"'). Đồng thời thì kể từ PHP 5.5 trở đi, việc sử dụng các byte null như %00 là vô dụng. Thế nên ở đây mình chỉ có thể render các file php (bởi vì hiện tại mình chưa tìm ra cách bypass).
Ý tưởng đã có, vậy nên mình thực hiện đọc source của index.php sử dụng filter wrapper (.php sẽ được tự động thêm vào sau parameter page ở phía server).
Sau khi review qua source code, mình nhận thấy ở đây có một endpoint khá tiền năng.
Và ở endpoint này, mình nhận thấy ở đây cũng tồn tại một LFI, tuy nhiên thì bởi vì endpoint được sử dụng để render log. Vì vậy mà back-end server không thực hiện nối chuỗi ".php". Nhờ đó mà mình dễ dàng include được /etc/passwd.
Và cuối cùng, mình đã có LFI, đã có web-server (nginx: được đính kèm trong response). Vậy nên mình thực hiện chèn webshell vào User-Agent -> access log -> RCE.
Kết quả được hiển thị bên dưới.
Mình thực sự không biết tại sao lại thêm HTTP Verb Tampering vào đây, vì vốn dĩ nó chỉ là một lỗ hổng nhỏ và hết sức đơn giản.
Thôi thì đã lỡ rồi mình cũng giới thiệu sơ qua luôn, nhưng vì đây là một lỗ hổng cơ bản, nên mình sẽ không thực hiện assessment mà chỉ đưa ra một ví dụ.
HTTP Verb Tampering là một lỗ hổng hoạt động dựa trên phương thức được request nhưng server lại không thực hiện xác định rõ ràng các phương thức đó. Ví dụ như:
Server được cấu hình xác thực user để thực hiện request đến một endpoint, tuy nhiên lại chỉ giới hạn GET và POST. Vì vậy có thể sử dụng các phương thức khác như PUT, OPTION, PATCH, HEAD để request đến mà không cần xác thực.
Ngoài ra thì HTTP Verb Tampering còn xảy ra với "insecure coding". Một lập trình viên kinh nghiệm yếu kém có thể xử lý các method một cách lộn xộn và không chặt chẽ, điều này tạo điều kiện để thực hiện một cuộc tấn công HTTP Verb Tampering.
Insecure Direct Object Reference hay IDOR là một lỗ hổng cực kỳ phổ biến. Nó xảy ra khi một người dùng có quyền truy cập đến một object (files, endpoints, databases,…) khi server thiếu một hệ thống kiểm soát truy cập mạnh mẽ.
Ví dụ cho IDOR, có thể tưởng tượng bạn đang là user A, tuy nhiên bạn lại có thể truy cập vào endpoint /profile?username=B. Ở trường hợp này, hệ thống kiểm soát chỉ nhận request mà không kiểm tra cookie để xác định user có quyền truy cập hay không.
Tuy nhiên việc xây dựng một hệ thống kiểm soát truy cập mạnh mẽ là hết sức khó khăn và tiêu tốn nhiều tài nguyên. Vậy nên kể cả các social media khổng lồ như fb, twitter, ins,… đôi khi tồn tại lỗ hổng này.
Có 2 loại IDOR thông dụng:
Mô phỏng cho IDOR, mình thực hiện một assessment của hackthebox (Web Attacks Assessment).
Khi login vào trang web bằng tài khoản được hackthebox cung cấp. Mình nhận thấy browser gửi đi một gói tin với endpoint /api.php/user/<userid>. Điều đáng nói ở đây, là khi mình thử với các id khác mà không chỉnh sửa cookie, mà server vẫn thực hiện trả về thông tin của các người dùng đó -> IDOR.
Được nước lấn tới, mình thực hiện fuzzing 200 user theo ID để tìm ra một admin (trường hợp thực tế sẽ có số lượng user nhiều hơn) bằng ffuf.
Và kết quả đúng như mình mong đợi, userid=52 là một admin với username=a.corrales.
Sau khi có được username admin, mình thực hiện reset password của admin thông qua POST một gói tin đến endpoint reset.php cùng với nội dung dung như hình dưới. Tuy nhiên thì có vẻ ở đây server thực hiện xác thực token, vậy nên yêu cầu của mình bị từ chối.
Sau một hồi mày mò thì mình nhận ra IDOR cũng tồn tại ở endpoint /api.php/token/<userid>.
Vậy nên mình có thể dễ dàng lấy được token của admin bằng cách request đến endpoint trên bằng userid của admin.
Và thành công thay đổi mật khẩu của admin thành testpass.
Login với admin creds, mình nhận thấy admin có quyền tạo event. Một quyền mà user bình thường không có. Và, gói tin được gửi đi dưới dạng XML, vậy nên mình nghĩ ngay đến việc thực hiện XXE.
Kết quả đúng như mình mong đợi, mình đã thu thập thành công /etc/passwd chỉ với một payload XXE đơn giản.
Và cuối cùng, mình sử dụng XXE để lấy thông tin của /flag.php.
Document type Definition là một tiêu chuẩn cho các dạng ngôn ngữ đánh dấu (html, xml,…). DTD định nghĩa cấu trúc element, attribute cho markup language.
Cơ bản XML không cần thiết phải có DTD, tuy nhiên để tránh các lỗ hổng như XSS và định nghĩa những tag có sẵn, thuận tiện cho việc sử dụng. Người ta đã tạo 1 DTD cho XML.
Về cơ bản XML external entity hiểu đơn giản là các định nghĩa của XML từ 1 file bên ngoài.
Như ví dụ trên ở phần DTD, thì khi sử dụng entity theo cú pháp &entity_name; → nội dung của file passwd sẽ được bao gồm trong &hehe; (chú ý từ khóa SYSTEM → cho phép load và sử dụng external entity).
XML parameter entity (%): là loại entity đặc biệt, thực hiện việc tái sử dụng entity. Nó cho phép khai báo 1 entity trong một entity khác, như vậy việc các entity lồng nhau dễ dàng được cho phép ở parameter entity. Với mỗi parameter entity, nó phải được sử dụng trong DTD.
Đặc biệt, parameter entity được sử dụng trực tiếp trong DTD, không giống như regular entity sử dụng trong body.
Một ví dụ cho XXE:
Ở ví dụ trên, ta thực hiện ghi đè parameter entities cho schema.dtd. Khi %local_dtd; được sử dụng → nó sẽ parse entity có trong schema.dtd → custom_entity có trong schema.dtd đã bị ghi đè → %eval; và %error; được thực hiện.
Ở trên thực hiện một error-based XXE cùng với local dtd. Ngoài kỹ thuật trên, thì XXE còn bao gồm rất nhiều kỹ thuật khác như XIncludes, via SSRF, via Office Open XML Parse, via SVG, SOAP,… và các kỹ thuật bypass được mình trình bày ở XML External Entity.
Tạm thời mình chưa có ví dụ hợp lý cho XXE, phần này sẽ được update trong thời gian tới. Tuy nhiên thì các bạn có thể tham khảo IDOR Assessment và blog XML External Entity để có cái nhìn tổng quát hơn về XXE.
Phần 2 sẽ focus vào Insecure Deseriliazation