What is ๐ŸŽญ XSRF(์‚ฌ์ดํŠธ ๊ฐ„ ์š”์ฒญ ์œ„์กฐ), ๐Ÿ’‰ XSS

shleecloudยท2021๋…„ 10์›” 24์ผ
0

Security

๋ชฉ๋ก ๋ณด๊ธฐ
5/6

๐ŸŽญ XSRF or CSRF (์‚ฌ์ดํŠธ ๊ฐ„ ์š”์ฒญ ์œ„์กฐ)

๊ทธ ์œ ๋ช…ํ•œ ๋ฐ”์ด๋Ÿฌ์Šค ๋ฉ”์ผ, ํ•ดํ‚น ๋ฉ”์ผ, ์‚ฌ์ดํŠธ์˜ ๋Œ€ํ‘œ์ ์ธ ๊ณต๊ฒฉ ๋ฐฉ๋ฒ•์ด๋‹ค. ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ธ์ฆ๋œ ์ƒํƒœ์ผ ๋•Œ ์–ด๋– ํ•œ ๋ฐฉ์‹์ด๋“  ๊ณต๊ฒฉ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๊ฒŒ ๋งŒ๋“ค์–ด์„œ ๋ฏผ๊ฐํ•œ ์ •๋ณด๋ฅผ ์กฐ์ž‘ํ•˜๊ฒŒ ๋งŒ๋“ ๋‹ค.

์‚ฌ์ดํŠธ ๊ฐ„ ์š”์ฒญ ์œ„์กฐ(๋˜๋Š” ํฌ๋กœ์Šค ์‚ฌ์ดํŠธ ์š”์ฒญ ์œ„์กฐ, ์˜์–ด: Cross-site request forgery, CSRF, XSRF)๋Š” ์›น์‚ฌ์ดํŠธ ์ทจ์•ฝ์  ๊ณต๊ฒฉ์˜ ํ•˜๋‚˜๋กœ, ์‚ฌ์šฉ์ž๊ฐ€ ์ž์‹ ์˜ ์˜์ง€์™€๋Š” ๋ฌด๊ด€ํ•˜๊ฒŒ ๊ณต๊ฒฉ์ž๊ฐ€ ์˜๋„ํ•œ ํ–‰์œ„(์ˆ˜์ •, ์‚ญ์ œ, ๋“ฑ๋ก ๋“ฑ)๋ฅผ ํŠน์ • ์›น์‚ฌ์ดํŠธ์— ์š”์ฒญํ•˜๊ฒŒ ํ•˜๋Š” ๊ณต๊ฒฉ์„ ๋งํ•œ๋‹ค.์œ ๋ช… ๊ฒฝ๋งค ์‚ฌ์ดํŠธ์ธ ์˜ฅ์…˜์—์„œ ๋ฐœ์ƒํ•œ ๊ฐœ์ธ์ •๋ณด ์œ ์ถœ ์‚ฌ๊ฑด์—์„œ ์‚ฌ์šฉ๋œ ๊ณต๊ฒฉ ๋ฐฉ์‹ ์ค‘ ํ•˜๋‚˜๋‹ค.

