Translated ['src/binary-exploitation/rop-return-oriented-programing/srop

This commit is contained in:
Translator 2025-08-19 21:11:34 +00:00
parent 81db2530d8
commit d23feb09a3
2 changed files with 19 additions and 19 deletions

View File

@ -103,7 +103,7 @@ payload += bytes(frame)
p.sendline(payload)
p.interactive()
```
## bof 예제 (sigreturn 없)
## bof 예제 (sigreturn 없)
### 코드
```c
@ -181,7 +181,7 @@ p.interactive()
## `sigreturn` 가젯 자동 찾기 (2023-2025)
현대 배포판에서 `sigreturn` 트램폴린은 여전히 **vDSO** 페이지에 의해 내보내지지만, 정확한 오프셋은 커널 버전 및 BTI(`+branch-protection`) 또는 PAC과 같은 빌드 플래그에 따라 달라질 수 있습니다. 이를 자동하면 오프셋을 하드코딩하는 것을 방지할 수 있습니다:
현대 배포판에서 `sigreturn` 트램폴린은 여전히 **vDSO** 페이지에 의해 내보내지지만, 정확한 오프셋은 커널 버전 및 BTI(`+branch-protection`) 또는 PAC과 같은 빌드 플래그에 따라 달라질 수 있습니다. 이를 자동으로 발견하면 오프셋을 하드코딩하는 것을 방지할 수 있습니다:
```bash
# With ROPgadget ≥ 7.4
python3 -m ROPGadget --binary /proc/$(pgrep srop)/mem --only "svc #0" 2>/dev/null | grep -i sigreturn
@ -191,11 +191,11 @@ rp++ -f ./binary --unique -r | grep "mov\s\+x8, #0x8b" # 0x8b = __NR_rt_sigret
```
두 도구는 **AArch64** 인코딩을 이해하며 *SROP 가젯*으로 사용할 수 있는 `mov x8, 0x8b ; svc #0` 시퀀스를 나열합니다.
> 참고: 바이너리가 **BTI**로 컴파일되면 모든 유효한 간접 분기 대상의 첫 번째 명령어는 `bti c`입니다. 링커에 의해 배치된 `sigreturn` 트램폴린은 이미 올바른 BTI 착륙 패드를 포함하고 있어 가젯이 비특권 코드에서 여전히 사용 가능합니다.
> 주의: 바이너리가 **BTI**로 컴파일되면 모든 유효한 간접 분기 대상의 첫 번째 명령어는 `bti c`입니다. 링커에 의해 배치된 `sigreturn` 트램폴린은 이미 올바른 BTI 착륙 패드를 포함하고 있어 가젯이 비특권 코드에서 여전히 사용 가능합니다.
## ROP와 SROP 연결하기 (`mprotect`를 통한 피벗)
`rt_sigreturn`*모든* 범용 레지스터와 `pstate`를 제어할 수 있게 해줍니다. x86에서 일반적인 패턴은: 1) SROP를 사용하여 `mprotect`를 호출하고, 2) 쉘코드를 포함하는 새로운 실행 가능한 스택으로 피벗하는 것입니다. ARM64에서도 동일한 아이디어가 작동합니다:
`rt_sigreturn`*모든* 범용 레지스터와 `pstate`를 제어할 수 있게 해줍니다. x86에서 일반적인 패턴은: 1) SROP를 사용하여 `mprotect`를 호출하고, 2) 쉘코드를 포함하는 새로운 실행 가능한 스택으로 피벗하는 것입니다. ARM64에서도 동일한 아이디어가 작동합니다:
```python
frame = SigreturnFrame()
frame.x8 = constants.SYS_mprotect # 226
@ -215,7 +215,7 @@ Linux 5.16은 사용자 공간 신호 프레임에 대한 더 엄격한 검증
* `struct rt_sigframe`의 예약어는 0이어야 합니다.
* *extra_context* 레코드의 모든 포인터는 정렬되어 있으며 사용자 주소 공간 내를 가리켜야 합니다.
`pwntools>=4.10`자동으로 준수하는 프레임을 생성하지만, 수동으로 구축하는 경우 *reserved*를 0으로 초기화하고 정말 필요하지 않는 한 SVE 레코드를 생략해야 합니다. 그렇지 않으면 `rt_sigreturn`이 반환 대신 `SIGSEGV`를 전달합니다.
`pwntools>=4.10`은 준수하는 프레임을 자동으로 생성하지만, 수동으로 구축하는 경우 *reserved*를 0으로 초기화하고 정말 필요하지 않는 한 SVE 레코드를 생략해야 합니다. 그렇지 않으면 `rt_sigreturn`이 반환 대신 `SIGSEGV`를 전달합니다.
주류 Android 14 및 Fedora 38부터 사용자 공간은 기본적으로 **PAC** (*Pointer Authentication*) 및 **BTI**가 활성화된 상태로 컴파일됩니다 (`-mbranch-protection=standard`). *SROP* 자체는 영향을 받지 않지만, 커널이 생성된 프레임에서 직접 `PC`를 덮어쓰므로 스택에 저장된 인증된 LR을 우회합니다. 그러나 간접 분기를 수행하는 **후속 ROP 체인**은 BTI가 활성화된 명령어 또는 PAC된 주소로 점프해야 합니다. 가젯을 선택할 때 이를 염두에 두십시오.

View File

@ -6,7 +6,7 @@
iframed 페이지의 내용을 나타내는 방법은 3가지가 있습니다:
- URL을 나타내는 `src`를 통해 (URL은 교차 출처 또는 동일 출처일 수 있)
- `src`를 통해 URL을 나타냅니다 (URL은 교차 출처 또는 동일 출처일 수 있습니다)
- `data:` 프로토콜을 사용하여 내용을 나타내는 `src`
- 내용을 나타내는 `srcdoc`
@ -45,8 +45,8 @@ var secret = "child secret"
alert(parent.secret)
</script>
```
이전 HTML에 HTTP 서버(예: `python3 -m http.server`)를 통해 접근하면 모든 스크립트가 실행되는 것을 알 수 있습니다(이를 방지하는 CSP가 없기 때문입니다). **부모는 어떤 iframe 안의 `secret` 변수를 접근할 수 없으며** **오직 if2 및 if3 iframe(같은 사이트로 간주됨)만 원래 창의 secret에 접근할 수 있습니다.**\
if4 `null` 출처로 간주된다는 점에 유의하세요.
이전 HTML에 HTTP 서버(예: `python3 -m http.server`)를 통해 접근하면 모든 스크립트가 실행되는 것을 알 수 있습니다(이를 방지하는 CSP가 없기 때문입니다). **부모는 어떤 iframe 안의 `secret` 변수를 접근할 수 없으며** **오직 if2 및 if3(같은 사이트로 간주됨)만 원래 창의 secret에 접근할 수 있습니다.**\
if4 `null` 출처로 간주된다는 점에 유의하세요.
### CSP가 있는 Iframes <a href="#iframes_with_csp_40" id="iframes_with_csp_40"></a>
@ -81,9 +81,9 @@ src="data:text/html;charset=utf-8,%3Cscript%3Evar%20secret='if4%20secret!';alert
![](<../../images/image (372).png>)
따라서 **서버에 JS 파일을 업로드하고 iframe을 통해 로드할 수 있다면 CSP를 우회할 수 있습니다. `script-src 'none'`이더라도 가능합니다.** 이는 **동일 사이트 JSONP 엔드포인트를 악용하여도 가능할 수 있습니다.**
따라서 **서버에 JS 파일을 업로드하고 iframe을 통해 로드할 수 있다면 CSP를 우회할 수 있습니다. `script-src 'none'`일지라도 가능합니다.** 이는 **동일 사이트 JSONP 엔드포인트를 악용하여도 가능할 수 있습니다.**
다음 시나리오로 테스트할 수 있습니다. `script-src 'none'`일 때도 쿠키가 도난당합니다. 애플리케이션을 실행하고 브라우저로 접근하세요:
다음 시나리오로 테스트할 수 있습니다. 쿠키가 `script-src 'none'`일지라도 도난당합니다. 애플리케이션을 실행하고 브라우저로 접근하세요:
```python
import flask
from flask import Flask
@ -107,7 +107,7 @@ app.run()
연구 커뮤니티는 제한적인 정책을 무력화하기 위해 iframes를 악용하는 창의적인 방법을 계속 발견하고 있습니다. 아래는 지난 몇 년 동안 발표된 가장 주목할 만한 기술들입니다:
* **Dangling-markup / named-iframe 데이터 유출 (PortSwigger 2023)** 애플리케이션이 HTML을 반영하지만 강력한 CSP가 스크립트 실행을 차단할 때, *dangling* `<iframe name>` 속성을 주입하여 여전히 민감한 토큰을 유출할 수 있습니다. 부분 마크업이 파싱되면, 별도의 출처에서 실행 중인 공격자 스크립트가 프레임을 `about:blank`로 탐색하고 `window.name`을 읽습니다. 이 값은 이제 다음 인용 문자까지의 모든 을 포함합니다(예: CSRF 토큰). 피해자 컨텍스트에서 JavaScript가 실행되지 않기 때문에, 공격은 일반적으로 `script-src 'none'`을 회피합니다. 최소한의 PoC는 다음과 같습니다:
* **Dangling-markup / named-iframe 데이터 유출 (PortSwigger 2023)** 애플리케이션이 HTML을 반영하지만 강력한 CSP가 스크립트 실행을 차단할 때, *dangling* `<iframe name>` 속성을 주입하여 여전히 민감한 토큰을 유출할 수 있습니다. 부분 마크업이 파싱되면, 별도의 출처에서 실행 중인 공격자 스크립트가 프레임을 `about:blank`로 탐색하고 `window.name`을 읽습니다. 이 값은 이제 다음 인용 문자까지의 모든 내용을 포함합니다(예: CSRF 토큰). 피해자 컨텍스트에서 JavaScript가 실행되지 않기 때문에, 공격은 일반적으로 `script-src 'none'`을 회피합니다. 최소한의 PoC는 다음과 같습니다:
```html
<!-- 민감한 <script> 바로 앞의 주입 지점 -->
@ -130,12 +130,12 @@ s.nonce = n;
top.document.body.appendChild(s);
```
* **폼 액션 하이재킹 (PortSwigger 2024)** `form-action` 지시어를 생략한 페이지는 주입된 iframe이나 인라인 HTML 로그인 폼이 *재타겟팅*될 수 있어, 비밀번호 관리자가 자격 증명을 외부 도메인에 자동으로 채우고 제출하게 할 수 있습니다. `script-src 'none'`이 존재할 때도 마찬가지입니다. 항상 `default-src``form-action`으로 보완하세요!
* **폼 액션 하이재킹 (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` **및** 주입 지점을 제거하세요.
2. nonce가 비밀이라고 의존하지 마세요—`strict-dynamic` **및** 주입 지점을 제거하세요.
3. 신뢰할 수 없는 문서를 포함해야 할 경우 `sandbox="allow-scripts allow-same-origin"`**매우 조심스럽게** 사용하세요(스크립트 실행 격리만 필요하다면 `allow-same-origin` 없이 사용).
4. 방어 심화 COOP+COEP 배포를 고려하세요; 새로운 `<iframe credentialless>` 속성(§ 아래)은 제3자 임베드를 깨뜨리지 않고도 이를 가능하게 합니다.
@ -158,13 +158,13 @@ iframe 내의 콘텐츠는 `sandbox` 속성을 사용하여 추가 제한을 받
사용될 때, `sandbox` 속성은 여러 가지 제한을 부과합니다:
- 콘텐츠는 고유한 출처에서 온 것처럼 취급됩니다.
- 양식 제출 시도가 차단됩니다.
- 양식 제출하려는 모든 시도가 차단됩니다.
- 스크립트 실행이 금지됩니다.
- 특정 API에 대한 접근이 비활성화됩니다.
- 링크가 다른 브라우징 컨텍스트와 상호작용하는 것을 방지합니다.
- `<embed>`, `<object>`, `<applet>` 또는 유사한 태그를 통한 플러그인 사용이 금지됩니다.
- 콘텐츠 자체가 콘텐츠의 최상위 브라우징 컨텍스트를 탐색하는 것이 방지됩니다.
- 비디오 재생이나 양식 컨트롤의 자동 포커스와 같 자동으로 트리거되는 기능이 차단됩니다.
- 비디오 재생이나 양식 컨트롤의 자동 포커스와 같 자동으로 트리거되는 기능이 차단됩니다.
Tip: 최신 브라우저는 `allow-scripts`, `allow-same-origin`, `allow-top-navigation-by-user-activation`, `allow-downloads-without-user-activation` 등과 같은 세분화된 플래그를 지원합니다. 이를 조합하여 임베디드 애플리케이션에 필요한 최소한의 기능만 부여하십시오.
@ -177,10 +177,10 @@ Tip: 최신 브라우저는 `allow-scripts`, `allow-same-origin`, `allow-top-nav
[이 기사](https://blog.slonser.info/posts/make-self-xss-great-again/)에서 설명한 바와 같이, iframe의 `credentialless` 플래그는 요청에 자격 증명을 전송하지 않고 iframe 내에서 페이지를 로드하는 데 사용되며, 로드된 페이지의 동일 출처 정책(SOP)을 유지합니다.
**Chrome 110(2023년 2월)부터 이 기능은 기본적으로 활성화되어** 있으며, 사양은 *anonymous iframe*이라는 이름으로 브라우저 간에 표준화되고 있습니다. MDN은 이를 다음과 같이 설명합니다: “실제 출처와 공유되지 않도록 제3자 iframe을 완전히 새로운 임시 저장소 파티션에 로드하는 메커니즘입니다. 따라서 쿠키, localStorage 또는 IndexedDB가 공유되지 않습니다.” 공격자와 방어자에게 미치는 결과:
**Chrome 110(2023년 2월)부터 이 기능은 기본적으로 활성화되어 있습니다**. 이 사양은 *anonymous iframe*이라는 이름으로 브라우저 간에 표준화되고 있습니다. MDN은 이를 다음과 같이 설명합니다: “실제 출처와 공유되지 않도록 제3자 iframe을 완전히 새로운 일시적인 저장소 파티션에 로드하는 메커니즘입니다. 따라서 쿠키, localStorage 또는 IndexedDB가 공유되지 않습니다.” 공격자와 방어자에게 미치는 결과:
* 서로 다른 credentialless iframe의 스크립트는 **여전히 동일한 최상위 출처를 공유**하며, DOM을 통해 자유롭게 상호작용할 수 있어 다중 iframe self-XSS 공격이 가능해집니다(아래 PoC 참조).
* 네트워크가 **자격 증명이 제거되었기 때문에**, iframe 내의 모든 요청은 사실상 인증되지 않은 세션처럼 작동합니다. CSRF 보호 엔드포인트는 일반적으로 실패하지만, DOM을 통해 유출될 수 있는 공개 페이지는 여전히 범위에 포함됩니다.
* 네트워크가 **자격 증명이 제거된** 상태이기 때문에 iframe 내의 모든 요청은 사실상 인증되지 않은 세션처럼 작동합니다. CSRF 보호 엔드포인트는 일반적으로 실패하지만, DOM을 통해 유출될 수 있는 공개 페이지는 여전히 범위에 포함됩니다.
* credentialless iframe에서 생성된 팝업은 암묵적으로 `rel="noopener"`를 가지며, 일부 OAuth 흐름을 깨뜨립니다.
```javascript
// PoC: two same-origin credentialless iframes stealing cookies set by a third
@ -209,13 +209,13 @@ document.forms[0].submit();
- 실제로 사용자가 로그인한 다른 iframe ( `credentialless` 플래그 없이).
그런 다음, XSS에서 동일한 SOP를 가지므로 다른 iframe에 접근할 수 있으며, 예를 들어 쿠키를 훔치는 것을 실행할 수 있습니다:
그런 다음, XSS에서 동일한 SOP를 가지므로 다른 iframe에 접근할 수 있으며, 예를 들어 쿠키를 훔치는 실행을 할 수 있습니다:
```javascript
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