HexBrain

Monero · Report #3240792

Reported RPC Overflow

Validstatus
25upvotes
6 Apr 2026disclosed

How it was found

This submission is being made by MAGIC Grants, a public charity that supports critical infrastructure. The MAGIC Monero Fund, one of our committees, recently contracted Ada Logics to perform fuzzing work on Monero's RPC endpoints. This submission has been forwarded from Ada Logics to the Monero team. We waive the opportunity for a monetary reward. If you prefer that we submit the findings from this engagement a different way, please let us know by emailing me at [email protected].


The issue happens specifically on these lines: https://github.com/monero-project/monero/blob/17f6fb871c09507cd13c23fdecd9cbcca3f01326/src/rpc/core_rpc_server.cpp#L1278-L1292

Specifically, on line 1291 there will be an overflow on 1291 if the size of b.data() does not match the size of crypto::key_image.

There is a missing return statement following line 1289.

ASAN Stack trace from fuzzer:

==9082==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fa31d153228 at pc 0x56045cd8cc32 bp 0x7ffd3ad28590 sp 0x7ffd3ad27d50
READ of size 32 at 0x7fa31d153228 thread T0
    #0 0x56045cd8cc31 in __asan_memcpy /src/llvm-project/compiler-rt/lib/asan/asan_interceptors_memintrinsics.cpp:63:3
    #1 0x56045d97ee5a in construct<crypto::key_image, const crypto::key_image &> /usr/local/bin/../include/c++/v1/__memory/allocator.h:173:24
    #2 0x56045d97ee5a in construct<crypto::key_image, const crypto::key_image &, void> /usr/local/bin/../include/c++/v1/__memory/allocator_traits.h:296:9
    #3 0x56045d97ee5a in crypto::key_image* std::__1::vector<crypto::key_image, std::__1::allocator<crypto::key_image>>::__push_back_slow_path<crypto::key_image const&>(crypto::key_image const&) /usr/local/bin/../include/c++/v1/vector:1
453:3                                                      
    #4 0x56045d6919ee in push_back /usr/local/bin/../include/c++/v1/vector:1467:13
    #5 0x56045d6919ee in cryptonote::core_rpc_server::on_is_key_image_spent(epee::misc_utils::struct_init<cryptonote::COMMAND_RPC_IS_KEY_IMAGE_SPENT::request_t> const&, epee::misc_utils::struct_init<cryptonote::COMMAND_RPC_IS_KEY_IMAGE_
SPENT::response_t>&, epee::net_utils::connection_context_base const*) /src/monero/monero/src/rpc/core_rpc_server.cpp:1291:18                                                                                                                
    #6 0x56045d16ffd2 in fuzz_is_key_image_spent(cryptonote::core_rpc_server&, unsigned char const*, unsigned long&, unsigned long) /src/fuzz_base.cpp:191:7
    #7 0x56045cdcead0 in operator() /usr/local/bin/../include/c++/v1/__functional/function.h:428:12
    #8 0x56045cdcead0 in operator() /usr/local/bin/../include/c++/v1/__functional/function.h:981:10                                                                                                                                        
    #9 0x56045cdcead0 in LLVMFuzzerTestOneInput /src/fuzz_rpc.cpp:20:5
    #10 0x56045cc82f70 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:614:13
    #11 0x56045cc82795 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:516:7
    #12 0x56045cc83f75 in fuzzer::Fuzzer::MutateAndTestOne() /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:760:19
    #13 0x56045cc84d05 in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector<fuzzer::SizedFile, std::__Fuzzer::allocator<fuzzer::SizedFile>>&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:905:5
    #14 0x56045cc73b4b in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:914:6
    #15 0x56045cc9ef22 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10                          
    #16 0x7fa31f359082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 5792732f783158c66fb4f3756458ca24e46e827d)
    #17 0x56045cc663cd in _start (/out/fuzz_rpc+0x7b03cd)                                                            
                                                                                                                     
