
今天又是喜闻乐见的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请求方法如下:
POST/GET方法可以向服务器传递参数,使用POST方法的话,传递的参数就在请求体当中。

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

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

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

/login.php 表示请求的服务器资源,它和第二行的Host字段组成完整的URL,即:
http://192.168.211.193/login.php
HTTP/1.1 则表示使用的协议名称和版本号。
常见请求头字段还包括:

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

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

HTTP/1.1表示使用的协议名称和版本号。
200 OK是状态码及状态描述,告诉客户端本次请求的处理结果。常见如下:

常见响应头字段还包括:

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=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!