者:京東零售 周明亮
亞馬遜商詳地址:
https://www.amazon.com/OtterBox-Commuter-Case-iPhone-Packaging
主要配合接口進行加密,采用多字段干擾,模板化加載。下發大量的模版數據,之后通過客戶端進行填充。
客戶端代碼為傳統的普通加密模式
這個只是部分代碼,如果將完整代碼,一段一段進行分析,你就可以得到完整上下文,不需要靠人去一段一段讀取代碼。
目前還有 ai 代碼調試如:
https://github.com/shobrook/adrenaline?
1)自身不愿意登錄,或者偷取正常用戶信息后,用于攻擊
2)如果是公司行為,很可能會被記錄IP,有法務風險。
3)多次進行嘗試修改 token ,偽裝發送請求
4)分析 DOM 結構特征 / 使用 Console 打印全局存儲變量
5)通過 cookies 分析特定的關鍵詞,全局搜索
6)網絡請求時,查看函數執行棧,逐級往下尋找核心請求函數。
1)前端代碼采用傳統加密方式
2)入口在 APP 內的 業務
3)對關鍵詞進行混淆處理,減少特征搜索
任何客戶端加密混淆都會被破解,只要用心都能解決,我們能做的就是拖延被破解的時間,而不是什么都不做,那樣只會被破解更快!
其實很多我們自己公司對外的頁面,都有很多外露風險,包括不規范的日志輸出,直接對外暴露加密的防刷 token。 比如:
?大家都可以自查下~
今互聯網時代,JavaScript已經成為了web前端開發的重點技術之一。其中,JavaScript代碼的安全性問題一直是關注的焦點。為了保護JavaScript代碼的安全性,很多人對其進行加密處理,眾所周知,對于單純的加密算法,通過反向工程或逆向分析也能夠破解。在此情況下,JavaScript代碼混淆技術成為了一種應對加密破解的有效措施。
一、JS加密算法
JS加密算法是指JavaScript代碼通過異或加密、Base64加密、MD5加密、SHA1加密等方式對其內容進行加密處理。例如,下面的加密函數中,通過異或運算對字符串進行了加密:
Copy codefunction encryptByXOR(message, key) {
var encrypted='';
for (var i=0; i < message.length; i++) {
var c=message.charCodeAt(i) ^ key.charCodeAt(i % key.length);
encrypted +=String.fromCharCode(c);
}
return encrypted;
}
var message='Hello world';
var key='1234567890';
var encrypted_message=encryptByXOR(message, key);
console.log('加密后的字符串:', encrypted_message);
通過對源代碼進行加密處理,能夠為JavaScript代碼的安全性提供一定的保障。不過,對于相同的JavaScript加密算法,破解者也可以使用同樣的加解密算法進行反向操作。而且,使用加密算法會增加代碼的體積,降低代碼的執行速度。因此,人們開始思考是否有一種更好的方法確保JavaScript代碼的安全性呢?
二、JS代碼混淆技術
JS代碼混淆技術可以將JavaScript代碼轉換成一個新的代碼形式,使其難以理解和破解。這種轉換通常包括將變量名和函數名替換為無意義的字符、刪除代碼中的空白和注釋、將多行代碼壓縮成一行等操作。混淆后的代碼和原代碼在功能上是等效的,但是由于其結構和命名被混淆,甚至看起來無法讀懂。
例如,下面的函數中,對一段JavaScript代碼進行了簡單的混淆處理:
Copy codefunction obfuscateCode(code) {
var lines=code.split("\n");
var obfuscatedCode="";
lines.forEach(function(line) {
obfuscatedCode +=line
.replace(/var /g, "")
.replace(/function /g, "")
.replace(/return /g, "")
.replace(/;/g, "")
.replace(/{/g, "")
.replace(/}/g, "");
});
return obfuscatedCode;
}
var original_code='function foo(a, b) {var c=a + b;return c;}';
var obfuscated_code=obfuscateCode(original_code);
console.log('原始代碼:', original_code);
console.log('混淆代碼:', obfuscated_code);
通過混淆技術,原始JavaScript代碼變得更加復雜和難以理解,進而降低了破解的可行性。同時,相比與加密算法,混淆代碼的運行速度和性能也更優秀。
三、JS解混淆技術
不過,對于代碼混淆技術,我們同樣可以將其污染(反混淆)。通過分析混淆代碼的結構和操作,我們能夠撰寫出解混淆代碼,進行JavaScript代碼的還原。例如,混淆代碼可能會將許多不同的變量名替換為相同的單個字符,或者將多個行的代碼壓縮到一個代碼行中,可以通過自動化工具或手動方法來反混淆代碼。
Copy codefunction unobfuscateCode(obfuscatedCode) {
var unobfuscatedCode=obfuscatedCode
.replace(/a /g, "var ")
.replace(/b /g, "function ")
.replace(/c /g, "return ")
.replace(/[0-9]+/g, "")
.replace(/=/g, "=")
.replace(/\+/g, " + ")
.replace(/;/g, ";\n")
.replace(/}/g, "\n}\n")
.replace(/^\n/, "");
return unobfuscatedCode;
}
var obfuscated_code="b foo(a, b){c a + b}"; //從js.jiami.com上獲得的混淆代碼
var unobfuscated_code=unobfuscateCode(obfuscated_code);
console.log('混淆代碼:', obfuscated_code);
console.log('原始代碼:', unobfuscated_code);
四、JS代碼安全實踐
如何選擇適當的JS代碼安全實踐方法,取決于應用程序所需的安全級別和安全需求。如果您需要保護代碼內容的安全,可以使用加密算法。如果您的代碼需要長期維護,可以使用代碼混淆技術,使代碼的可讀性降低,這樣也就不容易被別人拿來二次開發和篡改。如果您需要將代碼保持可讀性,但是又需要保護代碼的安全性,可以采取混合應用加密算法和混淆技術相互結合,以最佳的方式實現代碼保護。
總之,隨著互聯網技術的發展,對于網絡安全的要求越來越高,對于JavaScript的加密和解密,技術發展均取得了一定的進步。但無論是黑客攻擊還是加密解密技術,只是給我們提供了預防的參考方案,絕不能代替不斷加強網站的安全性實踐,并高度喚起安全保護意識。
jsjiami.com
如果您對文章內容有不同看法,或者疑問,歡迎到評論區留言,或者私信我都可以。
也可以到上方網站,底部有我聯系方式詳談。
java的bytecode很容易通過JAD等反編譯工具還原出源代碼。這樣勢必不滿足安全的定義。如何一定程度上保護需要防止被反編譯的源代碼呢?混淆(obfuscate)技術。注意:用obfuscate防盜版是根本不可能,連匯編這種東西都能被**掉,而java代碼基本上等同于開源的同義詞。用obfuscate只是為了增加反編譯的難度,保護源代碼的知識產權。混淆包照常運行,沒有任何問題??梢允褂梅淳幾g工具如jd-gui查看混淆后的包,驗證混淆效果。
將有意義的類,字段、方法名稱更改為無意義的字符串。生成的新名稱越 短,字節代碼越小。在名稱混淆的字節代碼中,包,類,字段和方法名稱已重命名,并且永遠不能恢復原始名稱。
用于if, switch, while,for等關鍵字,對字節碼進行細微的修改,模糊控制流,而不改變代碼在運行時的行為。通常情況下,選擇和循環等邏輯構造會被更改,因此它們不再具有直接等效的Java源代碼。流模糊的字節碼通常強制反編譯器將一系列標簽和非法的goto語句插入到它們生成的源代碼中。源代碼有時會因為反編譯錯誤而變得更加模糊。
proguard是一個免費的 Java類文件的壓縮,優化,混肴器。它刪除沒有用的類,字段,方法與屬性。使字節碼最大程度地優化,使用簡短且無意義的名字來重命名類、字段和方法
官網地址:https://www.guardsquare.com/en/products/proguard
yGuard是一款免費的Java混淆器(非開源),它有Java和.NET兩個版本。yGuard 完全免費,基于 Ant 任務運行,提供高可配置的混淆規則。
官網地址:https://www.yworks.com/products/yguard
第二代Java混淆器。所謂第二代混淆器,不僅僅能進行字段混淆,還能實現流混淆。
命名混淆,流混淆,調試信息混淆,字符串編碼,以及水印技術。對于教育和非商業項目來說這個混淆器是免費的。支持war和jar格式,支持對需要混淆代碼的應用程序添加有效日期。
官網地址:http://www.allatori.com/
推薦使用 proguard :開源, 使用簡單 ,文檔豐富完善。
工具 | 官網地址 | 官方文檔 | 開源免費 | 名稱混淆 | 流混淆 | maven支持 | 功能 |
proguard | https://www.guardsquare.com/proguard | https://www.guardsquare.com/manual/home | √ | √ | ? | √ | |
yGuard | https://www.yworks.com/products/yguard | https://yworks.github.io/yGuard/ | √ | √ | ? | √ | |
allatori | https://allatori.com/ | ?(免費用于教育和非商業項目) | √ | √ | √ | 減小包大小;混淆代碼;添加水印 |
是一個開源的 Java 類文件收縮器、優化器、混淆器和預驗證器。因此,ProGuard 處理的應用程序和庫更小、更快,并且在一定程度上可以抵御逆向工程。
<build>
<plugins>
<plugin>
<!--結合ant run 來使用yguard -->
<artifactId>maven-antrun-plugin</artifactId>
<dependencies>
<dependency>
<groupId>com.yworks</groupId>
<artifactId>yguard</artifactId>
<version>3.1.0</version>
</dependency>
</dependencies>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<property refid="maven.compile.classpath" name="mvn.classpath"/>
<!-- <echo message="Using Maven Classpath: ${mvn.classpath}" /> -->
<taskdef name="yguard"
classname="com.yworks.yguard.YGuardTask"/>
<yguard>
<!-- yguard配置 -->
</yguard>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<!-- yguard 是公用配置和rename以及shrink配置的容器標簽 -->
<yguard>
<!-- 必須至少指定一個inoutpair元素或一個非空inoutpairs元素才能運行yguard任務。此元素指定輸入和輸出 jar 文件的路徑
in out 必須指定設置值,不指定報錯
1.in 指定一個現有的jar/war文件,其中包含未收縮和未混淆的 .class文件。
2.out 指定一個 jar/war文件的路徑,該文件將被創建并用于放置收縮和混淆過程的結果。
3.resources 如何處理資源文件,支持三種值:copy,auto,none。 默認配置copy。
1.copy 直接復制資源文件 默認情況下,只需將所有資源文件復制到輸出 jar 中
2.auto 僅復制那些在壓縮后仍包含一個或多個 .class 文件的目錄中的資源文件。
3.none 丟棄所有資源文件。-->
<inoutpair
in="${project.build.directory}/${project.build.finalName}.${project.packaging}"
out="${project.build.directory}/${project.build.finalName}.${project.packaging}" />
<externalclasses>
</externalclasses>
<!-- 用于配置一些屬性 ,保存類的調試信息:比如 LineNumberTable:行號表;LocalVariableTable:本地變量表等。 -->
<attribute name="SourceFile, LineNumberTable, LocalVariableTable">
<patternset>
<include name="com.ewa.pipe.**"/>
</patternset>
</attribute>
<!-- shrink 用于收縮代碼配置。
1.logfile shrink過程的日志文件
2.在shrink過程中,如果有錯誤代碼,代碼將會被替換為: throw new InternalError("Badly shrinked")。
比如:當某些類的private屬性被刪除,但是public方法中有引用該屬性,而屬性被刪除了,即會輸出該異常錯誤。
-->
<shrink logfile="${project.build.directory}/yshrink.log.xml" createStubs="true">
<!-- shrink中的keep和rename中的keep一致。 -->
<keep>
<method name="void main(java.lang.String[])" class="${mainclass}" />
</keep>
</shrink>
<!-- 用于自定義某些配置和屬性更改。
1.mainclass 用于設置主程序啟動位置,該文件將不會被混淆。
2.logfile 混淆過程中的日志文件保存地址。名稱以“.gz”結尾,yGuard 將自動創建文件的 gzip 壓縮版本,默認為yguardlog.xml
3.conservemanifest 當為false時,重新生成 MANIFEST.MF的內容。默認為false。
4.replaceClassNameStrings 是否混淆代碼中某些字符串跟類名相關的東西。默認為true
比如源碼: System.out.print("com.ewa.pipe.dbtransfer.dpl.mapper.BlendMapper");混淆后: System.out.print("com.ewa.pipe.dbtransfer.dpl.A.B");
5.scramble 是否隨機混淆代碼,默認false。如果為true即每次打包生成的類名將隨機替換。比如Test.class 第一次混淆為A.class,第二次就為B.class
6.annotationClass 某些不必要混淆的數據,比如如下配置為Test注解,當配置到類上時,類中的所有東西不會被混淆;當配置到屬性時,屬性名稱不會被混淆。
-->
<rename
mainclass="com.ewa.pipe.dbtransfer.dpl.DplDbtransferApplication"
logfile="${project.build.directory}/yguard.log.xml"
conservemanifest="false"
replaceClassNameStrings="true"
scramble="false"
annotationClass="com.ewa.pipe.dbtransfer.dpl.Test"
>
<!-- -->
<keep>
</keep>
<!-- 1.error-checking 用于檢測錯誤,檢測到錯誤就失敗停止。 -->
<property name="error-checking" value="pedantic"/>
<!-- 2.error-checking 可用于告訴重命名引擎在混淆期間使用不同的命名方案。目前可以將此屬性設置為以下值之一(默認small,通常使用small就行了):
small:將產生非常短的名稱,即生成的 jar 文件將盡可能小。
best:會產生很可能被反編譯器和反匯編器誤解的名稱。使用這種命名方案,在大多數文件系統上甚至不可能成功解壓縮或解壓縮生成的 jar 文件(Windows、Standard Unix、Standard Linux、MacOS)。然而,這種方案占用了大量空間,并且生成的 jar 可能會變大(通常大約是兩倍大?。?
mix:是其他兩個值的混合,這會導致合理的小但仍然難以反編譯 jar 文件。
-->
<!-- 其他屬性( language-conformity ,overload-enabled,obfuscation-prefix,digests,expose-attributes)請參考官方文檔。 -->
<property name="naming-scheme" value="small"/>
</rename>
</yguard>
class用于在rename和shrink過程中排除某些類,字段和方法。其是keep的子元素。以下是配置說明(- 表示會被收縮,即被刪除 ):
可見性(是否被收縮) | public | protected | friendly | private |
none | - | - | - | - |
public | * | - | - | - |
protected | * | * | - | - |
friendly | * | * | * | - |
private | * | * | * | * |
屬性說明
注意事項
列1:
<shrink logfile="${project.build.directory}/yshrink.log.xml">
<keep>
<!-- 保留NameTest類不被刪除,但是內部的方法和會屬性會被刪除,不論私有還是共有。 -->
<class name="com.arm.code.mix.base.NameTest"/>
<!-- 保留所有公用的類,方法和屬性。其關聯的類,方法和屬性會被保留,不會被刪除 -->
<class classes="public" methods="public" fields="public"/>
<!-- 保留所有繼承了BaseClass的類不被刪除,但是內部的方法和會屬性會被刪除,不論私有還是共有。 -->
<class extends="com.arm.code.mix.base.BaseClass"/>
</keep>
</shrink>
列2:
<shrink logfile="${project.build.directory}/yshrink.log.xml">
<keep>
<!-- 保留NameTest類不被刪除,并保留其private級別的方法和屬性 -->
<class name="com.arm.code.mix.base.NameTest" methods="private" fields="private"/>
<!-- 保留所有繼承了BaseClass的類不被刪除,并保留其private級別的方法和屬性 -->
<class extends="com.arm.code.mix.base.BaseClass" methods="private" fields="private"/>
</keep>
</shrink>
列3:
一下舉列幾個模式集的列子,模式集可以參考ant。
<!-- include shrink:不需要被刪除的類,保留的類。rename:不需要被混淆的類名 -->
<class>
<patternset>
<include name="com.mycompany.**.*Bean"/>
<exclude name="com.mycompany.secretpackage.*"/>
<exclude name="com.mycompany.myapp.SecretBean"/>
<!-- 由于 Ant'$'用作轉義字符,因此如果您想將一個作為參數傳遞給任務,則必須使用兩個連續的'$'s( )。'$$'-->
<exclude name="org.w3c.sax?.**.*$$*"/>
</patternset>
</class>
method 用于在rename和shrink過程中排除方法。其是keep的子元素。以下是配置說明(- 表示會被收縮,即被刪除 ):
<!-- 這將保留MyClass類的main和foo方法。此外,所有readObject和writeObject方法(用于序列化)都將保存在com.mycompany.myapp.data包的所有類中。
請注意,您必須指定返回參數的類型,即使它是 void,并且您必須為所有類使用完全限定名稱,即使是java.lang package. -->
<method class="com.mycompany.myapp.MyClass"
name="void main(java.lang.String[])"/>
<method class="com.mycompany.myapp.MyClass"
name="int foo(double[][], java.lang.Object)"/>
<method name="void writeObject(java.io.ObjectOutputStream)">
<patternset>
<include name="com.mycompany.myapp.data.*"/>
</patternset>
</method>
<method name="void readObject(java.io.ObjectInputStream)">
<patternset>
<include name="com.mycompany.myapp.data.*"/>
</patternset>
</method>
field 您可以按名稱指定應從收縮或名稱混淆中要保留的字段
<!-- 保留MyClass類中的所有字段。
此外,所有serialVersionUID字段(用于序列化)都將保存在com.mycompany.myapp.data包的所有類中。 -->
<field class="com.mycompany.myapp.MyClass" name="field"/>
<field name="serialVersionUID">
<patternset>
<include name="com.mycompany.myapp.data.*"/>
</patternset>
</field>
package 用于從重命名過程中排除某些包的名稱。它不能用于收縮(shrink)過程 。這對類、方法或字段名稱沒有影響。
<package>
<patternset>
<!-- com.mycompany.myapp不被混淆。myapp下的包名還是會被混淆 -->
<include name="com.mycompany.myapp.*"/>
<!-- com.mycompany.myapp不被混淆。myapp下的包名也不會被混淆 -->
<include name="com.mycompany.myapp.**"/>
</patternset>
</package>
1.注意事項
2.項目使用失敗的問題收集總結
3.配置模版
<keep>
<!--包名不混淆配置-->
<package>
<patternset>
<include name="com.arm.oceansearch.**"/>
</patternset>
</package>
<!--mybaites 相關的mapper混淆后,會造成boot項目啟動失敗 -->
<class implements="com.arm.boot.core.base.BaseMapper"/>
<!--mybaites默認生成sql時是使用的實體類的類名,所以不能混淆-->
<class implements="com.arm.oceansearch.entity.BaseEntity"/>
<!-- 本包的controller混淆后,無法讀取mapping映射,原因未知。-->
<class>
<patternset>
<include name="com.arm.oceansearch.controller.*"/>
</patternset>
</class>
<!-- service的接口和實現都要暴露,不然spring的注入和nacos的服務發現都會存在問題。 -->
<class>
<patternset>
<include name="com.arm.oceansearch.service.**"/>
</patternset>
</class>
<!--main方法配置-->
<method name="void main(java.lang.String[])"
class="com.arm.oceansearch.OceanSearchApplication"/>
</keep>
ProGuard 是一個開源的 Java 類文件收縮器、優化器、混淆器和預驗證器。因此,ProGuard 處理的應用程序和庫更小、更快,并且在一定程度上可以抵御逆向工程。
反射和內省對于任何代碼的自動處理都存在特殊的問題。在 ProGuard 中,代碼中動態創建或調用(即按名稱)的類或類成員也必須指定為入口點。例如,Class.forName()構造可以在運行時引用任何類。通常不可能計算必須保留哪些類(使用它們的原始名稱),因為類名可能是從配置文件中讀取的,例如。因此,您必須在 ProGuard 配置中指定它們,同樣簡單-keep選項
處理:<inFilter>com/ewa/pipe/**</inFilter>, inFilter標簽設置為包路徑地址,把‘.’換成‘/’。
injar : 指定target中的一個目標地址:這里指定編譯后的 classes文件夾。 inFilter 指定的是 classes的內部的文件夾(package)地址。
<!-- 加載文件的過濾器,就是你的工程目錄了-->
<inFilter>com/arm/code/**</inFilter>
<!-- 對什么東西進行加載,這里僅有classes成功,畢竟你也不可能對配置文件及JSP混淆吧-->
<injar>classes</injar>
以下是一個例子說明,如果你想更多的有用信息,請查看文檔(https://www.guardsquare.com/manual/configuration/usage)
*請認真填寫需求信息,我們會在24小時內與您取得聯系。