用netfilterqueue和scapy修改HTTPheaders
Modification of HTTP headers with netfilterqueue and scapy
我想使用 netfilterqueue(0.6 - 最新)和 scapy 用我的值更改 "host" header。这是我的 iptables 规则:
iptables -A OUTPUT -p tcp --dport 80 -j NFQUEUE --queue-num 0
我有我的代码:
from netfilterqueue import *
from scapy.all import *
def change(pkt):
scapy_pkt = IP(pkt.get_payload())
if scapy_pkt.haslayer(TCP) and scapy_pkt.getlayer(TCP).dport == 80 and scapy_pkt.haslayer(Raw):
http_content = scapy_pkt.getlayer(Raw).load
list_of_headers = http_content.split("\r\n")
new_headers = []
for i in list_of_headers:
if "Host" in i:
new_headers.append("Host: google.pl")
else:
new_headers.append(i)
pkt.set_payload("\r\n".join(new_headers))
pkt.accept()
nfqueue = NetfilterQueue()
nfqueue.bind(0, change)
try:
nfqueue.run()
except KeyboardInterrupt:
print
但它不起作用..我不知道为什么..
我在更改前后打印了 header,唯一的更改是 "Host" header。 Soo.. 为什么它不起作用?有没有人有任何想法? :)
我使用 CURL 进行测试,使用 wireshark 进行调试。请求未发送。我在wireshark里找不到。
编辑:
我试图解决这个问题并将我的代码更改为:
from netfilterqueue import *
from scapy.all import *
def change(pkt):
scapy_pkt = IP(pkt.get_payload())
print dir(pkt);
if scapy_pkt.haslayer(TCP) and scapy_pkt.getlayer(TCP).dport == 80 and scapy_pkt.haslayer(Raw):
#http_content = scapy_pkt.getlayer(Raw).load
#list_of_headers = http_content.split("\r\n")
#new_headers = []
#for i in list_of_headers:
# if "Host" in i:
# new_headers.append("Host: google.pl")
# else:
# new_headers.append(i)
scapy_pkt.dst = 'google.pl'
del scapy_pkt[IP].chksum
del scapy_pkt[TCP].chksum
pkt.set_payload(str(scapy_pkt))
pkt.accept()
nfqueue = NetfilterQueue()
nfqueue.bind(0, change)
try:
nfqueue.run()
except KeyboardInterrupt:
print
但它仍然无法正常工作。在 wireshark 中,我通过 HTTP 进行过滤。但是当我通过 TCP 和 destport == 80 进行过滤时,我可以看到包,但目标是从传递给 CURL 的参数到 IP,而不是我在上面的代码中注入到数据包的 IP。
感谢提前:)
这里有几个问题。
[更新:PyPI 的最新版本 0.3 是评论中指出的 out-of-date。版本 0.6 确实 实现了 .set_payload()
] 在任何事情之前,您要使用的库似乎没有实现 .set_payload()
来改变数据包(参见 here). You may want to use nfqueue-bindings 代替。
首先(与您的第一次尝试相关),如果您必须更改数据的 length(这里就是这种情况,因为您尝试添加 HTTP header),因为您必须更改同一连接中其他数据包的序列号和确认号。
要实现这一点,您有两个选择:
- 使用透明的 HTTP 代理,它将修改或添加您想要的 headers,并将您想要篡改的连接重定向到代理。
- 确保您所做的更改将保留数据的大小(例如,将 header 替换为另一个,并注意长度)。
其次(与你的第二次尝试有关),scapy_pkt.dst = 'google.pl'
设置IP层的目的地(并且不改变数据),类似地做IP目的地NAT。这是非常不同的,应该更容易做到(不要弄乱这里的序列号/确认号)但是你必须在以下位置做同样的修改:
- 接收到的不包含数据的数据包(您的代码仅更改具有 TCP 负载的数据包,因此保留 SYN+ACK,例如,数据包未修改)。
- 您收到的数据包(您还需要一个 INPUT iptables 规则)。
我想使用 netfilterqueue(0.6 - 最新)和 scapy 用我的值更改 "host" header。这是我的 iptables 规则:
iptables -A OUTPUT -p tcp --dport 80 -j NFQUEUE --queue-num 0
我有我的代码:
from netfilterqueue import *
from scapy.all import *
def change(pkt):
scapy_pkt = IP(pkt.get_payload())
if scapy_pkt.haslayer(TCP) and scapy_pkt.getlayer(TCP).dport == 80 and scapy_pkt.haslayer(Raw):
http_content = scapy_pkt.getlayer(Raw).load
list_of_headers = http_content.split("\r\n")
new_headers = []
for i in list_of_headers:
if "Host" in i:
new_headers.append("Host: google.pl")
else:
new_headers.append(i)
pkt.set_payload("\r\n".join(new_headers))
pkt.accept()
nfqueue = NetfilterQueue()
nfqueue.bind(0, change)
try:
nfqueue.run()
except KeyboardInterrupt:
print
但它不起作用..我不知道为什么.. 我在更改前后打印了 header,唯一的更改是 "Host" header。 Soo.. 为什么它不起作用?有没有人有任何想法? :)
我使用 CURL 进行测试,使用 wireshark 进行调试。请求未发送。我在wireshark里找不到。
编辑: 我试图解决这个问题并将我的代码更改为:
from netfilterqueue import *
from scapy.all import *
def change(pkt):
scapy_pkt = IP(pkt.get_payload())
print dir(pkt);
if scapy_pkt.haslayer(TCP) and scapy_pkt.getlayer(TCP).dport == 80 and scapy_pkt.haslayer(Raw):
#http_content = scapy_pkt.getlayer(Raw).load
#list_of_headers = http_content.split("\r\n")
#new_headers = []
#for i in list_of_headers:
# if "Host" in i:
# new_headers.append("Host: google.pl")
# else:
# new_headers.append(i)
scapy_pkt.dst = 'google.pl'
del scapy_pkt[IP].chksum
del scapy_pkt[TCP].chksum
pkt.set_payload(str(scapy_pkt))
pkt.accept()
nfqueue = NetfilterQueue()
nfqueue.bind(0, change)
try:
nfqueue.run()
except KeyboardInterrupt:
print
但它仍然无法正常工作。在 wireshark 中,我通过 HTTP 进行过滤。但是当我通过 TCP 和 destport == 80 进行过滤时,我可以看到包,但目标是从传递给 CURL 的参数到 IP,而不是我在上面的代码中注入到数据包的 IP。
感谢提前:)
这里有几个问题。
[更新:PyPI 的最新版本 0.3 是评论中指出的 out-of-date。版本 0.6 确实 实现了 .set_payload()
] 在任何事情之前,您要使用的库似乎没有实现 .set_payload()
来改变数据包(参见 here). You may want to use nfqueue-bindings 代替。
首先(与您的第一次尝试相关),如果您必须更改数据的 length(这里就是这种情况,因为您尝试添加 HTTP header),因为您必须更改同一连接中其他数据包的序列号和确认号。
要实现这一点,您有两个选择:
- 使用透明的 HTTP 代理,它将修改或添加您想要的 headers,并将您想要篡改的连接重定向到代理。
- 确保您所做的更改将保留数据的大小(例如,将 header 替换为另一个,并注意长度)。
其次(与你的第二次尝试有关),scapy_pkt.dst = 'google.pl'
设置IP层的目的地(并且不改变数据),类似地做IP目的地NAT。这是非常不同的,应该更容易做到(不要弄乱这里的序列号/确认号)但是你必须在以下位置做同样的修改:
- 接收到的不包含数据的数据包(您的代码仅更改具有 TCP 负载的数据包,因此保留 SYN+ACK,例如,数据包未修改)。
- 您收到的数据包(您还需要一个 INPUT iptables 规则)。