Link: https://ctf.intigriti.io/challenges
NoSQL injection
Regex:
Bypass regex use CRLF (%0d%0a
)
sqlmap
https://rayhan0x01.github.io/ctf/2021/04/02/blind-sqli-over-websocket-automation.html
Vì sqlmap không hỗ trợ ws://
nên cần tạo server http trung gian để kết nối.
Script:
Khai thác bằng sqlmap
:
Offical wu (CryptoCat): https://www.youtube.com/watch?v=kgndZOkgVxQ&list=PLmqenIp2RQciRpl2GvZv1kQUq-INq7XvH&index=6
https://www.youtube.com/watch?v=fMrFxI4xXQc
Script:
Kết quả:
crypt0:c4tz on /4dm1n_z0n3, really?!
=>Login
Sử dụng jwt_tool:
Bài chỉ có chức năng /order
và hiển thị ra thông tin, không SQLi chắc cũng nghĩ đến SSTI (•_•)
Nhưng bất kỳ ký từ nào từ {}<>'"...
cũng bị filter.
=>Bypass vẫn là dùng CRLF để xuống dòng. (chắc filter bằng regex)
Test vài cái nữa dễ dàng biết được xài template Jinja2.
Dùng payload RCE thì ăn ngay:
Nhưng bị filter space:
Bypass bằng ${IFS}
:
Sau khi biết được có thể gen PDF, test:
Kết quả:
=> Server-side XSS
Sau 1 hồi test payload trên Server Side XSS (Dynamic PDF) - HackTricks. Tìm được payload:
<script>document.write("abc")</script>
thực thi được JS:<iframe src="file:///etc/passwd"></iframe>
có thể đọc được local file:Nhưng flag lại không phải là /flag.txt
hay /flag
,… (¬_¬ ). Thử đọc vài file local để khai thác LFI nhưng vẫn không thấy gì.
=> Đọc source… Offical wu (CryptoCat): https://ctftime.org/writeup/38300
༼ つ ◕_◕ ༽つ
<script>document.write(location.href)</script>
xem file hiện tại:Dễ đoán được /app/app.js
và đọc nó bằng <iframe src="file:///app/app.js" width="500" height="500"></iframe>
, được:
Tương tự:
/app/routes/index.js
:/app/routes/api.js
/app/controllers/user.js
/app/services/user.js
:Quan sát:
Như vậy userData
được lưu ở /app/data/[loginHash].json
, đồng thời userData
cũng được lấy ra để sử dụng từ file này.
Xem file /app/routes/index.js
biết được flag có trong check_admin.js
/app/middleware/check_admin.js
:Để thành admin cần thuộc tính isAdmin
vào userData
.
Tuy nhiên, xem kỹ lại:
Nếu userData = JSON.parse(userData);
không parsed được nghĩa là nó sẽ không đi vào đây: res.status(403);
và vậy thì middleware này đi tiếp vào next()
=> truy cập /admin
thành công.
Quan sát /app/routes/index.js
:
Tiếp tục đọc file: /app/utils/generateProfileCard.js
:
Quan sát:
Lúc tạo PDF có thể thêm 1 số options và ở đây nó sử dụng spread trong js để gộp thêm userOptions
(nếu có) vào options
ban đầu.
Ý tưởng sẽ dùng option path để ghi đè file chứa userData
=> parse gẫy lỗi và truy cập được vào /admin
Kết quả:
Wu: https://github.com/arthepsy/ctf/blob/main/writeups/2023-intigriti-1337up/owasp.md
Source search.php
:
Như vậy việc build sql query bằng cách duyệt qua các các cặp param (field
-value
) trong từng vòng lặp.
Ví dụ:
?title=a
, query đầy đủ sẽ là: select * from owasp where position('a' in title)
.?title=a&id=1
, query sẽ là select * from owasp where position('1' in id) AND position('a' in title)
.Truyền value
vào query được sử dụng bởi vsprintf với format string, lợi dụng điều này để ta khai thác.
Việc inject vào format string mình từng gặp trong bài ctf này: DownUnderCTF 2023 - Smooth Jazz (SQL Injection)
Đó là việc dùng %1$s
, 1
tức là lấy đối số thứ nhất để truyền vào, việc dùng cái này sẽ không bị lỗi như việc dùng %s ... %s
do chỉ được truyền 1 giá trị.
=> Payload: ?id=%1$s&title=in title) or 1=1 -- -
giá trị thứ nhất %1$s
sẽ được truyền vào trong vòng lặp thứ 2: position(%s in id) AND position('%1$s' in title)
và giá trị thứ 2 in title) or 1=1 -- -
sẽ được truyền vào %s
ở trên, khi đó query đầy đủ là:
select * from owasp where position('in title) or 1=1 -- -' in id) AND position(''in title) or 1=1 -- -'' in title)
Khai thác qua union
:
Việc validate url
bằng filter_var($url, FILTER_VALIDATE_URL)
Một số hợp lệ:
Ta sẽ dùng file:///flag.txt
để get flag.
Json dùng sẽ là {"flag":1,"url":"file:///flag.txt"}
.
Payload cuối cùng ?id=%1$s&title=in title) UNION SELECT 1,1,1,0x7b22666c6167223a312c2275726c223a2266696c653a2f2f2f666c61672e747874227d-- -
Offical Wu: https://ctftime.org/writeup/38279