Python网安基础:编写一个端口扫描器

最近有同学问我,说想用Python写渗透辅助工具,但是却不知道该如何下手,该怎么办。其实,细化渗透测试的过程,把其中的一些使用其他工具完成的步骤,尝试着使用Python来代替就差不多能够达到他的目标。

所以今天填一个坑,用Python来实现渗透测试过程中的端口扫描。

1、什么是端口

接触过网络技术的同学大概都知道端口是什么东西,没有接触过的同学,经过下面的简单介绍应该也能明白端口是个什么东西。

在网络上我们会使用到各种各样的服务(当然不是各种各样的网站,网站所提供的多是Web服务),比如浏览网站,发送邮件,使用FTP下载某些资源,使用SSH或Telnet连接远程服务器等。这些服务有可能都是由同一个服务器提供的。

同一个服务器上提供那么多服务,怎么对他们进行区分呢?端口就是用来对他们进行区分和唯一标识的,每一个服务都使用不同的端口,就像一栋楼里面的不同房间一样。

我们常见的网站Web服务默认使用的是80端口:

用来上传和下载文件的FTP使用的是21端口:

我们通过域名或IP地址找到对应的服务器,然后再通过端口号,找到对应的服务。

有需要更加详细的介绍的同学,可以查看各种百科:https://baike.baidu.com/item/%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%AB%AF%E5%8F%A3/718781?fr=aladdin

2、扫描端口与端口服务

2.1、目的与原因

我们知道服务器的端口之上运行着对应的服务,而服务都有其版本。我们对服务器进行端口扫描,有两个目的:

  • 一是要确定服务器上开启了哪些服务;
  • 二是要确定开启的服务使用的是什么版本的服务。

这两个目的都是为了缩小行动的范围,提高行动的效率和准确性。例如我们知道了某个主机开启了80端口,那么其就很有可能提供了Web服务,我们就可以进一步通过其Web服务使用的语言(比如PHP)和框架(比如WordPress)以及框架的版本(比如4.8.2)去寻找相应的漏洞:

又比如我们经常使用SSH来远程登录服务器,其默认运行于22端口之上,如果我们扫描到了服务器开启了这个端口,那么服务器很有可能开启了远程连接的功能,如果我们获取ssh的banner得到其服务版本正好是一个存在安全漏洞的版本,那么就有了一个新的测试攻击点:

2.2、Python实现

那么我们如何使用Python进行端口的识别和扫描呢?

在Python中,有一个内置模块——socket提供了网络socket的操作,其中包含了如下函数来支持socket连接的具体功能实现:

socket() -- 创建一个新的socket对象
socketpair() -- 创建一对新的socket对象
fromfd() -- 从打开文件描述符中创建一个socket对象
fromshare() -- 从接收的数据中创建socket对象
gethostname() -- 返回当前主机名
gethostbyname() -- 映射主机名到对应的IP地址上
gethostbyaddr() -- 映射主机名或IP地址到DNS信息上
getservbyname() -- 映射服务名称和端口名称到端口号上
getprotobyname() -- 映射协议名称到一个数字上
ntohs(), ntohl() -- 将16, 32位整数从网络转换为主机字节顺序
htons(), htonl() -- 将16, 32位整数从主机转换为网络字节顺序
inet_aton() -- 将IP地址从字符串转换为32位字节数据格式
inet_ntoa() -- 将IP地址从32位字节转换为字符串
socket.getdefaulttimeout() -- 获取默认连接超时值
socket.setdefaulttimeout() -- 设置默认连接超时值
create_connection() -- 通过源地址和设置连接超时创建一个链接

我们可以通过这个模块的socket()函数创建一个socket对象来连接服务器的指定端口,比如下列代码所示:

# 引入socket模块
import socket
# 实例化一个socket对象
s = socket.socket()
# 与远程服务器的指定端口建立socket连接
s.connect(('192.168.223.152',22))
# 关闭连接
s.close()

上述代码我们就通过socket模块的socket()函数建立了对192.168.223.152这个IP地址22端口的socket连接,然后进行了连接的关闭。

当然,连接成功是不可能的,这样做一辈子都不可能连接成功。运行这段代码甚至连输出的信息都不会有:

如何得到socket连接的输出信息呢?socket对象中的一个方法——recv()或许可以帮到我们:

仔细看看这个方法的说明:

它的作用是从socket连接中返回指定大小的字节,我们继续测试一下这个方法:

# 引入socket模块
import socket
# 实例化一个socket对象
s = socket.socket()
# 与远程服务器的指定端口建立socket连接
s.connect(('192.168.223.152',22))
# 打印输出从socket连接中返回的1024个字节
print(s.recv(1024))
# 关闭连接
s.close()