๋งŒ์ผ, A๋ผ๋Š” ์‚ฌ์ดํŠธ์˜ ์‚ฌ์šฉ์ž ๊ฐœ์ธ ๋น„๋ฐ€๋ฒˆํ˜ธ ๋ณ€๊ฒฝ์„ ํ•˜๋Š” ์ฃผ์†Œ ํŒจํ„ด์ด abc.com/user.do?cmd=user_passwd_change&user=admin&newPwd=1234 ๋ผ๊ณ  ํ•œ๋‹ค๋ฉด ์ด๋Ÿฌํ•œ ๋งํฌ๋ฅผ ์‚ฌ์šฉ์ž์˜ ๋ฉ”์ผ๋กœ ๋ณด๋‚ด๋Š”๋ฐ, ๋งŒ์•ฝ ์‚ฌ์šฉ์ž๊ฐ€ ๋ฉ”์ผ์„ ์ฝ๊ฒŒ ๋˜๋ฉด ํ•ด๋‹น ์‚ฌ์šฉ์ž์˜ ํŒจ์Šค์›Œ๋“œ๊ฐ€ 1234๋กœ ์ดˆ๊ธฐํ™”๋œ๋‹ค. ์ด๋ฅผ ๊ด€๋ฆฌ์ž์—๊ฒŒ ๋ณด๋‚ด์„œ ์ผ๋ฐ˜ ๊ณ„์ •์„ ๊ด€๋ฆฌ์ž ๊ณ„์ •์œผ๋กœ ๋ฐ”๊พธ๋„๋ก ํ•˜๊ฑฐ๋‚˜, ๊ด€๋ฆฌ์ž ๊ณ„์ • ํŒจ์Šค์›Œ๋“œ๋ฅผ ๋ฐ”๊พธ๋Š”๋ฐ ์ด์šฉํ•œ๋‹ค๋ฉด ํ•ด๋‹น ์‚ฌ์ดํŠธ์˜ ๋ชจ๋“  ์ •๋ณด๊ฐ€ ํ•ดํ‚น๋‹นํ•˜๋Š” ๋ฐ๋Š” ์˜ค๋žœ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฌ์ง€ ์•Š๋Š”๋‹ค.

๐Ÿ˜ˆ XSRF ๊ณต๊ฒฉ ์ „๋žต

<img src="http://auction.com/changeUserAcoount?id=admin&password=admin" width="0" height="0">
  • ์˜ฅ์…˜ ๊ด€๋ฆฌ์ž ์ค‘ ํ•œ๋ช…์ด ๊ด€๋ฆฌ ๊ถŒํ•œ์„ ๊ฐ€์ง€๊ณ  ํšŒ์‚ฌ๋‚ด์—์„œ ์ž‘์—…์„ ํ•˜๋˜ ์ค‘ ๋ฉ”์ผ์„ ์กฐํšŒํ•œ๋‹ค.
    (๋กœ๊ทธ์ธ์ด ์ด๋ฏธ ๋˜์–ด์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๋ฉด ๊ด€๋ฆฌ์ž๋กœ์„œ์˜ ์œ ํšจํ•œ ์ฟ ํ‚ค๋ฅผ ๊ฐ–๊ณ ์žˆ์Œ)
  • ํ•ด์ปค๋Š” ์œ„์™€ ๊ฐ™์ด ํƒœ๊ทธ๊ฐ€ ๋“ค์–ด๊ฐ„ ์ฝ”๋“œ๊ฐ€ ๋‹ด๊ธด ์ด๋ฉ”์ผ์„ ๋ณด๋‚ธ๋‹ค. ๊ด€๋ฆฌ์ž๋Š” ์ด๋ฏธ์ง€ ํฌ๊ธฐ๊ฐ€ 0์ด๋ฏ€๋กœ ์ „ํ˜€ ์•Œ์ง€ ๋ชปํ•œ๋‹ค.
  • ํ”ผํ•ด์ž๊ฐ€ ์ด๋ฉ”์ผ์„ ์—ด์–ด๋ณผ ๋•Œ, ์ด๋ฏธ์ง€ ํŒŒ์ผ์„ ๋ฐ›์•„์˜ค๊ธฐ ์œ„ํ•ด URL์ด ์—ด๋ฆฐ๋‹ค.
  • URL์ด ์—ด๋ฆฌ๋ฉด์„œ ๊ด€๋ฆฌ์ž์˜ ์„ธ์…˜์—์„œ ์•…์˜์ ์ธ ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์‹คํ–‰๋œ๋‹ค.
  • ํ•ด์ปค๊ฐ€ ์›ํ•˜๋Š” ๋Œ€๋กœ ๊ด€๋ฆฌ์ž์˜ ๊ณ„์ •์ด id์™€ pw ๋ชจ๋‘ admin์ธ ๊ณ„์ •์œผ๋กœ ๋ณ€๊ฒฝ๋œ๋‹ค.

