本文转载自【 python 渗透测试基础-网络通讯】https://www.lzfkj.vip/post/20
python 渗透测试基础-网络通讯
简述
在很多情况下,我们所在的测试环境并没有给我们提供很多有利的条件,特别是在一些审计等级高的地方,更是直接断开物理连接;除了这个方式,还有一个比较常用的方式是逻辑断开,即在路由器或智能交换机使用配置断开目标网络的连接,那么这个时候,我们就需要自己来提供网络交互手段。常用的网络交互一般都是服务端和客户端,常用的协议有http,https,再底层一点就是TCP和UDP。对于需要快速实现的场景来说,底层的TCP和UDP(网络层)比高层(应用层)的http更方便实现。
下面我们就来看看TCP和UDP的两个实例。
TCP实例
在python中,有提供了socket方式来实现TCP,使用的时候可直接导入使用,不需要二次安装。
import socket
TCP 服务端
首先,我们来看看TCP的服务端的实现。
def tcp_server():
bind_ip = '0.0.0.0'
bind_port = 1997
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((bind_ip, bind_port))
server.listen(5)
print(f'Listing on {bind_ip}:{bind_port}')
while True:
client, addr = server.accept()
print(f'[*]Accepted connect from {addr[0]},{addr[1]}')
client_handler = threading.Thread(target=_server_handle_client, args=(client,))
client_handler.start()
代码说明
- 在“0.0.0.0“的1997端口上进行监听
- 可以接受5个客户端实例
- 只要有客户端实例接入后,就开启一个线程去处理
- 线程中的处理函数是_server_handle_client
处理函数_server_handle_client的实现
def _server_handle_client(client_socket):
"""
客户端处理
:param client_socket:
:return:
"""
request = client_socket.recv(1024)
print(f'[*] Received:{request}')
client_socket.send('ACK!'.encode())
client_socket.close()
处理函数中,实现很简单,收到消息打印,然后返回“ACK!”
以上,TCP的服务端已完成。
TCP 客户端
从以上【TCP服务端】的实现可知,我们只要连接其绑定的IP和端口即可进行数据交互。下面我们来看看客户端的实现。
def tcp_client():
"""
关于 tcp 的一个客户端
:return:
"""
target_host = '192.168.1.103'
target_port = 1997
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
address = (target_host, target_port)
client.connect(address)
pay = 'GET / HTTP/1.1\r\nHost:192.168.1.103/\r\n\r\n'
client.send(pay.encode())
response = client.recv(4096)
print(response.decode())
运行结果
运行服务端
(csdn) michaelkoo@MacBook ai_auto % python handle_socket.py
Listing on 0.0.0.0:1997
[*]Accepted connect from 192.168.1.103,49261
[*] Received:b'GET / HTTP/1.1\r\nHost:192.168.1.103/\r\n\r\n'
其中“[*]”开头的部分是客户端连接之后才打印出来的。
运行客户端
/Users/michaelkoo/work/env/csdn/code/ImgBianhua/venv/bin/python /Users/michaelkoo/work/env/csdn/code/ImgBianhua/main.py
ACK!
客户端这边也收到了服务端的响应。
TCP的另外一个客户端
除了上面实现的本地连接客户端和服务端,那么我们能不能连接非本地或者说要连接外部网络的服务端呢?答案是可以的,现在我们来连接下外部网络服务。
在这里,我们以上面的客户端为基础进行小小的调整。代码如下。
def tcp_client_2():
"""
关于 tcp 的另外一个客户端
:return:
"""
target_host = 'www.lzfkj.vip'
target_port = 80
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
address = (target_host, target_port)
client.connect(address)
pay = 'GET / HTTP/1.1\r\nHost:lzfkj.vip\r\n\r\n'
client.send(pay.encode())
response = client.recv(4096)
print(response.decode())
运行之后,我们看看结果。
HTTP/1.1 301 Moved Permanently
Server: nginx/1.16.1
Date: Mon, 01 Mar 2021 14:35:07 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
Location: https://www.lzfkj.vip/
<html>
<head><title>301 Moved Permanently</title></head>
<body>
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx/1.16.1</center>
</body>
</html>
这里返回了301,状态码为301表示,这个地址的内容被永久转移到Location去了,也就是说“http://www.lzfkj.vip” 被永久的转移到了"https://www.lzfkj.vip"。
这是出错了吗?
没有,这是www.lzfkj.vip配置了80端口的请求被转发到了443端口上去处理了。
那么,我们是怎么来发起https的请求呢?
TCP的SSL请求客户端
在python中,我们发起SSL请求,可以使用ssl库,比如我们可以这样使用。
import ssl
那么我们该如何发起一个请求呢?我们可以这样做。
def tcp_client_ssl():
"""
发起SSL请求的TCP客户端
:return:
"""
target = 'www.lzfkj.vip'
port = 443
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ssl_sock = ssl.wrap_socket(sock)
ssl_sock.connect((target, port))
ssl_sock.send('GET / HTTP/1.1\r\nHost:lzfkj.vip\r\n\r\n'.encode())
resp = ssl_sock.recv(1024)
print(resp.decode())
返回结果:
/Users/michaelkoo/work/env/csdn/code/ImgBianhua/venv/bin/python /Users/michaelkoo/work/env/csdn/code/ImgBianhua/main.py
HTTP/1.1 200 OK
Server: nginx/1.16.1
Date: Mon, 01 Mar 2021 14:54:12 GMT
Content-Type: text/html;charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
Set-Cookie: JSESSIONID=lwq6tYCGIKmYADPD26b6ucgHRO96WD5ssYWWG4tG; path=/
Content-Language: zh-CN
1f2c
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--[if IE]>
<meta http-equiv='X-UA-Compatible' content='IE=edge,chrome=1'/>
<![endif]-->
<meta name="keywords" content="python,python基础教程,python爬虫">
<meta name="description" content="python教程, 做一个有内涵的技术社区,python基础教程,python爬虫,人工智能,python django,python flask,">
<meta name="robots" content="index,follow" />
<!-- sougou-->
<meta name="sogou_site_verification" content="aFOkC"/>
<!-- baidu-->
<meta name="baidu-site-verification" content="codoHdwUv" />
<!-- 360-->
<meta name="360-si
Process finished with exit code 0
从结果中,我们可以看到,已经请求成功了。
以上,就是TCP的相关实例。
UDP实例
UDP 服务端
def udp_server():
"""
关于udp的一个服务端
:return:
"""
bind_ip = '0.0.0.0'
bind_port = 1999
server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server.bind((bind_ip, bind_port))
print(f'Listing on {bind_ip}:{bind_port}')
while True:
data = server.recvfrom(1024)
print(f'resp:{data}')
server.sendto(data[0], data[1])
UDP 客户端
def udp_client():
"""
关于udp的一个客户端
:return:
"""
target_host = '192.168.1.103'
target_port = 1999
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
address = (target_host, target_port)
client.sendto('www.lzfkj.vip'.encode(), address)
data, addr = client.recvfrom(1024)
print(data, addr)
运行结果:
服务端
resp:(b'www.lzfkj.vip', ('127.0.0.1', 51010))
客户端
(csdn) michaelkoo@MacBook code % python udp_client.py
b'www.lzfkj.vip' ('127.0.0.1', 1999)