在此我们测试的IP地址是一个内网主机的IP地址,我们使用的是著名的渗透测试框架Metasploit提供的靶机虚拟机Metasploitable2来作为目标主机,这是一个容易受到攻击的Linux虚拟机。这个虚拟机可以用来进行安全培训,测试安全工具,并练习常用的渗透测试技术。

有需要的同学在sourceforge进行下载,下载链接为:https://sourceforge.net/projects/metasploitable/

运行代码,我们得到了socket返回的前1024个字节(一般是服务信息的banner):

通过这个返回的banner信息,我们可以知道这个服务器的22端口是开放的,而且其服务版本是ubuntu上的openssh 4.7。

可以发现,借助于recv()方法,我们可以获取到端口服务的最基本信息,但是如果对应的端口没有开启或者有其他的限制,那么就可能会报错。比如下面这样:

# 引入socket模块
import socket
# 实例化一个socket对象
s = socket.socket()
# 与远程服务器的指定端口建立socket连接
s.connect(('192.168.223.152',88))
# 打印输出从socket连接中返回的1024个字节
print(s.recv(1024))
# 关闭连接
s.close()

我们连接目标主机的23端口,其返回了一个XXX异常错误,如下动图所示:

综上所述的情况,我们利用socket的几个方法稍微组合一下,就可以创建一个用于端口扫描的脚本。

1.首先引入socket模块:

# coding:utf-8
import socket

2.接着实例化一个socket对象:

s = socket.socket()

3.设置socket连接超时时间为3秒

s.settimeout(3)

4.接收键盘输入需扫描的端口号:

port = input("请输入端口号:")

5.连接并打印返回的字节:

try:
    s.connect(("192.168.223.152",int(port)))
    print(s.recv(1024))
    s.close()
except Exception as e:
    print(">>>扫描错误:",e)

最后完整的代码如下所示:

# coding:utf-8
import socket

s = socket.socket()
s.settimeout(3)

port = input("请输入端口号:")

try:
    s.connect(('192.168.223.152',int(port)))
    print(s.recv(1024))
    s.close()
except Exception as e:
    print(">>>扫描错误:",e)

下面,我们来测试一下这个端口扫描器:

这样,一个简单的主机端口扫描器就完成了。

如何完善和增加它的功能?我们下一篇继续:)

原文发布于微信公众号 - 州的先生(zmister2016)

原文发表时间:2018-05-19

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

3 条评论
登录 后参与评论

相关文章

来自专栏星汉技术

Storm集群搭建

2973
来自专栏云计算教程系列

如何保护PostgreSQL免受攻击

服务器刚搭建,流量少,没有任何对黑客有价值的东西,你可能就会忽视相关的安全问题。但是,许多漏洞攻击都是自动化的,专门用于查找你服务中的BUG。这些服务器主要目的...

743
来自专栏散尽浮华

php安全配置记录和常见错误梳理

通常部署完php环境后会进行一些安全设置,除了熟悉各种php漏洞外,还可以通过配置php.ini来加固PHP的运行环境,PHP官方也曾经多次修改php.ini的...

3287
来自专栏禁心尽力

Solr_全文检索引擎系统

Solr介绍: Solr 是Apache下的一个顶级开源项目,采用Java开发,它是基于Lucene的全文搜索服务。Solr可以独立运行在Jetty、Tomca...

1918
来自专栏云计算教程系列

如何在Ubuntu 14.04上安装MySQL

MySQL是一个开源数据库管理系统,通常作为流行的LAMP(Linux,Apache,MySQL,PHP / Python / Perl)堆栈的一部分来进行安装...

1111
来自专栏逸鹏说道

SQL Server安全(2/11):身份验证(Authentication)

在保密你的服务器和数据,防备当前复杂的攻击,SQL Server有你需要的一切。但在你能有效使用这些安全功能前,你需要理解你面对的威胁和一些基本的安全概念。这篇...

2788
来自专栏吴柯的运维笔记

MongoDB安装配置基础教程

MongoDB是一个C++编写的基于分布式文件存储的开源数据库系统,是一个介于关系和非关系之间的数据库,当然也属于NoSQL的行列,MongoDB最大的特点就...

2805
来自专栏云计算教程系列

如何使用Ubuntu 16.04上的osquery监视系统安全性

osquery是一个安全开源工具,它采用操作系统并将其转换为一个巨大的数据库,使用可以使用类似SQL的语句进行查询的表。通过这些查询,您可以监控文件完整性,检查...

2260
来自专栏云计算教程系列

如何在CentOS 7上安装MySQL

MySQL是一个开源数据库管理系统,通常情况下,安装它作为流行的LEMP(Linux,Nginx,MySQL/ MariaDB,PHP / Python /Pe...

932
来自专栏py+selenium

linux 安装weblogic12.1.3.0步骤

需注意:fmw_12.1.3.0.0_wls.jar     需要jdk1.7.0_15以上的版本

1825

扫码关注云+社区