๐Ÿ˜‡ XSRF ๋ฐฉ์–ด ์ „๋žต

client / withCredentials: true

The XMLHttpRequest.withCredentials property is a Boolean that indicates whether or not cross-site Access-Control requests should be made using credentials such as cookies, authorization headers or TLS client certificates. Setting withCredentials has no effect on same-site requests.

ํ—ค๋”์— ์ ์šฉํ•˜๋Š” ์˜ต์…˜์œผ๋กœ ๋ณด์•ˆ ํ†ต์‹  ์ค‘ ๋‹ค๋ฅธ ๋„๋ฉ”์ธ(Cross) ์‚ฌ์ด์˜ ๋ณด์•ˆ ์ธ์ฆ(์ฟ ํ‚ค, TLS ์ธ์ฆ)์„ ๋ณด๋‚ด๋Š” ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•œ๋‹ค.
์„œ๋ฒ„์˜ CORS ์˜ต์…˜ ์ค‘ origin ๋˜๋Š” Access-Control-Allow-Origin ์˜ต์…˜์ด ์•„๋ฌด๋‚˜ ํ—ˆ์šฉ * ์ผ ๊ฒฝ์šฐ ๋™์ž‘ํ•˜์ง€ ์•Š๋Š”๋‹ค.
๊ฐ™์€ ๋„๋ฉ”์ธ์ผ ๊ฒฝ์šฐ ์ œํ•œํ•˜์ง€ ์•Š๋Š”๋‹ค.

axios
  .post(
    'https://localhost:4000/users/login',
    {
      userId: this.state.username,
      password: this.state.password,
    },
    { 'Content-Type': 'application/json', withCredentials: true } // <------
      )

server / credentials: true

The credentials read-only property of the Request interface indicates whether the user agent should send cookies from the other domain in the case of cross-origin requests. This is similar to XHRโ€™s withCredentials flag, but with three available values (instead of two):

  • omit: Never send cookies.
  • same-origin: Send user credentials (cookies, basic http auth, etc..) if the URL is on the same origin as the calling script. This is the default value.
  • include: Always send user credentials (cookies, basic http auth, etc..), even for cross-origin calls. (express์—์„  true์™€ ๋™์ผ)

๋ณด์•ˆ ์ธ์ฆ ์ •๋ณด๋ฅผ(cookies, basic http auth, etc..) ๋ณด๋‚ด๋Š” ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•œ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ same-origin์ผ ๊ฒฝ์šฐ ํ—ˆ์šฉํ•œ๋‹ค.

server / origin: 'https://localhost:3000' or true

๊ต์ฐจ ์ถœ์ฒ˜ ๋ฆฌ์†Œ์Šค ๊ณต์œ (Cross-Origin Resource Sharing, CORS) ์˜ต์…˜์ด๋‹ค. ํŠน์ • origin์—์„œ ์˜จ ํ†ต์‹ ๋งŒ ํ—ˆ์šฉํ•œ๋‹ค. ์‚ฌ์ดํŠธ๋ฅผ ์ œํ•œํ•ด์•ผ ํด๋ผ์ด์–ธํŠธ์˜ withCredentials: true ์˜ต์…˜์„ ํ™œ์„ฑํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค. origin ์ œํ•œ์ด ์—†์ด withCredentails ์˜ต์…˜์ด ์ ์šฉ๋˜๋ฉด ์•„๋ฌดํ•œํ…Œ๋‚˜ ๋‚˜์˜ ์ธ์ฆ ์ •๋ณด๋ฅผ ๋ฟŒ๋ฆฌ๊ฒŒ ๋œ๋‹ค.

app.use(
  cors({
    origin: 'https://localhost:3000', // <----- client / withCredentials: true 
    methods: ['GET', 'POST', 'OPTIONS'],
    credentials: true, // <------
  })
);

