目录
URLConnection
在java中,java抽象出来了一个URLConnection类,它用来表示应用程序以及与URL建立通信连接的所有类的超类,通过URL类中的 openConnection 方法获取到URLConnection的类对象。
Java中URLConnection支持的协议可以在sun.net.www.protocol看到。
gopher协议在jdk1.8+就被禁止了
package com.cxk.url;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
public class urlconnection {
public static void main(String[] args) throws IOException {
URL url = new URL("file:///E://123.txt");
//打开和url之间的连接
URLConnection connection = url.openConnection();
//设置请求参数
connection.setRequestProperty("user-agent","javasec");
connection.setConnectTimeout(1000);
connection.setReadTimeout(1000);
//创建实际连接
connection.connect();
//获取响应头字段信息列表
connection.getHeaderFields();
//获取URL响应
connection.getInputStream();
StringBuilder response = new StringBuilder();//可变字符串
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line;
while ((line = in.readLine())!=null){
response.append("/n").append(line);
}
System.out.println(response.toString());
}
}
大概流程就是通过URL建立一个对象,然后建立连接,设置一些配置,最后获得相应流,这里的StringBuilder和StringBuffer差不多,两者都可以进行多次修改,并且不产生新的使用对象。StringBuilder类相较于StringBuffer有速度优势。但在要求线程安全的情况下,必须使用StringBuffer。 如果用String的话太繁琐,因为String不可变。
SSRF
SSRF(Server-side Request Forge, 服务端请求伪造)。 由攻击者构造的攻击链接传给服务端执行造成的漏洞,一般用来在外网探测或攻击内网服务。
简述就是,执行者通过服务器发现可以访问一些敏感的数据。
比如上面的new URL() 中我们可以控制就可以读取/etc/passwd配置信息等。
JNI安全基础
java是基于c语言实现的,也就是底层是C的原理毕竟java在c后产生的,Java底层的很多API都是通过JNI(Java Native Interface)
来实现的。通过JNI
接口C/C++
和Java
可以互相调用(存在跨平台问题),这和前面的命令执行也是用了Native也就是c实现的呗。
构建动态链接库供Java调用
JNI-定义native方法
首先java中如果想要调用native方法需要在类中定义一个native方法。
这点和java中的接口差不多,都需要一个其他的类来实现这个接口。
package com.cxk.Jni;
public class JNITest {
public native void sayHello();
}
这里定义了native void就是没参数,因为只是为了简单的看出功能,sayHello方法需要c来实现。
JNI-生成类头文件
这个就可以理解为java和c之间连接的桥梁不能缺少。
完整的步骤如下:
- 生成一个class ,javac JNITest
- java com.cxk.Jni.JNITest 命令,这里不能在包内因为里面有引用路径。
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_cxk_Jni_JNITest */
#ifndef _Included_com_cxk_Jni_JNITest
#define _Included_com_cxk_Jni_JNITest
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_cxk_Jni_JNITest
* Method: sayHello
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_cxk_Jni_JNITest_sayHello
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
这个文件一定不要修改,
JNIEXPORT void JNICALL Java_com_cxk_Jni_JNITest_sayHello
无参 JNICALL想到与引用后面的,java 包.文件.方法
(JNIEnv *, jobject);这里需要注意java中的类型和c中的不同,所以需要转换JNI安全基础_「Java Web安全」 - 网安 参考连接
JNI-编写C/C++本地命令执行实现
如上,我们已经生成好了头文件,接下来我们需要使用C/C++编写函数的最终实现代码。
com_cxk.Jni.JNITest.cpp
示例:
#include <iostream>
#include <stdlib.h>
#include <cstring>
#include <string>
#include"com_cxk_Jni_JNITest.h"
using namespace std;
JNIEXPORT void JNICALL Java_com_cxk_Jni_JNITest_sayHello(JNIEnv *env, jobject obj)
{
cout<<"hello world!"<<endl;
}
这里仅仅是一个输出的功能。
后使用g++
命令编译成动态链接库,前提是您需要提前装好编译环境如:gcc/g++
。
x86_64-w64-mingw32-g++ -I"%JAVA_HOME%\include" -I"%JAVA_HOME%\include\win32" -shared -o cmd.dll com_cxk_Jni_JNITest.cpp
这样就生成了一个cmd.dll文件,cmd随机的
还有关键的一步,把cmd.dll文件放到system32中,这样电脑才能找到
C:\Windows\system32
主函数调用
package com.cxk.Jni;
public class JNITest {
public native void sayHello();
public static void main(String[] args) {
System.load( "E:\\2022java-servlet\\11\\javassist-learn\\src\\main\\java\\cmd.dll" );
System.loadLibrary("cmd");
JNITest tNative = new JNITest();
tNative.sayHello();
}
}
总结:JNI可以实现对操作系统底层的调用,JNI可以用来提高调用的速度,它是直接和操作系统的内存进行交互,而省去了JVM和操作系统进行内存交换的步骤;JNI的另一个使用场景就是某些核心类库的实现可能需要跨包调用或者需要绕过其他Java安全性检查,如Java中的sun.misc.Unsaef实现,所以会引起很多安全的漏洞。
文章评论