# XSS Portswigger
## 1. Reflect XSS
### 1.1 Reflected XSS into HTML context with nothing encoded
- Bài này dính XSS trong chức năng search
- Thử search ok để xem reponse trả về

- Chèn tag script vào để solve bài lab

### 1.2 Reflected XSS into attribute with angle brackets HTML-encoded
- Bài này cũng tương tự bài trên nhưng nó đã validate dấu ngoặc nhọn
- Chèn đoạn script vào và kiểm tra source code => Thấy nó có reflect về và được xử lý trong thẻ input


- Khai thác bằng cách chèn event attribute với payload như sau: "onmouseover="alert(1) để solve bài lab

### 1.3 Reflected XSS into a JavaScript string with angle brackets HTML encoded
- Bài này là sự kết hợp của 2 bài trên, lỗ hổng ở search và có validate dấu <>. Muốn slove được lab này thì cần thoát khỏi chuỗi javascript.
- Chèn script và kiểm tra mã nguồn => Nó được xử lý trong ở phần javascript

- Bypass bằng cách thoát khỏi biến searchTerms và thực hiện alert rồi sau đó comment để lại bỏ phần phía sau, payload như sau: ';alert(1)//


### 1.4 Reflected DOM XSS
- Dữ liệu từ yêu cầu được reflect vào HTML, sau đó một script JavaScript trên trang xử lý dữ liệu reflect đó một cách không an toàn và đưa vào một sink nguy hiểm.
- Sau khi search bất kì thì nó cũng reflect => kiểm tra source code thấy có đoạn script khá nghi ngờ như dưới, có thẻ nó được lưu vào searchResults.js.

- Kiểm tra trong burpsuite thấy nó được lưu vào thuộc tính searchTerm của object searchResults.

- Lúc này thực hiện escape searchTerm với payload: `\"-alert(1)}//` để solve bài lab (Khi thêm dấu \ (một ký tự đặc biệt trong JSON) vào một chuỗi, máy chủ phải thoát chính nó bằng cách thêm một dấu \ khác, từ đó sẽ trả về `\\` khiến việc thoát bị hủy bỏ và thực hiện được lệnh alert phía sau.)

### 1.5 Reflected XSS into HTML context with most tags and attributes blocked
- Thử comment đoạn script vào ô search => Thấy tag not a allow nghĩa là thẻ không được chấp nhận => Có vẻ như hệ thống đã block thẻ script

