EOS节点远程代码执行漏洞 — EOS智能合约WASM函数表数组越界

\u6f0f\u6d1e\u62a5\u544a\u8005

Yuki Chen of Qihoo 360 Vulcan Team

Zhiniang Peng of Qihoo 360 Core Security

\u6f0f\u6d1e\u63cf\u8ff0

\u6211\u4eec\u53d1\u73b0\u4e86EOS\u533a\u5757\u94fe\u7cfb\u7edf\u5728\u89e3\u6790\u667a\u80fd\u5408\u7ea6WASM\u6587\u4ef6\u65f6\u7684\u4e00\u4e2a\u8d8a\u754c\u5199\u7f13\u51b2\u533a\u6ea2\u51fa\u6f0f\u6d1e,\u5e76\u9a8c\u8bc1\u4e86\u8be5\u6f0f\u6d1e\u7684\u5b8c\u6574\u653b\u51fb\u94fe\u3002

\u4f7f\u7528\u8be5\u6f0f\u6d1e,\u653b\u51fb\u8005\u53ef\u4ee5\u4e0a\u4f20\u6076\u610f\u7684\u667a\u80fd\u5408\u7ea6\u81f3\u8282\u70b9\u670d\u52a1\u5668,\u5728\u8282\u70b9\u670d\u52a1\u5668\u89e3\u6790\u6076\u610f\u5408\u7ea6\u540e,\u653b\u51fb\u8005\u5c31\u80fd\u591f\u5728\u8282\u70b9\u670d\u52a1\u5668\u4e0a\u6267\u884c\u4efb\u610f\u4ee3\u7801\u5e76\u5b8c\u5168\u63a7\u5236\u670d\u52a1\u5668\u3002

\u5728\u63a7\u5236\u8282\u70b9\u670d\u52a1\u5668\u540e,\u653b\u51fb\u8005\u53ef\u4ee5\u5c06\u6076\u610f\u5408\u7ea6\u6253\u5305\u8fdb\u65b0\u7684\u533a\u5757,\u8fdb\u800c\u653b\u51fb\u548c\u63a7\u5236\u5176\u4ed6\u65b0\u7684\u8282\u70b9,\u6700\u7ec8\u653b\u51fb\u548c\u63a7\u5236\u6574\u4e2aEOS\u7f51\u7edc\u3002

\u6f0f\u6d1e\u62a5\u544a\u65f6\u95f4\u7ebf

2018-5-11\xa0 \xa0 \xa0 \xa0 \xa0 \xa0 \xa0 \xa0 \u53d1\u73b0EOS\u8d8a\u754c\u5199\u7f13\u51b2\u533a\u6ea2\u51fa\u6f0f\u6d1e

2018-5-28\xa0 \xa0 \xa0 \xa0 \xa0 \xa0 \xa0 \xa0 \u6d4b\u8bd5\u5f00\u53d1\u4e86\u5b8c\u6574\u653b\u7834EOS\u8d85\u7ea7\u8282\u70b9\u7684\u6f0f\u6d1e\u9a8c\u8bc1\u7a0b\u5e8f

2018-5-28\xa0 \xa0 \xa0 \xa0 \xa0 \xa0 \xa0 \xa0 \u5c06\u6f0f\u6d1e\u7ec6\u8282\u62a5\u544a\u7ed9\u5382\u5546

2018-5-29\xa0 \xa0 \xa0 \xa0 \xa0 \xa0 \xa0 \xa0 \xa0\u5382\u5546\u5728Github\u6258\u7ba1\u4ee3\u7801\u5e93\u4e2d\u4fee\u590d\u6f0f\u6d1e,\u5e76\u5173\u95ed\u95ee\u9898\u8ddf\u8e2a\u9879

2018-5-29\xa0 \xa0 \xa0 \xa0 \xa0 \xa0 \xa0 \xa0 \u63d0\u9192\u5382\u5546\u6f0f\u6d1e\u672a\u5b8c\u5168\u4fee\u590d

\u4e00\u4e9b\u5728Telegram\u4e0a\u4e0eDaniel Larimer\u7684\u6c9f\u901a\u7ec6\u8282:

