前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Python】通过Requests模块收发HTTP报文

【Python】通过Requests模块收发HTTP报文

作者头像
一名白帽的成长史
发布2019-10-14 15:21:08
5.1K0
发布2019-10-14 15:21:08
举报

今天又是喜闻乐见的pyhton模块...

这两天学习了用python的requests模块发送HTTP报文,然后以CTF题为例进行脚本练习。

跟我一起来看看吧~

Part.1

HTTP

HTTP报文

当我们访问一个网页时,首先会向网站发送HTTP请求报文。

服务器收到请求后,回复响应包,客户端就可以在页面上看到相应的响应内容。

除了通过浏览器方式发送HTTP请求以外,还可以通过curl等一系列的工具,或者编程发包的方式进行访问。

curl之前已经讲过一期了:

【Linux】关于Curl工具与HTTP的二三事

今天就来看看python怎么发送和接收HTTP请求吧~

HTTP请求包

首先我们来看一个HTTP请求报文:

HTTP请求包可以分为请求头和请求体两部分。

服务端根据客户端请求头可以获取客户端的信息,客户端通过请求体向服务器端传递参数。

请求头和请求体之间有一个空行间隔。

首先我们来看看请求头前两行:

第一行称为请求行,POST表示请求的方法,GET和POST是最常用的HTTP方法。

HTTP请求方法如下:

  • GET:获取资源
  • POST:传输实体主体
  • PUT:传输文件 (不带验证机制,因此存在安全性问题)
  • HEAD:获取报文首部 (和GET相同,只是服务器不返回报文主体部分;一般用于确认URI有效性,以及资源更新的日期时间等)
  • DELETE:删除文件 (不带验证机制,因此存在安全性问题)
  • OPTIONS:询问支持的方法 (用于查询针对请求URI指定的资源支持的方法)
  • TRACE:追踪路径
  • CONNECT:要求用隧道协议连接代理

POST/GET方法可以向服务器传递参数,使用POST方法的话,传递的参数就在请求体当中。

使用GET方法传参,参数会直接显示在URL中:

GET请求抓包如下,此时请求体为空:

使用POST方法并不比GET方法安全,因为两者都是明文传输的,但POST没有长度限制,因此可以传递更多数据。

/login.php 表示请求的服务器资源,它和第二行的Host字段组成完整的URL,即:

http://192.168.211.193/login.php

HTTP/1.1 则表示使用的协议名称和版本号。

常见请求头字段还包括:

  • User-Agent:表示客户端操作系统和浏览器的版本信息。
  • Accept:指定客户端可以接收哪些MIME类型的信息。
  • Accept-Language:指定客户端可以接收的语言类型。
  • Referer:当前访问URL的上一个URL,即从哪个网页跳转过来。
  • Cookie,客户端发给服务器证明用户状态的信息,用来表示请求者的身份。
  • x-forwarded-for:代表客户端的IP地址,可以有多个值。

HTTP响应包

我们来看一个HTTP响应报文:

同理,响应头第一行也是响应行。

HTTP/1.1表示使用的协议名称和版本号。

200 OK是状态码及状态描述,告诉客户端本次请求的处理结果。常见如下:

常见响应头字段还包括:

  • Server: 服务端所使用的Web服务名称。
  • Set-Cookie: 服务器向客户端设置的Cookie。
  • Last-Modified: 服务端资源的最后修改时间。
  • Location: 重定向到另一个页面,通常配合302状态码使用。
  • Content-Length: 响应体部分的长度。

Part.2

Requests模块

Requests基本用法

所以浏览器访问网页,其实就是和服务器端交互HTTP报文的一个过程。

在Python第三方库当中,有一个Requests模块。

该模块可以帮助我们发送HTTP请求,接收HTTP应答。

以python3为例,首先我们需要引入request模块:

使用get方法,可以向目标网站发送Get请求:

将应答存储在res变量中,直接打印res,会得到响应码,如上图。

查看text属性可以查看响应体内容:

但这样看比较乱,使用print()函数打印,会识别其中的空格符以及换行符:

如果想查看响应头,可以使用headers方法:

使用for-in语句可以进行遍历:

查看请求头的话,就查看request.headers:

同样使用for-in语句进行遍历:

以上就是一次简单的HTTP报文交互,那么怎么来传递参数呢?

GET/POST传参

我们用以下服务器代码curl.php来进行测试:

说明如下:

  • 通过Get方法接收到的flag参数赋值给变量flag1
  • 通过POST方法接收到的flag参数赋值给变量flag2
  • 如果flag1或者flag2不为空,则打印相应参数的值

我们尝试使用get方法来传递flag=123,需要以字典的方式进行传参,如下:

服务器端成功通过GET方法获取flag,返回flag1:

通过POST发包,只需要将方法改为post即可,依然以字典方式传参:

//注意此处是data={},可以看到服务器返回flag2

另外,可以输入help(requests)查看该模块帮助信息:

Part.3

代码实现

基本代码

了解了requests模块的基本用法,我们来解一道CTF题。Bugku-web-速度要快:

打开链接http://123.206.87.240:8002/web6/

查看页面源代码,需要以post方法提交margin的值:

使用burp发包试试,可以在响应中看到flag:

这是一串base64编码,对编码不了解的可以看看这篇文章:

【Coding】聊聊字符编码那些事儿

尝试base64解码,得到flag:

但其实这里有一个坑,解码后的flag还是base64编码。再次进行解码才可以得到真实的flag:

手动发送flag显然是不行的,并没有出现最后的KEY:

因为这题名叫“速度要快”,需要用脚本实现。

我们使用前面的python3的request模块实现:

从应答中提取出flag字段:

先进行第一次base64解码,提取出新的flag:

再进行第二次flag解码:

得到最终的flag:

最后以post方法传参即可,完整代码如下:

运行脚本,发现依然没有出现flag:

会话控制

再次审题,看看刚才抓的应答报文:

给客户端发放了session进行会话控制。

会话控制主要是进行客户端身份识别,主要是通过cookie或者session两种机制实现,不了解的小伙伴可以看看之前写的这篇文章。

【HTTP】浅谈Cookie与Session那些事

requests模块中,调用Session()方法就会记录服务器发放的cookie值,并在后续发送的报文中自动添加cookie字段。

因此修改代码如下:

再次发包,成功获取flag:

以上就是requests模块的基本用法了~

Part.4

结语

以上就是今天的全部内容了,大家都明白了吗?

如果有问题,欢迎到我的微信公众号留言~

Peace!

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-10-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 一名白帽的成长史 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
命令行工具
腾讯云命令行工具 TCCLI 是管理腾讯云资源的统一工具。使用腾讯云命令行工具,您可以快速调用腾讯云 API 来管理您的腾讯云资源。此外,您还可以基于腾讯云的命令行工具来做自动化和脚本处理,以更多样的方式进行组合和重用。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档