Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Untrusted Pointer Dereference in mrb_vm_exec() #5613

Closed
AiDaiP opened this issue Dec 27, 2021 · 2 comments
Closed

Untrusted Pointer Dereference in mrb_vm_exec() #5613

AiDaiP opened this issue Dec 27, 2021 · 2 comments

Comments

@AiDaiP
Copy link

AiDaiP commented Dec 27, 2021

Untrusted Pointer Dereference in mrb_vm_exec()

Description

An Untrusted Pointer Dereference was discovered in mrb_vm_exec(). The vulnerability causes a segmentation fault and application crash.

version

6de0fcb

./mruby -v
mruby 3.0.0 (2021-03-05)

System information
Ubuntu 20.04 focal, AMD EPYC 7742 64-Core @ 16x 2.25GHz

Proof of Concept

poc

base64 poc
Y2xhc3MgVmNsYXNzDQoJQEB2YXJyID0gWzE8MiwzLDQsNSw2LDcsOCw5LDEwLDExLDEyLDEzLDE0
LDE1LDE2LDE3XQ0KCWRlZiB2YXJyDQoJCUBAdmFycg0KCWVuZA0KCWRlZiB0b19pJnQNCgkJQEB2
YXJyLmNsZWFyDQoJCTExDQoJZW5kDQplbmQNCg0Kb2JqID0gVmNsYXNzLm5ldw0KDQpwcmludCBv
YmoudmFyci5zaGlmdChvYmop

command:

./mruby ./poc

Result

./mruby ./poc
[1]    283553 segmentation fault  ./mruby ./poc

gdb

Program received signal SIGSEGV, Segmentation fault.
mrb_vm_exec (mrb=<optimized out>, proc=<optimized out>, pc=0x55555561f7c3 <mrblib_proc_iseq_115+99> "/\006\003\001=\005\001%\377\331Q\006\002\001\a\004Q\b\003/\a\004\001<\006Q\a\004<\006\070\006") at /home/aidai/fuzzing/mruby/mruby-master/include/mruby/boxing_word.h:139
139       return x;
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
───────────────────────────────[ REGISTERS ]────────────────────────────────
 RAX  0x10
 RBX  0x38
 RCX  0x7
 RDX  0x0
 RDI  0x1
 RSI  0xffffffff
 R8   0x6
 R9   0x0
 R10  0x1
 R11  0x55555566fb08 ◂— 0x10
 R12  0x2eb
 R13  0x10
 R14  0x7
 R15  0x2f
 RBP  0x0
 RSP  0x7fffffffdad0 —▸ 0x55555565d2a0 —▸ 0x7fffffffdd50 ◂— 0x6
 RIP  0x55555557988e (mrb_vm_exec+2590) ◂— cmp    byte ptr [r13 + 0x10], 0x13
─────────────────────────────────[ DISASM ]─────────────────────────────────
 ► 0x55555557988e <mrb_vm_exec+2590>     cmp    byte ptr [r13 + 0x10], 0x13
   0x555555579893 <mrb_vm_exec+2595>     mov    rdx, r13
   0x555555579896 <mrb_vm_exec+2598>     ja     mrb_vm_exec+16844
     <mrb_vm_exec+16844>
    ↓
   0x55555557d03c <mrb_vm_exec+16844>    mov    rax, qword ptr [rdx]
   0x55555557d03f <mrb_vm_exec+16847>    jmp    mrb_vm_exec+1400
    <mrb_vm_exec+1400>
    ↓
   0x5555555793e8 <mrb_vm_exec+1400>     lea    rcx, [rsp + 0x268]
   0x5555555793f0 <mrb_vm_exec+1408>     mov    rdi, qword ptr [rsp]
   0x5555555793f4 <mrb_vm_exec+1412>     mov    edx, r12d
   0x5555555793f7 <mrb_vm_exec+1415>     mov    qword ptr [rsp + 0x268], rax
   0x5555555793ff <mrb_vm_exec+1423>     mov    rsi, rcx
   0x555555579402 <mrb_vm_exec+1426>     mov    qword ptr [rsp + 0x70], rcx
─────────────────────────────[ SOURCE (CODE) ]──────────────────────────────
In file: /home/aidai/fuzzing/mruby/mruby-master/include/mruby/boxing_word.h
   134 static inline union mrb_value_
   135 mrb_val_union(mrb_value v)
   136 {
   137   union mrb_value_ x;
   138   x.value = v;
 ► 139   return x;
   140 }
   141
   142 MRB_API mrb_value mrb_word_boxing_cptr_value(struct mrb_state*, void*);
   143 #ifndef MRB_NO_FLOAT
   144 MRB_API mrb_value mrb_word_boxing_float_value(struct mrb_state*, mrb_float);