\u6211\u4eec\u5c1d\u8bd5\u548cDaniel\u6c9f\u901a\u5e76\u62a5\u544a\u6f0f\u6d1e,Daniel\u56de\u5e94\u6211\u4eec\u5728\u6ca1\u6709\u4fee\u590d\u6f0f\u6d1e\u60c5\u51b5\u4e0b\u4e0d\u4f1a\u53d1\u5e03\u65b0\u7248EOS,\u540c\u65f6\u8bf7\u6c42\u6211\u4eec\u5728\u6709\u4eba\u516c\u5f00\u6d4b\u8bd5\u6f0f\u6d1e\u524d,\u5148\u5c06\u6f0f\u6d1e\u62a5\u544a\u63d0\u4ea4\u7ed9\u4ed6\u3002

Daniel\u7ed9\u4e86\u6211\u4eec\u4e00\u4e2a\u5b98\u65b9\u7684\u90ae\u4ef6\u5730\u5740,\u8ba9\u6211\u4eec\u4ee5\u90ae\u4ef6\u5f62\u5f0f\u63d0\u4ea4\u6f0f\u6d1e\u62a5\u544a\u3002

\u6700\u540eDaniel\u627f\u8bfa\u5728EOS\u7684\u6f0f\u6d1e\u4fee\u590d\u540e,\u5c06\u7ed9\u4e88\u6211\u4eec\u516c\u5f00\u81f4\u8c22\u3002

\u6f0f\u6d1e\u7ec6\u8282

\u8fd9\u662f\u4e00\u4e2a\u7f13\u51b2\u533a\u6ea2\u51fa\u8d8a\u754c\u5199\u6f0f\u6d1e

\u6f0f\u6d1e\u5b58\u5728\u4e8e\u5728 libraries/chain/webassembly/binaryen.cpp\u6587\u4ef6\u768478\u884c,

Function binaryen_runtime::instantiate_module:

for (auto& segment : module->table.segments) {

Address offset = ConstantExpressionRunner<TrivialGlobalManager>(globals).visit(segment.offs et).value.geti32();

assert(offset + segment.data.size() <= module->table.initial);

for (size_t i = 0; i != segment.data.size(); ++i) {

table[offset + i] = segment.data[i]; <= OOB write here !

}

}

\u8fd9\u91cc\u7684table\u662f\u4e00\u4e2astd :: vector\u5305\u542b\u5728\u51fd\u6570\u8868\u4e2d\u7684\u540d\u79f0,\u5728\u5c06\u5143\u7d20\u5b58\u50a8\u5230table\u4e2d\u65f6,|offset| \u5b57\u6bb5\u6ca1\u6709\u88ab\u6b63\u786e\u68c0\u67e5\u3002\u6ce8\u610f\u5728\u8bbe\u7f6e\u8be5\u503c\u4e4b\u524d\u662f\u6709\u4e00\u4e2aassert \u65ad\u8a00\u7684,\u5b83\u4f1a\u68c0\u67e5\u504f\u79fb\u91cf,\u4f46\u4e0d\u5e78\u7684\u662fassert \u4ec5\u9002\u7528\u4e8eDebug\u7248\u672c,\u4e0d\u9002\u7528\u4e8e\u53d1\u5e03\u7248\u672c\u3002

table.resize(module->table.initial);

|module->table.initial| \u8fd9\u4e2a\u4ee3\u7801\u7247\u6bb5\u8bfb\u53d6\u7684\u503c\u662f\u6839\u636e\u51fd\u6570\u8868\u58f0\u660e,\u5728WASM\u6587\u4ef6\u4e2d\u7684\u8bfb\u53d6\u7684,\u8be5\u5b57\u6bb5\u7684\u6709\u6548\u503c\u4e3a0\u301c1024\u3002

|offset| \u5b57\u6bb5\u7684\u503c\u662f\u6839\u636e\u6570\u636e\u6bb5\u4eceWASM\u6587\u4ef6\u4e2d\u8bfb\u53d6\u7684,\u5b83\u662f\u4e00\u4e2a\u5e26\u7b26\u53f7\u768432\u4f4d\u503c\u3002

\u6240\u4ee5\u901a\u8fc7\u8fd9\u4e2a\u6f0f\u6d1e,\u6211\u4eec\u53ef\u4ee5\u5728table\u5411\u91cf\u4e4b\u540e\u7684\u5185\u5b58,\u8d8a\u754c\u5199\u5165\u4e00\u5b9a\u8303\u56f4\u7684\u5185\u5bb9\u3002

\u91cd\u73b0\u6f0f\u6d1e\u8fc7\u7a0b

1.\u7f16\u8bd1\u6700\u65b0\u7684EOS\u4ee3\u7801release\u7248\u672c

./eosio-build.sh

