บทนำ
Redis คือที่เก็บข้อมูลแบบโอเพนซอร์สในหน่วยความจำที่ใช้กันอย่างแพร่หลายในฐานะแคช โบรกเกอร์ข้อความ และฐานข้อมูล NoSQL ประสิทธิภาพสูง Redis มีโครงสร้างข้อมูลที่หลากหลาย เช่น สตริง แฮช รายการ เซ็ต ชุดที่เรียงลำดับ บิตแมป HyperLogLogs และสตรีม ซึ่งได้รับการสนับสนุนโดยการดำเนินการแบบอะตอมมิกและความหน่วงต่ำมาก ความสามารถในการคงอยู่ (Persistence) สามารถใช้งานได้ผ่านสแนปช็อต RDB และ AOF และความพร้อมใช้งานสูงจะถูกส่งผ่านการจำลองข้อมูล, Sentinel และ Cluster Redis ยังรองรับการเขียนสคริปต์ฝั่งเซิร์ฟเวอร์ด้วย Lua เพื่อดำเนินการที่ซับซ้อนแบบอะตอมมิก ความเร็ว ความยืดหยุ่น และระบบนิเวศที่สมบูรณ์ทำให้ Redis เป็นองค์ประกอบสำคัญสำหรับระบบสมัยใหม่ที่ไวต่อความหน่วง
ในเดือนตุลาคม 2025 Redis ได้ออกเวอร์ชัน8.2.2ซึ่งเป็นการอัปเดตด้านความปลอดภัยที่แก้ไขช่องโหว่ 4 จุดในเอนจิน Lua แบบฝังตัว ช่องโหว่ที่ร้ายแรงที่สุดคือช่องโหว่การใช้หน่วยความจำ Lua หลังจากถูกปล่อย (use-after-free) ซึ่งอาจทำให้ผู้โจมตีหลุดออกจากแซนด์บ็อกซ์การเขียนสคริปต์และเรียกใช้โค้ดบนโฮสต์ได้ เมื่อผู้ใช้ที่ไม่น่าเชื่อถือสามารถเรียกใช้ Lua ได้ตามต้องการ การอัปเดตนี้ยังแก้ไขปัญหาการล้นค่าจำนวนเต็มในฟังก์ชัน unpack ช่องโหว่การเรียกใช้สคริปต์ข้ามผู้ใช้ และช่องโหว่การอ่านเกินขอบเขตในตัวแยกวิเคราะห์ Lua ในบทความนี้ เราจะอธิบายรายละเอียดของแต่ละ CVE อธิบายขั้น ตอนการ แก้ไข และสรุปขั้นตอนปฏิบัติเพื่อเพิ่มความปลอดภัยให้กับการใช้งาน Redis ของคุณ
ภาพรวมช่องโหว่
ก่อนจะเจาะลึกโค้ด มาดูแผนผังสั้นๆ ของสิ่งที่ 8.2.2 แก้ไขในเอ็นจิ้น Lua กันก่อน
CVE-2025-46817: การล้นของจำนวนเต็มในการแกะแพ็ก (CVSS 9.8, วิกฤต)
อาร์กิวเมนต์ที่มากเกินไปสำหรับ unpack(tbl, i, j) อาจทำให้จำนวนค่าภายในที่ต้องส่งคืนล้นได้ จำนวนที่ขาดหายไปนี้สามารถข้ามการตรวจสอบสแต็กและนำไปสู่ปัญหาขัดข้องหรือความเสียหายของหน่วยความจำ ทำให้เป็นไพรเมทีฟที่มีประโยชน์สำหรับการใช้ประโยชน์
CVE-2025-46818: การดำเนินการสคริปต์ข้ามผู้ใช้ผ่านสถานะรันไทม์ที่ใช้ร่วมกัน (CVSS 7.3, สูง)
การควบคุมที่หลวมๆ เกี่ยวกับเมตาเทเบิลและ API ที่เกี่ยวข้องกับสภาพแวดล้อมทำให้สคริปต์หนึ่งสามารถมีอิทธิพลต่อการทำงานของสคริปต์อื่นๆ ได้ ในบางกรณี หมายความว่าผู้ใช้ที่มีสิทธิ์น้อยกว่าอาจส่งผลกระทบต่อการทำงานในบริบทของผู้ใช้อื่น ซึ่งทำให้การแยกตัวอ่อนแอลง
CVE-2025-46819: การอ่าน Lua นอกขอบเขตในการวิเคราะห์สตริงยาว (CVSS 7.1, สูง)
การจัดการตัวคั่นสตริงยาว/ความคิดเห็นยาวที่เปราะบาง ([=[ … ]=] เป็นต้น) ใน Lexer ของ Lua อาจผลักดันให้เกินจุดสิ้นสุดของบัฟเฟอร์ ซึ่งอาจทำให้ Redis ล่ม และในกรณีร้ายแรงอาจเปิดเผยหน่วยความจำใกล้เคียง
CVE-2025-49844: การใช้ Lua หลังจากการปลดปล่อยในตัววิเคราะห์ (CVSS 10.0, วิกฤต)
สคริปต์ Lua ที่สร้างขึ้นสามารถจัดการการรวบรวมขยะและการแยกวิเคราะห์ได้ในลักษณะที่กระทบกับการใช้งานหลังจากการปลดปล่อยในเอ็นจิ้น Lua ที่ฝังไว้
ต่อไปเราจะดูแต่ละรายการเหล่านี้ในรายละเอียดเพิ่มเติมพร้อมทั้งตัวอย่างแพตช์ที่เกี่ยวข้อง
การแก้ไขภายใน: การเจาะลึกช่องโหว่
CVE-2025-46817: จำนวนเต็มล้นในการแกะแพ็ค
ปัญหานี้ส่งผลกระทบต่อ unpack(tbl, i, j) ของ Lua 5.1 ซึ่งฝังอยู่ใน Redis ด้วยค่า i/j ที่สูงเกินไป การคำนวณ "จำนวนผลลัพธ์ที่จะส่งคืน" อาจล้น ทำให้จำนวนผลลัพธ์ไม่ถูกต้อง และหลุดจากการตรวจสอบสแต็ก ซึ่งอาจนำไปสู่การหยุดทำงานหรือความเสียหายของหน่วยความจำ และสามารถใช้เป็นส่วนประกอบพื้นฐานสำหรับ RCE ในสถานการณ์ที่ไม่เอื้ออำนวย
แพทช์สำหรับช่องโหว่นี้สามารถดูได้ที่นี่: fc9abc7
การวิเคราะห์แพทช์
การแก้ไขนี้ทำให้การจัดการช่วงของการแกะแพ็คชัดเจนและปลอดภัย
- การคำนวณนับถูกสลับไปที่คณิตศาสตร์ที่ไม่มีเครื่องหมายที่ปลอดภัย
ก่อนการอัปเดตแพทช์ :
คงที่ int luaB_unpack (lua_State *L) {
int i, e, n;
luaL_checktype(L, 1, LUA_TTABLE);
i = luaL_optint(L, 2, 1);
e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1));
ถ้า (i > e) คืนค่า 0; /* ช่วงว่าง */
n = e – i + 1; /* อาจล้นได้ (มีเครื่องหมาย) */
ถ้า (n <= 0 || !lua_checkstack(L, n))
ส่งคืน luaL_error(L, “มีผลลัพธ์มากเกินไปที่จะแกะออก”)
/* ดัน n ผลลัพธ์… */
}
ในที่นี้ e – i + 1 จะถูกดำเนินการในรูปแบบ signed int หากค่ามีค่ามาก (เช่น 0 และ 2147483647) อาจทำให้ล้นได้ และ n <= 0 ไม่ใช่ตัวป้องกันที่เชื่อถือได้
หลังการอัปเดตแพทช์ :
คงที่ int luaB_unpack (lua_State *L) {
int i, e;
int n ที่ไม่มีเครื่องหมาย;
luaL_checktype(L, 1, LUA_TTABLE);
i = luaL_optint(L, 2, 1);
e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1));
ถ้า (i > e) คืนค่า 0; /* ช่วงว่าง */
n = (unsigned int)e – (unsigned int)i; /* องค์ประกอบลบ 1 */
ถ้า (n >= INT_MAX || !lua_checkstack(L, ++n))
ส่งคืน luaL_error(L, “มีผลลัพธ์มากเกินไปที่จะแกะออก”)
lua_rawgeti(L, 1, i); /* push arg[i] */
ในขณะที่ (i++ < e) {
lua_rawgeti(L, 1, i);
}
กลับ n;
}
จุดสำคัญ:
- ใช้ unsigned int สำหรับ span เพื่อหลีกเลี่ยงค่าติดลบ/ล้น
- ถือว่า n เป็น “นับ – 1” และเพิ่มขึ้นหนึ่งครั้งก่อนการตรวจสอบสแต็ก
- บังคับใช้ ขอบเขตบนแบบแข็ง (n >= INT_MAX → ข้อผิดพลาด)
- รับรองว่าสแต็กมีพื้นที่สำหรับผลลัพธ์ทั้งหมด ก่อน การผลักดันสิ่งใดก็ตาม
- การสร้างดัชนีอาร์เรย์ให้ชัดเจน
การกระชับที่เกี่ยวข้องในโค้ดตาราง:
หลังจากแพทช์
ถ้า (1 <= key && key <= t->sizearray)
กลับ &t->array[key-1];
แทนที่จะพึ่งพาการแคสต์แบบไม่มีเครื่องหมาย จะใช้การตรวจสอบขอบเขตที่ชัดเจน ซึ่งหลีกเลี่ยงพฤติกรรมที่แปลกประหลาดสำหรับดัชนีขนาดใหญ่หรือค่าติดลบ
การเปลี่ยนแปลงเหล่านี้ทำให้ช่วงการ unpack ที่รุนแรงไม่ทำให้เกิดการนับแบบ wrapped counts หรือการ push ที่ไม่ปลอดภัยอีกต่อไป การเรียกข้อมูลที่มีขนาดใหญ่เกินไปจะล้มเหลวโดยมีข้อผิดพลาด "มีผลลัพธ์มากเกินไปที่จะ unpack" ที่ชัดเจน แทนที่จะเสี่ยงต่อการหยุดทำงานหรือหน่วยความจำเสียหาย
CVE-2025-46819: การอ่าน Lua นอกขอบเขตในการวิเคราะห์สตริงยาว
ปัญหานี้เกิดขึ้นใน Lexer ของ Lua โดยเฉพาะในวิธีที่มันวิเคราะห์สตริงยาวๆ และคอมเมนต์ยาวๆ อย่างเช่น [=[ … ]=] ในเวอร์ชันที่มีช่องโหว่ รูปแบบตัวคั่นที่ผิดรูปหรือผิดขอบเขตบางอย่างอาจทำให้ Lexer เกินขอบเขตบัฟเฟอร์อินพุต ซึ่งอาจทำให้ Redis ล่ม (DoS) และในบางกรณีอาจทำให้ไบต์จากหน่วยความจำใกล้เคียงถูกเปิดเผย
แพทช์สำหรับช่องโหว่นี้สามารถดูได้ที่นี่: 3a1624d
การวิเคราะห์แพทช์
การแก้ไขนี้จะทำให้การจัดการสตริงยาวมีความเข้มงวดมากขึ้นและเปราะบางน้อยลง
การแยกวิเคราะห์ตัวกำหนดขอบเขตจะทำอย่างไม่คลุมเครือ
ตัวช่วยที่วิเคราะห์ลำดับเช่น [===[ และ ]===] ได้รับการอัปเดตเพื่อใช้ประเภทที่ปลอดภัยกว่าและส่งคืนค่าที่ชัดเจนและสอดคล้องกัน:
หลังจากแพทช์
ขนาดคงที่_t skip_sep(LexState *ls) {
size_t count = 0;
int s = ls->current; /* '[' หรือ ']' */
lua_assert(s == '[' || s == ']');
save_and_next(ls); /* ใช้มัน */
ในขณะที่ (ls->current == '=') { /* count '=' */
บันทึกและถัดไป(ls);
นับ ++;
}
ถ้า (ls->current == s) /* ตรงกับ '[' หรือ ']' ตัวที่สอง */
ส่งคืน count + 2; /* ตัวแบ่งแบบยาวที่ถูกต้อง */
มิฉะนั้นถ้า (นับ == 0)
กลับ 1; /* ไม่ใช่สตริงยาว/ความคิดเห็น */
อื่น
กลับ 0; /* ผิดรูป */
}
- ตัวแบ่งสตริงยาวที่ถูกต้องตอนนี้ส่งคืนความยาวที่กำหนดไว้ชัดเจนแล้ว (>= 2)
- ธรรมดา [ ตกกลับอย่างสะอาด (1).
- รูปแบบที่ผิดรูป [==… คืนค่า 0 และถือเป็นข้อผิดพลาด
การดำเนินการนี้จะปิดช่องว่างที่รูปแบบที่แปลกหรือไม่สมบูรณ์อาจทำให้ตัววิเคราะห์ข้อมูลสับสนจนต้องอ่านเกินบัฟเฟอร์
การแก้ไขออฟเซ็ตสำหรับการหั่นตัว
เมื่อทำการแยกเนื้อหาสตริงจริง แพตช์จะจัดเรียงสไลซ์ทางคณิตศาสตร์ให้ตรงกับผลลัพธ์ skip_sep:
หลังจากแพทช์:
ถ้า (seminfo) {
seminfo->ts = luaX_newstring(
ลส,
luaZ_buffer(ls->buff) + แยก,
luaZ_bufflen(ls->บัฟ) – 2 * ก.ย
);
}
ก่อนหน้านี้ ออฟเซ็ตไม่ตรงกับความหมายของตัวคั่นอย่างถูกต้อง ซึ่งอาจนำไปสู่พฤติกรรม off-by-N ที่ละเอียดอ่อน บัดนี้ จุดเริ่มต้นและความยาวได้มาจาก sep โดยตรง ดังนั้นตัววิเคราะห์คำจึงยังคงอยู่ในขอบเขต
ประเภทตรงกับสิ่งที่โค้ดทำจริงๆ
ตัวนับและดัชนีที่เกี่ยวข้องกับตรรกะนี้ใช้ชนิด unsigned/size ที่เหมาะสมแทนการใช้ signed int ที่มีภาระมากเกินไป ซึ่งจะช่วยลดความเสี่ยงของค่าติดลบหรือการห่อหุ้มที่คืบคลานเข้าสู่เลขคณิตของตัวชี้
ทั้งหมดนี้หมายความว่าแม้จะมีลำดับ [=…=[ … ]=…=] ขนาดใหญ่หรือลำดับที่ตั้งใจให้เสียหาย Lua ก็สามารถวิเคราะห์ลำดับเหล่านั้นได้อย่างถูกต้องหรือปฏิเสธด้วยข้อผิดพลาดปกติ ไม่มีเส้นทางที่สคริปต์ที่เป็นอันตรายสามารถผลักดันให้ตัววิเคราะห์วิเคราะห์ข้อมูลมองข้ามจุดสิ้นสุดของบัฟเฟอร์ได้อีกต่อไป
CVE-2025-46818: สคริปต์ Lua สามารถทำงานในบริบทของผู้ใช้รายอื่นได้
ประเด็นนี้เกี่ยวกับการจำกัดขอบเขตของสคริปต์ Lua ให้อยู่เฉพาะผู้ใช้และสภาพแวดล้อมที่สคริปต์นั้นสังกัดอยู่ในเวอร์ชันที่มีช่องโหว่ องค์ประกอบรันไทม์ที่ใช้ร่วมกัน เช่น เมตาเทเบิลบนประเภทหลักและ API สภาพแวดล้อมแบบเก่า มีความหลวมมากพอที่สคริปต์หนึ่งสามารถส่งผลต่อการทำงานของสคริปต์อื่นได้ ในบางการใช้งาน อาจทำให้การแยกส่วนระหว่างผู้ใช้ลดลง
แพทช์สำหรับช่องโหว่นี้สามารถดูได้ที่นี่: 45eac02
การวิเคราะห์แพทช์
การแก้ไขนี้มีผลหลักสองประการคือการปกป้องเมตาเทเบิลหลักและการป้องกันการเข้าถึง API เก่าที่มีความเสี่ยง
- เมตาเทเบิลประเภทแกนหลักได้รับการปกป้อง
ก่อนหน้านี้ ประเภทหลักของ Lua ที่เปิดให้ใช้งานสคริปต์ (สตริง ตัวเลข บูลีน ฯลฯ) ไม่มีข้อจำกัดที่เข้มงวดในการป้องกันการเปลี่ยนแปลงเมตาเทเบิลจากสคริปต์ของผู้ใช้ ซึ่งหมายความว่าการแก้ไขเมตาเทเบิลที่ใช้ร่วมกันอาจส่งผลกระทบต่อโค้ดอื่นๆ ที่รันในเอนจินเดียวกัน
โค้ดที่แก้ไขแล้วจะทำให้ metatable เหล่านั้นแข็งแกร่งขึ้นอย่างชัดเจนในระหว่างการตั้งค่าสภาพแวดล้อม Lua ในรูปแบบที่เรียบง่าย:
รหัสที่แก้ไข: ทำเครื่องหมาย metatable ดั้งเดิมว่าได้รับการป้องกัน
static void luaProtectPrimitiveMetatables(lua_State *L) {
ประเภท int const[] = {LUA_TSTRING, LUA_TNUMBER, LUA_TBOOLEAN, LUA_TNIL};
สำหรับ (size_t i = 0; i < sizeof(types)/sizeof(types[0]); i++) {
luaL_getmetatable(L, lua_typename(L, types[i]));
ถ้า (!lua_isnil(L, -1)) {
lua_pushliteral(L, “ได้รับการปกป้อง”);
lua_setfield(L, -2, “__metatable”); /* ล็อค metatable */
}
lua_pop(L, 1);
}
}
การป้องกันด้วยเมตาเทเบิลนี้หมายความว่าสคริปต์ของผู้ใช้ยังคงสามารถมองเห็นประเภทเหล่านี้ได้ แต่ไม่สามารถแทนที่หรือเขียนทับเมตาเทเบิลของประเภทเหล่านั้นได้ทั่วโลก การพยายามทำเช่นนั้นจะล้มเหลวอย่างชัดเจน แทนที่จะเปลี่ยนแปลงพฤติกรรมของผู้ใช้รายอื่นโดยไม่แจ้งให้ทราบล่วงหน้า
- API ของสภาพแวดล้อมแบบเดิมจะเลือกเข้าร่วมโดยชัดเจน
ปัจจุบัน API ของ Lua รุ่นเก่าที่สามารถจัดการสภาพแวดล้อมได้ถูกปิดใช้งานโดยค่าเริ่มต้นและจะเปิดใช้งานก็ต่อเมื่อผู้ใช้งานเปิดใช้งานอย่างชัดเจนเท่านั้น
ในทางแนวคิด การเปลี่ยนแปลงมีลักษณะดังนี้:
ก่อนแพตช์: API ที่ไม่รองรับจะพร้อมใช้งานในสคริปต์ env เสมอ
คงที่ const luaL_Reg redis_compat_funcs[] = {
{“getfenv”, luaB_getfenv},
{“setfenv”, luaB_setfenv},
{“นิวพร็อกซี”, luaB_newproxy},
{ว่าง, ว่าง}
};
สคริปต์CreateEnv(…) {
luaL_register(L, “_G”, redis_compat_funcs);
}
หลังจากแพตช์: ลงทะเบียนเฉพาะเมื่อตั้งค่า lua-enable-deprecated-api เท่านั้น
สคริปต์CreateEnv(…) {
หาก (server.lua_enable_deprecated_api) {
luaL_register(L, “_G”, redis_compat_funcs);
}
}
หากไม่ได้เปิดใช้งาน lua-enable-deprecated-api ฟังก์ชันเหล่านี้ก็จะไม่มีอยู่ในสภาพแวดล้อมสคริปต์ ซึ่งจะทำให้ไม่มีชุดกลไกอันทรงพลังสำหรับการจัดการข้ามบริบท
เมื่อนำมารวมกันแล้ว การเปลี่ยนแปลงเหล่านี้จะช่วยให้:
- สคริปต์ไม่สามารถแก้ไขพฤติกรรมพื้นฐานสำหรับสคริปต์อื่น ๆ ทั้งหมดโดยการเขียนเมตาเทเบิลหลักใหม่ได้
- พื้นฐานการจัดการสิ่งแวดล้อมคือ เพียง จะสามารถใช้งานได้หากผู้ปฏิบัติงานเปิดใช้งานโดยตั้งใจ
ซึ่งทำให้รันไทม์ Lua คาดเดาได้มากขึ้น และทำให้แต่ละสคริปต์อยู่ใกล้กับสิทธิพิเศษและบริบทที่ตั้งใจไว้มากขึ้น ซึ่งถือเป็นสิ่งสำคัญสำหรับการใช้งาน Redis ที่ใช้ร่วมกันหรือแบบผู้เช่าหลายราย
CVE-2025-49844: การใช้ Lua หลังจากปลดปล่อยในตัววิเคราะห์
ข้อบกพร่องนี้พบในวิธีที่ Redis ผสานรวมตัวแยกวิเคราะห์ของ Lua ภายใต้เงื่อนไขเฉพาะ สคริปต์ Lua ที่สร้างขึ้นสามารถทริกเกอร์การเก็บขยะในเวลาที่ไม่ถูกต้อง และทำให้ Redis อ่านผ่านตัวชี้ไปยังหน่วยความจำที่ถูกปลดปล่อยไปแล้ว
แพทช์สำหรับช่องโหว่นี้สามารถดูได้ที่นี่: d5728cb5795
การวิเคราะห์แพทช์
การเปลี่ยนแปลงที่สำคัญคือ Redis จะรักษาการอ้างอิงที่เหมาะสมไปยังวัตถุ Lua ที่ตัววิเคราะห์กำลังใช้ (เช่น ชื่อชิ้นส่วน) บนสแต็ก Lua ในระหว่างการวิเคราะห์ ดังนั้นตัวรวบรวมขยะจะมองว่าวัตถุเหล่านี้มีชีวิตและไม่สามารถปลดปล่อยหรือเคลื่อนย้ายวัตถุเหล่านั้นได้ก่อนเวลา

ก่อนหน้านี้ ชิ้นส่วน "ชื่อ" ถูกสร้างขึ้นแบบอินไลน์และส่งตรงไปยังตัววิเคราะห์ข้อมูล:
luaX_setinput(L, &lexstate, z, luaS_new(L, ชื่อ));
เนื่องจากค่าดังกล่าวไม่ได้ถูกยึดไว้อย่างชัดเจน (ตัวอย่างเช่น บนสแต็ก Lua) การสลับ GC หรือการดีแฟรกที่โชคร้ายบวกกับการเขียนสคริปต์ที่เข้มงวดในทางทฤษฎีอาจทำให้ตัววิเคราะห์ยังคงถือตัวชี้ไปยังสิ่งที่ถูกย้ายหรือปลดปล่อยไปแล้ว
โค้ดที่แก้ไขทำให้การเป็นเจ้าของชัดเจน:
TString *tname = luaS_new(L, ชื่อ);
setsvalue2s(L, L->top, tname); /* รักษาชื่อให้คงอยู่บนสแต็ก */
incr_top(L);
luaX_setinput(L, &lexstate, z, tname); /* ใช้สำหรับการ lexing/การแยกวิเคราะห์อย่างปลอดภัย */
/* … แยกวิเคราะห์ชิ้นส่วน … */
–L->top; /* ลบการอ้างอิงเมื่อเสร็จสิ้น */
การเก็บรักษาสถานะนี้ไว้ตลอดการแยกวิเคราะห์ ทำให้ GC และ defrag ถือว่าสถานะนี้ทำงานอยู่ และไม่สามารถเรียกคืนหรือย้ายตำแหน่งได้ระหว่างการทำงาน วิธีนี้ช่วยขจัดช่วงเวลาจำกัดที่ทำให้สามารถใช้หลังจากปลดปล่อยข้อมูลได้
สถานการณ์การใช้งานที่มีความเสี่ยง
ปัญหาเหล่านี้มีความเกี่ยวข้องโดยเฉพาะในสภาพแวดล้อมที่:
- แอปพลิเคชันใช้สคริปต์ Lua ใน Redis
- คลัสเตอร์ Redis เดียวกันจะถูกใช้ร่วมกันระหว่างทีมหรือผู้เช่า
- สามารถเข้าถึง Redis ได้โดยตรงหรือผ่านแอปพลิเคชันของคุณจากอินพุตที่ไม่น่าเชื่อถือหรือควบคุมโดยผู้ใช้
การดำเนินการที่แนะนำ
1. แปะก่อน
- อัปเกรดเป็น Redis 8.2.2 build ที่แก้ไขแล้ว
- ถือว่าสิ่งนี้มีความสำคัญสูงในทุกที่ที่โค้ดที่ไม่น่าเชื่อถือหรือเชื่อถือได้บางส่วนสามารถรัน Lua ได้ (เช่น ผ่าน EVAL / SCRIPT LOAD) หรือที่คลัสเตอร์ Redis มีการแบ่งปันระหว่างทีม/ผู้เช่า
2. ล็อคสคริปต์ Lua
- ใช้ ACL เพื่อจำกัดการเขียนสคริปต์ Lua เฉพาะกับบริการที่เชื่อถือได้เท่านั้น
- ให้ Redis อยู่บนเครือข่ายส่วนตัว ไม่มีการเปิดเผยอินเทอร์เน็ตโดยตรง
- ปล่อยให้ lua-enable-deprecated-api ปิดการใช้งาน เว้นแต่คุณจะมีความต้องการที่ชัดเจนและได้รับการตรวจสอบแล้ว
3. แบ่งส่วนงานที่ละเอียดอ่อน
- รัน Lua ที่ไม่น่าเชื่อถือหรือขับเคลื่อนโดยลูกค้าบนอินสแตนซ์ Redis ที่แยกจากกัน
- อย่าผสมสคริปต์ที่ควบคุมโดยผู้เช่ากับคลัสเตอร์ที่เก็บข้อมูลสำคัญหรือละเอียดอ่อน
4. ใช้การควบคุมความปลอดภัยเพื่อเพิ่มการมองเห็น (ไม่ใช่การทดแทนการแก้ไข)
- กำหนดค่า IPS/IDS/WAF เพื่อตรวจจับและบล็อกการเข้าถึง Redis โดยตรงและการใช้โปรโตคอล Redis ที่น่าสงสัย
- ใช้การป้องกัน EDR/AV/รันไทม์บนโฮสต์ Redis เพื่อตรวจจับพฤติกรรมที่คล้ายกับช่องโหว่
อ้างอิง:
ผู้เขียน:
Vinay Kumar
อาดริป มูเคอร์จี
นันทินี เซธ
สุวรรณจิต จักทับ