─────────────────────────────────[ STACK ]──────────────────────────────────
00:0000│ rsp 0x7fffffffdad0 —▸ 0x55555565d2a0 —▸ 0x7fffffffdd50 ◂— 0x6
01:0008│     0x7fffffffdad8 —▸ 0x55555561f7c3 (mrblib_proc_iseq_115+99) ◂— 0x2501053d0103062f
02:0010│     0x7fffffffdae0 —▸ 0x55555564c2a0 (mrblib_proc_irep_115) ◂— 0x30000000b0006
03:0018│     0x7fffffffdae8 —▸ 0x55555561f7f0 (mrblib_proc_syms_115) ◂— 0x36700000125
04:0020│     0x7fffffffdaf0 —▸ 0x7fffffffdd50 ◂— 0x6
05:0028│     0x7fffffffdaf8 —▸ 0x55555567be90 —▸ 0x55555567be60 —▸ 0x55555567be48 ◂— 0x1a
06:0030│     0x7fffffffdb00 ◂— 0x1
07:0038│     0x7fffffffdb08 —▸ 0x55555566a2b0 ◂— 0x0
───────────────────────────────[ BACKTRACE ]────────────────────────────────
 ► f 0   0x55555557988e mrb_vm_exec+2590
   f 1   0x55555558300b mrb_vm_run+155
   f 2   0x555555584ed5 mrb_top_run+133
   f 3   0x5555555c7540 mrb_load_exec+752
   f 4   0x5555555c92b0 mrb_load_detect_file_cxt+400
   f 5   0x5555555756de main+1486
   f 6   0x7ffff7c980b3 __libc_start_main+243
────────────────────────────────────────────────────────────────────────────
pwndbg> bt
#0  mrb_vm_exec (mrb=<optimized out>, proc=<optimized out>, pc=0x55555561f7c3 <mrblib_proc_iseq_115+99> "/\006\003\001=\005\001%\377\331Q\006\002\001\a\004Q\b\003/\a\004\001<\006Q\a\004<\006\070\006") at /home/aidai/fuzzing/mruby/mruby-master/include/mruby/boxing_word.h:139
#1  0x000055555558300b in mrb_vm_run (mrb=0x55555565d2a0, proc=proc@entry=0x555555661b50, self=..., stack_keep=0) at /home/aidai/fuzzing/mruby/mruby-master/src/vm.c:1091
#2  0x0000555555584ed5 in mrb_top_run (mrb=mrb@entry=0x55555565d2a0, proc=proc@entry=0x555555661b50, self=..., stack_keep=stack_keep@entry=0) at /home/aidai/fuzzing/mruby/mruby-master/src/vm.c:3050
#3  0x00005555555c7540 in mrb_load_exec (mrb=mrb@entry=0x55555565d2a0, p=p@entry=0x55555567aa10, c=c@entry=0x555555679940) at mrbgems/mruby-compiler/core/parse.y:6881
#4  0x00005555555c92b0 in mrb_load_detect_file_cxt (mrb=0x55555565d2a0, fp=0x555555679740, c=0x555555679940) at mrbgems/mruby-compiler/core/parse.y:6794
#5  0x00005555555756de in main (argc=argc@entry=2, argv=argv@entry=0x7fffffffe248) at /home/aidai/fuzzing/mruby/mruby-master/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c:347
#6  0x00007ffff7c980b3 in __libc_start_main (main=0x555555575110 <main>, argc=2, argv=0x7fffffffe248, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffe238) at ../csu/libc-start.c:308
#7  0x0000555555575a5e in _start () at /home/aidai/fuzzing/mruby/mruby-master/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c:282
@dearblue
Copy link
Contributor

The cause of this problem has to do with the mrb_get_args() function, which is called by the mrb_ary_shift_m() function.
To solve this problem, I think the choice depends on whether mrb_get_args() is allowed to reentrant to mruby VM or not.
# Note that I myself assumed that mrb_get_args() does not reentrant to the mruby VM.

If reentrants are allowed, at least two modifications are needed:

  • Fix mrb_ary_shift_m().
    Assign the variable len after mrb_get_args().
  • Correct wrong change in Refactor the mrb_get_args() function #5540.
    The variables argv and ci need to be adjusted after mrb_as_int() and mrb_as_float().
    Currently, SIGSEGV may occur even inside mrb_get_args().

If reentrancy is not allowed, we need to replace mrb_as_int() and mrb_as_float() used inside mrb_get_args().

dearblue added a commit to dearblue/mruby that referenced this issue Dec 30, 2021
ref. mruby#5613

I checked with Valgrind, and the methods that can cause use-after-free are `Array#rotate`, `Array#rotate!`, and `String#byteslice`.
Since `String#rindex` uses `RSTRING_LEN()` indirectly inside the function, no reference to the out-of-bounds range is generated.
dearblue added a commit to dearblue/mruby that referenced this issue Dec 30, 2021
ref. mruby#5613.

I mentioned in mruby#5540 that there was no reentrant to the virtual machine, but in fact it was still a possibility at that point.
Also, the variable `ci` needs to be recalculated at the same time.
matz added a commit that referenced this issue Dec 31, 2021
It should only call `to_f` for Rational and Complex numbers.
Ref #5540 #5613 #5620
@matz
Copy link
Member

matz commented Feb 16, 2022

The issue has been addressed by #5619 and #5620

@matz matz closed this as completed Feb 16, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants