๊ธ€ ๋ชฉ๋ก์œผ๋กœ

๋ฐฑ์—”๋“œ์—์„œ ํด๋ผ์ด์–ธํŠธ์˜ IP๋ฅผ ๋กœ๊น…ํ•˜๋Š” ๋ฐฉ๋ฒ•

2023. 02. 24.

โš ๏ธ ๋’ค๋กœ๋Š” ์žฌ๋ฏธ์žˆ๊ธด ํ•˜๋‚˜ ์ •๋ฆฌ๋˜์–ด ์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. tl;dr โš ๏ธ๊ฒฐ๋ก 

์•„๋งˆ๋„ ์—ฌ๋Ÿฌ๋ถ„๋“ค์€ ์ง์ ‘ ๋งŒ๋“  ๋ฐฑ์—”๋“œ๊ฐ€ ํ•˜๋‚˜ ์ฏค์€ ์žˆ์„๊ฑฐ๋‹ค.
๋‚˜์˜ ๊ฒฝ์šฐ์—๋Š” api.tmpf.me ์ด ์žˆ์—ˆ๋Š”๋ฐ ํ•œ๊ฐ€์ง€ ์•„์‰ฌ์šด ์ ์ด ์žˆ์—ˆ๋‹ค.

๋ฐ”๋กœ user access logging.., ์ ‘์†ํ•˜๋Š” ์œ ์ €๋“ค์˜ ๊ธฐ๋ก์„ ๋‚จ๊ธฐ๋Š” ์ž‘์—…์ด ๋ถ€์กฑํ–ˆ๋‹ค.
์‚ฌ์‹ค ๊ผญ ํ•„์š”ํ•˜์ง€ ์•Š์„ ์ˆ˜๋„ ์žˆ๋Š”๋ฐ ๋ญ ํ•„์š”ํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฉด์„œ ๊ธ€์„ ์ฝ์–ด๋ณด์ž.

์šฐ์„  ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์ธํ”„๋ผ ๊ตฌ์„ฑ์ด ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค.
๊ทธ ์ค‘์—์„œ ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„๊ฐ€ ๋ฐ”๋กœ ํ†ต์‹ ํ•˜๋Š” ๊ฒฝ์šฐ

๋งค์šฐ ๊ฐ„๋‹จํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.
๋ฐ”๋กœ RemoteAddr ํ•„๋“œ๋ฅผ ํŒŒ์‹ฑํ•ด์„œ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

์•„๋ž˜ ์ด๋ฏธ์ง€์— ๋ณด์ด๋Š” ๊ฒƒ์ฒ˜๋Ÿผ 211.104.53.76 ์ด ๋ฐ”๋กœ ํด๋ผ์ด์–ธํŠธ์˜ IP์ด๋‹ค.
(๊ธ€์„ ์ž‘์„ฑํ•˜๊ณ  ์žˆ๋Š” ๋‚ด IP) ์Šคํƒ€๋ฒ…์Šค ์•„์ดํ”ผ๋‹ค.. ๊ดด๋กญํžˆ์ง€ ๋ง์ž.

๋‘๋ฒˆ์งธ ๊ฒฝ์šฐ๋‹ค.
์„œ๋ฒ„์™€ ์ค‘๊ฐ„์— ํ”„๋ก์‹œ ์„œ๋ฒ„๊ฐ€ ์กด์žฌํ•˜๋Š” ๊ฒฝ์šฐ์ด๋‹ค.
์ด ๊ฒฝ์šฐ์—๋Š” ์ƒˆ๋กญ๊ฒŒ ์•Œ์•„์•ผ๋˜๋Š” ๊ฒƒ์ด ์žˆ๋Š”๋ฐ X-Forwarded-For ํ—ค๋”์ด๋‹ค.

ํ•ด๋‹น ํ—ค๋”๋Š” ํ”„๋ก์‹œ๋ฅผ ์ง€๋‚ ๋•Œ ์œ ์‹ค๋˜๋Š” RemoteAddr๋ฅผ ํ”„๋ก์‹œ ๋’ค์— ์„œ๋น„์Šค๊นŒ์ง€ ์ „๋‹ฌํ•˜๊ธฐ ์œ„ํ•ด ๋งŒ๋“  ์‚ฌ์‹ค์ƒ์˜ ํ‘œ์ค€ ํ—ค๋”์ด๋‹ค.
๋‹ค์Œ ์Šคํฌ๋ฆฐ์ƒท์€ whoami ์„œ๋น„์Šค๊ฐ€ 2๊ฐœ์˜ ๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ ๋’ค์—์„œ ์‹คํ–‰๋˜๊ณ  ์žˆ๋Š” ๊ฒฝ์šฐ์ด๋‹ค.

์ž์„ธํžˆ๋ณด๋ฉด ์›๋ณธ ํด๋ผ์ด์–ธํŠธ IP๋ฅผ ๋„ฃ์„ ์ˆ˜ ์žˆ๋Š” ๋ถ€๋ถ„์ด 2๊ฐ€์ง€ ์กด์žฌํ•˜๋Š”๋ฐ ํด๋ผ์šฐ๋“œํ”Œ๋ ˆ์–ด์—์„œ ์ถ”๊ฐ€ํ•œ Cf-Connecting-Ip ํ•„๋“œ์™€ X-Forwarded-For ํ•„๋“œ์˜ ์ฒซ๋ฒˆ์งธ ๊ฐ’์ด๋‹ค.