- Sau đó sẽ đi bruteforce tất cả các tag để xem các tag không bị block. Search với từ khóa bất kì và intruder (upload list cheat sheet tag của XSS [tại đây](https://portswigger.net/web-security/cross-site-scripting/cheat-sheet))=> Những pyload trả về status 200 là những thẻ không bị block => ở đây có body, custom tags,…


- Sau khi tìm ra được payload không bị block thì tiếp tục đến việc kiểm thử event attribute. Thử với payload sau: <body onload=1> => Lỗi không chấp nhận event (ở đây là onload)

- Tiếp tục bruteforce intruder để tìm ra event không bị block

- Do đó, chúng ta có thể kết hợp thẻ <body> và sự kiện onresize để thay đổi kích thước, xây dựng payload tấn công XSS như sau: <body onresize="print()">
- Config exploit server để gửi script tấn công tới victim: Sử dụng thẻ iframe với giá trị src là URL trang web đang chứa script của chúng ta. Sau đó thêm event: onload=this.style.width='123px' để thay đổi kích thước của trang ngay sau khi giá trị src được load.

### 1.6 Reflected XSS into HTML context with all tags blocked except custom ones
- Bài này tương tự bài trên, chặn tất cả các tag HTML ngoại trừ các tag tùy chỉnh. Để solve bài lab cần chèn tag tùy chỉnh kết hợp với alert tự động document.cookie
- Tạo payload như sau: `<script> location = "https://idbailab.web-security-academy.net/?search=<xss id=xss onfocus=alert(document.cookie) tabindex=1>#xss"; </script>`
- Dùng location để điều hướng đến địa chỉ lab
- Tiếp theo tạo 1 thẻ với tên tùy chỉnh (gán id=xss)
- Chèn mã độc onfocus=alert(document.cookie) nghĩa là khi phần tử nhận được focus thì sẽ gọi alert
- Thiết lập thuộc tính tabindex làm cho phần tử trở nên dễ focus
- Phần #xss ở cuối URL là chìa khóa để tự kích hoạt khai thác.Theo quy tắc HTML, khi trình duyệt tải một URL có #id ở cuối, nó sẽ tự động cuộn và focus đến phần tử có id đó.
- Nói ngắn gọn là phần tử XSS có id=xss và đã được chèn thành công vào DOM, khi trình duyệt chuyển focus đến nó, sự kiện onfocus sẽ được kích hoạt, chạy mã alert(document.cookie)

### 1.7 Reflected XSS with some SVG markup allowed
- Mô tả: This lab has a simple reflected XSS vulnerability. The site is blocking common tags but misses some SVG tags and events. To solve the lab, perform a cross-site scripting attack that calls the alert() function.
- Theo mô tả thì bài này không chặn 1 số tag và events của SVG. Vậy giờ chúng ta thực hiện fuzzing các tag trước thì thấy tag script đã bị block


- Nhưng khi thử với tag SVG thì không bị block

- Tiếp theo tìm các tags con của svg trong cheat sheet để brute force xem tag nào không bị block



- Tìm được 1 tag con không bị block của SVG là animatetransform, tiếp tục chúng ta brute force để tìm theo events nào không bị block


- Cuối cùng chèn alert() vào events onbegin để solve bài lab

## 2. Store XSS
### 2.1 Stored XSS into HTML context with nothing encoded
- Đây là bài cư bản của lỗ hổng Stored XSS, khi đưa payload lên thì nó được lưu trữ vĩnh viễn trên máy chủ (thường trong cơ sở dữ liệu) và được trình duyệt thực thi mỗi khi người dùng truy cập trang chứa payload.
- Ở đây thực hiện đưa payload khai thác XSS đăng lên phần comment => Khi người khác đăng nhập vào và đọc comment đó thì payload XSS sẽ được thực thi


### 2.2 Stored XSS into anchor href attribute with double quotes HTML-encoded
- Bài này cũng bị stored XSS nhưng không đơn giản giống bài trước, thử post comment rồi check mã nguồn xem

- Sau khi check mã nguồn thì không thể khai thác tiếp ở phần comment nhưng giá trị diền ở phần website xuất hiện trong href của thẻ a => Chèn payload khai thác của javascript vào để solve bài lab


### 2.3 Stored DOM XSS
- Bài này khai thác giống bài Reflect DOM XSS nhưng khó hơn 1 chút
- Đầu tiên test phần post comment trước rồi check mã nguồn


- Có thể thấy server dùng JSON.parse để xử lý mảng các comment đó rồi mới bắt đầu xử lý để hiển thị comment.
- Check tiếp các request khác thì thấy có file js chứa các function để xử lý commnet

- Phân tích 1 chút thì có thể hiểu hàm escapeHTML() có nhiệm vụ bypass các dấu <>.Tuy nhiên nó chỉ escape cặp dấu <> dầu tiên thôi, từ đó có thể lợi dùng chèn payload vào cặp dấu <> thứ 2. Có 1 số trường dùng escapeHTML như hình dưới

- Từ đó có thể dùng payload như dưới vào những trường đó rồi load lại để solve bài lab:


### 2.4 Stored XSS into onclick event with angle brackets and double quotes HTML-encoded and single quotes and backslash escaped
- Tiếp tục là lab về stored XSS, dầu tiên post comment sau đó check mã nguồn

- Có thể thấy giá trị của website đã được truyền vào hàm track() ở event onclick và thẻ a => Vậy giờ chỉ cần khai thác tại đây thôi
- Khai thác với payload sau để đóng ngoặc lại sau đó truyền alert và cuối cùng là comment để bỏ đoạn phía sau


- Có thể thấy dấu ' đã bị escape bằng cách nối thêm 1 dấu \ vì vậy encode dấu ' rồi đưa vào payload


## 3. DOM XSS
### 3.1 DOM XSS in document.write sink using source location.search
- Mô tả: This lab contains a DOM-based cross-site scripting vulnerability in the search query tracking functionality. It uses the JavaScript document.write function, which writes data out to the page. The document.write function is called with data from location.search, which you can control using the website URL. To solve this lab, perform a cross-site scripting attack that calls the alert function.
- Bài này có chức năng search, và giá trị search sẽ được reflect về

- Ta sẽ check đoạn script xử lý phần này của nó

- `var query = (new URLSearchParams(window.location.search)).get('search');`:
- Dòng này lấy giá trị của tham số search từ URL (phần sau dấu ?).
- Ví dụ: Nếu URL là example.com?search=laptop, thì biến query sẽ có giá trị là "laptop".
- Hàm trackSearch(query): `document.write('<img src="/resources/images/tracker.gif?searchTerms=' + query + '">');`
- Hàm này sử dụng document.write để chèn một thẻ ảnh (<img>) ẩn vào trang web.
- Mục đích là gửi từ khóa tìm kiếm về máy chủ thông qua một yêu cầu tải ảnh (thường dùng để làm analytics/thống kê).
- Lỗi nằm ở chỗ dữ liệu từ biến query (do người dùng kiểm soát qua URL) được nối trực tiếp vào chuỗi HTML và ghi ra trang web bằng document.write mà không qua bất kỳ khâu kiểm duyệt (sanitization) nào.
- Vậy để bypass được bài này thì ta cần thoát khỏi thẻ img và chèn payload khai thác vào


- Ở phần này ta không quan tâm đến "> còn thừa, vì khi đóng tag img đầu tiên và chèn tag image thứ 2 với src không đúng thì nó đã kích hoạt event onerror để thực thi XSS, ta cũng có thể chèn tag script va fsau khi escape tag img
### 3.2 DOM XSS in innerHTML sink using source location.search
- Mô tả: This lab contains a DOM-based cross-site scripting vulnerability in the search blog functionality. It uses an innerHTML assignment, which changes the HTML contents of a div element, using data from location.search. To solve this lab, perform a cross-site scripting attack that calls the alert function.
- Bài này thay vì document.write() thì nó sẽ dùng .innerHTML và nó cũng không xử lý data khi người dùng nhập vào.

- Vậy giờ sẽ chèn 1 tag img với event onerror để nó kích hoạt XSS (vì innerHTML không hỗ trợ tag script)

### 3.3 DOM XSS in jQuery anchor href attribute sink using location.search source
- Mô tả: This lab contains a DOM-based cross-site scripting vulnerability in the submit feedback page. It uses the jQuery library's $ selector function to find an anchor element, and changes its href attribute using data from location.search. To solve this lab, make the "back" link alert document.cookie.
- Đầu tiên ta check src thì thấy có 1 đoạn script trông như sau:

- Phân tích đoạn script trên ta có:
- `$(function() { ... });`: Đây là cách viết tắt của jQuery để đảm bảo đoạn mã chỉ chạy sau khi toàn bộ tài liệu HTML đã được tải xong (DOM Ready).
- `$('#backLink')`: jQuery tìm phần tử có thuộc tính id="backLink" (thường là một thẻ liên kết <a>).
- `.attr("href", ...)`: Hàm này dùng để thiết lập giá trị cho thuộc tính href của phần tử vừa tìm được.
- `(new URLSearchParams(window.location.search)).get('returnPath'):` Nó nhìn vào thanh địa chỉ URL, sau đó tìm tham số có tên là returnPath cuối cùng lấy giá trị của tham số đó
- Luồng hoạt động của nó như sau:
- Nếu ta truy cập vào trang với URL: `https://0a29007a03ee579f8171ca2a00de0077.web-security-academy.net/feedback?returnPath=/feedback`
- Đoạn mã sẽ lấy được chuỗi: "/feedback"
- Nó sẽ gán giá trị này vào thẻ link: `<a id="backLink" href="/feedback">.`
- Khi người dùng nhấn vào nút này, họ sẽ được đưa quay trở lại trang feedback.
- Áp dụng vào thao tác trên lab như sau:
- Đầu tiên khi đang ở trang chính của lab thì nó có chức năng submit feedback

- Khi click vào Submit feedback thì nó đưa ta đến /feedack với tham số returnPath có giá trị hiện tại chỉ là / (trang chủ)

- Khi tiếp tục click vào Submit feedback trong /feedback này thì nó cập nhật cho ta giá trị tham số returnPath là /feedback (trang feedback)

- Vậy cách khai thác của lab này như sau:
- Cách 1 tấn công open redirect: hacker sẽ dán 1 đường link như `http://webluadao.hack` cho tham số returnPath và khi người dùng click vào back thì nó sẽ redirect đến web hack
- Cách 2 là khai thác XSS - áp dụng cho bài này: Nó sẽ chèn 1 đoạn XSS cho giá trị của tham số returnPath để khi user back nó sẽ lấy được các thông tin quan trọng như cookie,... Vậy payload sẽ là `javascript:alert(document.cookie)`dùng để lấy cookie

### 3.4 DOM XSS in jQuery selector sink using a hashchange event
- Mô tả: This lab contains a DOM-based cross-site scripting vulnerability on the home page. It uses jQuery's $() selector function to auto-scroll to a given post, whose title is passed via the location.hash property. To solve the lab, deliver an exploit to the victim that calls the print() function in their browser.
- Đầu tiên ta check thử src xem thử script được viết như thế nào

- Phân tích đoạn script trên như sau:
- $(window).on('hashchange', function() { ... });: Lắng nghe sự kiện hashchange. Sự kiện này kích hoạt mỗi khi phần sau dấu # trên URL thay đổi (ví dụ từ index.html#About sang index.html#Contact).
- window.location.hash.slice(1): window.location.hash lấy toàn bộ phần hash (ví dụ: #Product) còn .slice(1) loại bỏ ký tự # ở đầu, chỉ giữ lại chữ Product.
- decodeURIComponent(...): Giải mã các ký tự đặc biệt trên URL (ví dụ chuyển %20 thành khoảng trắng).
- var post = $('section.blog-list h2:contains(' + ... + ')');: Đây là phần cốt lõi. Nó sử dụng selector :contains() của jQuery để tìm một thẻ h2 nằm trong section.blog-list mà nội dung văn bản của nó có chứa chuỗi từ hash. Ví dụ: Nếu URL là #Hello, nó sẽ tìm thẻ h2 nào có chữ "Hello".
- if (post) post.get(0).scrollIntoView();: Nếu tìm thấy thẻ h2 thỏa mãn, nó sẽ sử dụng hàm scrollIntoView() để trình duyệt tự động cuộn màn hình đến vị trí của thẻ đó. Những thẻ h2 để dùng cho scroll có dạng như dưới:

- Thử check 1 thẻ h2 bất kì là Meeting thì thấy nó đã xử lý script để scroll đến đoạn nội dung Meeting Up

- Vậy ta thử chèn 1 thẻ img để kích hoạt event error xem sao:

- Nó thực thi xss thành công nhưng chưa solve được bài lab, đọc lại descripton thì thấy nó yêu cầu phải viết payload trong exploit server.

- View exploit để xem kết quả:

- Payload trên có nghĩa như sau:
- onload="...": Đây là một trình xử lý sự kiện (event handler). Nó sẽ chạy ngay sau khi nội dung bên trong iframe đã tải xong lần đầu tiên.
- this.src += '...': this.src tham chiếu đến địa chỉ URL hiện tại của iframe. Phép toán += sẽ nối thêm chuỗi mã độc vào sau dấu #.
### 3.5 DOM XSS in document.write sink using source location.search inside a select element
- Mô tả: This lab contains a DOM-based cross-site scripting vulnerability in the stock checker functionality. It uses the JavaScript document.write function, which writes data out to the page. The document.write function is called with data from location.search which you can control using the website URL. The data is enclosed within a select element. To solve this lab, perform a cross-site scripting attack that breaks out of the select element and calls the alert function.
- Đầu tiên mở src để xem script xử lý phần check stock:

- Workflow của đoạn này như sau:
- Khởi tạo dữ liệu: Tạo một mảng stores chứa danh sách các thành phố: London, Paris, Milan.
- Lấy dữ liệu từ URL: Sử dụng URLSearchParams để lấy giá trị của tham số storeId trên thanh địa chỉ.
- Mở thẻ HTML: Dùng document.write để ghi thẻ mở <select name="storeId">.
- Xử lý lựa chọn hiện tại (dangerous): Nếu có giá trị store từ URL, nó sẽ tạo ra một thẻ <option> với thuộc tính selected. Vấn đề là biến store được nối trực tiếp vào chuỗi HTML: '+store+'.
- Duyệt danh sách: Chạy vòng lặp for qua mảng stores. Nếu thành phố trong mảng trùng với thành phố từ URL thì bỏ qua (vì đã hiển thị ở bước trên), nếu không thì hiển thị như một lựa chọn bình thường.
- Đóng thẻ: Ghi thẻ đóng </select>.
- Vậy đầu tiên khai bằng cách thêm parameter storeId vào URL với value bất kì là abc => Xuất hiện được option abc trong check stock


- Nó đã được tạo 1 thẻ option với thuộc tính selected. Vậy nếu ta đóng thẻ option đó lại rồi chèn 1 script vào thì nó có cấp 1 thẻ option mới và thực thi không?

=> Thành công solve được bài lab