๋˜ํ•œ GET/POST ๋“ฑ์„ ๊ตฌ๋ถ„ํ•˜์—ฌ ์ฃผ๋Š” ๊ฒƒ ์—ญ์‹œ ์œ ์šฉํ•˜๋‹ค. img ํƒœ๊ทธ ๋“ฑ์„ ์ด์šฉํ•  ๊ฒฝ์šฐ GET ์š”์ฒญ์œผ๋กœ ๋“ค์–ด์˜ค๊ฒŒ ๋  ๊ฒƒ์ด๊ณ , ๋ฐ˜๋ฉด ํ”ํžˆ ํ•˜๋“ฏ form์„ ์ด์šฉํ•ด ๊ฐ’์„ ๋ฐ›์„ ๊ฒฝ์šฐ POST๋ฅผ ์ด์šฉํ•˜๊ฒŒ ๋˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์ฟ ํ‚ค ์„ค์ • ์ค‘ sameSite ์˜ต์…˜์ด ์œ„ ๊ธฐ๋Šฅ์„ ํฌํ•จํ•˜๊ณ  ์žˆ๋‹ค. ํฌ๋กฌ์˜ ๊ธฐ๋ณธ ๊ฐ’์€ Lax๋กœ GET์„ ํฌํ•จํ•œ ์ผ๋ถ€ ํƒœ๊ทธ๋งŒ ์ฟ ํ‚ค ์ „์†ก์„ ํ—ˆ์šฉํ•œ๋‹ค.

// TODO: express-session ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ด์šฉํ•ด ์ฟ ํ‚ค ์„ค์ •์„ ํ•ด์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
app.use(
  session({
    secret: '@codestates', // ์•”ํ˜ธํ™”๋กœ ์“ฐ์ด๋Š” ํ‚ค
    resave: false, // ์„ธ์…˜์„ ํ•ญ์ƒ ์ €์žฅํ• ์ง€ ์„ค์ •
    saveUninitialized: true, // ์„ธ์…˜์ด ์ €์žฅ๋˜๊ธฐ ์ „ uninitialized ์ƒํƒœ๋กœ ์ €์žฅ
    cookie: { // ์„ธ์…˜ ์ฟ ํ‚ค ์„ค์ •
      domain: 'localhost', // ์ฟ ํ‚ค๋ฅผ ๋ณด๋‚ด๋Š” ์‚ฌ์ดํŠธ(์„œ๋ฒ„)๋ฅผ ๋ช…์‹œ
      path: '/', // URL ๊ฒฝ๋กœ. ํ•˜์œ„ ๊ฒฝ๋กœ๊นŒ์ง€ ๋ชจ๋‘ ํฌํ•จ.
      maxAge: 24 * 6 * 60 * 10000, // ์ฟ ํ‚ค ๋งŒ๋ฃŒ ์‹œ๊ฐ„. ์ดˆ๋‹จ์œ„.
      // XSRF(cross-site request forgery) ๊ณต๊ฒฉ ๋ฐฉ์–ด ์˜ต์…˜
      sameSite: 'None', // ์‚ฌ์ดํŠธ ์™ธ๋ถ€์—์„œ ์š”์ฒญ์„ ๋ณด๋‚ผ ๋•Œ ์ฟ ํ‚ค ์ •์ฑ…
      // Strict : ์™ธ๋ถ€ ๋„๋ฉ”์ธ ์ฟ ํ‚ค ์ฐจ๋‹จ
      // Lax : ์™ธ๋ถ€ ๋„๋ฉ”์ธ ์ฟ ํ‚ค ์ผ๋ถ€ ํ—ˆ์šฉ(HTTP get method / a href / link href)
      // None : ์™ธ๋ถ€ ๋„๋ฉ”์ธ ์ฟ ํ‚ค ๋ชจ๋‘ ํ—ˆ์šฉ. ๊ฐ•์ œ๋กœ origin ์˜ต์…˜๊ณผ ๊ฐ™์ด ์จ์•ผํ•จ
      httpOnly: true, // ํด๋ผ์ด์–ธํŠธ ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์ฟ ํ‚ค๋ฅผ ๋ชป๋ณด๊ฒŒ ํ•จ (document.cookie)
      secure: true, // HTTPS ํ™˜๊ฒฝ๋งŒ ์ฟ ํ‚ค๋ฅผ ์ „์†ก
    },
  })
);
// CORS ์ฟ ํ‚ค ์„ค์ • ํ™œ์„ฑํ™”
app.use(
  cors({
    // origin: 'https://localhost:3000',
    origin: true,
    methods: ['GET', 'POST', 'OPTIONS'],
    credentials: true, // ๋‹ค๋ฅธ ๋„๋ฉ”์ธ๊ฐ„ ์ž๊ฒฉ์ฆ๋ช…(credential, ์ฟ ํ‚ค ํฌํ•จ)์„ ์ „์†กํ• ์ง€ ์—ฌ๋ถ€
  })
);