์šฐ์„  Cf-Connecting-Ip ์˜ ๊ฒฝ์šฐ ํด๋ผ์šฐ๋“œํ”Œ๋ ˆ์–ด์—์„œ Proxied records๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ์—๋งŒ ํ•ด๋‹น๋˜๋ฏ€๋กœ ์ œ์™ธํ•˜๊ณ  ์•„๋ž˜์˜ X-Forwarded-For ํ—ค๋”๋ฅผ ์œ ์‹ฌํžˆ ์‚ดํŽด๋ณด์ž.

์ฒซ๋ฒˆ์งธ ๊ฐ’์€ ๋ถ„๋ช… client ip ์ด๋‹ค. ๊ทธ๋Ÿผ ๋‹ค์Œ ๊ฐ’์„ ๋ฌด์—‡์ผ๊นŒ?
๋ฐ”๋กœ ํด๋ผ์šฐ๋“œํ”Œ๋ ˆ์–ด ํ”„๋ก์‹œ ์„œ๋ฒ„์˜ ์•„์ดํ”ผ์ด๊ณ  ๊ทธ ๋‹ค์Œ ์œ„์—์„  client ip ์˜€๋˜ RemoteAddr์˜ ๊ฒฝ์šฐ ํด๋ผ์šฐ๋“œํ”Œ๋ ˆ์–ด ๋‹ค์Œ ๋ฆฌ๋ฒ„์Šคํ”„๋ก์‹œ์ธ traefik์˜ ์•„์ดํ”ผ์ด๋‹ค.

์œ„์˜ ์ด๋ฏธ์ง€์™€ ์•„์ดํ”ผ๋Š” ๋‹ค๋ฅด์ง€๋งŒ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ตฌ์กฐ๋ฅผ ์ง€๋‹Œ๋‹ค.

X-Forwarded-For ํ—ค๋”๋Š” ํ”„๋ก์‹œ๋ฅผ ํ•˜๋‚˜ ์ง€๋‚ ๋•Œ ๊ธฐ์กด์˜ RemoteAddr ๋ถ€๋ถ„์„ X-Forwarded-For ํ—ค๋”์— appendํ•˜๊ณ  ๋ณธ์ธ์ธ ํ”„๋ก์‹œ ์„œ๋ฒ„์˜ IP๊ฐ€ RemoteAddr์— ๋“ค์–ด๊ฐ€๋Š” ํ˜•์‹์ด๋‹ค.

๋”ฐ๋ผ์„œ โ€œ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐโ€์— ๋‹ค์Œ ๋กœ์ง์€ ์ •์ƒ์ ์œผ๋กœ ํด๋ผ์ด์–ธํŠธ์˜ IP๋ฅผ ๊ฐ€์ ธ์˜ค๋Š”๋ฐ ์„ฑ๊ณตํ•œ๋‹ค.

forward := r.Header.Get("X-Forwarded-For")
  var ip string
  var err error
  if forward != "" {
    // With proxy
    ip = strings.Split(forward, ",")[0]
  } else {
    // Without proxy
    ip, _, err = net.SplitHostPort(r.RemoteAddr)
    if err != nil {
      http.Error(w, "Error parsing remote address ["+r.RemoteAddr+"]", http.StatusInternalServerError)
      return
    }
  }

๊ทผ๋ฐ ์œ„์— ๋กœ์ง์—๋Š” ์‹ฌ๊ฐํ•œ ์˜ค๋ฅ˜๊ฐ€ ํ•œ๊ฐ€์ง€ ์กด์žฌํ•œ๋‹ค.

๋งŒ์•ฝ ์œ„์—์„œ ๋„ฃ์€ IP๋กœ ์ ‘๊ทผ์ œ์–ด๋ฅผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ด๋ณด์ž.

์„œ๋ฒ„๊ฐ€ ํ”„๋ก์‹œ๊ฐ€ ์žˆ๋Š” ์ƒํƒœ์ด๋“  ์—†๋Š” ์ƒํƒœ์ด๋“  r.Header๋ผ๋Š” ๊ฐ’์€ โ€œ์œ ์ €์—๊ฒŒ์„œโ€ ์ „์†ก๋˜๊ฒŒ ๋˜์–ด์žˆ๋‹ค.

๋˜ํ•œ X-Forwarded-For ํ—ค๋”๋Š” ๋ง ๊ทธ๋Œ€๋กœ HTTP ํ—ค๋”์ด๋‹ค.

ํ—ค๋”๋Š” ๊ฐ„๋‹จํ•˜๊ฒŒ ์กฐ์ž‘ ๊ฐ€๋Šฅํ•˜๋‹ค.

๋งŒ์•ฝ X-Forwarded-For ํ—ค๋”๋ฅผ ์ฒ˜์Œ ์ „์†กํ•  ๋•Œ โ€œ์ถ”๊ฐ€โ€ ํ•œ ์ƒํƒœ๋กœ ์ „์†กํ•˜๊ฒŒ ๋œ๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ˜•ํƒœ๋กœ ์ „์†ก๋œ๋‹ค.

X-Forwarded-For: <๋ณ€์กฐํ•˜์—ฌ ์ถ”๊ฐ€ํ•œ IP A>, <ํด๋ผ์ด์–ธํŠธ์˜ ์‹ค์ œ IP B>, <PROXY 1 C>

