Access vào bài lab, ta thấy có chức năng Search
Khi sử dụng tính năng này, nhận thấy vì input được reflect trong response nên chỉ cần call alert function để solve bài lab
<script>alert(1)</script>
Tìm được hai tag là body
và custom tag thông qua cheat sheet của port swigger không bị chặn bởi WAF
Tiếp theo là tìm các event của hai tag này với phương pháp tương tự
Ở đây ta thử event onresize
của tag body
, search trong cheet sheet thì thấy có một payload: <body onresize=print()>
, khi window được resize sẽ call đến event -> print function
Việc còn lại là tìm cách "delivery" payload này đến victim, setup exploit server như sau:
Tạo một iframe với src là trang web bị lỗi reflected xss và sau đó áp dụng event onload để resize iframe => trigger payload xss và thực thi print function
Cuối cùng chọn Delivery exploit to victim để solve bài lab
Ở bài lab này các tag đều bị block trừ custom tag, theo như cheet sheet của portswigger ta tìm được payload:
<xss tabindex=1 onfocus=alert(document.cookie) id=x>#x
Về bản chất ta tạo ra một custom tag xss
với id là x
, thuộc tính onfocus
sẽ call đến alert function khi được focus, tabindex
chỉ định thứ tự sẽ được focus khi ấn nút Tab. Có thêm fragment x
ở url để focus vào custom tag này
Scan các tag không bị chặn:
Sau một hồi search với các keyword liên quan, ta tìm được một blog để tham khảo
Final payload: <svg><a><animate attributeName=href values="javascript:alert(1)" /><text x=20 y=20>Click me</text></a>
Các tag không bị chặn là animatetransform
, svg
…
Đồng thời scan được event là onbegin
cũng không bị chặn bởi waf
Cấu trúc của tag svg khi sử dụng với animatetransform như sau
Vậy nếu ta thử thêm thuộc tính onbegin cho animatetransform tag => XSS
Ở bài lab này các dấu <
, >
đã bị html encode
Vì thế ta sẽ cần inject vào attribute của một tag, để ý ở dưới có một tag input có thể khai thác
Payload " autofocus onfocus=alert(1) a="
Từ bài research của portswigger, ta có thể dễ dàng solve bài lab với payload
Kết quả
Ở lab này, input của ta sẽ được reflect trong một block script
Để XSS ta cần break script tag này và chèn payload xss: </script><img src=x onerror=alert(1)>//
Thử search với input là <a>
, ta được response như sau
=> các kí tự <
và >
đã bị encode
Ta có thể break khỏi string hiện tại bằng dấu -
, payload: -alert(1)-
Search với input là bla'bla
Ta thấy lần này '
đã được escape với \
, tuy nhiên có thể bypass bằng cách sử dụng thêm một kí tự \
Final payload: \'-alert(1)//
Ý tưởng dựa vào bài research https://portswigger.net/research/xss-without-parentheses-and-semi-colons
Payload: &%27},x=x=%3E{throw/**/onerror=alert,1337},toString=x,window%2b%27%27,{x:%27
=> url decode: &'},x=x=>{throw/**/onerror=alert,1337},toString=x,window+'',{x:'
Giải thích
Implicit Globals
Khi ta khai báo một biến mà không sử dụng var
, let
,const
nó sẽ được gán cho thuộc tính của global object. Trên trình duyệt, global object là window
.
Arrow Function
x=x=>{onerror=alert; throw 1337}
Tạo ra một arrow function và gán cho x
. Function x chứa đoạn statement gán error handler onerror
thành alert function sau và đó throw 1337
sẽ truyền tham số 1337 cho error handler function (lúc này đã bị ghi đè thành alert). Như đã nói ở trên x
sẽ được hiểu "implicit global" và được gán vào window
.
Ghi đè toString
toString=x
Khi đè toString
method của window
thành x
, vì thế khi ta convert window
sang một string, nó sẽ gọi đến x
Converting window
to String
window+''
Khi ta concate với ''
sẽ trigger method window.toString()
-> window.x()
Ở chức năng search, input của ta được đưa một template literal của JS
Bởi vì các kí tự angle brackets, single, double quotes, backslash và backticks đã bị escape nên chỉ còn cách sử dụng ${...}
để thực thi JS
Payload: ${alert(1)}
Từ mô tả, có thể dễ dàng khai thác store xss như sau
Sau khi Post Comment, ta chọn Back to blog và sẽ thấy alert function được gọi
Từ mô tả, chức năng XSS có liên quan đến tính năng comment của trang web -> thử với các thông tin
-> Input của ta được đưa vào attribute href
của tag a
Để thỏa yêu cầu đề bài, ta chỉ cần chỉnh cho giá trị của field Website là javascript:alert(1)
Kết quả
Ở tính năng comment, ta thử Post với các giá trị như sau
Sau khi Post, back to blog và view source sẽ thấy input của ta (trường Website) rơi vào value của tag a
Nhưng vì angle brackets và double quotes đã bị html encode, single quotes và backslash bị escaped nên ta phải sử dụng cách đó là html encode vài kí tự trong payload. Bởi vì trình duyệt sẽ HTML decode giá trị của thuộc tính onclick trước khi parse JS
Payload ban đầu : ');alert(1)//
-> HTML encode: ');alert(1)//
Kết quả:
Từ đoạn JS sau
ta có thể suy ra được
search
paramdocument.write
ở trackSearch
function-> XSS với payload như sau
Chức năng stock check:
Đoạn code JS trong trang này như sau
=> Source là storeId
GET param và sink là document.write
(sẽ cần đóng tag option
)
Test với storeId=abc
:
Solve bài lab:
View source trang web, ta tìm được đoạn JS dính lỗi DOM-XSS
Source: search
param, sink: document.innerHTML
. Tuy nhiên đối với innerHTML ta không thể dùng script
tag bởi vì trình duyệt đã có cơ chế không thực thi đoạn mã JS trong tình huống đó vì vậy có thể xài img
hoặc iframe
tag cũng với các event quen thuộc để trigger XSS
Ở trang dùng để submit feedback
Có một đoạn jquery mà ta có thể lợi dụng để khai thác DOM XSS
=> Dễ dàng thay đổi giá trị của thuộc tính href thành giá trị bất kì thông qua GET param returnPath
-> ?returnPath=javascript:alert(1)
Follow của trang web, khi ta ấn search một GET request sẽ được gửi đến /search-results?search=<input>
Response trả về sẽ được process bởi file searchResults.js
Nội dung file này khá dài nhưng ta cần để ý tới điểm sau
Response được đưa vào hàm eval -> sink tại đây
Vậy điều ta cần làm là nhập input sao cho response trả về của GET request đến /search-results chứa payload xss
Sau một hồi fuzzing, suy ra có thể dùng \
để escape JSON response và chèn payload XSS
Solve bài lab
Về luồng hoạt động, khi post lên một comment
Các thông tin sẽ được lưu trên server sau đó trang sử dụng một file JS là loadCommentsWithVulnerableEscapeHtml.js
để oad comments từ server và render
Sau khi xem qua một lượt về file này, dễ thấy sink nằm ở đoạn code
comment.author
chính là giá trị name
khi ta post comment
Tuy nhiên nếu muốn khai thác XSS ta phải bypass được function escapeHTML()
.Chức năng của hàm này như sau:
-> thực hiện thay thế kí tự <
thành <
và >
thành >
.
Nhưng trong JS nếu ta sử dụng .replace()
với tham số thứ nhất là một value chứ không phải regex patern thì nó chỉ thay thế kí tự đầu tiên của chuỗi
Payload:
Kết quả:
Đề bài mô tả bài lab này bị lỗi stored XSS ở chức năng comment, thực hiện khai thác như sau:
Post Comment, chở một vài giây ta lấy được cookie của victim
Chỉnh thành giá trị cookie của victim
Vào lại My account kiểm tra -> giả mạo được user admin và solve bài lab
Lợi dụng chức năng auto fill, tạo hai ô input giả mạo ứng với username và password bằng cách post comment với nội dung:
Chờ một vài giây và kiểm tra burp collab client, ta lấy được username và password của victim
Username administrator
:
Password:
Login với account vừa lấy được để solve bài lab
Ý tưởng: lợi dụng Stored XSS để extract csrf token và áp dụng csrf để change email.
Login với account được cung cấp
Sau đó change email, request sẽ có dạng như sau
Csrf token có thể được lấy ở /my-account
Stored xss tại chức năng comment
Payload:
Kết quả
Ở chức năng Update email, ta thấy trang web tự fill vào ô input email với giá trị ứng với ?email
Vậy có thể khai thác dangling markup để steal csrf token của victim với payload:
Thử ấn Click me
(bên phía exploit server setup cho alert(name)
)
Setup lại exploit server
Delivery exploit to victim và check access log
Tạo lại CSRF form để Update email của user admin
Delivery exploit to victim và Solve
Sau một hồi fuzzing, nhận ra ta có thể khai thác csp injection tại param token
Final payload
Solve
portswigger