
CVE-2021-22600 の悪用成功時に攻撃者が獲得する権限を検証するための、af_packet.c の権限チェックを行う Proof-Of-Concept
これは LLM によって生成されたサンプル Proof of Concept であり、すべてのケースを網羅するものではありません。 この Proof of Concept の基本的な考え方は、ターゲットコードがどのような権限(例えばユーザースペースかカーネルスペースか)で実行されるかを確認し、CVE-2021-22600 を利用したエクスプロイトがどのような影響を及ぼすかを理解することです。 このコードは、前述の CVE のエクスプロイトでは決してありません。VM 内の Ubuntu で試しました。環境によって結果は異なる場合があります。
コードのコンパイルと実行手順:
gcc program.c -o runme
chmod +x runme
./runme
sudo ./runme
通常ユーザーとして実行した場合のサンプル出力:
<..SNIP..>
=== AF_PACKET privilege probe ===
UID=1000 EUID=1000
WARNING: couldn't read CapEff from /proc/self/status. Continuing anyway.
Stage 1: try AF_PACKET + SOCK_DGRAM (no CAP_NET_RAW required by kernel check)
socket(AF_PACKET, SOCK_DGRAM, ETH_P_ALL) => FAILED: Operation not permitted (errno=1)
Stage 2: try AF_PACKET + SOCK_RAW (kernel checks CAP_NET_RAW for SOCK_RAW)
socket(AF_PACKET, SOCK_RAW, ETH_P_ALL) => FAILED: Operation not permitted (errno=1)
RAW socket creation failed: you cannot reach packet_set_ring() from user-land without CAP_NET_RAW.
Common results:
- errno=EPERM (Operation not permitted) : you lack CAP_NET_RAW
- errno=EACCES : sometimes indicates policy or network namespace restrictions
Notes:
- The kernel enforces CAP_NET_RAW at socket creation: look for a check like
if (sock->type == SOCK_RAW && !capable(CAP_NET_RAW)) return -EPERM;
in net/packet/af_packet.c (this is why PACKET_RX_RING is unreachable without that socket).
- If you run this program as root or with CAP_NET_RAW, the RAW socket will succeed and
setsockopt(PACKET_RX_RING) will attempt to configure the ring (it may still fail with EINVAL
if your parameters are invalid, but you will have invoked packet_set_ring()).
=== Done ===
<..SNIP..>
sudo / root ユーザーとして実行した場合のサンプル出力:
<..SNIP..>
=== AF_PACKET privilege probe ===
UID=0 EUID=0
CapEff (hex) = 0x000001ffffffffff
-> CAP_NET_RAW (bit 12) = YES
Stage 1: try AF_PACKET + SOCK_DGRAM (no CAP_NET_RAW required by kernel check)
socket(AF_PACKET, SOCK_DGRAM, ETH_P_ALL) => OK (fd=3)
Stage 2: try AF_PACKET + SOCK_RAW (kernel checks CAP_NET_RAW for SOCK_RAW)
socket(AF_PACKET, SOCK_RAW, ETH_P_ALL) => OK (fd=3)
Since RAW socket creation succeeded, we likely have CAP_NET_RAW (or are root).
Stage 3: try setsockopt PACKET_RX_RING (this invokes packet_set_ring in kernel)
setsockopt(PACKET_RX_RING) => OK
Notes:
- The kernel enforces CAP_NET_RAW at socket creation: look for a check like
if (sock->type == SOCK_RAW && !capable(CAP_NET_RAW)) return -EPERM;
in net/packet/af_packet.c (this is why PACKET_RX_RING is unreachable without that socket).
- If you run this program as root or with CAP_NET_RAW, the RAW socket will succeed and
setsockopt(PACKET_RX_RING) will attempt to configure the ring (it may still fail with EINVAL
if your parameters are invalid, but you will have invoked packet_set_ring()).
=== Done ===
<..SNIP..>