PDF簽名從入門到精通(1):PDF簽名機制的漏洞分析
研究PDF文件的簽名機制有一段時間了,剛開始學習的時候就看到有提到說,被簽名的PDF內容的Range gap,會成為這個機制的漏洞,但是一直不能完全參透。直到昨天看到一篇文章的分析,才對這個問題有了一個更清晰的認識,所以做一個小小總結整理。
這裡假設讀者對PDF文件格式和數字簽名的原理有一定了解。
首先,我們來看一下PDF文檔里的Signature Dictionary:
我們知道,PDF文件是由一系列Objects組成的,通過objects的互相引用,組織成了一個文檔的appearance. 對於一個簽過名的文檔來說,最重要的就是上圖這樣一個dictionary類型的object.
用一張圖來簡單說明一下PDF的簽名機制。
上圖是一個加入了數字簽名的PDF文檔內容。被簽名的文檔內容是整個文檔,但是除去了Contents入口下面的具體值。簡單來說,是對圖中藍色部分的所有內容做哈希,然後對哈希做簽名,最後把簽名值以及相關內容寫進圖中粉色部分。
好了,這樣的方法,有什麼漏洞呢?
先簡單描繪一下PDF文檔的簽名流程:
1. 把文檔序列化成一個位元組串,中間預留出合適的空間存放簽名值,此步驟稱為preliminary serialization
2. 將位元組串預留的空間去掉,生成新的位元組串,稱為signing serialization
3. 根據signing serilization生成簽名數據塊寫入步驟一的preliminary serialization。簽名完畢。
下面來詳細描述下這個機制隱含的一個漏洞:
假設生成兩個preliminary serilization位元組串A1,A2;可以看到文檔里包含兩個catalog.
Note:一般來說,catalog是整個PDF的入口,所有用來顯示PDF所用到的內容object都是從catalog開始逐級引用的。所以理論上來說,文檔內容里允許有冗餘的object,也就是說,此object雖然在文檔中定義了,但是在顯示的時候,並沒有被引用到。
另外,我們可以知道,object的相對位置是可以改變的,只要修改了xreftable里對object的offset的描述,那麼最終顯示的效果是一樣的。
我們可以看到,通過將A1和A2中的gap去掉,生成signing serialization B1和B2之後,B1和B2可以是完全一樣的位元組串。因此最終的簽名值也會是一樣的。
當簽名值被嵌入回原來的A1和A2之後,生成了最終簽名文件C1和C2.
可以看到,C1和C2是兩個不同的文檔了,雖然是相同的xreftable,相同的catalog的offset,但是C1索引到了catalog1,C2索引到了catalog2,所以C1和C2渲染出來的文檔可以是totally不同的內容。但是簽名值確實對兩個文檔都是合法的簽名值,這有悖於數字簽名的原則。
思考下這個問題的根源來自PDF文檔允許冗餘的object存在,所以這個漏洞能否存在取決於是否認為這是PDF符合語法規範的。
參考文檔:
Collisions in PDF Signatures
推薦閱讀:
※怎樣把PDF 里的文件其中一頁單獨拿出來另存為一個文件?
※kindle對pdf的支持真的很糟糕嗎?
※PDF 應用評測:Adobe Acrobat VS PDF Expert VS PDFelement
※PDF 用什麼軟體閱讀效果較好?
※有哪些好用的pdf虛擬印表機推薦?