๊ธ€ ์ž‘์„ฑ์ž: heogi

# Adult Simple GoCurl

์ด์ „ ๋ฌธ์ œ์ธ Baby Simple GoCurl์—์„œ ์—…๊ทธ๋ ˆ์ด๋“œ๋œ ๋ฌธ์ œ์ด๋‹ค.

์†Œ์Šค์ฝ”๋“œ์ƒ ๋ณ€๊ฒฝ๋œ ๋ถ€๋ถ„๋งŒ ์‚ดํŽด๋ณด๋ฉด flag ๋ฌธ์ž์—ด์„ ๊ฒ€์‚ฌํ•˜๋Š” ๋กœ์ง์ด || ์œผ๋กœ ๋ฐ”๋€Œ์—ˆ๊ณ , ClientIP() ํ•จ์ˆ˜๋ฅผ ์ฒดํฌํ•˜๋Š” ๋กœ์ง์ด ์—†์–ด์กŒ๋‹ค.

reqUrl := strings.ToLower(c.Query("url"))
		reqHeaderKey := c.Query("header_key")
		reqHeaderValue := c.Query("header_value")
		reqIP := strings.Split(c.Request.RemoteAddr, ":")[0]
		fmt.Println("[+] " + reqUrl + ", " + reqIP + ", " + reqHeaderKey + ", " + reqHeaderValue)

		if strings.Contains(reqUrl, "flag") || strings.Contains(reqUrl, "curl") || strings.Contains(reqUrl, "%") {
			c.JSON(http.StatusBadRequest, gin.H{"message": "Something wrong"})
			return
		}

๋•Œ๋ฌธ์— Baby Simple GoCurl์—์„œ ์‚ฌ์šฉํ–ˆ๋˜ ๋ฐฉ๋ฒ•์œผ๋กœ๋Š” ๋” ์ด์ƒ flag๋ฅผ ํ™•์ธํ•  ์ˆ˜ ๊ฐ€ ์—†๋‹ค.

์†Œ์Šค์—์„œ redirectChecker ํ•จ์ˆ˜๊ฐ€ ์กด์žฌํ•œ๋‹ค.

func redirectChecker(req *http.Request, via []*http.Request) error {
	reqIp := strings.Split(via[len(via)-1].Host, ":")[0]

	if len(via) >= 2 || reqIp != "127.0.0.1" {
		return errors.New("Something wrong")
	}

	return nil
}

์š”์ฒญํ•˜๋Š” IP๊ฐ€ 127.0.0.1๊ฐ€ ์•„๋‹ˆ๋ฉด ์•ˆ๋˜๋„๋ก ํ•„ํ„ฐ๋ง์ด ๋˜๊ณ ์žˆ๋‹ค.

gin์˜ ์†Œ์Šค์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด redirect์— ๊ด€๋ จ๋œ ์•„๋ž˜ ์ฝ”๋“œ๊ฐ€ ์žˆ๋‹ค.

// RedirectTrailingSlash enables automatic redirection if the current route can't be matched but a
// handler for the path with (without) the trailing slash exists.
// For example if /foo/ is requested but a route only exists for /foo, the
// client is redirected to /foo with http status code 301 for GET requests
// and 307 for all other request methods.
func redirectTrailingSlash(c *Context) {
	req := c.Request
	p := req.URL.Path
	if prefix := path.Clean(c.Request.Header.Get("X-Forwarded-Prefix")); prefix != "." {
		prefix = regSafePrefix.ReplaceAllString(prefix, "")
		prefix = regRemoveRepeatedChar.ReplaceAllString(prefix, "/")

		p = prefix + "/" + req.URL.Path
	}
	req.URL.Path = p + "/"
	if length := len(p); length > 1 && p[length-1] == '/' {
		req.URL.Path = p[:length-1]
	}
	redirectRequest(c)
}

trailing slash๊ฐ€ ๋ถ™์–ด์žˆ๋Š” URL์˜ ๊ฒฝ์šฐ redirect ์‹œ์ผœ์ฃผ๋Š”๋ฐ X-Forwarded-Prefix ํ—ค๋”๊ฐ€์žˆ์œผ๋ฉด ํ•ด๋‹น ํ—ค๋”์˜ value๋ฅผ URL path์— ๋ถ™์—ฌ์„œ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ ์‹œ์ผœ์ค€๋‹ค.

ํ•ด๋‹น ๊ธฐ๋Šฅ์„ ํ†ตํ•ด url์— ์ง์ ‘ /flag ๋ฌธ์ž์—ด์„ ์ž…๋ ฅํ•˜์ง€ ์•Š๊ณ ๋„ ์š”์ฒญ์„ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๋‹ค.

redirectTrailingSlash() ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๊ธฐ ์œ„ํ•ด์„œ url์— // ๊ฐ’์„ ๋ถ™์—ฌ์„œ X-Forwarded-Prefix ํ—ค๋”๋ฅผ ์„ค์ •ํ•˜์—ฌ ์š”์ฒญ์„ ํ•œ๋‹ค.

์•„๋ž˜ ์ฒ˜๋Ÿผ ๊ฐ’์„ ์ž…๋ ฅํ•˜์—ฌ ์š”์ฒญํ•˜๋ฉด flag ๊ฐ’์„ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.

'๐Ÿ›ก๏ธCTF > LineCTF' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

LineCTF(2023) - Baby Simple GoCurl  (0) 2023.08.13
LineCTF 2022 - memo drive  (0) 2022.04.13
LineCTF 2022 - gotm  (0) 2022.03.29