网站建设| 数据库类| 图形图象| 程序设计| 现代办公| 操作系统| 考试认证| 网络技术| 软件工程| 电脑相关| 文学作品
网站开发| 网页制作| 操作系统| 图象图形| 考试认证| 数据库类| 程序设计| 硬件技术| 现代办公| 网络技术| 笑话频道
 
您的位置: 电脑书库首页-> 电脑文摘-> 网站开发-> CGI/PERL-> CGI扫描器的原理和实现过程

CGI扫描器的原理和实现过程
作者:佚名 来源:InterNet 加入时间:2005-3-28
相关文章
  • 访问标准CGI变量
  • CGI应用程序开发基础
  • ASP、CGI、ISAPI、ODBC之间的差别
  • 利用CGI方式实现Web查询
  • CGI技术及其开发
  • CGI编程--Perl的安装配置
  • CGI程式设计疑难杂症
  • CGI绝对路径和相对路径的简便设置方法
  • Perl CGI编程安全点滴
  • 相关书籍:
  • CGI,Java Script 探索
  • CGI脚本入门学习
  • CGI-Perl实例起步
  • 有很多网站为了安全起见,在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上运行良好:)

    [文章录入员:nancy]

    相关文章
  • 访问标准CGI变量
  • CGI应用程序开发基础
  • ASP、CGI、ISAPI、ODBC之间的差别
  • 利用CGI方式实现Web查询
  • CGI技术及其开发
  • CGI编程--Perl的安装配置
  • CGI程式设计疑难杂症
  • CGI绝对路径和相对路径的简便设置方法
  • Perl CGI编程安全点滴
  • 相关书籍:
  • CGI,Java Script 探索
  • CGI脚本入门学习
  • CGI-Perl实例起步
  • 本站推荐内容

    近期主机类热搜关键词:
    美国服务器 美国服务器租用 海外服务器租用 国外服务器租用

    CGI/PERL
    ASP/ASP.NET
    PHP技术
    JSP技术
    XML技术
    CGI/PERL
    WEB服务器
    WordPress专题
    其它
    电脑教程阅读排行
    ·perl中的日期处理
    ·深入研究表单提交方式:GET/P...
    ·如何利用Perl开发Intern...
    ·CGI应用程序开发基础
    ·本地调试PERL CGI程序
    ·PERL与MySQL(DBI接口...
    ·PerlScript编写ASP
    ·CGI编程--Perl的安装配置
    ·Perl用于实现遗传算法
    ·ASP、CGI、ISAPI、OD...