javaweb-codereview 學習記錄-5
1.關於URLConnection
應用程式利用url與遠端通訊的所有類的超類
jdk1.8中支援的協議包括以上這些,gopher在jdk8中取消了。
java中預設對(http|https)做了一些事情,比如: 預設啟用了透明NTLM認證 預設跟隨跳轉
httpURLconnection可能jdk7低版本可能在win機器上導致ntlmrelay攻擊https://zhuanlan.zhihu.com/p/64889695
使用URLconnection的子類可能只適合http|https,對ssrf也有一定的限制
HttpURLConnection HttpClient Request okhttp
2.關於java agent
Java中
Instrumentation(Java Agent API)
和JVMTI(JVM Tool Interface)
功能,允許JVM
在載入某個class檔案
之前對其位元組碼進行修改,同時也支援對已載入的class(類位元組碼)
進行重新載入(Retransform
),rsap和iast都基於這個功能實現動態修改java位元組碼來插入檢測程式碼
java agent的兩種執行模式:
1.直接在命令新增執行引數 -javaagent(Instrumentation API實現方式)或-agentpath/ -agentlib(JVMTI的實現方式)
2.attach方式,直接將agent加到對應的java程序
helloWorld.java
public class helloWorld { public static void main(String[] args){ System.out.println("hello world"); } }
比如就上面一段簡單的程式碼,編譯後取修改器位元組碼讓其輸出hello world,想一下hello world在編譯後儲存在class檔案中,那麼此時已經編譯成位元組碼,要輸出的字串肯定也是以位元組碼儲存著,那麼此時可以直接替換獲取編譯好的位元組碼進行修改
testagent.java
import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.IllegalClassFormatException; import java.lang.instrument.Instrumentation; import java.security.ProtectionDomain; import java.util.Arrays; public class testagent { private static byte[] relaceBytes(String classname,byte[] classbuffer) { String bufferStr = Arrays.toString(classbuffer).replace("[","").replace("]",""); System.out.println("classname:"+classname); System.out.println("byes:"+ bufferStr); byte[] findBytes = "hello world".getBytes(); String findStr = Arrays.toString(findBytes).replace("[","").replace("]",""); System.out.println("world"+findStr); byte[] replaceBytes = "hello agent".getBytes(); String replaceStr = Arrays.toString(replaceBytes).replace("[","").replace("]",""); System.out.println("agent"+replaceStr); bufferStr = bufferStr.replace(findStr,replaceStr); System.out.println(bufferStr); String[] bytearr = bufferStr.split("\\s*,\\s*"); byte[] bytes = new byte[bytearr.length]; for(int i=0;i < bytearr.length;i++) { bytes[i] = Byte.parseByte((bytearr[i])); } System.out.println("new byte :"+Arrays.toString(bytes)); return bytes; } public static void premain(String args,final Instrumentation inst){ inst.addTransformer(new ClassFileTransformer() { public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { className = className.replace("/","."); if(className.equals("helloWorld")){ return relaceBytes(className,classfileBuffer); } return classfileBuffer; } },true); } }
這裡的classfileBuffer就是要修改位元組碼的class檔案,這裡替換位元組的函式可以自定義,只要返回一個位元組陣列即可
測試的時候testagent.java編譯後要包含MANIFEST.MF,宣告premain-class
然後使用jar命令打包
jar -cvfm agent.jar MANIFEST.MF *.class
之後再到helloWorld.class的目錄執行agent即可
java -javaagent:agent.jar helloWorld
這裡一般修改位元組碼用ASM庫
Instrumentation
java提供的監測jvm程式的api,利用Instrumentation我們可以實現
1.動態新增Transformer(addTransformer),上面的例子就是
2.動態修改classpath(appendToBootstrapClassLoaderSearch、appendToSystemClassLoaderSearch)
3.動態獲取所有JVM已經載入的類(getAllLoadedClasses)
4.動態獲取某個類載入器已經例項化的所有類(getInitiatedClasses)
5.直接修改已載入的類的位元組碼
6.動態設定JNI字首(setNativeMethodPrefix)
7.重載入指定類位元組碼(retransformClasses)
ClassFileTransformer
轉換類檔案的代理介面,拿到Instrumentation後可以呼叫addTransformer方法新增自定義的類檔案轉換器,上面的例子實際上就自定義了
一個Transformer,此時transform(類名,類載入器,類位元組碼等)方法就包含了我們要修改的目標類的一些資訊,修改完再返回位元組碼,jvm對位元組碼進行驗證後將決定是否載入。
這裡簡單記錄一下,後面有機會再深入學習。
&n