๋ฏผ๊ฐํ•œ ์ •๋ณด์— ์ ์šฉ๋˜๋Š” ๊ฐ•ํ™”๋œ ๋ฐฉ์–ด

๊ทธ ์™ธ์—๋Š” ํŒจ์Šค์›Œ๋“œ ๋ณ€๊ฒฝ ๊ฐ™์€ ๋ฏผ๊ฐํ•œ ์ •๋ณด๋ฅผ ๋‹ค๋ฃฐ ๋•Œ์—๋Š” ์„ธ์…˜์— ์ž„์˜๋‚œ์ˆ˜(ํ† ํฐ)๋ฅผ ๋ฐœ๊ธ‰ํ•ด์„œ, ํ•ด๋‹น ๋‚œ์ˆ˜๊ฐ€ ์—†๋Š” ์ƒํ™ฉ์—์„œ ํ•ด๋‹น ๋™์ž‘๋“ค์ด ์ด๋ฃจ์–ด์ง€๋ฉด ์š”์ฒญ์„ ๊ฑฐ๋ถ€ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ํ†ตํ•˜์—ฌ ์‚ฌ์šฉ์ž๊ฐ€ ์ •๋ง๋กœ ๋ณ€๊ฒฝ์„ ์˜๋„ํ•˜๋Š” ๊ฒฝ์šฐ์—๋งŒ ๋ณ€๊ฒฝ์„ ์‹œ์ผœ์ฃผ๋Š” ๋ฐฉ๋ฒ•, ๋ณ€๊ฒฝ ์‹œ์— CAPTCHA๋ฅผ ์ด์šฉํ•˜์—ฌ CAPTCHA ์ธ์ฆ์ฝ”๋“œ๊ฐ€ ์—†๊ฑฐ๋‚˜ ํ‹€๋ฆฌ๋ฉด ๊ฑฐ๋ถ€ํ•˜๋„๋ก ํ•˜๋Š” ๋ฐฉ๋ฒ• ๋“ฑ์ด ์ด์šฉ๋˜๊ณ  ์žˆ๋‹ค.

๋ฏผ๊ฐํ•œ ์ •๋ณด๋Š” ์ถ”๊ฐ€ ๋ณด์•ˆ ์กฐ์น˜๋ฅผ ํ•ด๋‘๋Š”๊ฒŒ ์ข‹๋‹ค. ์ฟ ํ‚ค๋Š” ๊ฐ์ข… ๊ณต๊ฒฉ์˜ (CSRF) ํƒ€๊ฒŸ์ด ๋˜๊ธฐ ์‰ฌ์šฐ๋ฏ€๋กœ ์ค‘์š”ํ•œ ๋ณด์•ˆ ์ •๋ณด๋Š” ์ฟ ํ‚ค์— ํƒ‘์žฌํ•˜๋Š” ๊ฒƒ์„ ์ง€์–‘ํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ๊ณ ํ•˜๊ณ  ์žˆ๋‹ค.

