<pre id="vvttv"><mark id="vvttv"><progress id="vvttv"></progress></mark></pre>
    <pre id="vvttv"></pre>

      <p id="vvttv"></p>

          <p id="vvttv"></p>

                <p id="vvttv"></p>

                <pre id="vvttv"><cite id="vvttv"><progress id="vvttv"></progress></cite></pre>

                  <output id="vvttv"><dfn id="vvttv"><th id="vvttv"></th></dfn></output>

                    <p id="vvttv"></p>

                    原文地址:http://drops.wooyun.org/papers/9893

                    前言:zip壓縮格式應用廣泛,各個平臺都有使用,Windows平臺使用來壓縮文件,Android平臺使用來作為apk文件的格式。由于zip文件格式比較復雜,在解析zip文件格式時,如果處理不當,可能導致一些有意思的邏輯漏洞,本篇文章將挑選有意思的漏洞進行解析。

                    一、文件擴展名欺騙漏洞


                    很早之前,國外安全研究人員爆料Winrar 4.x版本存在文件擴展名欺騙漏洞,黑客可以通過該漏洞誘騙受害者執行惡意程序。該漏洞的主要原理是:Winrar在文件預覽和解壓縮顯示文件名使用的是不同結構體的字段導致的。

                    1.1 zip格式文件的結構

                    在了解漏洞的原理前,先熟悉下zip格式的文件結構。

                    如果一個壓縮包文件里有多個文件,可以認為每個文件都是被單獨壓縮,然后再拼成一起。

                    一個 ZIP 文件由三個部分組成:壓縮源文件數據區+壓縮源文件目錄區+壓縮源文件目錄結束標志,如下圖:

                    enter image description here

                    1)文件頭(壓縮源文件目錄區)在文件末尾,即圖1中的File Header,記錄了索引段的偏移、大小等等。

                    2)數據段(壓縮源文件數據區)在文件開頭,即圖1中的Local Header,記錄了數據的一些基本信息,可以用來跟File Header中記錄的數據進行比較,保證數據的完整性。

                    3)Local Header還包含了文件被壓縮之后的存儲區,即圖1中的Data區域。

                    4)圖2和圖3為Local Header(圖2中的ZIPFILERECORD)和File Header(圖3中的ZIPDIRENTRY)的數據對比,兩者數據是一致的。

                    enter image description here

                    enter image description here

                    1.2 漏洞產生原因

                    Winrar在文件預覽的時候使用的是ZIPDIRENTRY下面的deFileName字段來顯示文件名,解壓縮的時候使用的是ZIPFILERECORD下面的frFileName字段來顯示文件名。如果將deFileName字段文件擴展名改成jpggif等圖片的文件擴展名,可以欺騙用戶運行惡意程序。

                    Winrar文件預覽示意圖:

                    enter image description here

                    用戶看到的是jpg圖片,打開的確實exe文件,真坑啊!

                    Winrar解壓縮文件示意圖:

                    enter image description here

                    解壓縮之后顯示的exe,兩處顯示的不一樣。

                    二、Android Master Key漏洞


                    之前,國外安全研究人員爆出第三個Android Master Key漏洞,該漏洞的主要原理是:android在解析Zip包時,沒有校驗ZipEntryHeader中的FileNameLength是否一致。

                    2.1 zip文件格式的結構

                    在了解漏洞的原理前,還是先熟悉下zip格式的文件結構。

                    如果一個壓縮包文件里有多個文件,可以認為每個文件都是被單獨壓縮,然后再拼成一起。

                    一個 ZIP 文件由三個部分組成:壓縮源文件數據區+壓縮源文件目錄區+壓縮源文件目錄結束標志,如圖1所示:

                    1)文件頭(壓縮源文件目錄區)在文件末尾,即圖1中的File Header,記錄了索引段的偏移、大小等等。

                    2)數據段(壓縮源文件數據區)在文件開頭,即圖1中的Local Header,記錄了數據的一些基本信息,可以用來跟File Header中記錄的數據進行比較,保證數據的完整性。

                    3)Local Header還包含了文件被壓縮之后的存儲區,即圖1中的Data區域。

                    4)圖2和圖3為Local Header(圖2中的ZIPFILERECORD)和File Header(圖3中的ZIPDIRENTRY)的數據對比,兩者數據是一致的。

                    enter image description here

                    enter image description here

                    2.2 漏洞產生原因

                    先來看一下是如何定位到Local Header中的Data數據:

                    off64_t dataOffset = localHdrOffset + 
                                         kLFHLen + 
                                         get2LE(lfhBuf + kLFHNameLen) +
                    

                    Data的偏移是通過Header的起始偏移+Header的大小(固定值)+Extra data的大小+文件名的大小,如下圖

                    enter image description here

                    回頭看一下,java在獲取Data偏移的處理,在讀取Extra data的長度的時候,它已經預存了文件名在FileHeader中的長度。

                    // We don't know the entry data's start position. 
                    // All we have is the position of the entry's local 
                    // header. At position 28 we find the length of the 
                    // extra data. In some cases this length differs 
                    // from the one coming in the central header. 
                    
                    RAFStream rafstrm = new RAFStream(raf, 
                             entry.mLocalHeaderRelOffset + 28); 
                    DataInputStream is = new DataInputStream(rafstrm); 
                    int localExtraLenOrWhatever = 
                    

                    漏洞就在這里產生了,如果Local Header中的FileNameLength被設成一個大數,并且FileName的數據包含原來的數據,File Header中的FileNameLength長度不變,那么底層C++運行和上層Java運行就是不一樣的流程。

                    C++ Header 64k Name Data 
                    +--------> +----------------------> +----------> 
                    length=64k classes.dex dex\035\A... dex\035\B... 
                    +--------> +---------> +----------> 
                    

                    如上面所示,底層C++的執行會讀取64k的FileName長度,而Java層由于是讀取File Header中的數據,FileName的長度依舊是11,于是Java層校驗簽名通過,底層執行會執行惡意代碼。

                      <pre id="vvttv"><mark id="vvttv"><progress id="vvttv"></progress></mark></pre>
                      <pre id="vvttv"></pre>

                        <p id="vvttv"></p>

                            <p id="vvttv"></p>

                                  <p id="vvttv"></p>

                                  <pre id="vvttv"><cite id="vvttv"><progress id="vvttv"></progress></cite></pre>

                                    <output id="vvttv"><dfn id="vvttv"><th id="vvttv"></th></dfn></output>

                                      <p id="vvttv"></p>

                                      这里只有精品视频