第 2 章 用 Python 进行渗透测试
编写一个端口扫描器
Python 提供了访问 BSD 套接字的接口
Web 服务器可能位于 TCP 80 端口、电子邮件服务器在 TCP 25 端口、FTP 服务器在 TCP 21 端口
TCP 全连接扫描
为了抓取目标主机上应用的 Banner,找到开放的端口后,向它发送一个数据串并等待响应
#!/bin/env python3
# -*- coding: utf-8 -*-
# version: Python3.X
"""
2017.01.29 按照第 2 章编写一个端口扫描器
"""
import optparse
import socket
__author__ = '__L1n__w@tch'
def initialize():
parser = optparse.OptionParser("usage %prog -H <target host> -p <target port>")
parser.add_option("-H", dest="target_host", type=str, help="specify target host")
parser.add_option("-p", dest="target_port", type=int, help="specify target port")
options, args = parser.parse_args()
target_host = options.target_host
target_port = options.target_port
if target_host is None or target_port is None:
print(parser.usage)
exit(-1)
return target_host, target_port
def connect_scan(target_host, target_port):
"""
TCP 全连接扫描
:param target_host: 目标主机
:param target_port: 目标端口
:return:
"""
try:
conn_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
conn_sock.connect((target_host, target_port))
print("[+] {}/tcp open".format(target_port))
conn_sock.send(b"Violent Python")
results = conn_sock.recv(1024)
print("[+] Get Response: {}".format(results))
conn_sock.close()
except socket.timeout:
print("[-] {}/tcp closed".format(target_port))
def port_scan(target_host, target_ports):
"""
执行端口扫描操作
:param target_host: 目标主机
:param target_ports: 目标端口列表
:return:
"""
try:
target_ip = socket.gethostbyname(target_host)
except RuntimeError:
print("[-] Can not resolve {}: Unknown host".format(target_host))
return
try:
target_name = socket.gethostbyaddr(target_ip)
print("[+] Scan results for {}".format(target_name[0]))
except RuntimeError:
print("[+] Scan Results for {}".format(target_ip))
socket.setdefaulttimeout(1)
for target_port in target_ports:
print("[*] Scanning port {}".format(target_port))
connect_scan(target_host, target_port)
if __name__ == "__main__":
host, port = initialize()
port_scan(host, [port])线程扫描
多线程可以提升速度,但是有一个缺点,屏幕打印消息可能会出现乱码和失序。因此需要信号量来进行加解锁,在打印消息前使用 acquire(),打印结束后使用 release()
使用 NMAP 端口扫描代码
除了 TCP 连接扫描外,还需要其他类型的扫描,比如 ACK、RST、FIN 或 SYN-ACK 扫描等
Fyodor Vaskovich 编写的 Nmap 能使用 C 和 Lua 编写的脚本,但是 Nmap 还能被很好地整合到 Python 中。Nmap 可以生成基于 XML 的输出。
其他端口扫描类型
TCP SYN SCAN——半开放扫描,这种类型的扫描发送一个 SYN 包,启动一个 TCP 会话,并等待响应的数据包。如果收到的是一个 reset 包,表明端口是关闭的,而如果收到的是一个 SYN/ACK 包,则表示相应的端口是打开的
TCP NULL SCAN——NULL 扫描把 TCP 头中的所有标志位都设为 NULL。如果收到的是一个 RST 包,则表示相应的端口是关闭的
TCP FIN SCAN——TCP FIN 扫描发送一个表示拆除一个活动的 TCP 连接的 FIN 包,让对方关闭连接。如果收到了一个 RST 包,则表示相应的端口是关闭的
TCP XMAS SCAN——TCP XMAS 扫描发送 PSH、FIN、URG 和 TCP 标志位被设为 1 的数据包。如果收到了一个 RST 包,则表示相应的端口是关闭的
安装好 Python-Nmap 之后,就可以将 Nmap 导入到现有的脚本中,并在 Python 中直接使用 Nmap 扫描功能。创建一个 PortScanner() 类对象,则可以用这个对象完成扫描操作。PortScanner 类有一个 scan() 函数,它可将目标和端口的列表作为参数输入,并对它们进行基本的 Nmap 扫描。
用 Python 构建一个 SSH 僵尸网络
Morris 蠕虫有三种攻击方式,其中之一就是用常见的用户名和密码尝试登录 RSH 服务(remote shell)。RSH 是 1988 年问世的,它为系统管理员提供了一种很棒的远程连接一台机器,并能在主机上运行一系列终端命令对它进行管理的办法。
后来人们在 RSH 中增加一个公钥加密算法,以保护其经过网络传递的数据,这就是 SSH(Secure Shell)协议,最终 SSH 取代了 RSH。
SSH 蠕虫已经被证明是非常成功的和常见的攻击方式
用 Pexpect 与 SSH 交互
为了能完成控制台交互过程,需要用 Pexpect 模块实现与程序交互、等待预期的屏幕输出等。
以下实现 connect() 函数,该函数接收用户名、主机名和密码,返回此 SSH 连接的结果。
一旦通过验证,就可以使用一个单独的 command() 函数在 SSH 会话中发送命令。
【PS】下面这个在 macOSX 上就没跑通过,相关问题链接
用 Pxssh 暴力破解 ssh 密码
Pxssh 导入方式:import pexpect.pxssh
Pxssh 是一个包含了 pexpect 库的专用脚本,它能用预先写好的 login()、logout() 和 prompt() 等函数直接与 SSH 进行交互。
【PS】以下仅实现了连接功能,但是依旧连接不上,问题同上。
接下来稍微修改下 connect() 函数即可实现爆破。如果异常显示 socket 为 read_nonblocking,可能是 SSH 服务器被大量的连接刷爆了;如果该异常显示 pxssh 命令提示符提取困难,可以等一会再试。这里实现的 connect() 可以递归地调用另一个 connect() 函数,所以必须让只有不是由 connect() 递归调用的 connect() 函数才能够释放 connection_lock 信号,书中给的最终脚本如下:
iPhone 设备上 root 用户的默认密码为:alpine,当设备越狱后,用户会在 iPhone 上启用一个 OpenSSH 服务
利用 SSH 中的弱私钥
对于 SSH 服务器,密码验证并不是唯一的手段。除此之外,SSH 还能使用公钥加密的方式进行验证。在使用这一验证方法时,服务器和用户分别掌握公钥和私钥。使用 RSA 或是 RSA 算法,服务器能生成用于 SSH 登录的密钥。
不过,2006 年 Debian Linux 发行版中发生了一件有意思的事。软件自动分析工具发现了一行已被开发人员注释掉的代码。这行被注释掉的代码用来确保创建 SSH 密钥的信息量足够大。被注释掉之后,密钥空间的大小的熵值降低到只有 15 位大小。此时可能的密钥只有 32767 个。Rapid7 的 CSO 和 HD Moore 在两个小时内生成了所有的 1024 位和 2048 位算法的可能的密钥。而且,把结果放在了网上中,大家都可以下载使用。
由此可以进行暴力破解,在使用密钥登录 SSH 时,需要键入 ssh user@host -i keyfile -o PasswordAuthentication=no 格式的一条命令。DEMO 代码如下:
构建 SSH 僵尸网络
每个单独的僵尸或者 client 都需要有能连上某台肉机,并把命令发送给肉机的能力
利用 FTP 与 Web 批量抓 “肉机”
用 Python 构建匿名 FTP 扫描器
可以利用 Python 中的 ftplib 库编写一个小脚本,确定一个服务器是否允许匿名登录
使用 Ftplib 暴力破解 FTP 用户口令
FileZilla 之类的 FTP 客户端程序往往将密码以明文形式存储在配置文件中
只要将上面的 ftp.login() 替换上对应的用户名和密码就可以验证了
在 FTP 服务器上搜索网页
使用 nlst 函数,这会列出目录中所有文件的命令
在网页中加入恶意注入代码
直接使用 metasploit 框架生成:
上传的命令:
完整的代码 DEMO
虽然很多余,但还是把整个流程打一遍吧
Conficker,为什么努力做就够了
蠕虫病毒,Conficker(或称为 W32DownandUp),在其基本的感染方法中,Conficker 蠕虫使用了两种不同的攻击方法。首先利用了 Windows 服务器中一个服务的 0Day 漏洞。利用这个栈溢出漏洞,蠕虫能在被感染的主机上执行 ShellCode 并下载蠕虫。当这种攻击失败时,Conficker 蠕虫又尝试暴力破解默认的管理员网络共享(ADMIN$)的口令以获取肉机访问权。
使用 Metasploit 攻击 Windows SMB 服务
虽然攻击者可以通过交互驱动的方式使用 Metasploit,但 Metasploit 也能读取批处理脚本(rc)完成攻击。在攻击时,Metasploit 会顺序执行批处理文件中的命令。
编写 Python 脚本与 Metasploit 交互
首先需要扫描网段内所有开放 445 端口的主机,TCP 445 端口主要是作为 SMB 协议的默认端口用的
接下来需要编写一个监听器,这个监听器或称命令与控制信道,用于与目标主机进行远程交互
Metasploit 提供了一个 Meterpreter 的高级动态负载,当 Meterpreter 进程回连接到攻击者的计算机等候执行进一步的命令时,要使用一个名为 multi/handler 的 Metasploit 模块去发布命令。接下来需要把各条指令写入 Metasploit 的 rc 脚本中
注意脚本发送了一条指令:在同一个任务(job)的上下文环境中(-j),不与任务进行即时交互的条件下(-z)利用目标计算机上的漏洞
暴力破解口令,远程执行一个进程
需要用暴力攻击的方式破解 SMB 用户名/密码,以此获取权限在目标主机上远程执行一个进程(psexec)
整合
最主要的是 main 函数如何与 metasploit 交互,发现是通过 rc 文件
编写你自己的 0day 概念验证代码
Morris 蠕虫成功的原因在某种程度上其实就是利用了 Finger service 中的一个基于栈的缓冲区溢出
基于栈的缓冲区溢出攻击
发送漏洞利用代码
使用 Berkeley Socket API 发送,其实就是套接字发送,之前在学校课程已经接触过了,不记录了
Last updated
Was this helpful?