美文网首页
python 模拟http请求走私

python 模拟http请求走私

作者: BoatingTao | 来源:发表于2023-09-14 21:44 被阅读0次

笔者准备使用python尝试模拟下http请求走私的一些情况(CL-TE),我看网上用brup的比较多哈。
首先准备一个WebServer,笔者这里准备使用python和tornado (tornado这里是支持keep-alive的), 都用最新的吧。

  1. tornado起一个简单的web服务。
# -*- coding: utf-8 -*-
import tornado.ioloop
import tornado.web
import logging

logging.basicConfig(level=logging.DEBUG)


class MainHandler(tornado.web.RequestHandler):
    def get(self):
        try:
            data = self.request.body.decode()
            print('data: ', data)
            self.write({"code": 2000, "msg": "get ok", "data": data})
        except Exception as e:
            print(e)

    def post(self):
        try:
            data = self.request.body.decode()
            self.write({"code": 2000, "msg": "post ok", "data": data})
        except Exception as e:
            print(e)


def make_app():
    return tornado.web.Application([
        (r"/get_demo", MainHandler),
        (r"/post_demo", MainHandler)
    ])


if '__main__' == __name__:
    app = make_app()
    app.listen(address="127.0.0.1", port=9000)
    print('listen 9000 success')
    tornado.ioloop.IOLoop.current().start()
  1. python使用socket发送http协议的数据
# -*- coding: utf-8 -*-
import socket
import time

server_host = "127.0.0.1"
server_port = 9000


def main():
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client_socket.connect((server_host, server_port))
    try:
        http_request = (f"GET /get_demo HTTP/1.1\r\n"
                        f"Host: {server_host}\r\n"
                        f"Transfer-Encoding: chunked\r\n"
                        f"\r\n"
                        f"3\r\n"
                        f"abc\r\n"
                        f"0\r\n"
                        f"\r\n"
                        f"GGET /get_demo HTTP/1.1\r\n\r\n"
                        )

        client_socket.send(http_request.encode())
        response_data = b""
        time.sleep(1)
        data = client_socket.recv(1024)
        response_data += data
        print("响应内容如下:")
        print(response_data.decode())

    except Exception as e:
        print(e)


if '__main__' == __name__:
    main()

这里如果同时启用Transfer-Encoding和Content-Length,tornado会出现报错(Response with both Transfer-Encoding and Content-Length)因此请求头内只给chunked,注释掉了length。

分析结果首先 /get_demo 请求成功,但是后续的 GGET /get_demo 请求会报405(405: Method Not Allowed)。
查看tornado源码,会发现httputil.py文件里的parse_request_start_line会被反复调用,直到解析http协议出错。
一次http请求让后端执行了两次解析。第二次请求其实就类似于协议走私,因为第一次请求里面夹带了私货嘛~~~

关于Content-Length的长度问题,笔者还想分享下。
一般而言,如果length的长度大于实际body内容的长度,会导致后端服务器一直等待;如果长度小于body内容,会导致后端报错(Malformed HTTP request line)。如果内容为 "abc", 则长度为5。要注意 特殊符号 "\r\n"占了2字节,需要放在"abc"后面。也就是body实际内容为 "abc\r\n",如果想包含最后一个换行和空格,也行(也就是7)。但是超过7就不行了,会导致后端一直等待。

笔者这里列出content-length分别为 1至8的全部结果,仅供参考。

f"Content-Length: 1\r\n"
f"\r\nabc\r\n\r\n"

Content-Length 1: {"code": 2000, "msg": "get ok", "data": "a"}HTTP/1.1 400 Bad Request
Content-Length 2: {"code": 2000, "msg": "get ok", "data": "ab"}HTTP/1.1 400 Bad Request
Content-Length 3: {"code": 2000, "msg": "get ok", "data": "abc"}HTTP/1.1 400 Bad Request
Content-Length 4: {"code": 2000, "msg": "get ok", "data": "abc\r"}HTTP/1.1 400 Bad Request
Content-Length 5: {"code": 2000, "msg": "get ok", "data": "abc\r\n"}
Content-Length 6: {"code": 2000, "msg": "get ok", "data": "abc\r\n\r"}
Content-Length 7: {"code": 2000, "msg": "get ok", "data": "abc\r\n\r\n"}
Content-Length 8: 无响应

相关文章

网友评论

      本文标题:python 模拟http请求走私

      本文链接:https://www.haomeiwen.com/subject/xxkjvdtx.html