๐Ÿ’‰ XSS (์‚ฌ์ดํŠธ ๊ฐ„ ์Šคํฌ๋ฆฝํŠธ ์‹คํ–‰)

Cross-Site Scripting. CSS์™€ ๊ตฌ๋ถ„ํ•˜๊ธฐ ์œ„ํ•ด์„œ ์•ž ๋‹จ์–ด๋ฅผ X ๋กœ ์“ด๋‹ค.
ํ•ด์ปค๊ฐ€ ์˜๋„๋˜์ง€ ์•Š๋Š” ๋ฐฉ์‹์œผ๋กœ ์•…์˜์ ์ธ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹ฌ์–ด๋†“๋Š” ๊ณต๊ฒฉ์ด๋‹ค. ์ทจ์•ฝํ•œ ์‚ฌ์ดํŠธ์˜ ๊ฒฝ์šฐ, ํ•ด์ปค๊ฐ€ ๋Œ“๊ธ€์— <script> ์—˜๋ฆฌ๋จผํŠธ ํ˜•ํƒœ์˜ ๋ฌธ์ž์—ด์„ ๋“ฑ๋กํ•˜๋ฉด ๋ฌธ์ž์—ด๋กœ ๋ณด์—ฌ์ง€์ง€ ์•Š๊ณ  ํƒœ๊ทธ๋กœ ์ธ์‹๋˜๊ณ  ๋‹ค๋ฅธ ์‚ฌ์šฉ์ž๋Š” ์•…์˜์ ์ธ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰ํ•˜๊ฒŒ ๋œ๋‹ค.

SQL injection๊ณผ ํ•จ๊ป˜ ์›น ์ƒ์—์„œ ๊ฐ€์žฅ ๊ธฐ์ดˆ์ ์ธ ์ทจ์•ฝ์  ๊ณต๊ฒฉ ๋ฐฉ๋ฒ•์˜ ์ผ์ข…์œผ๋กœ, ์•…์˜์ ์ธ ์‚ฌ์šฉ์ž๊ฐ€ ๊ณต๊ฒฉํ•˜๋ ค๋Š” ์‚ฌ์ดํŠธ์— ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋„ฃ๋Š” ๊ธฐ๋ฒ•์„ ๋งํ•œ๋‹ค. ๊ณต๊ฒฉ์— ์„ฑ๊ณตํ•˜๋ฉด ์‚ฌ์ดํŠธ์— ์ ‘์†ํ•œ ์‚ฌ์šฉ์ž๋Š” ์‚ฝ์ž…๋œ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๊ฒŒ ๋˜๋ฉฐ, ๋ณดํ†ต ์˜๋„์น˜ ์•Š์€ ํ–‰๋™์„ ์ˆ˜ํ–‰์‹œํ‚ค๊ฑฐ๋‚˜ ์ฟ ํ‚ค๋‚˜ ์„ธ์…˜ ํ† ํฐ ๋“ฑ์˜ ๋ฏผ๊ฐํ•œ ์ •๋ณด๋ฅผ ํƒˆ์ทจํ•œ๋‹ค.

๊ณต๊ฒฉ ๋ฐฉ๋ฒ•์— ๋”ฐ๋ผ Stored XSS์™€ Reflected XSS๋กœ ๋‚˜๋‰œ๋‹ค. Stored XSS๋Š” ์‚ฌ์ดํŠธ ๊ฒŒ์‹œํŒ์ด๋‚˜ ๋Œ“๊ธ€, ๋‹‰๋„ค์ž„ ๋“ฑ ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์„œ๋ฒ„์— ์ €์žฅ๋˜์–ด ์‹คํ–‰๋˜๋Š” ๋ฐฉ์‹์ด๊ณ , Reflected XSS๋Š” ๋ณดํ†ต URL ํŒŒ๋ผ๋ฏธํ„ฐ(ํŠนํžˆ GET ๋ฐฉ์‹)์— ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋„ฃ์–ด ์„œ๋ฒ„์— ์ €์žฅํ•˜์ง€ ์•Š๊ณ  ๊ทธ ์ฆ‰์‹œ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ์‹์ด๋‹ค. ํ›„์ˆ ๋œ ๋‚ด์šฉ ๋Œ€๋ถ€๋ถ„์€ Stored XSS๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋œ๋‹ค. Reflected XSS์˜ ๊ฒฝ์šฐ ๋ธŒ๋ผ์šฐ์ € ์ž์ฒด์—์„œ ์ฐจ๋‹จํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์•„ ์ƒ๋Œ€์ ์œผ๋กœ ๊ณต๊ฒฉ์„ ์„ฑ๊ณต์‹œํ‚ค๊ธฐ ์–ด๋ ต๋‹ค.

