分享
 
 
 

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

王朝other·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

作者: .abu.

有很多网站为了安全起见,在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 timevaltimeout;//连接、发送和接收的超时值

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_setr,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"

"\nStartIP StopIP ==>Don‘t forgot StopIP must large than StartIP "

"\nThreadNum ==>Thread number,please input between 1-500"

"\nCONNTIMEO ==>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上运行良好:)

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有