Address 0x7fa31d153228 is located in stack of thread T0 at offset 552 in frame
    #0 0x56045d690f2f in cryptonote::core_rpc_server::on_is_key_image_spent(epee::misc_utils::struct_init<cryptonote::COMMAND_RPC_IS_KEY_IMAGE_SPENT::request_t> const&, epee::misc_utils::struct_init<cryptonote::COMMAND_RPC_IS_KEY_IMAGE_
SPENT::response_t>&, epee::net_utils::connection_context_base const*) /src/monero/monero/src/rpc/core_rpc_server.cpp:1261                                                                                                                  
  This frame has 16 object(s):
    [32, 48) 'lock.i' (line 108)
    [64, 144) 'pt_is_key_image_spent' (line 1262)
    [176, 200) 'ref.tmp' (line 1262)
    [240, 264) 'ref.tmp2' (line 1262)
    [304, 336) 'tracker' (line 1262)
    [368, 369) 'ok' (line 1263)
    [384, 388) 'ref.tmp9' (line 1264)
    [400, 424) 'ref.tmp10' (line 1264)
    [464, 488) 'key_images52' (line 1278)
    [528, 552) 'b' (line 1281) <== Memory access at offset 552 overflows this variable
    [592, 616) 'spent_status' (line 1293)
    [656, 660) 'ref.tmp112' (line 1302)
    [672, 696) 'txs' (line 1305)
    [736, 760) 'ki' (line 1306)
    [800, 832) 'hash' (line 1315)
    [864, 896) 'spent_key_image' (line 1316)
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow /src/monero/monero/src/rpc/core_rpc_server.cpp:1291:18 in cryptonote::core_rpc_server::on_is_key_image_spent(epee::misc_utils::struct_init<cryptonote::COMMAND_RPC_IS_KEY_IMAGE_SPENT::requ
est_t> const&, epee::misc_utils::struct_init<cryptonote::COMMAND_RPC_IS_KEY_IMAGE_SPENT::response_t>&, epee::net_utils::connection_context_base const*)
Shadow bytes around the buggy address:                                                                                                                                                                                                      
  0x7fa31d152f80: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
  0x7fa31d153000: f1 f1 f1 f1 f8 f8 f2 f2 00 00 00 00 00 00 00 00
  0x7fa31d153080: 00 00 f2 f2 f2 f2 f8 f8 f8 f2 f2 f2 f2 f2 f8 f8
  0x7fa31d153180: f8 f2 f8 f8 f8 f2 f2 f2 f2 f2 00 00 00 f2 f2 f2
=>0x7fa31d153200: f2 f2 00 00 00[f2]f2 f2 f2 f2 f8 f8 f8 f2 f2 f2
  0x7fa31d153280: f2 f2 f8 f2 f8 f8 f8 f2 f2 f2 f2 f2 f8 f8 f8 f2
  0x7fa31d153300: f2 f2 f2 f2 f8 f8 f8 f8 f2 f2 f2 f2 f8 f8 f8 f8
  0x7fa31d153380: f3 f3 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00
  0x7fa31d153400: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
  0x7fa31d153480: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00        
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa      
  Freed heap region:       fd  
  Stack left redzone:      f1        
  Stack mid redzone:       f2        
  Stack right redzone:     f3            
  Stack after return:      f5                                                                                        
  Stack use after scope:   f8            
  Global redzone:          f9          
  Global init order:       f6  
  Poisoned by user:        f7  
  Container overflow:      fc    
  Array cookie:            ac              
  Intra object redzone:    bb                                                                                        
  ASan internal:           fe                    
  Left alloca redzone:     ca                                                                                                                                                                                                              
  Right alloca redzone:    cb                                                                                                                                                                                                              
==9082==ABORTING                      
MS: 5 CopyPart-CopyPart-ChangeByte-ShuffleBytes-EraseBytes-; base unit: f64317d83d7d96e23d2ca5976ca263cb6c35a5c2
0x0,0x8,0x23,                                                                                                        
\000\010#                                                                                                            
artifact_prefix='./'; Test unit written to ./crash-6133c92848a171509d0711f60b758025242bb03d
Base64: AAg

Impact

Potential denial of service

This report was disclosed publicly on HackerOne and belongs to its author and the program. See the original