## https://sploitus.com/exploit?id=KITPLOIT:TOOLS-GITHUB-MRUNALP-BLOCK-COPYFAIL
## μμ½
CVE-2026-31431("Copy Fail")μ Linux 컀λμ `algif_aead` μνΈν μΈν°νμ΄μ€μμ λ°μνλ κΆν μμΉ μ·¨μ½μ μ
λλ€. 곡격μλ `authencesn` μκ³ λ¦¬μ¦κ³Ό `splice()`λ₯Ό μ¬μ©νλ AF_ALG μμΌμ μ΄μ©νμ¬ `/usr/bin/su`μ κ°μ setuid λ°μ΄λ리λ₯Ό ν¬ν¨ν 컀λ νμ΄μ§ μΊμμ μμ νμΌμ μμμν¬ μ μμ΅λλ€.
μ΄ λ¬Έμλ Copy Failμ΄ μ
μ©νλ νμ μμ€ν
μΈ λͺ¨λ AF_ALG AEAD λ°μΈλλ₯Ό μ°¨λ¨νλ BPF LSM DaemonSetμ μ¬μ©ν **μ¬λΆν
μλ μν λ°©λ²** μ μ 곡ν©λλ€. μ΄λ μνΈν ν
νλ¦Ώ μ€μ²©(μ: `pcrypt(authencesn(...))`)μ ν΅ν μ°νλ₯Ό λ°©μ§ν©λλ€. λ€λ₯Έ AF_ALG μ¬μ©(ν΄μ, skcipher)μ μν₯μ λ°μ§ μμ΅λλ€. λ³λμ OCP 4.22 ν΄λ¬μ€ν° 3κ°μμ μλν¬μλλ‘ ν
μ€νΈλμμ΅λλ€.
## λΉ λ₯Έ μμ
root@kitploit:~
# 1. BPF LSMμ΄ νμ±νλμ΄ μλμ§ νμΈν©λλ€ (RHEL CoreOS 9.8μλ κΈ°λ³Έμ μΌλ‘ νμ±νλμ΄ μμ)
oc debug node/<any-node> -- chroot /host cat /sys/kernel/security/lsm
# "bpf"κ° ν¬ν¨λμ΄ μμ΄μΌ ν©λλ€
# 2. λ€μμ€νμ΄μ€λ₯Ό λ°°ν¬νκ³ privileged SCCλ₯Ό λΆμ¬ν©λλ€
oc apply -f daemonset.yaml
# 3. DaemonSet νλλ λͺ¨λ λ
Έλμμ μλμΌλ‘ μμλ©λλ€
# 4. νμΈ
oc get pods -n block-copyfail # λͺ¨λ λ
Έλμμ Running μνμ¬μΌ ν©λλ€
oc logs -n block-copyfail -l app=block-copyfail
# μμ μΆλ ₯: "block-copyfail: blocker active β all AF_ALG AEAD binds blocked"
μ¬λΆν
μ΄ νμ μμ΅λλ€. λ
Έλ λλ μΈμ΄ νμ μμ΅λλ€. νλ μ¬μμμ΄ νμ μμ΅λλ€. 보νΈλ μ¦μ μ μ©λλ©° λͺ¨λ λ
Έλμ λͺ¨λ νλ‘μΈμ€λ₯Ό ν¬ν¨ν©λλ€(100% μ μ© λ²μ).
## λͺ©μ°¨
1. μ·¨μ½μ μλ λ°©μ
2. ν΄λ¬μ€ν°μ μ·¨μ½μ νμΈ
3. BPF LSM DaemonSet λ°°ν¬
4. λ°°ν¬ ν κ²μ¦
5. μμ€μμ μ΄λ―Έμ§ λΉλ
6. μ κ±°
* * *
## μ·¨μ½μ μλ λ°©μ
μ΄ μ·¨μ½μ μ μΈ κ°μ§ 컀λ κΈ°λ₯μ μ°κ²°ν©λλ€:
1. **AF_ALG μμΌ** β `socket(AF_ALG, SOCK_SEQPACKET, 0)`μ ν΅ν΄ 컀λ μνΈνμ λν μ¬μ©μ κ³΅κ° νΈλ€μ μμ±ν©λλ€
2. **AEAD λ°μΈλ** β νΉμ μΈμ¦ μνΈν μκ³ λ¦¬μ¦μΈ `authencesn(hmac(sha256),cbc(aes))`μ λ°μΈλ©ν©λλ€
3. **splice() + sendmsg()** β 컀λμ΄ μμ€μ λμ νμ΄μ§ λ§€νμ΄ λ€λ₯Έ "μ μ리" μμ
μ μλͺ» μννμ¬ μ½κΈ° μ μ© νμΌμ νμ΄μ§ μΊμλ₯Ό μμμν΅λλ€
곡격μλ (νμΌμ λν μ°κΈ° κΆν μμ΄) νμ΄μ§ μΊμμ `/usr/bin/su`λ₯Ό μμμν¨ λ€μ μ€ννμ¬ root κΆνμ μ»μ΅λλ€.
* * *
## ν΄λ¬μ€ν°μ μ·¨μ½μ νμΈ
ν΄λ¬μ€ν°μ μ `cve-2026-31431-test` λ€μμ€νμ΄μ€λ₯Ό λ§λ€κ³ `test` λλ ν 리μ λ§€λνμ€νΈλ₯Ό μ μ©νμ¬ ν
μ€νΈ μ€ν¬λ¦½νΈλ₯Ό μ€νν©λλ€:
root@kitploit:~
oc apply -f test
κ²°κ³Όλ₯Ό νμΈν©λλ€:
root@kitploit:~
oc wait pod/cve-test -n cve-2026-31431-test \
--for=jsonpath='{.status.phase}'=Succeeded --timeout=120s
oc -n cve-2026-31431-test logs -l app=cve-2026-31431-test
**μ·¨μ½ν ν΄λ¬μ€ν°μμ** λ€μκ³Ό κ°μ μΆλ ₯μ΄ νμλ©λλ€:
root@kitploit:~
=== CVE-2026-31431 Vulnerability Test ===
Target: /usr/bin/su
Original SHA256: 8969560ae8e6e21c6184c1451f59418822ee69dd5d946d71987b55236bbc0feb
Attempting splice + AF_ALG page-cache corruption (160 bytes in 40 chunks)...
After SHA256: 30b0f5b5a054c4df65b48ca792863bf7054b4d793f15f57163792ba6c2b151ae
PAGE CACHE CORRUPTION: YES - /usr/bin/su was modified in the page cache
Attempting to execute corrupted /usr/bin/su ...
exit code: 0
RESULT: PARTIALLY MITIGATED
Page-cache corruption succeeded (kernel is vulnerable)
Privilege escalation blocked (allowPrivilegeEscalation=false)
### 4λ¨κ³: μ 리
root@kitploit:~
oc delete namespace cve-2026-31431-test
* * *
## BPF LSM DaemonSet λ°°ν¬
BPF LSM μ κ·Ό λ°©μμ 컀λ μμ€μμ `socket_bind`λ₯Ό ννΉνκ³ ν
νλ¦Ώ μ€μ²©μ κ΄κ³μμ΄ λͺ¨λ AF_ALG AEAD λ°μΈλλ₯Ό μ°¨λ¨ν©λλ€. μ΄λ OCP λ°°ν¬λ₯Ό μν΄ libbpfλ₯Ό μ¬μ©νμ¬ Cλ‘ λ€μ μμ±λ block-copyfailμ κΈ°λ°μΌλ‘ ν©λλ€.
### μ¬μ μꡬ μ¬ν
BPF LSMμ΄ νμ±νλμ΄ μμ΄μΌ ν©λλ€. RHEL CoreOS 9.8(OCP 4.22)μλ κΈ°λ³Έμ μΌλ‘ νμ±νλμ΄ μμ΅λλ€. λ€μμΌλ‘ νμΈν©λλ€:
root@kitploit:~
oc debug node/<any-node> -- chroot /host cat /sys/kernel/security/lsm
μμ μΆλ ₯μλ `bpf`κ° ν¬ν¨λ©λλ€:
root@kitploit:~
lockdown,capability,landlock,yama,selinux,bpf
`bpf`κ° **μλ** κ²½μ° μΌνμ± MachineConfigκ° νμν©λλ€(μ¬λΆν
μ΄ νμν μ μΌν μλ리μ€):
root@kitploit:~
apiVersion: machineconfiguration.openshift.io/v1
kind: MachineConfig
metadata:
labels:
machineconfiguration.openshift.io/role: worker
name: 99-enable-bpf-lsm
spec:
kernelArguments:
- lsm=lockdown,capability,selinux,bpf
### 1λ¨κ³: λ€μμ€νμ΄μ€ μμ±, SCC λΆμ¬, λ°°ν¬
μ `block-copyfail` λ€μμ€νμ΄μ€λ₯Ό λ§λ€κ³ SCCλ₯Ό λΆμ¬ν λ€μ `daemonset.yaml` λ§€λνμ€νΈλ₯Ό μ μ©νμ¬ DaemonSetμ λ°°ν¬ν©λλ€. DaemonSet νλκ° μμ±λκΈ° μ μ privileged SCCκ° λΆμ¬λμ΄μΌ ν©λλ€. κ·Έλ μ§ μμΌλ©΄ SCC κ²μ¦ μ€λ₯λ‘ νλ μμ±μ΄ μ€ν¨ν©λλ€.
root@kitploit:~
oc apply -f daemonset.yaml
### 2λ¨κ³: λͺ¨λ λ
Έλμμ νλκ° μμλ λκΉμ§ λκΈ°
root@kitploit:~
oc get pods -n block-copyfail -o wide
μμ: λ
ΈλλΉ νλμ νλ, λͺ¨λ `Running` μν:
root@kitploit:~
NAME READY STATUS AGE NODE
block-copyfail-2jhzf 1/1 Running 34s ci-...-master-2
block-copyfail-4dfq7 1/1 Running 34s ci-...-master-1
block-copyfail-c2ts8 1/1 Running 34s ci-...-worker-c
block-copyfail-ctblk 1/1 Running 34s ci-...-worker-a
block-copyfail-m26sx 1/1 Running 34s ci-...-worker-b
block-copyfail-xsh6d 1/1 Running 34s ci-...-master-0
### 3λ¨κ³: μ°¨λ¨κΈ°κ° νμ± μνμΈμ§ νμΈ
root@kitploit:~
oc logs -n block-copyfail -l app=block-copyfail
μμ:
root@kitploit:~
block-copyfail: blocker active β all AF_ALG AEAD binds blocked
* * *
## λ°°ν¬ ν κ²μ¦
μ·¨μ½μ νμΈ μΉμ
μ λμΌν μ·¨μ½μ ν
μ€νΈλ₯Ό λ€μ μ€νν©λλ€.
**BPF LSM DaemonSet λ°°ν¬ ν** μΆλ ₯μ λ€μκ³Ό κ°μ΅λλ€:
root@kitploit:~
=== CVE-2026-31431 Vulnerability Test ===
Target: /usr/bin/su
Original SHA256: 30b0f5b5a054c4df65b48ca792863bf7054b4d793f15f57163792ba6c2b151ae
Attempting splice + AF_ALG page-cache corruption (160 bytes in 40 chunks)...
AF_ALG bind failed: [Errno 1] Operation not permitted
RESULT: CANNOT TEST - AF_ALG or splice not available/permitted
DaemonSet λ‘κ·Έμλ μ°¨λ¨λ μλκ° νμλ©λλ€:
root@kitploit:~
oc logs -n block-copyfail -l app=block-copyfail
root@kitploit:~
block-copyfail: blocker active β all AF_ALG AEAD binds blocked
block-copyfail: BLOCKED pid=16777 comm=python3 time=2026-05-01 16:37:23
### λ€λ₯Έ μκ³ λ¦¬μ¦μ΄ μν₯μ λ°μ§ μλμ§ νμΈ
λ
Έλμμ `verify-algos.py`λ₯Ό μ€ννμ¬ λͺ¨λ AEAD μκ³ λ¦¬μ¦μ΄ μ°¨λ¨λλ λμ λ€λ₯Έ AF_ALG μ ν(ν΄μ, skcipher)μ΄ κ³μ μλνλμ§ νμΈν©λλ€:
root@kitploit:~
oc debug node/<any-node> -- chroot /host python3 -c "
import socket
tests = [
('aead', 'gcm(aes)'),
('aead', 'ccm(aes)'),
('aead', 'rfc4106(gcm(aes))'),
('hash', 'sha256'),
('skcipher', 'cbc(aes)'),
('aead', 'authencesn(hmac(sha256),cbc(aes))'),
]
for t, n in tests:
s = socket.socket(socket.AF_ALG, socket.SOCK_SEQPACKET, 0)
try:
s.bind((t, n))
print(f' ALLOWED {t}/{n}')
except OSError as e:
print(f' BLOCKED {t}/{n} -- {e}')
finally:
s.close()
"
μμ μΆλ ₯:
root@kitploit:~
BLOCKED aead/gcm(aes) -- [Errno 1] Operation not permitted
BLOCKED aead/ccm(aes) -- [Errno 1] Operation not permitted
BLOCKED aead/rfc4106(gcm(aes)) -- [Errno 1] Operation not permitted
ALLOWED hash/sha256
ALLOWED skcipher/cbc(aes)
BLOCKED aead/authencesn(hmac(sha256),cbc(aes)) -- [Errno 1] Operation not permitted
μ΄λ BPF LSMμ΄ λ€λ₯Έ AF_ALG μ νμ κ·Έλλ‘ λλ©΄μ λͺ¨λ AEAD λ°μΈλλ₯Ό μ°¨λ¨ν¨μ νμΈν©λλ€.
* * *
## μμ€μμ μ΄λ―Έμ§ λΉλ
BPF LSM μ°¨λ¨κΈ° μμ€λ `block-copyfail/`μ μμ΅λλ€:
root@kitploit:~
block-copyfail/
block_copyfail.bpf.c # BPF 컀λ νλ‘κ·Έλ¨ (LSM νν¬)
block_copyfail.c # μ¬μ©μ κ³΅κ° λ‘λ (libbpf μ€μΌλ ν€)
block_copyfail.h # 곡μ μ΄λ²€νΈ ꡬ쑰체
Makefile # λΉλ νμ΄νλΌμΈ
Dockerfile # λ€λ¨κ³ λΉλ
daemonset.yaml # λ€μμ€νμ΄μ€ + DaemonSet λ§€λνμ€νΈ
trigger-test.py # λΉ λ₯Έ κ²μ¦ μ€ν¬λ¦½νΈ
λΉλ λ° νΈμ:
root@kitploit:~
cd block-copyfail/
podman build -t quay.io/<org>/block-copyfail:latest .
podman push quay.io/<org>/block-copyfail:latest
Dockerfileμ λ€λ¨κ³ λΉλλ₯Ό μ¬μ©ν©λλ€: μ»΄νμΌμ μν clang/bpftool/libbpf-develμ΄ ν¬ν¨λ Fedora, λ°νμ μ΄λ―Έμ§μ© UBI 9 μ΅μ(~122 MB).
* * *
## μ κ±°
DaemonSetμ μμ νλ©΄ λͺ¨λ λ
Έλμμ μν μ‘°μΉκ° μ¦μ μ κ±°λ©λλ€:
root@kitploit:~
oc delete -f daemonset.yaml
# λλ
oc delete namespace block-copyfail
BPF νλ‘κ·Έλ¨μ λ‘λ νλ‘μΈμ€κ° μ’
λ£λλ©΄ μλμΌλ‘ λΆλ¦¬λ©λλ€. μ¬λΆν
μ΄λ νλ μ¬μμμ΄ νμ μμ΅λλ€.