动网论坛,站长建站首选,国内使用量最多的论坛软件 动网论坛官方技术讨论区 站长工具 申请属于您自己的免费论坛
首页 | 新闻资讯 | 网站运营 | 网络编程 | 数据库 | 服务器 | 网页设计 | 图像媒体 | 网络应用 | 搜索优化 | 资源下载 | 动网主机 | DVBOX
    本站内  互联网 ASP论坛  ASP.Net论坛  PHP论坛
  
   Cgi/Perl → 阅读文章

 CGI扫描器的原理和实现过程

作者来源: 
阅读 1560 人次 , 2006-3-29 4:05:00 


有很多网站为了安全起见,在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 13\r\nserver: microsoft-iis/5.0"//根据此标志来检查目标是否有漏洞


 


#pragma comment(lib,"ws2_32.lib")


///////////////////////////////////////////////////////////////////////////


//


//定义&初始化全局变量


//


char *sendbuff="get /null.printer\n",//发送的请求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("\nall done.");


              break;


           }


           sleep(500);


       }


    }//end of try


    //搞定,清场,收工


    __finally


    {


       //计时结束


       end=clock();


       //转换时间格式


       duration = (double)(end - start) / clocks_per_sec;


       //显示所用时间


       printf("\n\ncomplete.scan %d targets use %2.1f seconds.speed %0.3g/s\n",itotal,duration,itotal/duration);


       //关闭句柄


       closehandle(hstdout);


       closehandle(hsemaphore);


       wsacleanup();


    }


    return 0;


}


///////////////////////////////////////////////////////////////////////////


//


//回显错误信息函数


//


void showerror(char *msg)


{


    messagebox(null,msg,"error",0);


    //printf("\n%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 ********       \n",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("\ncreate 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("\n%x ioctl ok.strat conn",i);


       //connect to target


       connect(s,(struct sockaddr *)&server,sizeof(server));


       //printf("\n%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("\n%x select w return %d",i,ierr);


       //等待返回后,socket仍不可写则退出


       if((ierr==socket_error) || (ierr==0))


       {


           //printf("\n%x select return w err,exit",i);


           __leave;


       }


       //socket可写则继续


       else


       {


           //send buff to target


           //printf("\n%x send",i);


           ierr=send(s,sendbuff,sendbufflen,0);


           //printf("\n%x send return",i);


           if(ierr==socket_error)


              __leave;


       }


       //等待socket可读


       fd_zero(&r);


       fd_set(s, &r);


       //printf("\n%x start select r",i);


       ierr=select(0, &r, 0, 0, &timeout);


       //printf("\n%x select r return %d",i,ierr);


       if((ierr==socket_error) || (ierr==0))


       {


           //printf("\n%x select r err,exit",i);


           __leave;


       }


       else


       {


           //recv buff from target


           //printf("\n%x start recv",i);


           ierr=recv(s,recvbuff,recvbufflen,0);


           //printf("\n%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.        \n",inet_ntoa(server.sin_addr));


       }


    }


    __finally


    {


       if(!releasesemaphore(hsemaphore,1,null))


           showerror("thread releasesemaphore failed");


       closesocket(s);


    }


    return 0;


}


///////////////////////////////////////////////////////////////////////////


void usage(char *proname)


{


    printf("\n%s v0.1 only can find iis5 .printer mapped"


       "\npower by ey4s<ey4s@21cn.com> 2001.5.20"


       "\nhttp://www.patching.net"


       "\n\nusage:%s <startip> <endip> <threadnum> <conntimeo>"


       "\n\nnotice"


       "\n    startip stopip ==>don‘t forgot stopip must large than startip "


       "\n    threadnum ==>thread number,please input between 1-500"


       "\n    conntimeo ==>tcp connect timeout,please input between 2-6"


       "\n\nexample"


       "\n    %s 192.168.0.0 192.168.255.255 200 2",proname,proname,proname);


}


   程序在vc++6.0上编译通过,在windows2000上运行良好:)

 
 收藏本文  打印本文  论坛讨论  关闭窗口
· 上一篇:ISAPI与CGI的比较及其实现
· 下一篇:CGI技术及其开发
· 在Perl中使用sendmail发送MIME邮件
· Perl教学 第九篇 关联数组之一
· CGI教程(6)调用CGI脚本文件的例子之二
· 实战 FastCGI_2. 安装 FastCGI之五
· Perl语言的文字处理模式之三(3)


关于本站 | 联系我们 | 业务合作 | 客户案例 | 诚聘英才 | 广告合作 | 收藏本站
海口动网先锋网络科技有限公司版权所有
Copyright © 2000 - 2006 Cndw.Com
中华人民共和国电信与信息服务业务经营许可证编号 琼 ICP 020077