Arang.dev
搜索
TSG CTF 2020🏁 CTF🌐 已翻译

2020 TSG CTF - Slick Logger 题解

利用 Time-based Blind Regex Injection 获取 Flag

#tsg-ctf#regex-injection#blind#golang

本文由 AI 从韩语机器翻译,部分表达可能与原文有所不同。

阅读原文(韩语)

slick-logger web 5 solvers

func searchHandler(w http.ResponseWriter, r *http.Request) {
 channelID, ok := r.URL.Query()["channel"]
 if !ok || !validateParameter(channelID[0]) {
 http.Error(w, "channel parameter is required", 400)
 return
 }
 
 queries, ok := r.URL.Query()["q"]
 if !ok || !validateParameter(queries[0]) {
 http.Error(w, "q parameter is required", 400)
 return
 }
 
 users := []User{}
 readJSON("/var/lib/data/users.json", &users)
 
 dir, _ := strconv.Unquote(channelID[0])
 query, _ := strconv.Unquote(queries[0])
 
 if strings.HasPrefix(dir, "G") {
 http.Error(w, "You cannot view private channels, sorry!", 403)
 return
 }
 
 re, _ := regexp.Compile("(?i)" + query)
 
 messages := []Message{}
 filepath.Walk("/var/lib/data/", func(path string, _ os.FileInfo, _ error) error {
 if strings.HasPrefix(path, "/var/lib/data/"+dir) && strings.HasSuffix(path, ".json") {
 newMessages := []Message{}
 readJSON(path, &newMessages)
 for _, message := range newMessages {
 if re.MatchString(message.Text) {
 // Fill in user info
 for _, user := range users {
 if user.ID == message.UserID {
 messages = append(messages, Message{
 Text: re.ReplaceAllString(message.Text, "<em>$0</em>"),
 UserID: message.UserID,
 UserName: user.Name,
 Icon: user.Profile.Image,
 Timestamp: message.Timestamp,
 })
 break
 }
 }
 }
 }
 }
 return nil
 })
 
 result, _ := json.Marshal(messages)
 
 w.WriteHeader(http.StatusOK)
 header := w.Header()
 header.Set("Content-type", "application/json")
 fmt.Fprint(w, string(result))
}

在搜索功能中,程序接收我们的输入:channel 和 q

但它们使用了特定的参数格式,比如 "value",并对其进行去引号(unquote)处理。

因此,如果我们输入 """,它会变成空值,我们就可以像在 MySQL 数据库中使用 like '%' 一样进行搜索。

(感谢 GON 的 @Payload)

接下来,

filepath.Walk("/var/lib/data/", func(path string, _ os.FileInfo, _ error) error {
 if strings.HasPrefix(path, "/var/lib/data/"+dir) && strings.HasSuffix(path, ".json") {
 newMessages := []Message{}
 readJSON(path, &newMessages)

我们可以获取秘密频道的管理员消息,

users := []User{}
readJSON("/var/lib/data/users.json", &users)
 
...
 
for _, user := range users {
 if user.ID == message.UserID {

但由于这个条件的限制,users.json 中不存在 userid 为 USLACKBOT 的用户

for _, message := range newMessages {
>>> if re.MatchString(message.Text) {
 // Fill in user info
 for _, user := range users {

但是我们的搜索词 query 会作为参数传递给 regexp.Compile,而且它是在 userid 匹配之前被使用的。

所以我们可以利用它进行 Blind Regex Injection。 (https://portswigger.net/daily-swig/blind-regex-injection-theoretical-exploit-offers-new-way-to-force-web-apps-to-spill-secrets)

随着搜索词长度的增加,Blind Regex Injection 的准确率会降低。

适当地切分搜索词来获取 Flag!

另外准确率有点低,所以我们多次发送相同的 Payload,通过统计延迟最长的词来判断!XD

[*] 5 : 0.06300497055053711
[*] } : 0.062014102935791016
[*] N : 0.05901360511779785
---------------------
[*] } : 0.06202411651611328
[*] 0 : 0.060013771057128906
[*] W : 0.058012962341308594
---------------------
[*] U : 0.09402132034301758
[*] B : 0.0660254955291748
[*] } : 0.06601500511169434
---------------------
[*] } : 0.06301426887512207
[*] Z : 0.06101393699645996
[*] Y : 0.060013532638549805
---------------------
[*] } : 0.06601476669311523
[*] H : 0.06502485275268555
[*] 6 : 0.05902361869812012
---------------------
[Finished in 13.1s]
 
## this could be `}` is the currect word

查看我的利用脚本(Exploit)

https://github.com/JaewookYou/ctf-writeups/blob/master/2020TSGCTF/slick-logger/ex.py

评论

正在加载评论...
2020 TSG CTF - Slick Logger 题解 | TSG CTF 2020 | Arang