2.\u542f\u52a8EOS\u8282\u70b9Start EOS node, \u5b8c\u6210\u5982\u4e0b\u6240\u6709\u5fc5\u8981\u7684\u914d\u7f6e

https://github.com/EOSIO/eos/wiki/Tutorial-Getting-Started-With-Contracts

3.\u8bbe\u7f6e\u4e00\u4e2a\u6f0f\u6d1e\u5408\u7ea6

\u6211\u4eec\u63d0\u4f9b\u4e86\u4e00\u4e2a\u4f1a\u9020\u6210\u7a0b\u5e8f\u5d29\u6e83\u7684WASM\u6f0f\u6d1e\u9a8c\u8bc1\u6587\u4ef6(POC)

\u5728\u8fd9\u4e2aPoC\u4e2d, \u6211\u4eec\u7b80\u5355\u7684\u8bbe\u7f6e\u4e86 |offset| \u5b57\u6bb5\u5f15\u7528 0xfffffff\u5730\u5740,\u6240\u4ee5\u4f1a\u89e6\u53d1\u8d8a\u754c\u5199\u9020\u6210\u7a0b\u5e8f\u5d29\u6e83

\u5f00\u59cb\u6d4b\u8bd5 PoC:

cd poc

cleos set contract eosio ../poc -p eosio

\u987a\u5229\u7684\u8bdd\u6211\u4eec\u4f1a\u770b\u5230 nodeos \u8fdb\u7a0b\u51fa\u73b0 segment fault\u9519\u8bef

\u5d29\u6e83\u4fe1\u606f:

(gdb) c

Continuing.

Program received signal SIGSEGV, Segmentation fault.

0x0000000000a32f7c in eosio::chain::webassembly::binaryen::binaryen_runtime::instantiate_module(char const*, unsigned long, std::vector<unsigned char, std::allocator<unsigned char> >) ()

(gdb) x/i $pc

=> 0xa32f7c <_ZN5eosio5chain11webassembly8binaryen16binaryen_runtime18instantiate_moduleEPKcmSt6vectorIhSaIhEE+2972>:\xa0 \xa0mov\xa0 \xa0 %rcx,(%rdx,%rax,1)

(gdb) p $rdx

$1 = 59699184

(gdb) p $rax

$2 = 34359738360

Here |rdx| points to the start of the |table| vector,

And |rax| is 0x7FFFFFFF8, which holds the value of |offset| * 8.

\u5229\u7528\u6f0f\u6d1e\u5b9e\u73b0\u8fdc\u7a0b\u4ee3\u7801\u6267\u884c

\u5229\u7528\u6b64\u6f0f\u6d1e\u53ef\u4ee5\u5728nodeos\u8fdb\u7a0b\u4e2d\u5b9e\u73b0\u8fdc\u7a0b\u4ee3\u7801\u6267\u884c,\u6f0f\u6d1e\u5229\u7528\u65b9\u6cd5\u662f\u5c06\u6076\u610f\u5408\u7ea6\u4e0a\u4f20\u5230\u53d7\u5bb3\u8282\u70b9,\u5e76\u8ba9\u8282\u70b9\u89e3\u6790\u6076\u610f\u5408\u7ea6\u3002\u800c\u5728\u771f\u6b63\u7684\u653b\u51fb\u4e2d,\u653b\u51fb\u8005\u53ef\u80fd\u4f1a\u5411EOS\u4e3b\u7f51\u7edc\u53d1\u5e03\u6076\u610f\u5408\u7ea6\u3002

EOS\u8d85\u7ea7\u8282\u70b9\u89e3\u6790\u6076\u610f\u5408\u7ea6\u89e6\u53d1\u6f0f\u6d1e\u540e,\u653b\u51fb\u8005\u5c06\u53ef\u4ee5\u5b8c\u5168\u63a7\u5236\u8fd9\u4e2a\u8282\u70b9\u3002

\u653b\u51fb\u8005\u53ef\u4ee5\u7a83\u53d6\u8d85\u7ea7\u8282\u70b9\u7684\u79c1\u94a5\u6216\u63a7\u5236\u65b0\u533a\u5757\u7684\u5185\u5bb9,\u66f4\u91cd\u8981\u7684\u662f\u653b\u51fb\u8005\u53ef\u4ee5\u5c06\u6076\u610f\u5408\u7ea6\u6253\u5305\u6210\u4e00\u4e2a\u65b0\u5757\u5e76\u53d1\u5e03\u8fdb\u884c\u653b\u51fb,\u6700\u7ec8\u6574\u4e2a\u7f51\u7edc\u4e2d\u7684\u6240\u6709\u8282\u70b9\u90fd\u5c06\u53d7\u5230\u653b\u51fb\u5e76\u88ab\u63a7\u5236\u3002