ํฌ๋กœ์Šค ์‚ฌ์ดํŠธ ์Šคํฌ๋ฆฝํŒ…์ด๋ž€ ์ด๋ฆ„ ๋‹ต๊ฒŒ, ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ณต๊ฒฉํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๋‹ค. ๊ณต๊ฒฉ ๋ฐฉ๋ฒ•์ด ๋‹จ์ˆœํ•˜๊ณ  ๊ฐ€์žฅ ๊ธฐ์ดˆ์ ์ด์ง€๋งŒ, ๋งŽ์€ ์›น์‚ฌ์ดํŠธ๋“ค์ด XSS์— ๋Œ€ํ•œ ๋ฐฉ์–ด ์กฐ์น˜๋ฅผ ํ•ด๋‘์ง€ ์•Š์•„ ๊ณต๊ฒฉ์„ ๋ฐ›๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๋‹ค. ์—ฌ๋Ÿฌ ์‚ฌ์šฉ์ž๊ฐ€ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ ๊ฒŒ์‹œํŒ ๋“ฑ์— ์ฝ”๋“œ๋ฅผ ์‚ฝ์ž…ํ•˜๋Š” ๊ฒฝ์šฐ๋„ ๋งŽ์œผ๋ฉฐ, ๊ฒฝ์šฐ์— ๋”ฐ๋ผ์„œ๋Š” ๋ฉ”์ผ๊ณผ ๊ฐ™์€ ๋งค์ฒด๋ฅผ ํ†ตํ•ด์„œ๋„ ์ „ํŒŒ๋œ๋‹ค. ์‹ฌ์ง€์–ด๋Š” ๋‹‰๋„ค์ž„์— ์ฝ”๋“œ๋ฅผ ์‹ฌ๊ธฐ๋„ ํ•œ๋‹ค.

