java审计-RCE/SSRF

java开发语言中可以执行命令的函数有Runtime.getRuntime.exec和ProcessBuilder.start 

java1.5之前用Runtime.getRuntime.exec   1.5后用ProcessBuilder类构造进程       

1.ProcessBuilder命令执行漏洞

ProcessBuilder执行命令的方式如下:

ProcessBuilder pb = new ProcessBuilder("command","param");

Process process = pb.start();

例如ProcessBuilder执行ls -al命令

public class exec{
public static void main(String[] args ) throws IOException {
    //执行系统命令
    ProcessBuilder p = new ProcessBuilder("ls","-al");
  //ProcessBuilder p = new ProcessBuilder("ping","-t","3",ip); #这里不能用分号链接 127.0.0.1;id 会报错
  //ProcessBuilder p = new ProcessBuilder("bash","-c",exec);  #这里调用了bash才可以链接命令执行
Process pb
= p.start(); //获取执行完成命令后的结果并输出 String line; BufferedReader reader = new BufferedReader(new InputStreamReader(pb.getInputStream(),"GBK"));  #缓冲区读取输入流 while((line= reader.readLine())!=null){    #并读取输入流后逐行写入字符串中 System.out.println(line); } reader.close(); } }

tips:直接使用ProcessBuilder进行命令执行的时候是不支持用;号或者&来连接命令一起执行,这些需要使用linux管道之类的功能,必须得使用shell程序来执行

2.Runtime exec 命令执行漏洞

Runtime exec 执行字符串参数和数组参数

Process proc = Runtime.getRuntime(),exec("ping 127.0.0.1");是正常的

当执行 Process proc = Runtime.getRuntime(),exec("ping 127.0.0.1;id")是没有返回值的

因为在exec调用的过程中会对通过StringTokenizer进行处理,它会对传入的字符串进行分割再返回

结论

所以要通过数组类型的传参才能进行多个命令执行

String command ="/bin/sh -c \ "ping -t 3 ip;id \"";   \\exec执行字符串参数

String[] command = { "/bin/sh","-c","ping -t 3 ip;id"}`  \\执行数组参数   

Runtime exec 不以参数的形式来传命令执行
Process proc = Runtime.getRuntime(),exec(cmd);
cmd = sh -c ls ;cat /etc/passwd
#因为stringTokenizer对空格处理拆分导致命令无法执行 可以用${IFS},${IFS}$9等替换空格 cmd
= sh -c ls ;cat${IFS}/etc/passwd #修改之后会有以下报错 Invaild character found in the request target . The valid characters are defined in RFC 7230 and RFC 3986 RFC规范中url只允许包含 a-z A-Z 0-9 -_.~ !*'();:@&=+$,/?#[]共84个 因此要进行url编码 修改前:cmd = sh -c ls ;cat${IFS}/etc/passwd 编码后:cmd = sh%20-c%20ls;cat$%7BIFS%7B/etc/passwd

SSRF

ssrf通常出现在社交分享,远程图片下载,图片或文章收藏,转码,通过网址在线翻译,网站采集,从远程服务器请求资源等功能点处

java中的SSRF只支持sun.net.www.protocal下所有的协议 file/ftp/http/https/jar/mailto/netdoc

特别留意能够发起http请求的类和函数

URLConnection

URL

HttpURLConnection

HttpClient

OkHttpClient.newCall.execute

1.urlConnection

String url = request.getParameter("url");
URL u = new URL(url);
URLConnection urlConnection
= u.openConnection();    #urlConnection获取资源 BufferedReader in = new BufferedReader(new InputStreaReader(urlConnection.getInputSream()));  #输入流读取urlconnection对象 String inpuLine; StringBuffer html = new StringBuffer(); while((inputLine=in.readLine())!= null){ html.append(inputLine); } in.close(); return html.toString();

2.HttpURLConnection

继承于URLConnection 用于向指定网站发送GET请求与POST请求.

HttpURLConnection httpUrl = (HttpURLConnection)urlConnection;
BufferedReader in = new BufferedReader(new InputStreaReader(urlConnection.getInputSream()));

 3.Request

request与python中的request对象类似,主要用来发http请求

String url = request.getParameter("url");
return Request.Get(url).execute(),returnContent().toString();

4.openStream

通过url对象的openStream()方法,能够得到指定资源的输入流.

String downLoadImgFileName = Files.getNameWithoutExtension(url)+"."+Files.getFileExtension(url);
URL u = new URL(url);
inputStream = u.openStream();//send request
outputStream = response.getOutputStream();
while((length = inputStream.read(bytes))>0){
 outputStream.write(bytes,0,length);

 5.HttpClient

client.execute(httpGet);
BufferedReader rd = new BufferedReader(new InputStreamReader (client.execute(httpdGet).getEntity().getContent()));
StringBuffer result = new StringBuffer();
String line="";
while((line = rd.readLine())!=null) {
result.append(line);
}

 

 

 

posted @ 2023-03-14 14:54  lisenMiller  阅读(200)  评论(0)    收藏  举报