\u6211\u4eec\u5b8c\u6210\u4e86\u6982\u5ff5\u6027\u7684\u6f0f\u6d1e\u9a8c\u8bc1\u7a0b\u5e8f,\u5e76\u5728\u57fa\u4e8e64\u4f4dUbuntu\u7cfb\u7edf\u7684nodeos\u4e0a\u8fdb\u884c\u4e86\u6d4b\u8bd5\u3002\u8fd9\u4e2a\u6f0f\u6d1e\u7684\u653b\u51fb\u8fc7\u7a0b\u662f\u8fd9\u6837\u7684:

1.\u653b\u51fb\u8005\u5c06\u6076\u610f\u5408\u7ea6\u4e0a\u4f20\u5230nodeos\u670d\u52a1\u5668\u3002

2.\u670d\u52a1\u5668nodeos\u8fdb\u7a0b\u89e3\u6790\u5f15\u53d1\u6f0f\u6d1e\u7684\u6076\u610f\u5408\u7ea6\u3002

3.\u4f7f\u7528\u8d8a\u754c\u5199\u5165\u7684\u539f\u751f\u4ee3\u7801,\u6211\u4eec\u53ef\u4ee5\u8986\u76d6WASM\u6a21\u5757\u5b9e\u4f8b\u7684WASM\u5185\u5b58\u7f13\u51b2\u533a,\u5728\u6076\u610fWASM\u4ee3\u7801\u7684\u5e2e\u52a9\u4e0b,\u6700\u7ec8\u53ef\u4ee5\u5728nodeos\u8fdb\u7a0b\u4e2d\u5b9e\u73b0\u4e86\u4efb\u610f\u5185\u5b58\u8bfb/\u5199\u64cd\u4f5c,\u5e76\u7ed5\u8fc7\u4e8664\u4f4d\u64cd\u4f5c\u7cfb\u7edf\u4e0a\u7684DEP / ASLR\u7b49\u5e38\u89c1\u7684\u653b\u51fb\u7f13\u89e3\u6280\u672f\u3002

4.\u6f0f\u6d1e\u5229\u7528\u4e00\u65e6\u6210\u529f,\u4f1a\u542f\u52a8\u4e00\u4e2a\u53cd\u5411shell\u8fde\u63a5\u653b\u51fb\u8005\u3002

\u53ef\u4ee5\u53c2\u8003\u6211\u4eec\u63d0\u4f9b\u7684\u89c6\u9891,\u4e86\u89e3\u8fd9\u4e2a\u6982\u5ff5\u6027\u7684\u6f0f\u6d1e\u5229\u7528\u8fc7\u7a0b,\u7a0d\u540e\u6211\u4eec\u53ef\u80fd\u4f1a\u63d0\u4f9b\u5b8c\u6574\u7684\u6f0f\u6d1e\u5229\u7528\u94fe\u3002

\uff08\u8bf7\u79fb\u6b65\u89c2\u770bhttp://v.youku.com/v_show/id_XMzYzMTg1NjYwMA==.html\uff09

\u6f0f\u6d1e\u4fee\u590d

Bytemaster\u5728EOS\u7684Github\u6258\u7ba1\u9879\u76ee\u4e2d,\u4e3a\u6211\u4eec\u62a5\u544a\u7684\u6f0f\u6d1e\u5efa\u7acb\u4e863498\u7f16\u53f7\u7684issue\u8ddf\u8fdb\u4fee\u590d\u95ee\u9898\u3002

\u4fee\u590d\u7684\u76f8\u5173\u4ee3\u7801

\u4f46\u662f\u6839\u636e\u6b64\u6b21\u6f0f\u6d1e\u53d1\u73b0\u8005Yuki\u6240\u63d0\u4ea4\u7684\u8bc4\u8bba,\u8fd9\u4e2a\u6f0f\u6d1e\u5e76\u6ca1\u6709\u5b8c\u5168\u88ab\u4fee\u590d,\u572832\u4f4d\u8fdb\u7a0b\u7684\u5904\u7406\u8fc7\u7a0b\u4e2d\u4ecd\u7136\u5b58\u5728\u95ee\u9898\u3002