Mô tả thử thách
We recently started a new CMS, we've had issues with random bots scraping our pages but found a solution with robots! Anyways, besides that there are no new bug fixes. Enjoy our product!
Fuzzing is NOT allowed for this challenge, doing so will lead to IP rate limiting!
https://asteroid.sunshinectf.games
Phân tích
Có vẻ như là một web tĩnh và không có gì tiếp, vậy thì mình sẽ tiến hành kiểm tra file robots.txt trước xem sao


Nhận thấy nó để lộ ra 4 URL là /.gitignore_test, /login, /admin/dashboard, /2FA
Tiến hành xem qua từng URL
Đầu tiên là /.gitignore_test

Mình nhận được 3 file backup là /index/static/login.html~, /index/static/index.html~ , /index/static/error.html~
Tiếp tục check 3 file này
Bắt đầu với /index/static/login.html~

File này sẽ cho mình email:password của admin là admin@lunarfiles.muhammadali:jEJ&(32)DMC<!*###
Tiếp đến là /index/static/index.html~

Có vẻ như file này không chứa thông tin gì, vậy mình sẽ tiếp tục đến với file cuối cùng là /index/static/error.html~

Cũng không có gì nốt, vậy thì mình sẽ quay lại với 4 file ban đầu, tiếp tục với /login

Trang web này sẽ chuyển hướng mình đến /admin/dashboard, vậy mình sẽ qua đó xem sao

Tiếp tục chuyển hướng mình đến với /admin/help

Ở đây mình thấy nó có những đường dẫn như sau
<div class="nav-links">
<a href="/admin/help" class="nav-link">
<span class="link-icon">❓</span>
<span>Help</span>
</a>
<a href="/admin/lunar_files" class="nav-link">
<span class="link-icon">📁</span>
<span>Manage Files</span>
</a>
<a href="/admin/logout" class="nav-link logout-link">
<span class="link-icon">🚀</span>
<span>Logout</span>
</a>
</div>
Mình sẽ thử đến /admin/lunar_files xem sao

Ở đây nó cho mình 3 file là secret1.txt, secret2.txt, secret3.txt và một hàm đọc file là
function fetchFileContent(filename) {
// no need ot URLEncode this is JS argument being pssed in,
// plug we already URLencoded via flask's | urlencode
const viewUrl = `/admin/download/${filename}`;
fetch(viewUrl)
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.text();
})
.then(content => {
const contentArea = document.getElementById('fileContentArea');
contentArea.innerHTML = `<pre>${escapeHtml(content)}</pre>`;
})
.catch(error => {
const contentArea = document.getElementById('fileContentArea');
contentArea.innerHTML = `<div class="error-msg">
<h4>🚨 Access Denied</h4>
<p>Error loading file: ${escapeHtml(error.message)}</p>
<p><em>This incident has been logged with our security systems.</em></p>
</div>`;
});
}
Vậy mình có thể khá chắc chắn rằng đây là lỗ hỗng Path traversal do filename được truyền thẳng vào viewURL mà không thông qua bước tiền xử lý nào
Khai thác
Mình sẽ sử dụng Burp Intruder để tấn công Path traversal trước xem sao

Sử dụng Burp Intruder không lấy ra được kết quả gì nên mình sẽ thử một dạng encode ít phổ biến và cũng khá hiệu quả khác là /.././ với .. sẽ gọi đến thư mục cha của thư mục hiện tại và . để gọi chính nó

Chúng ta đã thành công đọc được /app.py và nhận thấy có một đường dẫn là /FLAG/flag.txt

Flag
Flag: sun{lfi_blacklists_ar3_sOo0o_2O16_8373uhdjehdugyedy89eudioje}
'WriteUp > Web' 카테고리의 다른 글
| [Web] cookie - Dreamhack (0) | 2025.10.11 |
|---|---|
| [Web] Puzzle - Securinets CTF Quals 2025 (0) | 2025.10.06 |
| [Web] Web Forge (SunshineCTF 2025) (0) | 2025.10.01 |
| [Web] Lunar Shop (SunshineCTF 2025) (0) | 2025.10.01 |
| [Web] Intergalactic Webhook Service (SunshineCTF 2025) (0) | 2025.10.01 |
