Loading HuntDB...

Buffer overflow in mrb_time_asctime

High
S
shopify-scripts
Submitted None
Reported by haquaman

Vulnerability Details

Technical details and impact analysis

Uncontrolled Resource Consumption
Hi, This one doesn't always crash every time, but with ASAN on it will. Crash file is: ``` Time.new-0XD00000000000000&0 ``` But you could always do `Time.at(sec,usec)` with special values, and basically anything that gets to_s called (`mrb_time_asctime` in C) (in this case, no method found exception does this). Crashes sometimes in mruby: ``` $ ./dev/bin/mruby crash.rb Segmentation fault: 11 ``` The times it doesn't crash, it could either return strings outside of memory with a buffer-overead. Some of the lldb runs shows this: ``` $ lldb ./dev/bin/mruby crash.rb (lldb) target create "./dev/bin/mruby" Current executable set to './dev/bin/mruby' (x86_64). (lldb) settings set -- target.run-args "crash.rb" (lldb) r Process 66222 launched: './dev/bin/mruby' (x86_64) trace: [0] crash.rb:1 crash.rb:1: undefined method '&' for Sun 00 16:03:04 1901 (NoMethodError) Process 66222 exited with status = 1 (0x00000001) (lldb) r Process 66665 launched: './dev/bin/mruby' (x86_64) trace: [0] crash.rb:1 crash.rb:1: undefined method '&' for Sun Jan 00 16:03:04 1900 (NoMethodError) Process 66665 exited with status = 1 (0x00000001) (lldb) r Process 66889 launched: './dev/bin/mruby' (x86_64) trace: [0] crash.rb:1 crash.rb:1: undefined method '&' for Sun Jan 00 16:03:04 1900 (NoMethodError) Process 66889 exited with status = 1 (0x00000001) (lldb) r Process 67075 launched: './dev/bin/mruby' (x86_64) trace: [0] crash.rb:1 crash.rb:1: undefined method '&' for Sun Jan 01 16:03:04 1900 (NoMethodError) Process 67075 exited with status = 1 (0x00000001) (lldb) r Process 67127 launched: './dev/bin/mruby' (x86_64) trace: [0] crash.rb:1 crash.rb:1: undefined method '&' for Sun _defined? 486 16:03:04 2259 (NoMethodError) Process 67127 exited with status = 1 (0x00000001) (lldb) r Process 67341 launched: './dev/bin/mruby' (x86_64) trace: [0] crash.rb:1 crash.rb:1: undefined method '&' for Sun Jan 04 16:03:04 1900 (NoMethodError) Process 67341 exited with status = 1 (0x00000001) (lldb) r Process 67904 launched: './dev/bin/mruby' (x86_64) trace: [0] crash.rb:1 crash.rb:1: undefined method '&' for Sun Jan 00 16:03:04 1900 (NoMethodError) Process 67904 exited with status = 1 (0x00000001) (lldb) r Process 68098 launched: './dev/bin/mruby' (x86_64) trace: [0] crash.rb:1 crash.rb:1: undefined method '&' for Sun Jan 00 16:03:04 1900 (NoMethodError) Process 68098 exited with status = 1 (0x00000001) (lldb) r Process 68320 launched: './dev/bin/mruby' (x86_64) trace: [0] crash.rb:1 crash.rb:1: undefined method '&' for Sun 01 16:03:04 1900 (NoMethodError) Process 68320 exited with status = 1 (0x00000001) (lldb) r Process 68514 launched: './dev/bin/mruby' (x86_64) trace: [0] crash.rb:1 crash.rb:1: undefined method '&' for Sun Jan 00 16:03:04 1900 (NoMethodError) Process 68514 exited with status = 1 (0x00000001) (lldb) r Process 68628 launched: './dev/bin/mruby' (x86_64) trace: [0] crash.rb:1 crash.rb:1: undefined method '&' for Sun ) 62 16:03:04 1983 (NoMethodError) Process 68628 exited with status = 1 (0x00000001) (lldb) r Process 68870 launched: './dev/bin/mruby' (x86_64) trace: [0] crash.rb:1 crash.rb:1: undefined method '&' for Sun 00 16:03:04 1901 (NoMethodError) Process 68870 exited with status = 1 (0x00000001) (lldb) r Process 68908 launched: './dev/bin/mruby' (x86_64) trace: [0] crash.rb:1 crash.rb:1: undefined method '&' for Sun 01 16:03:04 1901 (NoMethodError) Process 68908 exited with status = 1 (0x00000001) (lldb) r Process 69130 launched: './dev/bin/mruby' (x86_64) trace: [0] crash.rb:1 crash.rb:1: undefined method '&' for Sun Jan 00 16:03:04 1900 (NoMethodError) Process 69130 exited with status = 1 (0x00000001) (lldb) r Process 69324 launched: './dev/bin/mruby' (x86_64) Process 69324 stopped * thread #1: tid = 0x88a312d, 0x00007fff95b0e152 libsystem_c.dylib`strlen + 18, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x14010ef30) frame #0: 0x00007fff95b0e152 libsystem_c.dylib`strlen + 18 libsystem_c.dylib`strlen: -> 0x7fff95b0e152 <+18>: pcmpeqb (%rdi), %xmm0 0x7fff95b0e156 <+22>: pmovmskb %xmm0, %esi 0x7fff95b0e15a <+26>: andq $0xf, %rcx 0x7fff95b0e15e <+30>: orq $-0x1, %rax (lldb) bt * thread #1: tid = 0x88a312d, 0x00007fff95b0e152 libsystem_c.dylib`strlen + 18, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x14010ef30) * frame #0: 0x00007fff95b0e152 libsystem_c.dylib`strlen + 18 frame #1: 0x00007fff95b53a54 libsystem_c.dylib`__vfprintf + 5713 frame #2: 0x00007fff95b7c6c9 libsystem_c.dylib`__v2printf + 669 frame #3: 0x00007fff95b60915 libsystem_c.dylib`_vsnprintf + 596 frame #4: 0x00007fff95b609ca libsystem_c.dylib`vsnprintf + 80 frame #5: 0x00007fff95b91d08 libsystem_c.dylib`__snprintf_chk + 128 frame #6: 0x000000010004f15a mruby`mrb_time_asctime + 282 frame #7: 0x000000010003cf0b mruby`mrb_funcall_with_block + 1515 frame #8: 0x000000010003c901 mruby`mrb_funcall_argv + 113 frame #9: 0x000000010000c023 mruby`mrb_method_missing + 275 frame #10: 0x000000010000da7b mruby`mrb_bob_missing + 123 frame #11: 0x000000010003fc13 mruby`mrb_vm_exec + 6739 frame #12: 0x000000010003e1a7 mruby`mrb_vm_run + 135 frame #13: 0x0000000100046604 mruby`mrb_top_run + 100 frame #14: 0x0000000100071adf mruby`load_exec + 1183 frame #15: 0x0000000100071623 mruby`mrb_load_file_cxt + 67 frame #16: 0x00000001000017d8 mruby`main + 904 frame #17: 0x00007fff8a9db5ad libdyld.dylib`start + 1 (lldb) register read General Purpose Registers: rax = 0x00000000ffffffff rbx = 0x00000000ffffffff rcx = 0x000000014010ef38 rdx = 0x000000014010ef38 rdi = 0x000000014010ef30 rsi = 0x00007fff95b52eb9 libsystem_c.dylib`__vfprintf + 2742 rbp = 0x00007fff5fbfbca0 rsp = 0x00007fff5fbfbca0 r8 = 0x0000000000000003 r9 = 0x000000010007f803 "%s %02d %02d:%02d:%02d %s%d" r10 = 0x00007fffa10cd401 r11 = 0x00007ffe5fb713a0 r12 = 0x000000010007f805 " %02d %02d:%02d:%02d %s%d" r13 = 0x0000000000000073 r14 = 0x0000000000000073 r15 = 0x0000000000000003 rip = 0x00007fff95b0e152 libsystem_c.dylib`strlen + 18 rflags = 0x0000000000010206 cs = 0x000000000000002b fs = 0x0000000000000000 gs = 0x0000000000000000 (lldb) q Quitting LLDB will kill one or more processes. Do you really want to proceed: [Y/n] y ``` With some symbols compiled in: ``` $ lldb ./mruby/bin/mruby crash.rb (lldb) target create "./mruby/bin/mruby" Current executable set to './mruby/bin/mruby' (x86_64). (lldb) settings set -- target.run-args "crash.rb" (lldb) r Process 1457 launched: './mruby/bin/mruby' (x86_64) Process 1457 stopped * thread #1: tid = 0x88ab040, 0x00007fff95b0e152 libsystem_c.dylib`strlen + 18, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x101946780) frame #0: 0x00007fff95b0e152 libsystem_c.dylib`strlen + 18 libsystem_c.dylib`strlen: -> 0x7fff95b0e152 <+18>: pcmpeqb (%rdi), %xmm0 0x7fff95b0e156 <+22>: pmovmskb %xmm0, %esi 0x7fff95b0e15a <+26>: andq $0xf, %rcx 0x7fff95b0e15e <+30>: orq $-0x1, %rax (lldb) up frame #1: 0x00007fff95b53a54 libsystem_c.dylib`__vfprintf + 5713 libsystem_c.dylib`__vfprintf: 0x7fff95b53a54 <+5713>: movq %rax, -0x2f8(%rbp) 0x7fff95b53a5b <+5720>: movb $0x0, -0x18f(%rbp) 0x7fff95b53a62 <+5727>: movl $0x0, -0x304(%rbp) 0x7fff95b53a6c <+5737>: movl %r14d, %r13d (lldb) up frame #2: 0x00007fff95b7c6c9 libsystem_c.dylib`__v2printf + 669 libsystem_c.dylib`__v2printf: 0x7fff95b7c6c9 <+669>: movl %eax, %ebx 0x7fff95b7c6cb <+671>: jmp 0x7fff95b7c718 ; <+748> 0x7fff95b7c6cd <+673>: callq 0x7fff95b91fe4 ; symbol stub for: __error 0x7fff95b7c6d2 <+678>: movl (%rax), %ebx (lldb) up frame #3: 0x00007fff95b60915 libsystem_c.dylib`_vsnprintf + 596 libsystem_c.dylib`_vsnprintf: 0x7fff95b60915 <+596>: testq %rbx, %rbx 0x7fff95b60918 <+599>: je 0x7fff95b60924 ; <+611> 0x7fff95b6091a <+601>: movq -0x1e0(%rbp), %rcx 0x7fff95b60921 <+608>: movb $0x0, (%rcx) (lldb) up frame #4: 0x00007fff95b609ca libsystem_c.dylib`vsnprintf + 80 libsystem_c.dylib`vsnprintf: 0x7fff95b609ca <+80>: addq $0x10, %rsp 0x7fff95b609ce <+84>: popq %rbx 0x7fff95b609cf <+85>: popq %r12 0x7fff95b609d1 <+87>: popq %r14 (lldb) up frame #5: 0x00007fff95b91d08 libsystem_c.dylib`__snprintf_chk + 128 libsystem_c.dylib`__snprintf_chk: 0x7fff95b91d08 <+128>: cmpq -0x10(%rbp), %rbx 0x7fff95b91d0c <+132>: jne 0x7fff95b91d1d ; <+149> 0x7fff95b91d0e <+134>: addq $0xd8, %rsp 0x7fff95b91d15 <+141>: popq %rbx (lldb) frame #6: 0x000000010004e8da mruby`mrb_time_asctime(mrb=0x00000001002029f0, self=mrb_value @ 0x00007fff5fbfc530) + 282 at time.c:506 503 504 tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); 505 d = &tm->datetime; -> 506 len = snprintf(buf, sizeof(buf), "%s %s %02d %02d:%02d:%02d %s%d", 507 wday_names[d->tm_wday], mon_names[d->tm_mon], d->tm_mday, 508 d->tm_hour, d->tm_min, d->tm_sec, 509 tm->timezone == MRB_TIMEZONE_UTC ? "UTC " : "", (lldb) p *tm (mrb_time) $0 = { sec = -936748721012153088 usec = 105092 timezone = MRB_TIMEZONE_LOCAL datetime = { tm_sec = 12 tm_min = 5 tm_hour = 16 tm_mday = 1 tm_mon = 6484120 tm_year = 1 tm_wday = 0 tm_yday = 1 tm_isdst = 0 tm_gmtoff = 1701667182 tm_zone = 0x000a000000000000 <no value available> } } (lldb) p *d (tm) $1 = { tm_sec = 12 tm_min = 5 tm_hour = 16 tm_mday = 1 tm_mon = 6484120 tm_year = 1 tm_wday = 0 tm_yday = 1 tm_isdst = 0 tm_gmtoff = 1701667182 tm_zone = 0x000a000000000000 <no value available> } (lldb) q Quitting LLDB will kill one or more processes. Do you really want to proceed: [Y/n] y ``` Patch to fix would be this: ``` diff --git a/mrbgems/mruby-time/src/time.c b/mrbgems/mruby-time/src/time.c index dfd4450..5dc5b34 100644 --- a/mrbgems/mruby-time/src/time.c +++ b/mrbgems/mruby-time/src/time.c @@ -238,7 +238,9 @@ time_alloc(mrb_state *mrb, double sec, double usec, enum mrb_timezone timezone) tm->usec -= 1000000; } tm->timezone = timezone; - mrb_time_update_datetime(tm); + if (!mrb_time_update_datetime(tm)) { + mrb_raisef(mrb, E_ARGUMENT_ERROR, "%S out of Time range", mrb_float_value(mrb, sec)); + } return tm; } ``` Which now returns: ``` $ ./mruby/bin/mruby crash.rb [0] crash.rb:1 crash.rb:1: -9.3674872101215e+17 out of Time range (ArgumentError) ``` Also affected `mruby-engine`: ``` $ ./bin/sandbox crash.rb ./bin/sandbox:20: [BUG] Segmentation fault at 0x0000014531cca0 ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-darwin15] -- Crash Report log information -------------------------------------------- See Crash Report log file under the one of following: * ~/Library/Logs/CrashReporter * /Library/Logs/CrashReporter * ~/Library/Logs/DiagnosticReports * /Library/Logs/DiagnosticReports for more details. Don't forget to include the above Crash Report log file in bug reports. -- Control frame information ----------------------------------------------- c:0003 p:---- s:0011 e:000010 CFUNC :sandbox_eval c:0002 p:0214 s:0006 E:000c80 EVAL ./bin/sandbox:20 [FINISH] c:0001 p:0000 s:0002 E:001810 (none) [FINISH] -- Ruby level backtrace information ---------------------------------------- ./bin/sandbox:20:in `<main>' ./bin/sandbox:20:in `sandbox_eval' -- Machine register context ------------------------------------------------ rax: 0x00000000ffffffff rbx: 0x00000000ffffffff rcx: 0x000000014531cca0 rdx: 0x000000014531cca0 rdi: 0x000000014531cca0 rsi: 0x00007fff95b52eb9 rbp: 0x00007fff528d0400 rsp: 0x00007fff528d0400 r8: 0x0000000000000003 r9: 0x000000010dd2a24a r10: 0x00007fffa10cd401 r11: 0x00007ffe44bac7b4 r12: 0x000000010dd2a24c r13: 0x0000000000000073 r14: 0x0000000000000073 r15: 0x0000000000000003 rip: 0x00007fff95b0e152 rfl: 0x0000000000010206 -- C level backtrace information ------------------------------------------- 0 ruby 0x000000010d4cb5d4 rb_vm_bugreport + 388 1 ruby 0x000000010d36d023 rb_bug_context + 483 2 ruby 0x000000010d440653 sigsegv + 83 3 libsystem_platform.dylib 0x00007fff9826d52a _sigtramp + 26 4 libsystem_c.dylib 0x00007fff95b0e152 strlen + 18 5 ??? 0x00007fff528d07f0 0x0 + 140734578362352 -- Other runtime information ----------------------------------------------- * Loaded script: ./bin/sandbox * Loaded features: 0 enumerator.so 1 thread.rb 2 rational.so 3 complex.so <snip various gems> 185 /Users/<snip>/mruby-engine/lib/mruby_engine/mruby_engine.bundle 186 /Users/<snip>/mruby-engine/lib/mruby_engine.rb [NOTE] You may have encountered a bug in the Ruby interpreter or extension libraries. Bug reports are welcome. For details: http://www.ruby-lang.org/bugreport.html Abort trap: 6 ``` Patch to fix `mruby-engine`: ``` diff --git a/ext/mruby_engine/mruby-time/src/time.c b/ext/mruby_engine/mruby-time/src/time.c index 8884a5d..2b5d770 100644 --- a/ext/mruby_engine/mruby-time/src/time.c +++ b/ext/mruby_engine/mruby-time/src/time.c @@ -236,7 +236,9 @@ time_alloc(mrb_state *mrb, double sec, double usec, enum mrb_timezone timezone) tm->usec -= 1000000; } tm->timezone = timezone; - mrb_time_update_datetime(tm); + if (!mrb_time_update_datetime(tm)) { + mrb_raisef(mrb, E_ARGUMENT_ERROR, "%S out of Time range", mrb_float_value(mrb, sec)); + } return tm; } ``` Now returns: ``` $ ./bin/sandbox crash.rb ./bin/sandbox:20:in `sandbox_eval': -9.3674872249306e+17 out of Time range (MRubyEngine::EngineRuntimeError) from ./bin/sandbox:20:in `<main>' ``` Cheers, Hugh

Report Details

Additional information and metadata

State

Closed

Substate

Resolved

Bounty

$10000.00

Submitted

Weakness

Uncontrolled Resource Consumption