๋ฌผ๋ก  ๊ฒฝ์šฐ์— ๋”ฐ๋ผ์„œ proxy C๊ฐ€ ์—†์„ ์ˆ˜๋„ ์žˆ๊ณ , ํด๋ผ์ด์–ธํŠธ์˜ ์‹ค์ œ IP๊ฐ€ RemoteAddr์— ์žˆ์„ ์ˆ˜๋„ ์žˆ์ง€๋งŒ ์ƒ๊ด€ ์—†๋‹ค.

์œ„์— ๋…ผ๋ฆฌ๋Œ€๋กœ๋ฉด XFF ํ—ค๋”๊ฐ€ ์„ค์ •๋˜์–ด ์žˆ๋‹ค. โ†’ XFF ํ—ค๋” ์ฒซ๋ฒˆ์งธ ๊ฐ’์„ ์ฝ๋Š”๋‹ค. ์ด๊ธฐ ๋•Œ๋ฌธ์— ์œ ์ €๊ฐ€ ๋ณ€์กฐํ•˜์—ฌ ์ถ”๊ฐ€ํ•œ ๊ฐ’์ด ์‹ค์ œ IP๋กœ ์ธ์‹๋˜๊ฒŒ ๋œ๋‹ค.

์ด๊ฑด ๋ฌธ์ œ๋‹ค.
๋”ฐ๋ผ์„œ ์ด๊ฑธ ์ฒ˜๋ฆฌํ•  ๋ณ„๋„์˜ ๋กœ์ง์ด ํ•„์š”ํ•œ๋ฐ โ€ฆ..
๋Œ€๋ถ€๋ถ„์˜ ํ”„๋กœ๋•์…˜ ํ”„๋กœ๊ทธ๋žจ์—์„œ ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ฐพ์•„๋ƒˆ๋‹ค.

์ƒˆ๋กœ์šด ์„ค์ • ๊ฐ’ FORWORDED๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
์ด ์„ค์ •๊ฐ’์€ ์ˆซ์ž๋กœ ๊ฐ ์ˆซ์ž๋Š” ๋‹ค์Œ์„ ๋‚˜ํƒ€๋‚ธ๋‹ค.

์ˆซ์ž์˜๋ฏธ
0๋ฆฌ๋ฒ„์Šคํ”„๋ก์‹œ๊ฐ€ ์—†์œผ๋ฉฐ RemoteAddr๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
1์„œ๋น„์Šค ์•ž์— 1๊ฐœ์˜ ๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ๊ฐ€ ์žˆ์œผ๋ฉฐ XFF ํ—ค๋”์˜ -1 ๋ฒˆ์งธ ๊ฐ’์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
....
3์„œ๋น„์Šค ์•ž์— 3๊ฐœ์˜ ๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ๊ฐ€ ์žˆ์œผ๋ฉฐ XFF ํ—ค๋”์˜ -3 ๋ฒˆ์งธ ๊ฐ’์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
4์„œ๋น„์Šค ์•ž์— 4๊ฐœ์˜ ๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ๊ฐ€ ์žˆ์œผ๋ฉฐ XFF ํ—ค๋”์˜ -4 ๋ฒˆ์งธ ๊ฐ’์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
....

์ด๋ ‡๊ฒŒ ํ•œ๋‹ค๋ฉด ๋‹น์žฅ ์‚ฌ์šฉ์ž๊ฐ€ ํ—ค๋” ๊ฐ’์„ ๋ณ€์กฐํ•˜์—ฌ ๋ณด๋‚ธ ๊ฒฝ์šฐ์—๋„ ์„ค์ •๊ฐ’์„ ์ดˆ๊ณผํ•˜๋Š” ์š”์ฒญ์— ๋Œ€ํ•ด์„œ๋Š” ๊ทธ๋ƒฅ ๋ฌด์‹œ ํ•˜๊ธฐ์— ๋ณ„ ์˜์–‘์„ ๋ฐ›์ง€ ์•Š๊ฒŒ ๋œ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด ํด๋ผ์šฐ๋“œ ํ”Œ๋ ˆ์–ด์™€ traefik๋ฅผ ๊ฑฐ์ณ์„œ ์„œ๋น„์Šค๋กœ ํŠธ๋ ˆํ”ฝ์ด ๋„์ž‘ํ•˜๋Š” ๊ฒฝ์šฐ FORWORDED ํ™˜๊ฒฝ๋ณ€์ˆ˜๋ฅผ 2๋กœ ์„ค์ •ํ•˜๊ณ  XFF ํ—ค๋” ๋ฐฐ์—ด์—์„œ -2๋ฒˆ์งธ ๊ฐ’์„ ์‚ฌ์šฉํ•˜๊ฒŒ ๋œ๋‹ค.
๋”ฐ๋ผ์„œ ์œ ์ €๊ฐ€ ์ž„์˜๋กœ ๊ฐ’์„ ์ถ”๊ฐ€ํ•˜์—ฌ๋„ ๋ฌด์‹œ๋œ๋‹ค๋Š” ์˜๋ฏธ์ด๋‹ค.

๊ทผ๋ฐ ์ด ๋ฐฉ๋ฒ•์€ ์•ž์„œ ๋งํ–ˆ๋“ฏ ์™„๋ฒฝํ•˜์ง€ ์•Š๋‹ค.
์™œ๋ƒํ•˜๋ฉด ๋ญ”๊ฐ€ ์„ค์ •๊ฐ’์ด ์ถ”๊ฐ€๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ชจ๋“  ํ™˜๊ฒฝ์—์„œ ์ ์‘ํ•˜์—ฌ ์„œ๋น„์Šคํ•˜๋Š” ๊ฒƒ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.


โš ๏ธ ๋’ค๋กœ๋Š” ์žฌ๋ฏธ์žˆ๊ธด ํ•˜๋‚˜ ์ •๋ฆฌ๋˜์–ด ์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. tl;dr โš ๏ธ

  • FORWORDED ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋Š” ์ƒ๊ฐ๋ณด๋‹ค ๋‚˜์˜์ง€ ์•Š๋Š” ๋ฐฉ์‹์ด๋‹ค. ์ถ”์ฒœํ•œ๋‹ค.
  • XFF ํ—ค๋”์˜ ์•„์ดํ”ผ ๋Œ€์—ญ์„ ์‹ ๋ขฐํ•˜๋Š” ํ”„๋ก์‹œ์˜ ๋Œ€์—ญ์œผ๋กœ ์„ค์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ์žˆ๋‹ค.
  • XFF ํ—ค๋”๋Š” ์กฐ์ž‘์ด ๊ฐ€๋Šฅํ•˜๋‹ˆ ๋ฏฟ์ง€ ๋ง์ž.

์–ด์ฉŒ๋‹ค ๋ณด๋‹ˆ burp suite๋ฅผ ์ด์šฉํ•ด์„œ ๋‚ด๊ฐ€ ์ œ์ž‘ํ•œ ์‚ฌ์ดํŠธ๋ฅผ ๊ณต๊ฒฉํ•˜๊ณ  ์ฝ”๋“œ๋ฅผ ๋‹ค์‹œ ๊ฒ€์ฆํ•˜๊ณ  ์ž์นซ ๊ทธ๋ƒฅ ๋„˜์–ด๊ฐˆ ์ˆ˜ ์žˆ๋Š” ๋ถ€๋ถ„์„ ์ ๊ฒ€ํ•˜๊ธฐ๊นŒ์ง€ ํ–ˆ๋‹ค.

์ด ๋ฌธ์ œ๋Š” ์–ด๋–ป๊ฒŒ ์•Œ๋ ค์ ธ ์žˆ์„๊นŒ?

๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ž๋ฃŒ๋“ค์„ ์ฐพ์„ ์ˆ˜ ์žˆ์—ˆ๋Š”๋ฐ ๊ทธ ์ค‘ ํฅ๋ฏธ๋กœ์šด ๋ช‡๊ฐ€์ง€ ์ž๋ฃŒ๋‹ค.

Untitled

https://blog.ircmaxell.com/2012/11/anatomy-of-attack-how-i-hacked.html

ํ•œ๋งˆ๋””๋กœ ๊ธ€์“ด์ด๊ฐ€ SSH ํ„ฐ๋„๋กœ ์ธํ•ด ์šฐ๋ฐœ์ ์œผ๋กœ XFF ํ—ค๋”์— 127.0.0.1 ์ฃผ์†Œ๊ฐ€ ๋“ค์–ด๊ฐ€๊ฒŒ ๋˜์—ˆ๋Š”๋ฐ ์ด๋ฅผ ์Šคํƒ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ๊ฐ€ โ€œ๊ด€๋ฆฌ์žโ€์˜ ์ ‘๊ทผ์œผ๋กœ ์ธ์‹ํ•ด ๊ถŒํ•œ ์ƒ์Šน์ด ์ผ์–ด๋‚ฌ๋‹ค๋Š” ์ด์•ผ๊ธฐ์ด๋‹ค.

๋˜ ์ด๋Ÿฐ ์ž๋ฃŒ๋„ ์ฐพ์„ ์ˆ˜ ์žˆ์—ˆ๋‹ค.

https://www.acunetix.com/vulnerabilities/web/x-forwarded-for-http-header-security-bypass/

XFF HTTP header security bypass, ๋ถ„๋ฅ˜๋ฒˆํ˜ธ CWE-289

CTFd ์ฒ˜๋Ÿผ ํ”„๋ก์‹œ ํ™‰์„ ์ œํ•œํ•˜์—ฌ ๋ฐฉ์ง€ํ•˜๋Š” ๋กœ์ง์ด ์žˆ๋Š” ๊ฒฝ์šฐ๋„ ์žˆ์—ˆ์ง€๋งŒ ๋ฌด๋ ค ์Šคํƒ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ์—์„œ ๊ถŒํ•œ ์ƒ์Šน์ด ์ผ์–ด๋‚˜๊ธฐ๋„ ํ•˜๋Š” ๋“ฑ ์ƒ๋‹นํžˆ ์žฌ๋ฐŒ๋Š” ๊ธฐ๋ฒ•์ด์˜€๋‹ค.

์žฌ๋ฏธ์žˆ์œผ๋‹ˆ ์กฐ๊ธˆ ๋” ๋‚˜์•„๊ฐ€ ๋‹ค๋ฅธ ์„œ๋น„์Šค๋“ค์—์„œ IP ๋กœ๊น… ๋ฐฉ๋ฒ•์„ ๊ณต๊ฒฉํ•˜๊ณ  ๋ถ„์„ํ•ด๋ณด์ž.

๋จผ์ € ifconfig.me ์ด๋‹ค.

