WARNING! 配置不當,或致使Kotlin源碼泄漏!

自從去年Google扶正了Kotlin,使之成爲了Android官方的推薦開發語言,Kotlin便迎來了春天。不少團隊/產品也紛紛加入了Kotlin的支持,大廠的應用也不少,社區對Kotlin也是讚不絕口。正在看此文的同窗,也相信要麼用上Kotlin,要麼準備使用Kotlin。html

這裏,筆者要給你們提個醒:舊項目引入Kotlin,如配置不當,會致使源碼泄露!。這意味着咱們所作的混淆、加固之類的防禦操做都白費了!這但是至關嚴重的安全問題!java

如圖。這是筆者在網上閒逛的時候,偶然發現的某應用包內居然包含了Kotlin的源文件!android

妥妥的如假包換的源文件,代碼、註釋都是全套的。編程

緣由分析

當筆者發現這個狀況的時候,心裏暗喜:難道筆者不當心挖到了一個Kotlin的大新聞,只要使用了Kotlin,就會被開源?安全

筆者嘗試在本地復現這個場景,但遺憾的是,不論是新版本的Kotlin Plugin仍是舊版本的Kotlin Plugin,打出來的包都不包含.kt文件。隨後筆者又嘗試去應用寶抓取Top50的應用,發現使用了Kotlin的應用雖然多,但也沒出現圖上的應用通常的代碼泄露狀況。沒法復現,還怎麼定位問題的緣由?此時陷入了僵局。bash

後來,筆者查看自家的應用時,發現自家應用引入了Kotlin後,也出現了這樣的問題。那這就不是小事了。編程語言

排查和定位過程按下不表,直觀的結果就是,打出來的APK包裏,混入了源代碼目錄下的.kt源文件。ide

咱們知道,打包過程當中,有一個步驟叫作Jar包資源合併,這個步驟會把Jar包內資源合併到一塊兒,打包到apk中。既然APK裏包含的.kt文件,那極有多是合併資源的任務出了問題。工具

惋惜,比對了有問題的項目和正常的項目的build.gradle以後,無奈的發現,即使是一樣的GradleKotlin Pluginbuild tools版本,一樣的配置,依然沒法在正常的項目下復現這個問題。佈局

也就說,gradle的Jar包資源合併任務並非致使問題的元兇。也是,Gradle若是有問題,社區也早就發現了。

但問題仍是得解決,既然是資源被合併打包了,那就找方法作指定資源的排除唄。

這部分的工做是由java plugin乾的,那就到文檔: The Java Plugin裏找答案。

首先看到這個任務:

從描述可知,這個任務就是咱們要找的,拷貝資源到jar包的資源目錄。

再往下看,項目的默認目錄結構:

資源目錄是放置在src/main/resources,或對應的src/<代碼集>/resources目錄內。

若是要自定義資源目錄的配置,看這個:

也就是說,這個配置指定了代碼集的資源目錄的位置。它會排除掉目錄內的.java文件,其餘的插件,也可能從這裏移除掉額外的文件類型。

看到這裏,你們也差很少明白了吧?

講道理,默認生成的項目的目錄結構中,資源目錄和代碼目錄是區分開的。既然APK裏包含了.kt源代碼,那必然是資源目錄和代碼目錄是同一個的狀況。

因爲java plugin默認會移除資源目錄內的.java文件,所以,在以往的打包中,源代碼可以被安全的移除掉,不至於致使泄露。

而如今,咱們引入Kotlin的時候,會依舊保持原有的代碼目錄結構,此時代碼目錄中就混入的.kt文件,因爲不屬於資源剔除的範圍,天然就被當作資源文件打包進APK裏了。

在出現了源碼泄露的應用裏,我還發現了.aidl文件,也就是IPC通信時定義的接口文件。這類文件的泄露也是一樣的緣由形成的。

至此,這個源碼泄露案,也就告破了。

固然,說告破還有點早,畢竟上面給出的是推測,就算是真理,也是須要檢驗的。

回到自家工程的build.gradle裏一查:

android {
    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
            resources.srcDirs = ['src']
        }
    }
}
複製代碼

果不其然,資源文件所在的目錄和源碼所在的目錄配置成了同一個。

至於出現這個問題緣由,筆者反思了一下。這個項目屬於比較早期的項目,代碼目錄結構遵循的是Eclipse時代的規範,後面擁抱變化轉Android Studio時,Gradle默認的那套項目佈局規範和Eclipse相差較大,爲了不對項目形成大的改動,因此採起了自定義目錄配置的作法,用較小的代價,完成了遷移。時過境遷,到了擁抱Kotlin變化的時候,就出問題了。

修復方案

明瞭問題的所在,定解決方案天然也就方便了:

  1. 方案一:直接移除resources.srcDirs = ['src']配置。
  2. 方案二:爲資源目錄增長新的提出類型.kt
  3. 方案三:將資源目錄和代碼目錄區分開來,再也不混雜在一塊兒。

這些方案裏,方案一有點簡單粗暴。對Android項目來講,影響倒還好,由於不少資源都是放在assets目錄裏,工程內不多會放這種資源文件了。

方案二適用於那些資源文件裏除了.kt文件以外,還有別的資源文件的狀況,傳統java開發可能會有這種場景。

方案三是最穩妥,最合乎規範的推薦作法。將資源和代碼分開,使得相關文件在物理上保持了隔離,對整個項目來講,總體結構更加清晰。

對筆者這種狀況,更好的方式是作一次項目結構的改造,使之符合Gradle的規範。

但歸根結底,這個問題屬於技術債務。不少時候,咱們在開發的過程當中,會爲了貪圖方便,本着儘量的減小影響面的想法,採起了一種折中的妥協的作法,度過了一時,但每每就埋下了禍根。

短時間內沒時間,確實能夠這麼作,但從長期來看,仍是要把債務還上的。只是時間的問題罷了。

最後的最後

最後的最後,建議你們自查一下,避免出現和筆者統一的狀況。尤爲是那些從Eclipse時代轉過來的Android項目!

感謝閱讀到最後,但願本文對你有所幫助。若是以爲筆者的文章對你有所幫助,還請給個喜歡/感謝/贊。若有紕漏,也請不吝賜教。歡迎你們留言一塊兒討論。:-)

後記

本文發出後,有朋友留言,指本文有標題黨的嫌疑。恕筆者沒法苟同。誠然,若有些朋友所言,不就是本身一個配置錯了,關Kotlin什麼事情,Kotlin乃無辜躺槍。

但筆者認爲,這當然不是編程語言的鍋,但倒是Kotlin工具鏈上的Kotlin Plugin沒兼顧到這種場景緻使的安全漏洞。與之相對的Java Plugin對這種場景就處理得周到得多。

雖然最後筆者將問題的緣由歸根於項目配置致使的問題,但筆者仍然認爲,這種狀況的發生,Kotlin Plugin也有必定的責任。完善的工具鏈,能爲開發和使用帶來極大的便利,Kotlin Plugin也不例外。筆者在Kotlin接入的配置教程裏,看到不少人在宣揚Kotlin的引入很方便,方便的背後,卻可能會不當心帶來這麼大的安全隱患,筆者認爲,是頗有必要提醒使用了Kotlin的各位的。

另外,安全問題的產生,每每都是小細節上的失誤致使的,而失誤,每每來自於人。愛因斯坦這樣說道:「只有兩種事物是無窮盡的——宇宙和人類的愚蠢」。

能趕上這個問題的項目,基本都是從Eclipse時代過來的,這樣的項目,其具備的價值,料想是不言而喻的。筆者看到,有的同窗認爲,源碼泄露就泄露,愛誰看誰看。我的認爲,這是對項目的一種不負責任。

以上。

再更新

以前的標題《使用Kotlin或致使源碼泄漏!》,評論指出有蹭熱度的嫌疑,參考了承香墨影的推送,改爲《配置不當,或致使Kotlin源碼泄漏!》,更直觀和開門見山。:-)

相關文章
相關標籤/搜索