Buffer overflow in mrb_time_asctime
High
S
shopify-scripts
Submitted None
Actions:
Reported by
haquaman
Vulnerability Details
Technical details and impact analysis
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