ํ‰์†Œ์— ์ฆ๊ฒจ์“ฐ๋Š” ์„œ๋น„์Šค์ด๊ธฐ์— ์„ ํƒํ•ด๋ณด์•˜๋‹ค.

Untitled

๋‹ค์Œ๊ณผ ๊ฐ™์ด proxy option๋ฅผ ์„ ํƒํ•˜์—ฌ intercept๋ฅผ ์ง„ํ–‰ํ–ˆ๋‹ค.

Untitled

์•„๋ฌด๋Ÿฐ ๋ณ€์กฐ๋ฅผ ํ•˜์ง€ ์•Š์•˜์„ ๋–„ ์‘๋‹ต์ด๋‹ค.

Untitled

์š”์ฒญ ํ—ค๋”์— ๊ฐ•์ œ๋กœ ๊ฐ’์„ ๋„ฃ์–ด๋ณด์•˜๋‹ค.

Untitled

๋ถ„๋ช… ๋” ๊ฐ’์€ ์กฐ์ž‘๋˜์—ˆ๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด ifconfig.me๋Š” ์–ด๋–ค ๋ฐฉ์‹์œผ๋กœ client ip๋ฅผ ํ™•์ธํ• ๊นŒ?

github์—์„œ repo๋ฅผ ์ฐพ์•˜๋‹ค.

GitHub - pmarques/ifconfig.me: Simple HTTP application for demos and tests

์ธ์ค„ ์•Œ์•˜์œผ๋‚˜ ๋‹ค๋ฅธ ์„œ๋น„์Šค์˜€๋‹ค๋Š” ์ด์•ผ๊ธฐ..

์‹ค์ œ๋กœ ๋กœ์ปฌ์—์„œ ์‹คํ–‰์‹œํ‚ค๊ณ  โ€œ์•„ ์ด๊ฑด ์•„๋‹ˆ๋‹ค ์‹ถ์—ˆ๋‹ค.โ€

์‹ฌ์ง€์–ด ์—ฌ๊ธฐ์—์„  ํ•ด๋‹น ์šฐํšŒ์— ๋Œ€ํ•œ ๋Œ€๋น„๋ฅผ ํ•˜์ง€ ์•Š์•˜์œผ๋ฉฐ ์‚ฌ์‹ค ํ•  ํ•„์š”๊ฐ€ ์žˆ์ง€๋Š”.. ๊ทธ๋ƒฅ ๋ณด์—ฌ์ฃผ๋Š”๊ฑฐ๋‹ˆ๊นŒ ~

์‚ฌ์‹ค ์ด์™ธ์—๋„ ๋‹ค์–‘ํ•œ ๋ž˜ํฌ๊ฐ€ โ€œA IP echo server inspired byย http://ifconfig.meโ€ ๋ผ๋Š” ํƒ€์ดํ‹€ ํ•˜์— ์ œ์ž‘๋˜์–ด ์žˆ์—ˆ๋Š”๋ฐ ๋ช‡๊ฐ€์ง€ ๋ž˜ํฌ์˜ IP ํš๋“ ๋กœ์ง์„ ๊ฐ€์ ธ์™€๋ณด์•˜๋‹ค.

ip := this.GetString("ip", this.Ctx.Input.IP())

์—ฌ๊ธฐ์„œ this ๋ณ€์ˆ˜๋Š” beego ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ๋ผ์šฐํ„ฐ ํŒŒ๋ผ๋ฏธํ„ฐ์˜€๋‹ค.

์žฌ๋ฐŒ๋Š” ๊ฑธ ์ฐพ์•˜๋‹ค.

Security issue: Trusted Reverse Proxy and X-Forwarded-* headers ยท Issue #4589 ยท beego/beego

์ง€๊ธˆ ๋‚ด๊ฐ€ ํ•ด๊ฒฐํ•˜๊ณ ์ž ํ•˜๋Š” ๋ฌธ์ œ์˜ ๋Œ€ํ•œ ์ด์Šˆ์ธ๋ฐ.. ๊ทธ๋ƒฅ ๋‹ซํ˜”๋‹ค.

์ด๋ ‡๋‹ค๋Š”๊ฑด ๋Œ€๋ถ€๋ถ„์˜ beego๋กœ ์ž‘์„ฑ๋œ golang ๋ฐฑ์—”๋“œ, ๊ทธ ์ค‘ ์ด์ „์— ์–ธ๊ธ‰ํ•œ ์Šคํƒ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ๊ฐ™์€ ๋กœ์ง์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ๊ฐ„๋‹จํ•˜๊ฒŒ ํ•ดํ‚นํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ด์•ผ๊ธฐ๊ฐ€ ๋œ๋‹ค.

// IP returns request client ip.
// if in proxy, return first proxy id.
// if error, return RemoteAddr.
func (input *BeegoInput) IP() string {
	return (*context.BeegoInput)(input).IP()
}

ํ˜„์ œ beego์˜ develop ๋ธŒ๋žœ์น˜์˜ ์ฝ”๋“œ ๊ตฌํ˜„ ๋ฐ ์ฃผ์„์„ ๋ฐœ์ต€ํ•ด ์™”๋‹ค.

์Œ.. 2๋ฒˆ์— ์ฃผ์„์˜ ๋œป์„ ์ง์ž‘ํ•ด๋ณด๋ฉด โ€œ์šฐ๋ฆฐ ๊ทธ๋ƒฅ ๋ฌด์ง€์„ฑ์œผ๋กœ XXF ๋” ์ฒซ ๋ฒˆ์งธ ๊ฐ’ ๋บด์˜ฌ๊บผ์ž„ ใ……ใ„ฑ ใ…Žโ€

Untitled

๋‹ค์Œ์€ ์ € (*context.BeegoInput)(input).IP() ๊ตฌํ˜„์ฒด๋‹ค.

https://github.com/beego/beego/blob/031c0fc8af57ea1a18e21fd5a7a8e6f23c26bbea/server/web/context/input.go ์ค‘ ์ผ๋ถ€์ฝ”๋“œ์ด๋‹ค.

// IP returns request client ip.
// if in proxy, return first proxy id.
// if error, return RemoteAddr.
func (input *BeegoInput) IP() string {
	ips := input.Proxy()
	if len(ips) > 0 && ips[0] != "" {
		rip, _, err := net.SplitHostPort(ips[0])
		if err != nil {
			rip = ips[0]
		}
		return rip
	}
	if ip, _, err := net.SplitHostPort(input.Context.Request.RemoteAddr); err == nil {
		return ip
	}
	return input.Context.Request.RemoteAddr
}

์ด๊ฑฐ ๋ญ”๊ฐ€ ๊ตฌํ˜„์ด ์ด์ƒํ•˜๋‹คโ€ฆ

๋งˆ์ง€๋ง‰ ํฌ๋ง์œผ๋กœ input.Proxy() ๊ตฌํ˜„์„ ๋ณด์ž

// Proxy returns proxy client ips slice.
func (input *BeegoInput) Proxy() []string {
	if ips := input.Header("X-Forwarded-For"); ips != "" {
		return strings.Split(ips, ",")
	}
	return []string{}
}

๊นŒ์•ฝโ€ฆ

์ด๊ฒŒ ๋งž๋‚˜ ์‹ถ์€ ๊ตฌํ˜„์ด๋‹ค.

์ผ๋‹จ ์—ฌ๊ธฐ๊นŒ์ง€ ๋ดค์œผ๋ฉด ์กฐ์šฉํžˆ ๋ฐฉ๊ธˆ ์ด์Šˆ๋ฅผ ์—ด ์ˆ˜ ๋„ ์žˆ์ง€๋งŒโ€ฆ ์ผ๋‹จ์€ beego ๋‚ด๋ถ€์—์„œ IP() ๊ตฌํ˜„์„ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•˜๋Š”์ง€ ๊ฒ€์ƒ‰ํ•ด๋ณด์ž.

server/web/error.go

"AppError":      fmt.Sprintf("%s:%v", BConfig.AppName, err),
"RequestMethod": ctx.Input.Method(),
"RequestURL":    ctx.Input.URI(),
"RemoteAddr":    ctx.Input.IP(),
"Stack":         stack,
"BeegoVersion":  beego.VERSION,
"GoVersion":     runtime.Version(),

์ด๊ฑด ์ผ๋‹จ RemoteAddr๊ฐ€ ์•„๋‹ˆ๋‹ค. ์ด๋Ÿฌ๋ฉด ์—๋Ÿฌ๋กœ๊ทธ๋ฅผ ์†์ผ ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

server/web/server.go

record := &logs.AccessLogRecord{
RemoteAddr:     ctx.Input.IP(),
RequestTime:    requestTime,
RequestMethod:  r.Method,
Request:        fmt.Sprintf("%s %s %s", r.Method, r.RequestURI, r.Proto),

์—ฌ๊ธฐ์„œ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ด๋‹ค.

server/web/router.go

if p.cfg.RunMode == DEV && !p.cfg.Log.AccessLogs {
		match := map[bool]string{true: "match", false: "nomatch"}
		devInfo := fmt.Sprintf("|%15s|%s %3d %s|%13s|%8s|%s %-7s %s %-3s",
			ctx.Input.IP(),
			logs.ColorByStatus(statusCode), statusCode, logs.ResetColor(),
			timeDur.String(),
			match[findRouter],

์—ฌ๊ธฐ๋Š” dev ๋ชจ๋“œ์—์„œ ์—‘์„ธ์Šค๋กœ๊น…์„ ๋ฌธ์ œ์žˆ๋Š” ๊ตฌํ˜„์ฒด๋กœ ํ•˜๊ฒŒ ๋œ๋‹ค.

๋ญ beego์—์„œ ์—‘์„ธ์Šค๋กœ๊น…์„ ๋ฏฟ์ง€ ์•Š๋Š”๊ฑธ๋กœโ€ฆ

๋‹ค์Œ์€ fiber, echo๋ฅผ ์•Œ์•„๋ณด๊ฒ ๋‹ค.

๐Ÿš€ Trusted Reverse Proxy and get c.Hostname() value from X-Forwarded-Host and etc ยท Issue #1300 ยท gofiber/fiber

๋ˆ„๊ฐ€ TrustedProxy ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ–ˆ๋‹ค

IP Address | Echo - High performance, minimalist Go web framework

๊ฐœ๋ฐœ์ž๊ฐ€ ์•Œ์ž˜๋”ฑ ํ•ด๋ฒ„๋ ธ๋”ฐ.

๊ฒฐ๋ก 

์ด๊ฒŒ ๋‚ด ๊ฒฐ๋ก ์ด๋‹ค.

๋ฒ”์šฉ์ ์œผ๋กœ ๋ฐฐํฌํ•  ๋ฐฑ์—”๋“œ์—์„œ ์ฒ˜์Œ ๊ฐœ๋ฐœ์ž๊ฐ€ ๋ณ„๋„์˜ ์„ค์ • ํŒŒ์ผ ์—†์ด โ€œ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š”โ€ ํด๋ผ์ด์–ธํŠธ์˜ IP๋ฅผ ์–ป๋Š”๋‹ค๋Š”๊ฑด ํž˜๋“ค๋‹ค.

ํ•˜์ง€๋งŒ ๋ช‡๊ฐ€์ง€ ์„ ํƒ ๊ฐ€๋Šฅํ•œ ์˜ต์…˜์ด ์กด์žฌํ•˜๋Š”๋ฐ

  1. RemoteAddr ๋งŒ ๋ฏฟ๊ณ  ๋ฐฑ์—”๋“œ๋ฅผ ํ”„๋ก์‹œ ์—†์ด ๋ฐฐํฌํ•˜๋Š” ๊ฒฝ์šฐ
  2. XFF ํ—ค๋” ์ฒซ๋ฒˆ์งธ ๊ฐ’์„ ์‚ฌ์šฉํ•˜๋‚˜ ์‹ ๋ขฐํ•  ์ˆ˜ ์—†๋Š” ์ƒํƒœ๋กœ ์‚ฌ์šฉ
  3. ์„œ๋ฒ„๊ฐ€ ๋ฐฐํฌ๋  ํ™˜๊ฒฝ์˜ ํ”„๋ก์‹œ ๊ฐฏ์ˆ˜๋ฅผ ํ™˜๊ฒฝ๋ณ€์ˆ˜๋กœ ์„ค์ •ํ•˜์—ฌ ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ํ”„๋ก์‹œ ๊ฐฏ์ˆ˜๋ฅผ ์„ค์ • ํ•ด๋‹น ๊ฐฏ์ˆ˜ ๋งŒํผ๋งŒ XFF ํ—ค๋”๋ฅผ ์ฝ๋„๋ก ์„ค์ •
  4. ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ํ”„๋ก์‹œ์˜ IP ๋Œ€์—ญ๋Œ€๋ฅผ ์„ค์ •ํ•ด๋‘๊ณ  ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ์‹ ๋ขฐํ•  ์ˆ˜ ์—†๋Š” XFFํ—ค๋”์˜ IP๋ฅผ ์‚ฌ์šฉ

์—ฌ๊ธฐ์„œ 3๋ฒˆ๊ณผ 4๋ฒˆ์€ ์„ค์ • ํŒŒ์ผ์ด ํ•„์š”ํ•˜๋‚˜ ์„ค์ •๋งŒ ์ž˜ํ•œ๋‹ค๋ฉด ์–ธ์ œ๋‚˜ ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” IP๋ฅผ ๊ฐ€์ง€๊ฒŒ ๋˜๊ณ ,

1๋ฒˆ์€ ์‹ ๋ขฐ๋Š” ๊ฐ€๋Šฅํ•˜๋‚˜ ํ™˜๊ฒฝ์— ๋”ฐ๋ผ ํด๋ผ์ด์–ธํŠธ IP๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ๊ฐ€ (ํ”„๋ก์‹œ๊ฐ€ ์กด์žฌํ•˜๋Š” ๊ฒฝ์šฐ) ์ƒ๊ธธ ์ˆ˜ ์žˆ๋‹ค.

2๋ฒˆ์€ ๋ฒ”์šฉ์„ฑ์€ ๋†’์œผ๋‚˜ ์†์‰ฝ๊ฒŒ ํ•ดํ‚นํ•  ์ˆ˜ ์žˆ๋‹ค.

๋˜ ์ด์™ธ์— ํ•ด๊ฒฐ๋ฐฉ๋ฒ•๋„ ์กด์žฌํ•œ๋‹ค.

ํด๋ผ์šฐ๋“œํ”Œ๋ ˆ์–ด๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋Š” ๊ฐ€์ •ํ•˜์— Cf-Conโ€ฆ ํ—ค๋”๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ์„œ๋ฒ„ ์•ž๋‹จ์— ์žˆ๋Š” ํ”„๋ก์‹œ์—์„œ X-Real-IP ๊ฐ’์„ ์„ค์ •ํ•˜๊ณ  ๊ทธ ๊ฑธ ์‹ ๋ขฐํ•˜๋Š” ๋ฐฉ๋ฒ•๋“ฑ ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค.

์–ธ์ œ๋‚˜ ์„ ํƒ์ด ํ•„์š”ํ•˜๊ณ  ๋˜ ๋ฐฑ์—”๋“œ ํ”„๋กœ๊ทธ๋žจ์„ ๊ฐœ๋ฐœํ•  ๋•Œ๋‚˜ ์‚ฌ์šฉํ•˜๊ฒŒ ๋ ๋•Œ ํ•ด๋‹น ํ”„๋กœ๊ทธ๋žจ์ด ์–ด๋– ํ—ฅ ๊ฐœ๋ฐœ๋˜์—ˆ๋Š”์ง€ ๋ถ„์„ํ•˜๊ณ  ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ์‹์ธ์ง€ ๊ฒ€์ฆํ•˜์—ฌ์•ผ๊ฒ ๋‹ค.

๊ทธ๋ž˜์„œ ์ €๋Š” ์–ด๋–ป๊ฒŒ ๊ฐœ๋ฐœํ• ๊ฑฐ๋ƒ๋ฉด์š”โ€ฆ

  1. XFF ํ—ค๋”๋ฅผ ์‚ฌ์šฉ
  2. ๋ฌด์กฐ๊ฑด ์‹ ๋ขฐ๊ฐ€ ์•„๋‹Œ ๋กœ์ปฌ์ฃผ์†Œ์™€ ํด๋ผ์šฐ๋“œํ”Œ๋ ˆ์–ด์˜ IP๋ฅผ ์‹ ๋ขฐ
  3. ์ถ”๊ฐ€ ํ”„๋ก์‹œ ์˜ต์…˜์œผ๋กœ RemoteAddr๋ฅผ ์‚ฌ์šฉ
  4. ์ถ”๊ฐ€ ์˜ต์…˜ ์‹ ๋ขฐ ๊ฐ€๋Šฅํ•œ ํ”„๋ก์‹œ ์ฃผ์†Œ๋ฅผ ์ถ”๊ฐ€ ํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค์ •
  5. ์ถ”๊ฐ€ ์˜ต์…˜ ํ”„๋ก์‹œ ํ™‰ ์ˆ˜๋กœ๋งŒ ์„ค์ •ํ•˜์—ฌ ์‹ ๋ขฐ

๊ทผ๋ฐ ๋์€ ์•„๋‹ˆ๋‹ค.

๊ทธ๋ž˜๋„ WAF๋‚˜ ์•Œ ์ˆ˜ ์—†๋Š” ์›์ธ์œผ๋กœ ์ธํ•ด XFF ๋”๊ฐ€ ๊ฐ•์ œ ๋ณ€๊ฒฝ๋˜์–ด ๊ณ ์ •๋˜๊ฑฐ๋‚˜ ํ•  ์ˆ˜๋„ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ผ€๋ฐ”์ผ€๋‹ค..

๋ญ ๋‚ด๊ฐ€ ๊ฐœ๋ฐœํ•  ๋–„๋Š” ์—ด์‹ฌํžˆ ์ฐธ๊ณ ํ•ด์•ผ


Q. ์ „์— ํ•œ๋ฒˆ ๊ด€์ œ ์ธํ”„๋ผ ์ ๊ฒ€ ๋‹น์‹œ XFF ํ—ค๋”๊ฐ€ ์‹ค์ข…๋˜๋Š” ์ด์ƒํ•œ ์ผ์ด ์žˆ์—ˆ์—ˆ์ฃ ?

๊ทธ๋•Œ ์›์ธ์ด ๋ญ์˜€๋‚˜์š”?

A. ๋ฐ”๋ณด๊ฐ™์ด ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜์„ ํ•œ๋‹ต์‹œ๊ณ  ์„ค์ •ํ•ด๋‘” swarm์—์„œ overlay ๋„คํŠธ์›Œํฌ ์„ค์ • ๋•๋ถ„์— ๋„คํŠธ์›Œํฌ๊ฐ€ ์ด์ƒํ•ด์ง„ ํƒ“์ด์˜€์Šต๋‹ˆ๋‹ค.

ํ™•์‹คํžˆ ์ˆœ๋ จ๋œ ๊ธฐ์ˆ ์ž๊ฐ€ ์—†์œผ๋ฉด ๊ธฐ์ˆ ๋„์ž…์„ ๋ฏธ๋ค„์•ผ๋œ๋‹ค๊ณ  ๋А๋‚€ ๋Œ€๋ชฉ์ด์˜€์ฃ .

Q. ipLogger ํ”„๋กœ์ ํŠธ๋ฅผ ์ตœ์ข…์ ์œผ๋กœ ์ง„ํ–‰ํ•˜์…จ๋˜๋ฐ, ์–ด๋–ค๊ฑธ ๋А๋ผ์…จ๋‚˜์š”?

A. ์ƒ๊ฐ๋ณด๋‹ค ๋งŽ์€ ํ”„๋กœ์ ํŠธ์—์„œ XFF ํ—ค๋”๋ฅผ ๋ฏฟ๊ณ  ์žˆ๋Š” ๊ฒƒ ๊ฐ™๊ณ  ๊ทธ ๊ตฌํ˜„์ด ๋ถˆ์•ˆ์ •ํ•œ ๊ฒฝ์šฐ๋„ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

๋ฌผ๋ก  ipLogger ํ”„๋กœ์ ํŠธ๊ฐ€ ์™„๋ฒฝํ•˜๋‹ค๋Š” ๊ฒƒ์€ ์•„๋‹ˆ์ง€๋งŒ ์ œ์ž‘ํ•˜๋ฉฐ ๋กœ๊น… ๊ธฐ์ˆ ๊ณผ ํด๋ผ์ด์–ธํŠธ์˜ ์ง„์งœ IP๋ฅผ ์–ป๊ฒŒ๋˜๋Š” ๊ธฐ์ˆ ๋ฉด์—์„œ๋Š” ํ™•์‹คํžˆ ๊ณต๋ถ€๊ฐ€ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์ž‘์„ฑ์ผ:2023. 02. 24.
โ€ข
์ˆ˜์ •์ผ:2025. 05. 12.

์ด์ „๊ธ€ / ๋‹ค์Œ๊ธ€

โ† git default branch ์„ค์ • ๋ณ€๊ฒฝWSL Arch distro ์„ค์ • โ†’
Purple Pikmin carrying fruit

written by minpeter โ€ข source code

Toggle theme