ssh [email protected] -p2222 (pw:guest)
์ํ์ด ์ ธ(Secure Shell, SSH)๋ ๋คํธ์ํฌ ์์ ๋ค๋ฅธ ์ปดํจํฐ์ ๋ก๊ทธ์ธํ๊ฑฐ๋ ์๊ฒฉ ์์คํ ์์ ๋ช ๋ น์ ์คํํ๊ณ ๋ค๋ฅธ ์์คํ ์ผ๋ก ํ์ผ์ ๋ณต์ฌํ ์ ์๋๋ก ํด ์ฃผ๋ ์์ฉ ํ๋ก๊ทธ๋จ ๋๋ ๊ทธ ํ๋กํ ์ฝ์ ๊ฐ๋ฆฌํจ๋ค. ๊ธฐ์กด์ rsh, rlogin, ํ ๋ท ๋ฑ์ ๋์ฒดํ๊ธฐ ์ํด ์ค๊ณ๋์์ผ๋ฉฐ, ๊ฐ๋ ฅํ ์ธ์ฆ ๋ฐฉ๋ฒ ๋ฐ ์์ ํ์ง ๋ชปํ ๋คํธ์ํฌ์์ ์์ ํ๊ฒ ํต์ ์ ํ ์ ์๋ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ค.
SSH๋ ์ํธํ ๊ธฐ๋ฒ์ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์, ํต์ ์ด ๋ ธ์ถ๋๋ค ํ๋๋ผ๋ ์ดํดํ ์ ์๋ ์ํธํ๋ ๋ฌธ์๋ก ๋ณด์ธ๋ค.
SSH์ ์ฃผ์ ๊ธฐ๋ฅ์ ๋ค์๊ณผ ๊ฐ๋ค.
- ๋ณด์ ์ ์์ ํตํ rsh, rcp, rlogin, rexec, telnet, ftp ๋ฑ์ ์ ๊ณต
- IP spoofing (IP์คํธํ, ์์ดํผ ์/๋ณ์กฐ ๊ธฐ๋ฒ์ค ํ๋)์ ๋ฐฉ์งํ๊ธฐ ์ํ ๊ธฐ๋ฅ์ ์ ๊ณต
- X11 ํจํท ํฌ์๋ฉ ๋ฐ ์ผ๋ฐ์ ์ธ TCP/IP ํจํท ํฌ์๋ฉ์ ์ ๊ณต
pwnable.kr์ ๋ฌธ์ ์์๋ ๋ค์๊ณผ ๊ฐ์ ํ์์ ์ฌ์ฉํด์ SSH์ ์ ์ํ๋๋ก ํ๋ค.
ssh [email protected] -p2222
์ฌ๊ธฐ์ fd
๋ ์๊ฒฉ ์๋ฒ์ ์ ์ ๋ช
์(pwnable์์๋ ๋ฌธ์ ์ ์ด๋ฆ์ ์ ์ ๋ช
์ผ๋ก ์ฌ์ฉํ๊ณ ์๋ค.), pwnable.kr
์ ์๊ฒฉ ์๋ฒ์ ๋๋ฉ์ธ์ ๋ํ๋ธ๋ค. -p2222
๋ ํฌํธ ๋ฒํธ์ด๋ค.
ํฐ๋ฏธ๋์์ ssh [email protected] -p2222
๋ฅผ ์น๊ณ Are you sure you want to continue connecting (yes/no)? ๋ผ๋ ์ง๋ฌธ์ด ๋์ค๋ฉด yes
๋ฅผ ์น๋ค. password๋ ๋ฌธ์ ์์ ์๋ ค์ค guest
๋ฅผ ์น๋ฉด ์๊ฒฉ ์๋ฒ์ ์ ์์ด ๋๋ค.
ํฐ๋ฏธ๋์์ ls -l
์ ์น๋ฉด ํ์ผ์ ์ฝ์ ์ ์๋ ๊ถํ์ ๋ณผ ์ ์๋ค. root ๊ถํ์ผ๋ก๋ง ๋ณผ ์ ์๋ ํ์ผ์ ๊ฒฝ์ฐ permission denied๋ผ๋ ๋ฌธ๊ตฌ๊ฐ ๋จ๋ฉด์ ๋ด์ฉ์ ๋ณผ ์ ์๋ค.
์ด ๋ฌธ์ ๋ toddler's bottle์ด๊ธฐ ๋๋ฌธ์ c ํ์ผ์ ์ ๊ณตํ๋ค.
#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;
}
์ฝ๋๋ฅผ ์ดํด๋ณด๋ฉด fd๋ฅผ ์คํํ๊ธฐ ์ํด์๋ ๋งค๊ฐ ๋ณ์๊ฐ ํ์ํ ๊ฒ์ ์ ์ ์๋ค. fd๋ ๋งค๊ฐ ๋ณ์๋ฅผ ์
๋ ฅ๋ฐ์ ๋ค ๋งค๊ฐ ๋ณ์๊ฐ 2๋ณด๋ค ์๋ค๋ฉด "pass argv[1] a number" ๊ตฌ๋ฌธ์ ์ถ๋ ฅํ๋ค. 2 ์ด์์ผ ๊ฒฝ์ฐ์๋ atoi()
๋ฅผ ์ด์ฉํด ์ ์๋ก ๋ณํํ ํ์ 16์ง์ 0x1234
(10์ง์ 4660)์ ๋นผ์ ์ ์ํ ๋ณ์ fd์ ์ ์ฅํ๋ค. ์ด ๊ฐ์ read(fd, buf, 32)
์์ file descriptor ๊ฐ์ผ๋ก ์ฌ์ฉ ๋๋ค.
์ด ๋ค์ ์ฝ๋๋ฅผ ๋ณด๋ฉด buf์ ์ ์ฅ๋ ๋ฌธ์์ด์ด "LETMEWIN"๊ณผ ๊ฐ์์ผ ์คํ๋๊ธฐ ๋๋ฌธ์ (strcmp๋ ๋ฌธ์์ด ๋น๊ต ํ ๋ ๋ฌธ์์ด์ด ๊ฐ์ ๋ 0์ ๋ฐํํ๋ค.) buf์ "LETMEWIN"์ด๋ผ๋ ๋ฌธ์์ด์ ๋ฃ์ด์ฃผ์ด์ผ ํ๋ ๊ฒ์ ์ ์ ์๋ค. buf์ ๋ฌธ์์ด์ ๋ฃ๊ธฐ ์ํด์๋ file descriptor ๊ฐ์ด standard input์ธ 0์ด์ด์ผ ํ๋ค.
file descriptor์ ๊ฐ์ด 0์ด๊ธฐ ์ํด์๋ ์ ์ํ ๋ณ์ fd์ ๊ฐ์ด 0์ด ๋์ด์ผ ํ๊ธฐ ๋๋ฌธ์ fd ์คํํ์ผ์ ์คํํ ๋ ๋งค๊ฐ๋ณ์๋ฅผ 4660์ผ๋ก ๋ฃ์ด์ฃผ๋ฉด ๋๋ค. ๊ทธ๋ฌ๋ฉด if(!strcmp("LETMEWIN\n", buf))
๋ฌธ์ด ์คํ๋์ด /bin/cat flag
๋ฅผ ๋ณผ ์ ์๋ค. ์ด flag ๊ฐ ์ ๋ต์ด ๋๋ค.
file descriptor๋ ์์คํ ์ผ๋ก๋ถํฐ ํ ๋น๋ฐ์ ํ์ผ์ด๋ ์์ผ์ ๋ํํ๋ ์ ์์ด๋ค. ํ์ค ์ ๋ ฅ ๋ฐ ํ์ค ์ถ๋ ฅ๋ file descriptor๋ก ํํ๋๋๋ฐ ์ด๋ค์ ํ๋ก๊ทธ๋จ์ด ์์๋๋ฉด ๊ธฐ๋ณธ์ ์ผ๋ก ์ด๋ฆฌ๊ณ , ์ข ๋ฃ์ ์๋์ผ๋ก ๋ซํ๊ฒ ๋๋ค.
- 0: Standard Input(ํ์ค ์ ๋ ฅ)
- 1: Standard Output(ํ์ค ์ถ๋ ฅ)
- 2: Standard Error(ํ์ค ์๋ฌ)
๋ฐ๋ผ์ ํ์ผ์ ์ด๊ฑฐ๋ ์์ผ์ ์์ฑํ ๋ ๋ถ์ฌ๋๋ file descriptor๋ 3๋ถํฐ ์์๋๋ค.
ssize_t read (int fd, void *buf, size_t nbytes)
- int fd : ํ์ผ ๋์คํฌ๋ฆฝํฐ
- void *buf : ํ์ผ์ ์ฝ์ด ๋ค์ผ ๋ฒํผ
- size_t nbytes : ๋ฒํผ์ ํฌ๊ธฐ
open() ํจ์๋ก ์ด๊ธฐ๋ฅผ ํ ํ์ผ์ ๋ด์ฉ์ ์ฝ๋๋ค. ์ ์์ ์ผ๋ก ์คํ๋์๋ค๋ฉด ์ฝ์ด๋ค์ธ ๋ฐ์ดํธ ์๋ฅผ, ์คํจํ๋ค๋ฉด -1์ ๋ฐํํ๋ค.
ssh [email protected] -p2222 (pw:guest)
MD5(Message-Digest algorithm 5)๋ 128๋นํธ ์ํธํ ํด์ ํจ์๋ก ์ฃผ๋ก ํ๋ก๊ทธ๋จ์ด๋ ํ์ผ์ด ์๋ณธ ๊ทธ๋๋ก์ธ์ง๋ฅผ ํ์ธํ๋ ๋ฌด๊ฒฐ์ฑ ๊ฒ์ฌ ๋ฑ์ ์ฌ์ฉ๋๋ค.
MD5๋ ์ค๊ณ์ ์ค๋ฅ๊ฐ ๋ฐ๊ฒฌ๋์ด ํ์ฌ๋ MD5 ์๊ณ ๋ฆฌ์ฆ์ ๋ณด์ ๊ด๋ จ ์ฉ๋๋ก ์ฐ๋ ๊ฒ์ ๊ถ์ฅํ์ง ์์ผ๋ฉฐ, ์ฌ๊ฐํ ๋ณด์ ๋ฌธ์ ๋ฅผ ์ผ๊ธฐํ ์๋ ์๋ค. ๋ค๋ง ๊ณ ์ ์ฐ์ฐ์ด ๊ฐ๋ฅํ๊ณ (์ ์ ์ฐ์ฐ ๋ฐ ๋นํธ ์ํํธ ์ฐ์ฐ๋ง ์ฌ์ฉํ๋ค.) ์์๋ก ๋ณ๊ฒฝ๋ ํจํด์ ๋ํด์๋ ์ถฉ๋ ๊ฐ๋ฅ์ฑ์ด ์ถฉ๋ถํ ๋ฎ๊ธฐ ๋๋ฌธ์, ํ์ฌ๋ ์ฃผ๋ก ๋คํธ์ํฌ๋ก ์ ์ก๋ ํฐ ํ์ผ์ ๋ฌด๊ฒฐ์ฑ์ ํ์ธํ๋๋ฐ ์ฌ์ฉํ๋ค.
๋จ๋ฐฉํฅ ์ํธํ์ด๊ธฐ ๋๋ฌธ์ MD5 hash ๊ฐ์์ ์๋ ๋ฐ์ดํฐ๋ฅผ ์ฐพ์๋ด๋ ๊ฒ์ ๋ถ๊ฐ๋ฅํ์ง๋ง ๊ฐ์ MD5๋ฅผ ๊ฐ๋ ๋ฌธ์์ด, ์ฆ ์ถฉ๋(collision)์ด ๋ฐ์ํ ์ ์๋ค. MD5 ๊ฐ์ด ๊ฐ์ผ๋ฉด ๋ฐ์ดํฐ๊ฐ ๋ค๋ฅด๋๋ผ๋ ๊ฐ์ ๋ฌธ์์ด์ด๋ผ๊ณ ํ๋จํ๊ธฐ ๋๋ฌธ์ ๋ฌธ์ ๊ฐ ๋ ์ ์๋ค. ์ด๋ ๋ชจ๋ ๋จ๋ฐฉํฅ ์ํธํ์ ํต์ฉ๋๋ ๊ธฐ๋ฒ์ด๋ค.
#include <stdio.h>
#include <string.h>
unsigned long hashcode = 0x21DD09EC;
unsigned long check_password(const char* p){
int* ip = (int*)p;
int i;
int res=0;
for(i=0; i<5; i++){
res += ip[i];
}
return res;
}
int main(int argc, char* argv[]){
if(argc<2){
printf("usage : %s [passcode]\n", argv[0]);
return 0;
}
if(strlen(argv[1]) != 20){
printf("passcode length should be 20 bytes\n");
return 0;
}
if(hashcode == check_password( argv[1] )){
system("/bin/cat flag");
return 0;
}
else
printf("wrong passcode.\n");
return 0;
}
๋งค๊ฐ๋ณ์์์ด ์ฝ๋๋ฅผ ์คํํ ๊ฒฝ์ฐ "usage : [passcode]"๋ผ๋ ๋ฌธ์ฅ์ด ์ถ๋ ฅ๋๊ณ ๋งค๊ฐ๋ณ์ ๋ฌธ์์ด์ ๊ธธ์ด๊ฐ 20์ด ์๋ ๊ฒฝ์ฐ "passcode length should be 20 bytes"๋ผ๋ ๋ฌธ์ฅ์ด ์ถ๋ ฅ๋๋ค. ๋ง์ฝ ์ฐ๋ฆฌ๊ฐ ์
๋ ฅํ ๋งค๊ฐ๋ณ์ ๋ฌธ์์ด์ check_password
ํจ์์ ๋ฃ์ ๊ฒฐ๊ณผ๊ฐ์ด hashcode
๊ฐ์ธ 0x21DD09EC์ ๊ฐ์ผ๋ฉด /bin/cat flag
๋ฅผ ๋ณผ ์ ์๋ค.
check_password
ํจ์๋ฅผ ์ดํด๋ณด๋ฉด charํ์ ํฌ์ธํฐ์ธ p
๋ฅผ ์ ์ํ ํฌ์ธํฐ๋ก ํ๋ณํํ๋ค. passcode
์ ๊ธธ์ด๋ 20byte์ด๊ณ ์ ์ํ ํฌ์ธํฐip
๋ 4byte์ด๊ธฐ ๋๋ฌธ์ ip
์ ์ ์ฅ๋์ด์๋ ๊ฐ 5๊ฐ๋ฅผ ๋ํด์ hascode
๊ฐ์ธ 0x21DD09EC๋ก ๋ง๋ค์ด์ฃผ๋ฉด ๋๋ค.
res
๊ฐ์ ์ ์ํ ๋ค์ฏ๊ฐ๋ฅผ ๋ํด์ ๊ตฌํด์ง๋ค. res
์ ๋ค์ด๊ฐ์ผํ 0x21DD09EC๋ฅผ 5๋ก ๋๋๋ฉด 0x6C5CEC8๊ฐ ๋์จ๋ค. ๋๋จธ์ง๊ฐ ๋ฐ์ํ๊ธฐ ๋๋ฌธ์ 0x6C5CEC8๋ฅผ ๋ค ๋ฒ ๋ํ ํ 0x6C5CECC๋ฅผ ํ ๋ฒ ๋ํด์ฃผ๋ฉด 0x21DD09EC๊ฐ ๋์ค๊ฒ ๋๋ค.
๊ทธ๋ฐ๋ฐ ip
์ ๋ฃ์ด์ผ ํ ๊ฐ์ ์์คํค ์ฝ๋ ๋ฒ์๋ฅผ ๋๊ธฐ ๋๋ฌธ์ ๊ฐ ๋์
์ผ๋ก ๋ฃ์ด์ค ์ ์๋ค. ๊ทธ๋์ ์ฝ๋๋ก ์ง์ ๋ฃ์ด์ฃผ๋ ์์คํ
์ little-endian์ ๋ฐ๋ฅด๊ธฐ ๋๋ฌธ์ little-endian๋ฐฉ์์ผ๋ก ๋ฃ์ด์ฃผ์ด์ผ ํ๋ค.
๊ฒฐ๊ณผ์ ์ผ๋ก ๋ค์๊ณผ ๊ฐ์ ๋ฐฉ๋ฒ์ผ๋ก ๋ฃ์ด์ฃผ๋ฉด /bin/cat flag
๋ฅผ ๋ณผ ์ ์๋ค.
./col $(perl -e 'print "\xc8\xce\xc5\x06"x4 . "\xcc\xce\xc5\x06"')
./col `python -c 'print "\xc8\xce\xc5\x06"*4+"\xcc\xce\xc5\x06"'`
๋ฏธ๊ตญ์ ๋ณด๊ตํํ์ค๋ถํธ(American Standard Code for Information Interchange; ASCII)๋ ์๋ฌธ ์ํ๋ฒณ์ ์ฌ์ฉํ๋ ๋ํ์ ์ธ ๋ฌธ์ ์ธ์ฝ๋ฉ์ด๋ค. ์์คํค๋ ์ปดํจํฐ์ ํต์ ์ฅ๋น๋ฅผ ๋น๋กฏํ ๋ฌธ์๋ฅผ ์ฌ์ฉํ๋ ๋ง์ ์ฅ์น์์ ์ฌ์ฉ๋๋ฉฐ, ๋๋ถ๋ถ์ ๋ฌธ์ ์ธ์ฝ๋ฉ์ด ์์คํค์ ๊ธฐ์ด๋ฅผ ๋๊ณ ์๋ค.
์์คํค ์ฝ๋๋ ๋ฏธ๊ตญ์์ ํ์คํํ ์ ๋ณด๊ตํ์ฉ 7๋นํธ ๋ถํธ์ฒด๊ณ์ด๋ค. 000(0x00)๋ถํฐ 127(0x7F)๊น์ง ์ด 128๊ฐ์ ๋ถํธ๊ฐ ์ฌ์ฉ๋๋ค. ์ด๋ ์๋ฌธ ํค๋ณด๋๋ก ์ ๋ ฅํ ์ ์๋ ๋ชจ๋ ๊ธฐํธ๋ค์ด ํ ๋น๋์ด ์๋ ๋ถํธ ์ฒด๊ณ์ด๋ฉฐ, ๋งค์ฐ ๋จ์ํ๊ณ ๊ฐ๋จํ๊ธฐ ๋๋ฌธ์ ์ด๋ ์์คํ ์์๋ ์ ์ฉ๊ฐ๋ฅํ๋ค๋ ์ฅ์ ์ด ์์ผ๋, 2๋ฐ์ดํธ ์ด์์ ์ฝ๋๋ฅผ ํํํ ์ ์๋ค.