๐Ÿ˜ˆ XSS ๊ณต๊ฒฉ ์ „๋žต

  • ์Šคํฌ๋ฆฝํŠธ ํƒœ๊ทธ
    ์Šคํฌ๋ฆฝํŠธ ํƒœ๊ทธ์˜ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰์‹œํ‚จ๋‹ค. ์•ˆํƒ€๊น๊ฒŒ๋„, ๋งค์šฐ ์ •์งํ•œ ๋ฐฉ๋ฒ•์ด๋ผ ๋Œ€๋ถ€๋ถ„์˜ ์‚ฌ์ดํŠธ์—์„œ ๋ง‰๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๋‹ค.
    <script>alert('XSS');</script>

  • ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋งํฌ
    ๋งํฌ ํƒœ๊ทธ๋กœ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.
    <a href="javascript:alert('XSS')">XSS</a>

  • ์ด๋ฒคํŠธ ์†์„ฑ
    ์ด๋ฒคํŠธ ์†์„ฑ์„ ์‚ฌ์šฉํ•œ๋‹ค. ์ด๋ฒคํŠธ ์†์„ฑ์œผ๋กœ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ฃผ๋กœ on ์œผ๋กœ ์‹œ์ž‘ํ•˜๋Š” ์†์„ฑ์ด ์ด๋ฒคํŠธ ์†์„ฑ์ด๋‹ค. ์ž์ฃผ ์‚ฌ์šฉ๋˜๋Š” ์ด๋ฒคํŠธ ์†์„ฑ์œผ๋กœ๋Š” onload onerror onclick ๋“ฑ์ด ์žˆ๋‹ค.
    <img src="#">

  • ๋ธ”๋ž™๋ฆฌ์ŠคํŠธ ์šฐํšŒ
    ์•Œ๋ ค์ง€์ง€ ์•Š์€ ํƒœ๊ทธ์™€ ์†์„ฑ๋“ค์„ ์‚ฌ์šฉํ•œ๋‹ค. ๋ธ”๋ž™ ๋ฆฌ์ŠคํŠธ ๋ฐฉ์‹์œผ๋กœ ๋ง‰๋Š” ์‚ฌ์ดํŠธ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
    <ruby>XSS</ruby>

  • ๋‚ด์šฉ ๋‚œ๋…ํ™”
    ๋”ฐ์˜ดํ‘œ๋กœ ๊ฐ์‹ธ๋Š” ๋ฌธ์ž์—ด ์‚ฌ์ด์— ๊ณต๋ฐฑ ๋ฌธ์ž๋“ค์„ ๋„ฃ๊ณ , HTML ์ธ์ฝ”๋“œ๋ฅผ ํ•˜์—ฌ ๋‚œ๋…ํ™”ํ•œ๋‹ค. ์ผ๋ถ€ ๋ธŒ๋ผ์šฐ์ €์—์„œ javascript: ๋งํฌ ์‚ฌ์ด์— ๊ณต๋ฐฑ ๋ฌธ์ž๊ฐ€ ๋“ค์–ด๊ฐˆ ์ˆ˜ ์žˆ๊ณ , HTML ์ธ์ฝ”๋“œ๋ฅผ ํ•ด๋„ ๋””์ฝ”๋“œ๋œ ๋‚ด์šฉ์ด ์ถœ๋ ฅ๋œ๋‹ค๋Š” ์ ์„ ์ด์šฉํ•œ๋‹ค. ์—ฌ๊ธฐ์—์„œ๋Š” '์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋งํฌ' ๋ฐฉ๋ฒ•๊ณผ ์‚ฌ์šฉํ•˜์˜€์ง€๋งŒ, ๋‹น์—ฐํžˆ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

<a href="&#x6A;&#x61;&#x76;&#x61;&#x73;&#xA;&#x63;&#x72;&#x69;&#x70;&#x74;&#xA;&#x3A;&#xA;&#x61;&#x6C;&#x65;&#x72;&#x74;&#xA;&#x28;&#x27;&#x58;&#x53;&#x53;&#x27;&#x29;">XSS</a>
  • ์Šคํฌ๋ฆฝํŠธ ๋‚œ๋…ํ™”
    ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ผ๋ณธ์–ด๋ฅผ ์‚ฌ์šฉํ•œ ์ด๋ชจํ‹ฐ์ฝ˜๋“ค๋กœ ๋‚œ๋…ํ™”ํ•œ๋‹ค. ์Šคํฌ๋ฆฝํŠธ ์‹คํ–‰์€ ๊ฐ€๋Šฅํ•˜์ง€๋งŒ, document.cookie ์™€ ๊ฐ™์€ ๋‹จ์–ด๋ฅผ ๋ง‰์„ ๊ฒฝ์šฐ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.
    https://utf-8.jp/public/aaencode.html

์ฐธ์กฐURL

https://namu.wiki/w/CSRF
https://www.imperva.com/learn/application-security/csrf-cross-site-request-forgery/
https://sj602.github.io/2018/07/14/what-is-CSRF/
https://docs.w3cub.com/dom/request/credentials
https://docs.w3cub.com/dom/xmlhttprequest/withcredentials
https://namu.wiki/w/XSS

profile
๋ธ”๋กœ๊ทธ ์˜ฎ๊ฒผ์Šต๋‹ˆ๋‹ค. https://shlee.cloud

0๊ฐœ์˜ ๋Œ“๊ธ€