<span id="7ztzv"></span>
<sub id="7ztzv"></sub>

<span id="7ztzv"></span><form id="7ztzv"></form>

<span id="7ztzv"></span>

        <address id="7ztzv"></address>

            原文地址:http://drops.wooyun.org/tips/3168

            0x01契機


            一直沒有機會也沒下定決心認真的去研究某個安全領域,很早之前就看到好多人研究RFID,一直很憧憬那片天空,趁著老大給機會,決定選這個方向作為個人業余努力的方向。 差不多四天前入手了ACR122U,決定拿自己母校的餐廳飯卡練手。 ACR122U的使用很簡單,只要安裝上驅動,使用M1卡服務程序就可以很快破解,破解完成后查看其生成的dump文件,找到加密扇區的密碼,將密碼導入到MCT (Mifare Classic Tool),剩下的就可以完全使用MCT完成了,個人很懷疑破解過程是否完全可以通過手機(支持NFC)APP完成。ACR122U的詳細使用過程可以參考:RFID安全之某學校水卡破解,本文主要介紹目前M1卡中的數據分析和M1卡安全防護方案。

            0x02背景知識


            了解M1卡的結構可以知道M1卡共16個扇區,編號從0到15,每個扇區配備了從0到3共4個段,每個段可以保存16字節的內容。

            0x03數據分析


            閱讀《RFID安全之某學校水卡破解》可以發現該學校的水卡中數據存儲比較簡單,按照作者的分析,4號扇區的1、2號數據段(編號從0開始)存儲了水卡余額,將已知的余額32.31,換算為分為3231,再轉為16進制為C9F,即00000C9F,而0C9F取反為FFFFF360,這時比較下4號扇區的值,很容易發現規律:前四個字節不取反倒序(9F0C0000)存儲余額,接下來四個字節取反倒序(60F3FFFF)存儲余額,再接下來四個字節不取反倒序(9F0C0000)存儲余額。

            enter image description here

            上面提到的“倒序”,可以結合計算機數據存儲方式來理解:如下圖所示,變量a存儲的數據對應的16進制為0A112233,變量b存儲的數據對應的16進制為0B445566。

            enter image description here

            這樣就很明顯了,5634120A,就是變量a所代表的數據的十六進制0A123456的倒序。 作為入門教程,個人認為《RFID安全之某學校水卡破解》是非常不錯的。看完這個教程,并實踐結束后,我停下來思考這樣一個問題:M1卡的密碼破解是傻瓜式的,當然也有文章介紹破解原理,但是作為門外漢,目前我還不是特別關心,我只想找到那種破解成功,可以修改金額的快感!那么在整個M1卡的破解過程中,我自己到底起了什么作用?答案是卡片的數據分析。 《RFID安全之某學校水卡破解》中的數據分析并不難,只要知道水卡的余額就可以定位卡片中余額數據的存儲位置,細心的讀者肯定可以發現文中的截圖5號扇區也存在非0值塊,作者在《RFID安全之某學校水卡破解后記——不留后患》中作了進一步分析;《任意修改學校食堂飯卡余額》這篇文章所描述的卡片和《RFID安全之某學校水卡破解》的分析非常相似;而另一篇《破解學校水卡---||||RFID Hack初探 》文中的數據就更簡單了,只有余額和消費金額之和,連取反的校驗都沒做。 分析了幾篇圖文教程式入門文章,加上自己的實際破解過程,總結了一下數據分析的經驗。 首先,需要收集信息,然后可以通過數據比對法定位余額,如果卡片數據采取了校驗保護,可以采用試錯法進行排查定位,正如《RFID安全之某學校水卡破解后記——不留后患》中所用到的方法。

            0x03.1比對法

            比對法,就是將已知數據換算成十六進制,尋找卡片中能與之對應的數據,從而確定卡片中對應的存儲位置所存儲的數據的意義,或者將卡片中變化的字節轉成十進制,判斷是否存在相應的數據信息。 最常用的比對值當然是卡片余額,還有當前的消費金額,或者是累計的消費金額,這兩個數據有出現在前文的引用文中。那么除了這些,還應該考慮哪些數據呢?這里我作一個簡單的羅列:消費次數、日期、時間、讀卡器編號、卡號(非UID)等 之所以認為上面的數據可以存儲在卡片中,是因為兩個字節(16bit),不考慮符號位,可以表示的最大數值是65535,一個字節(8bit)可以表示最大數值為255。一張卡按四年有效期來算的話,每天要刷44次才能再四年內超過這個數值;日期也可以用兩個字節來表示,可以選擇整體表示,譬如12月31日,記為1231,對應到16進制04CF,也可以一個字節表示月一個字節表示日,仍然是12月31日,可以記為0C1F(1F=31);時間(不考慮秒)的最大表示數字是23:59,也可以參考日期的表示方式,選擇不同的方案;讀卡器編號,一般情況下一個單位也不會同時具有65535臺讀卡設備;卡號,這里卡號一般可以用兩個字節表示,如果單位人數較多(超過65535),也可以使用四個字節表示,卡號的意義可以標識一個人,也可以標識單位內的一個部門等。

            0x03.2試錯法

            試錯法就是針對一些不明意義的字節(可能是校驗字節),通過修改已知意義的字節來確定其關聯性,找出不明意義字節的計算方法。 數據比對法,有時并不能分析出所有數據塊的數據,這時可以考慮試錯法來確定隱晦數據和哪些字段有關聯,譬如下面的案例: 卡片只有0號扇區有數據:

            43 9A ** ** ** ** 04 00 46 BA 14 12 51 10 03 10             第0段
            0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
            37 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1D 05 60             第2段
            11 01 ** ** ** ** FF 07 80 69 FF FF FF FF FF FF             第3段
            

            第0段為廠商寫死的UID,不可修改,經過多次信息收集發現第1段的數據是不變的,變化的只有第二段,經過比對法,發現第1段的4A 3D是卡號,第2段的01 C2是本次消費金額,0E A6是余額,027D是消費和充值次數,081D是日期,到此,第2段中還有前四個字節以及最后兩個字節的意義不明。 下面通過試錯來定義各個字節的意義 嘗試直接修改K1余額,讀卡會失敗,于是認為刷卡消費過程存在驗證,余額和消費金額并不能構成驗證對,所以認為驗證信息在意義不明的6個字節內。 只修改消費金額也會導致讀卡失敗。 嘗試使用K2的值整體替換K1的第2段,結果讀卡依然失敗。 最后嘗試使用K2的值,整體替換K1的第1和第2段,等價于復制卡片,終于讀卡成功了。 通過以上幾步,可以確定消費讀卡器在進行扣錢之前,會先校驗卡片的正確性,校驗值和余額、消費金額以及第1段中的數據都有關聯。為了進一步定位信息,做出如下試錯計劃:

            1、修改卡號,確認卡片是否可正確識別; 2、逐個修改第2段中已知意義的字節,確認卡片是否可正確識別,排除與校驗無關的字節 3、對第2段中不明意義的6個字節逐個修改,確認卡片是否可正確識別,排除非校驗字節 4、對第1段中的3個不明意義的字節逐個修改,確認卡片是否可正確識別 本質是就是對所有數據字節進行試錯,排除與校驗無關的字節! 通過以上過程縮小與校驗相關的字節,再結合比對法中找出的已知意義的字節,從而確定不明意義字節的意義和校驗算法。 由于刷卡條件限制,以上案例尚未破解完成,試錯法也有待該案例進一步驗證。 破解過程需要大膽猜測,努力求證!

            0x04卡片防護


            破解和防護是一對冤家,既然M1卡這么容易被破解,那有沒有合適的防護方法呢?上一小節中提到的校驗案例就算是一個很小的防護手段,但是依然存在很大被破解的風險。 為了降低水卡和飯卡被破解的風險,同時又不增加替換M1卡的成本,可以完全加密數據字段,基于密鑰和算法保密性,保證即使可以通過驗證攻擊獲取到M1卡中的數據,黑客也無法快速判斷各個數據字段的意義,從而無法完成余額修改! 譬如,參考上一小節的校驗案例,如果所有數據再與一個2字節的密鑰進行異或處理,這時就無法簡單的通過比對法判斷出哪些字節是余額、哪些是消費金額,進一步降低了破解風險。當然針對密鑰可以設計一套動態密鑰方案,效果類似支付寶令(需要考慮如何處理長期不使用的卡片),而加密算法可以選擇更加復雜的對稱加密算法,只要保證不會對消費刷卡機造成過大延遲即可。

            0x05復制攻擊


            數據加密雖然可以增加黑客分析卡片數據的難度,降低黑客惡意修改余額的風險,但是無法應對卡片復制攻擊! 復制攻擊可能造成的后果是盜刷他人飯卡或水卡,這一點是最容易理解的,當然前提是黑客可以接觸到別人的飯卡或水卡。 除了這一點,復制攻擊是否還存在其它危害? 在分析這之前,需要明確幾個前提,1)刷卡機中會記錄哪些信息;2)我們假設刷卡機沒7天向中央數據庫服務器提交一次數據,刷卡機向中央數據庫提交的是哪些數據。 如果刷卡機只記錄一張卡片的最后一次消費記錄,那么其向數據庫提交的數據必然要包含余額信息。如果在刷卡機兩次向數據庫提交數據的時間間隔內,利用復制的卡片(復制較早的卡片數據)做最后一次消費,那么真實卡片消費的數據就會被覆蓋掉。 當然個人猜測目前的刷卡機應該會記錄卡號(非UID)、消費累計金額、消費次數,同步數據庫時只需要基于卡號找到對應的記錄,然后將余額減去消費累計金額、總消費次數疊加本次提交的消費次數。這種情況下,復制攻擊就只能盜刷他人的飯卡或水卡余額了,但是即使是這樣,如果不影響被復制的卡,也算是一種修改余額的方式,畢竟刷卡機不會基于數據庫信息向卡片寫數據! 本來以為復制攻擊就這些影響了,晚上睡覺前忽然想到,既然可以復制別人的卡,為什么不能復制自己的卡呢。T1時間充值m元,并記錄下卡內的數據信息D1,消費一段時間后,T2時間卡內余額n元(n<m),此時將數據信息D1重新拷貝回卡內,卡片信息重新回到T1時間的狀態,等價于T1-T2時間段內沒做任何消費!這種情況即使是使用UID作校驗也無法防護了,除非刷卡機是在線實時查詢數據庫的,后來發現這種攻擊方式12年就有人提出了,并稱之為重放/重置攻擊

            0x06后記


            剛接觸RFID,有描述不準確或錯誤的地方,請輕拍指正!

            0x07卷土再來


            基于0x05節的分析和實際驗證,通過復制攻擊(重放攻擊)已經實現0x03.2節示例中卡片的余額修改,但是為了論證 0x03.2節試錯法的可行性,規劃了如下方案:

            43 9A ** ** ** ** 04 00 46 BA 14 12 51 10 03 10             第0段
            0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
            37 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1D 05 60             第2段
            11 01 ** ** ** ** FF 07 80 69 FF FF FF FF FF FF             第3段
            

            針對以上信息,對第1、2段內容,逐字節進行試錯,確認卡片是否可讀 驗證結果如下: 1、修改第1段第0字節

            0D 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
            37 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1D 05 60             第2段
            

            2、修改第1段第1字節

            0C 0E 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
            37 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1D 05 60             第2段
            

            3、修改第1段第2字節

            0C 0D 0D 11 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
            37 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1D 05 60             第2段
            

            4、修改第1段第3字節

            0C 0D 0C 12 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
            37 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1D 05 60             第2段
            

            5、修改第1段第4字節

            0C 0D 0C 11 01 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
            37 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1D 05 60             第2段
            

            6、修改第1段第5字節

            0C 0D 0C 11 00 01 4A 3D 00 2D 00 00 00 01 00 47             第1段
            37 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1D 05 60             第2段
            

            7、修改第1段第6字節

            0C 0D 0C 11 00 00 4B 3D 00 2D 00 00 00 01 00 47             第1段
            37 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1D 05 60             第2段
            

            8、修改第1段第7字節

            0C 0D 0C 11 00 00 4A 3E 00 2D 00 00 00 01 00 47             第1段
            37 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1D 05 60             第2段
            

            9、修改第1段第8字節

            0C 0D 0C 11 00 00 4A 3D 01 2D 00 00 00 01 00 47             第1段
            37 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1D 05 60             第2段
            

            10、修改第1段第9字節 0C 0D 0C 11 00 00 4A 3D 00 2E 00 00 00 01 00 47 第1段 37 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1D 05 60 第2段

            11、修改第1段第10字節 0C 0D 0C 11 00 00 4A 3D 00 2D 01 00 00 01 00 47 第1段 37 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1D 05 60 第2段

            12、修改第1段第11字節

            0C 0D 0C 11 00 00 4A 3D 00 2D 00 01 00 01 00 47             第1段
            37 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1D 05 60             第2段
            

            13、修改第1段第12字節

            0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 01 01 00 47             第1段
            37 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1D 05 60             第2段
            

            14、修改第1段第13字節

            0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 02 00 47             第1段
            37 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1D 05 60             第2段
            

            15、修改第1段第14字節

            0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 01 47             第1段
            37 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1D 05 60             第2段
            

            16、修改第1段第15字節

            0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 48             第1段
            37 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1D 05 60             第2段
            

            17、修改第2段第0字節

            0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
            38 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1D 05 60             第2段
            

            18、修改第2段第1字節

            0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
            37 0C BC E4 01 C2 00 00 0E A6 02 7D 08 1D 05 60             第2段
            

            19、修改第2段第2字節

            0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
            37 0B BD E4 01 C2 00 00 0E A6 02 7D 08 1D 05 60             第2段
            

            20、修改第2段第3字節

            0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
            37 0B BC E5 01 C2 00 00 0E A6 02 7D 08 1D 05 60             第2段
            

            21、修改第2段第4字節

            0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
            37 0B BC E4 02 C2 00 00 0E A6 02 7D 08 1D 05 60             第2段
            

            22、修改第2段第5字節

            0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
            37 0B BC E4 01 C3 00 00 0E A6 02 7D 08 1D 05 60             第2段
            

            23、修改第2段第6字節

            0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
            37 0B BC E4 01 C2 01 00 0E A6 02 7D 08 1D 05 60             第2段
            

            24、修改第2段第7字節

            0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
            37 0B BC E4 01 C2 00 01 0E A6 02 7D 08 1D 05 60             第2段
            

            25、修改第2段第8字節

            0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
            37 0B BC E4 01 C2 00 00 0F A6 02 7D 08 1D 05 60             第2段
            

            26、修改第2段第9字節

            0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
            37 0B BC E4 01 C2 00 00 0E A7 02 7D 08 1D 05 60             第2段
            

            27、修改第2段第10字節

            0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
            37 0B BC E4 01 C2 00 00 0E A6 03 7D 08 1D 05 60             第2段
            

            28、修改第2段第11字節

            0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
            37 0B BC E4 01 C2 00 00 0E A6 02 7E 08 1D 05 60             第2段
            

            29、修改第2段第12字節

            0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
            37 0B BC E4 01 C2 00 00 0E A6 02 7D 09 1D 05 60             第2段
            

            30、修改第2段第13字節

            0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
            37 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1E 05 60             第2段
            

            31、修改第2段第14字節

            0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
            37 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1D 06 60             第2段
            

            32、修改第2段第15字節

            0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
            37 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1D 05 61             第2段
            

            本來期望可以得到一個很不錯的結果的,甚至連測試結果位置都預留了,天不遂人愿,畏畏縮縮的在一個窗口連刷了32次,每次都是讀卡失敗,這下郁悶了,本以為破解只能止步于此了。 又拖了一周,感覺自己都沒激情了,只是偶爾抽時間看看之前收集的數據,卻總結出了下面的結果:

            13 05 71 22 04 E2 00 00 01 54 03 15 08 19 0D FC         0E0E
            13 05 71 22 27 10 00 00 28 64 03 16 08 19 0D 37         0404
            59 04 71 96 04 E2 00 00 23 82 03 17 09 01 0D EC         6767
            13 05 86 B3 04 E2 00 00 1E A0 03 18 09 02 0D 66         E7E7
            13 05 89 8E 01 90 00 00 1D 10 03 19 09 03 04 99         E7E7
            13 05 92 5C 04 E2 00 00 18 2E 03 1A 09 04 0D 11         F5F5
            59 04 78 53 03 52 00 00 14 DC 03 1B 09 05 09 F2         3535
            

            注:這是另一張卡上收集的數據,兩個字節兩個字節進行異或運算再與始終不變的第1段逐兩字節異或 開始時,始終沒能搞清楚這個異或結果,今天突然想到,每兩個字節進行異或的結果出現的是兩個相同的字節值,那么逐個字節異或豈不就是0,經此確認,試錯法終于可以再次登場了,結合之前的32次試錯,大膽猜測卡片的校驗過程:第1和第2段逐字節異或為0。 現在明確了卡片關鍵的兩段數據逐字節異或為0的校驗條件,再次進行如下試錯測試: 前提:當前卡片數據(消費讀卡器可識別)

            43 9A 5D A7 23 88 04 00 46 BA 14 12 51 10 03 10     第0段
            0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 47     第1段
            26 02 99 63 01 2C 00 00 0D 7A 02 7E 08 1F 03 EC     第2段
            11 01 08 46 04 20 FF 07 80 69 FF FF FF FF FF FF     第3段
            

            1、嘗試修改第一段中的數據

            1.1 4A3D-->5324                                         結果:不可讀
            1.2 4A3D-->4A3E 0047-->0044                         結果:可讀
            

            2、修改第二段中的數據 2.1修改第二段中的最后兩個字節:

            03EC-->00EF     結果:可讀
            

            2.2修改第二段中最前面的兩個字節:

            2602-->2400     結果:可讀
            

            2.3修改第二段中第三四個字節:

            9963-->966C     結果:可讀
            

            2.4整段替換第二段:

            26 02 99 63 01 2C 00 00 0D 7A 02 7E 08 1F 03 EC3-->13 05 86 B3 04 E2 00 00 1E A0 03 18 09 02 0D 66

            結果:可讀,金額變化一致;卻與之前的一次實驗結果沖突!

            通過上面的試錯,基本可以明確針對第2段的校驗過程:逐字節異或,判斷結果是否為0。為進一步驗證猜測,構造如下數據:

            1E 02 66 83 02 3C 00 00 EF C4 03 FF 08 FF 03 E4
            

            這條人為構造的數據,余額為613.8元,消費金額為5.72元,消費日期為一個不存在的日期,如果該該數據能夠校驗通過,那么破解基本就可以結束了。 1E 02 66 83 02 3C 00 00 EF C4 03 FF 09 1E 03 04,如果上一條不能成功,則嘗試該日期正確的數據。 經過驗證,隨意構造的兩條數據都成功修改了卡片余額,如下圖:

            enter image description here

            到此,卡片的破解算是告一段落,雖然遺留了一下問題: 1、整體替換兩次實驗結果沖突? 2、第2段中的前四個字節以及最后兩個字節的數據是如何產生的? 第一個問題可能是自己粗心造成的;第二個問題并不影響卡片破解。

            0x08小結


            通過上面的實例分析,再次總結卡片破解過程中數據分析的兩大步驟: 1、數據比對 收集多組數據,結合消費金額、余額、日期、消費次數等已知信息確定數據段中各個字節的含義 2、試錯分析 在直接修改余額出錯的情況下,逐字節或整體試錯,確定校驗相關字節,并猜測校驗算法,一般情況下,校驗算法是可逆算法,字節運算一般主要考慮異或運算;然后通過試錯進行論證;最后自己構造數據實現卡片余額修改,完成破解。

            <span id="7ztzv"></span>
            <sub id="7ztzv"></sub>

            <span id="7ztzv"></span><form id="7ztzv"></form>

            <span id="7ztzv"></span>

                  <address id="7ztzv"></address>

                      亚洲欧美在线