
استغلال تنفيذ أوامر بصلاحيات الجذر عبر بث UDP في خدمة infosvr لراوترات ASUS
تتضمن عدة طرازات من موجهات ASUS خدمة تُسمى infosvr تستمع على منفذ بث UDP رقم 9999 على واجهة LAN أو WLAN. تُستخدم من قِبل إحدى أدوات ASUS لتسهيل إعداد الموجه عبر تحديد مواقع الموجهات تلقائيًا على الشبكة الفرعية المحلية. تعمل هذه الخدمة بصلاحيات root وتحتوي على ثغرة تنفيذ أوامر بدون مصادقة. الكود المصدري لهذه الخدمة، بالإضافة إلى بقية أجزاء الموجه، متاح من موقع دعم ASUS.
معرّف CVE المخصص لهذه المشكلة هو CVE-2014-9583 (للأسف، ليس CVE-2014-10000 في النهاية :-/).
حاليًا، يُفترض أن جميع إصدارات البرامج الثابتة المعروفة للموجهات المعنية (RT-AC66U، RT-N66U، إلخ) معرّضة للثغرة. تم إجراء الاختبار على الإصدار 3.0.0.376.2524-g0013f52.
الموجهات/إصدارات البرامج الثابتة التالية مؤكدة التأثر بالثغرة:
| الموجه | إصدار البرنامج الثابت | تم التحقق بواسطة |
|---|---|---|
| RT-N66U | 3.0.0.4.376_1071-g8696125 | Friedrich Postelstorfer |
| RT-AC87U | 3.0.0.4.378_3754 | David Longenecker |
| RT-N56U | 3.0.0.4.374_5656 | @argilo |
| RT-AC68U | 3.0.0.4.376_3626-g9a8323e | @Arie |
| DSL-N55U | 3.0.0.4.374_4422-gc83c78f | @S2- |
| DSL-AC68U | 3.0.0.4.376_2158-g340202b | @magJ, @gitFurious |
| RT-AC66R | 3.0.0.4.376_2524-g0013f52 | @asgh |
| RT-AC66R | 3.0.0.4.376_3602 | @facerolling |
| RT-AC55U | 3.0.0.4.376_6587-gaa506e9 | @pellaeon |
| RT-N12HP_B1 | 3.0.0.4.374_1327 | @vittee |
| RT-N16 | 3.0.0.4.220 | @xorrbit |
بالإضافة إلى ذلك، فإن الموجهات التي تعمل ببرامج ثابتة مبنية على مشروع asuswrt-merlin المدعوم من المجتمع تكون معرّضة للثغرة في الإصدارات الأقدم من 376.49_5.
لا ينبغي أن تتأثر الموجهات التي تستخدم إصدارات برامج ثابتة صدرت في 12 يناير 2015 أو بعده. يتتبع الجدول التالي البلاغات عن الموجهات/البرامج الثابتة غير المتأثرة.
| الموجه | إصدار البرنامج الثابت | تم التحقق بواسطة |
|---|---|---|
| RT-AC66R | 3.0.0.4.376_3754-g5ef7c1f | @asgh |
| RT-N12HP_B1 | 3.0.0.4.376_3754-g5ef7c1f | @vittee |
تأمل المقتطف التالي من مشروع ASUSWRT-Merlin، وهو فرع محسّن من كود ASUS. يمكنك عرض الملف بالكامل (موصى به لمتعة إضافية) هنا.
177 char *processPacket(int sockfd, char *pdubuf)
178 {
...
202 phdr = (IBOX_COMM_PKT_HDR *)pdubuf;
...
207 if (phdr->ServiceID==NET_SERVICE_ID_IBOX_INFO &&
208 phdr->PacketType==NET_PACKET_TYPE_CMD)
209 {
...
تُستدعى الدالة processPacket بعد استلام حزمة بحجم INFO_PDU_LENGTH (512) بايت. مسار الكود المعرّض للثغرة تحديدًا هو main->processReq->processPacket. تقوم الخدمة بعد ذلك بتحويل الحزمة إلى بنية وتتحقق من أن حقلي ServiceID وPacketType يطابقان القيم المتوقعة.
تحتوي الكتلة التالية على ما يُعتقد أنه السبب الجذري لهذه الثغرة.
222 if (phdr->OpCode!=NET_CMD_ID_GETINFO && phdr->OpCode!=NET_CMD_ID_GETINFO_MANU)
223 {
224 phdr_ex = (IBOX_COMM_PKT_HDR_EX *)pdubuf;
225
226 // Check Mac Address
227 if (memcpy(phdr_ex->MacAddress, mac, 6)==0)
228 {
229 _dprintf("Mac Error %2x%2x%2x%2x%2x%2x\n",
230 (unsigned char)phdr_ex->MacAddress[0],
231 (unsigned char)phdr_ex->MacAddress[1],
232 (unsigned char)phdr_ex->MacAddress[2],
233 (unsigned char)phdr_ex->MacAddress[3],
234 (unsigned char)phdr_ex->MacAddress[4],
235 (unsigned char)phdr_ex->MacAddress[5]
236 );
237 return NULL;
238 }
239
240 // Check Password
241 //if (strcmp(phdr_ex->Password, "admin")!=0)
242 //{
243 // phdr_res->OpCode = phdr->OpCode | NET_RES_ERR_PASSWORD;
244 // _dprintf("Password Error %s\n", phdr_ex->Password);
245 // return NULL;
246 //}
247 phdr_res->Info = phdr_ex->Info;
248 memcpy(phdr_res->MacAddress, phdr_ex->MacAddress, 6);
249 }
تبدأ الكتلة باستثناء قيمتين من OpCode، واللتين يُفترض أنهما لا تتطلبان مصادقة بحكم التصميم. بعد ذلك، تستدعي الدالة memcpy وتتحقق بشكل مريب من قيمة الإرجاع مقابل الصفر. هذا يشير بشدة إلى أن المؤلف كان يقصد استخدام memcmp بدلًا من ذلك. ومع ذلك، حتى لو تم تنفيذ هذا الفحص بشكل صحيح، فإن معرفة عنوان MAC الخاص بالجهاز لا تكاد تكون مصادقة كافية.
الكتلة التالية تم تعليقها (commented out)، لكنها تُظهر أن المؤلف جرّب في مرحلة ما التحقق من كلمة مرور. وإن كان في هذه الحالة، كلمة المرور كانت مثبتة بشكل ثابت (hardcoded) على أنها "admin".
بالانتقال إلى الأمام، تقوم جملة switch التالية بتوزيع المعالجة بناءً على قيمة OpCode المقدمة.
251 switch(phdr->OpCode)
252 {
...
428 case NET_CMD_ID_MANU_CMD:
429 {
430 #define MAXSYSCMD 256
431 char cmdstr[MAXSYSCMD];
432 PKT_SYSCMD *syscmd;
...
440 syscmd = (PKT_SYSCMD *)(pdubuf+sizeof(IBOX_COMM_PKT_HDR_EX));
...
443 if (syscmd->len>=MAXSYSCMD) syscmd->len=MAXSYSCMD;
444 syscmd->cmd[syscmd->len]=0;
445 syscmd->len=strlen(syscmd->cmd);
446 fprintf(stderr,"system cmd: %d %s\n", syscmd->len, syscmd->cmd);
447 #if 0
...
512 #endif
513 {
514 sprintf(cmdstr, "%s > /tmp/syscmd.out", syscmd->cmd);
515 system(cmdstr);
إذا حدد المهاجم قيمة OpCode كـ NET_CMD_ID_MANU_CMD، تقوم الكتلة السابقة بمعالجة الحزمة عبر تحويلها إلى بنية PKT_SYSCMD. وبناءً عليه، فإن أي أعضاء في syscmd يتحكم بها المهاجم بالكامل. وقبل الاهتمام (غمزة) بإنهاء سلسلة الأوامر بحرف NUL، ينفذ المؤلف الأمر في السطر 514. بعد تنفيذ الأمر، يُقرأ المخرَج من الملف المؤقت ويُعاد إرساله إلى عنوان المصدر للحزمة التي بدأت الطلب.
المستخدمون النهائيون: حدّث البرنامج الثابت إلى الإصدار 3.0.0.4.376.3754 أو أحدث. من المهم ملاحظة أن وظيفة "التحقق من وجود تحديثات" في الموجه قد لا تعمل بشكل صحيح. تحقق يدويًا من إصدار البرنامج الثابت الذي تشغّله، وإذا كان أقدم، فقم بتنزيل/تثبيت البرنامج الثابت الجديد.
ASUS/Merlin: أزل وظيفة تنفيذ الأوامر عن بُعد من هذه الخدمة. حتى لو كانت محمية بمصادقة قوية، فإن بث كلمة مرور إلى الشبكة المحلية بأكملها ليس أمرًا مرغوبًا فيه حقًا. إذا كان تنفيذ الأوامر مطلوبًا فعلًا، فيجب توفيره عبر SSH أو آلية آمنة مماثلة.
يوصي David Longenecker باستخدام سكربت (JFFS) بالاشتراك مع إعداد nvram script_usbmount لقتل عملية infosvr عند الإقلاع. لمزيد من المعلومات، راجع منشوره في المدونة.
يوصي Eric Sauvageau (@RMerl) بحظر المنفذ 9999 عبر جدار الحماية. لمزيد من المعلومات، راجع منشوره على منتدى Small Net Builder.
بدلًا من ذلك، يمكنك تعطيل خدمة infosvr بقتل العملية بعد كل إقلاع. لمتعة/سخرية إضافية، استخدم الاستغلال للقيام بذلك:
$ ./asus-cmd "killall -9 infosvr"
[...]
ملاحظة: لن تحصل على استجابة لهذا الأمر. ومرة أخرى، ستحتاج إلى القيام بذلك في كل مرة يُعاد فيها تشغيل الجهاز.
بعد الإفصاح الأولي عن هذه المشكلة، عالجت عدة جهات المشكلة في قواعد أكوادها.
2015/01/08 - أصلح Eric Sauvageau هذه المشكلة في قاعدة كود asuswrt-merlin. الإصدار الأول الذي يتضمن الإصلاح هو 376.49_5. يمكن مراجعة تغييراته هنا، هنا، وهنا. 2015/01/12 - أصدرت ASUS إصدارات برامج ثابتة جديدة للأجهزة المتأثرة (3.0.0.4.376.3754) والتي يُذكر أنها غير معرّضة للثغرة.
عالجت ASUS المشكلة بضمان تعيين متغير nvram ateCommand_flag إلى 1 قبل تنفيذ الأمر المقدم. لا يتم تعيين هذا المتغير في البنيات الاعتيادية.
loc_404958:
la $v0, 0x400000
addiu $a0, $v0, (aAtecommand_fla - 0x400000) # "ateCommand_flag"
la $v0, 0x400000
addiu $a1, $v0, (g_ascONE - 0x400000) # "1"
la $v0, 0x400000
addiu $t9, $v0, (check_nvram - 0x400000)
jalr $t9 ; check_nvram
nop
lw $gp, 0x290+var_270($fp)
bnez $v0, lbl_execute_command
nop
sw $zero, 0x290+var_14($fp)
b lbl_return_zero
يحتوي المستودع الذي توجد به هذه الاستشارة الأمنية على استغلال عملي لهذه المشكلة.
$ ./asus-cmd "nvram show | grep -E '(firmver|buildno|extendno)'"
[*] sent command: nvram show | grep -E '(firmver|buildno|extendno)'
[!] received 512 bytes from 10.0.0.2:37625
0c 15 0033 54ab7bc4 41:41:41:41:41:41
0031 nvram show | grep -E '(firmver|buildno|extendno)'
[!] received 512 bytes from 10.0.0.1:9999
0c 16 0033 54ab7bc4 xx:xx:xx:xx:xx:xx
004e buildno=376
extendno_org=2524-g0013f52
extendno=2524-g0013f52
firmver=3.0.0.4
"ASUSWRT 3.0.0.4.376_1071 - تنفيذ أوامر عبر باب خلفي في الشبكة المحلية"
(هذا ما دفعني إلى النشر. استغلاله منسوخ أيضًا في مجلد others/)
http://www.exploit-db.com/exploits/35688/
"أمان: ثغرة أمنية في جانب الشبكة المحلية - تخفيف"
http://forums.smallnetbuilder.com/showthread.php?t=21774
"هل لديك موجه Asus؟ من المحتمل أن شخصًا ما على شبكتك يمكنه اختراقه"
http://arstechnica.com/security/2015/01/got-an-asus-router-someone-on-your-network-can-probably-hack-it/
"ثغرة في ASUS تتيح لمن هم على شبكتك المحلية السيطرة على الموجه اللاسلكي الخاص بك"
http://dnlongen.blogspot.com/2015/01/asus-bug-lets-those-on-your-local.html
"استغلال يسمح باختراق موجهات Asus من الشبكة المحلية"
http://www.itworld.com/article/2867255/exploit-allows-asus-routers-to-be-hacked-from-local-network.html
"موجهات Asus اللاسلكية قابلة للاستغلال من قبل أي شخص داخل الشبكة"
http://it.slashdot.org/story/15/01/09/1349229/asus-wireless-routers-can-be-exploited-by-anyone-inside-the-network
"معظم موجهات Asus متأثرة بثغرة اختطاف؛ تم نشر استغلال" http://www.zdnet.com/article/asus-routers-vulnerable-to-network-attack-exploit-published/
"ثغرة تنفيذ أوامر بصلاحيات root تطارد موجهات ASUS" http://threatpost.com/root-command-execution-flaw-haunts-asus-routers/110276