안녕하세요. 이번엔 webhacking의 27번문제를 풀어보겠습니다.

홈페이지로 들어가 27번 문제를 눌러주세요.

SQL INJECTION란 문구와 밑의 제출칸이 나오는군요. 여기서 SQL INJECTION는 해킹기법중 하나입니다. 흠.. 일단 소스를 한번 봅시다.

24번 문제와 마찬가지로 주석처리 되있는 부분이 있습니다. 출처인것 같군요. 주소창에 index.phps를 적고 들어가 봅시다.

역시 이런 문제는 solve부터 봐야 합니다. 역시 앞에 조건문이 있군요. id의 변수값이 admin일 경우 문제가 해결된다고 하네요. 그런데 이 소스를 아무리 봐도 id는 보이지 않습니다. id가 어디있을까요? 일단 id의 앞푸분에 $q가 붙어있습니다. $q는 바로 위에 보이네요. 

$q=@mysql_fetch_array(mysql_query("select id from challenge27_table where id='guest' and no=($_GET[no])")) or die("query error");

딱 봐도 머리가 아파요. 꼭 영어문장 보는 것 같습니다. 일단 @는 수 실행시 발생하는 오류를 표시하지 않겠다는 뜻입니다. 참 너무하죠. 암튼 그다음 문장이 중요합니다. 

mysql_fetch_array 이 함수는 정말 간단하게 말하면 mysql_query()함수의 호출을 통한 결과값을 반환한다는 것입니다. 그럼 mysql_query()의 함수를 알아야겠죠? 

mysql_query()는 연결된 객체를 이용하여 MySQL 쿼리를 실행시키는 함수입니다. 즉 위문구는  mysql_query의 가로안의 문구를 쿼리형태로 실행시키라는 것입니다. 다음 문구를 보시면 select id from challenge27_table 라고 적혀있습니다. select는 mysql에서 찾아서 보여달라라는 명령어입니다. 뭐를? id를 어디서? from challenge27_table, 27번문제 테이블에서 id를 찾아 보여달라라는 의미입니다. 그 다음은 where이 나오는데 이는 조건이라고 보시면 됩니다. 즉 id='guest'인 and(그리고) no가 $_GET[no](입력받은 no값)인 id값을 27번문제 테이블에서 찾아서 보여달라는 소리입니다. 그리고 mysql_fetch_array에 의해 찾아서 보여준 id값을 반환하라 뭐 대충 이런 뜻이겠군요. 맨 뒤쪽 문구는 or(또는) die(실패했을경우) query error를 찾아서 보여준다. 라는 뜻입니다.

자 이제 정리하면 

1. 테이블의 이름은 문제27번 테이블이며 테이블의 칼럼(열)은 id와 no로 나뉘어져있습니다.

2. 아래 그림처럼 no는 ()가 있으므로 정수형을 담는 칼럼입니다.

no는 문제에 나와있는 박스의 이름이고 테이블의 시작은 0부터 시작하므로 0부터 차례대로 입력해봅시다. 

다른건 전부 쿼리 에러가 뜨는데 no값이 1일 경우에만 quest가 뜹니다. 위의 $q의 조건으로 봤을때 id가 guest인 no의 값은 1인것 같습니다. 하지만 우리의 목표는 id가 admin인 no의 값을 찾아내는 것입니다. 일단 소스를 다시 봅시다. no값은 정수형이고 테이블은 순서대로 존재하므로 no=0 admin no=1 guest 이거나 no=1 guest no=2 admin . 아마 테이블은 이 둘중 하나일 듯 싶습니다. 일단 첫번째 테이블이 맞다는 가정하에 no값을 조금 특수하게 적어보겠습니다. 

$q=@mysql_fetch_array(mysql_query("select id from challenge27_table where id='guest' and no=($_GET[no])")) or die("query error");

앞서 문제에 있는 SQL INJECTION은 ID 와 비밀번호를 넣는 공간에 ' 등의 특수문자를 집어넣어 sql문을 변조시키는 해킹기법중 하나입니다.위의 문구를 보시면 where id='?' and no=(?) or die() 형식으로 되어있습니다. 그런데 여기서 no값에 특수문자를 주면 어떻게 될까요? 예를 들어 no값에 0) 라고 값을 준다면 no=($_GET[no])"))의 값이 no=(0))"))라는 값이 되어 에러가 납니다. 닫는 가로가 하나 늘었기 때문이지요. 그런데? 만약 뒤가로를 주석처리 해준다면? no값에 0) -- 라고 값을 주면 no=($_GET[no])"))의 값이 no=(0) -- )")) 이렇게 되버립니다. 참고로 --는 주석처리하라는 명령어로 -- 뒤쪽의 문구는 주석처리가 되어 실제로 아무런 효과도 없어집니다. 즉 no=(0) 가 되버려 에러가 뜨지 않고 작동하는 것이지요.

자 그러면 이제 쿼리문을 변조해 봅시다.

where 다음의 조건은 id가 guest이고 no값이 (입력된 값)인 데이터를 찾아달라 라는 뜻인데 우리는 id가 admin인 no값을 찾아야 하므로 첫번째 조건 id='guest' and no=($_GET[no])는 절대 참이 될 수 없습니다. 그러면 이 첫번째 조건문을 건드려야 하는데 지금 우리 권한으론 건드릴수 있는 부분이 없습니다. 그러면 이제 두번째 조건을 볼까요?

or die("query error"); 만약 첫번째 조건에 맞지 않을 경우(실패) query error를 출력해라 . 이것을 건드려야 합니다. 근데 어떻게 건드리냐구요? 음 문구를 조금 뗴어오겠습니다.

no=($_GET[no])")) or die("query error"); 우리는 저 진한 부분만 건드릴 수 있습니다. 그런데 무슨 값을 넣어야 될까요? 우리는 첫번째 조건에 맞지 않기 때문에 두번째 조건을 바꿔줘야 합니다. 근데 두번째 조건 까진 손이 안닿습니다. 그러면? 당연히 직접 써야죠.

no값에 0) or no=0 라고 값을 줘봅시다. 그러면 no=($_GET[no])")) or die("query error")에서 no=(0) or no=0)")) or die("query error")가 됩니다. 그런데 or문은 두개가 올 수 없으므로 뒤쪽에 or문은 주석처리를 해줘 무효를 시켜줘야 합니다. 그러면 0) or no=0 -- 를 넣어서 뒤쪽의 문장을 무효화시키면 no=(0) or no=0 가 되버립니다. 그러면 이제 이 값을 입력해 봅시다. 참고로 --의 앞과 뒷부분은 뛰어쓰기를 해줘야 합니다.


??? 넣으니까 no hack 이란 문구가 나옵니다? 이상하군요. 소스를 확인해봅시다.

이 문구를 깜빡했군요. eregi함수의 형식은 (찾는문자열, 제시하는 변수) 이며 제시한 변수에 찾는 문자열이 있을 경우 다음과 같이 수행하라 라는 뜻입니다. 뒤쪽엔 exit no hack이라 있는걸로 보아 no hack을 반환한다는 군요. 그리고 찾는 문구에 =가 포함되어있습니다. 즉 아까 적었던 문구 0) or no=0 -- 에 =가 포함되어 있어 노핵을 출력한것 같습니다. 그러면 = 을 대신할 것을 적어줍시다. 여기선 like를 사용해봅시다. like는 조건이란 뜻으로 ~와 같은 이란 뜻을 가집니다. 예시로 no like 0이라고 한다면 0과 같은 no값 이란 뜻이지요. 결국 0이란 소리입니다. 자 이제 =을 뺴고 like를 넣어 적어봅시다.

제출 버튼을 눌러주세요.

아무래도 no=0 admin no=1 guest 은 아닌것 같군요. 그럼 두번째 예시 no=1 guest no=2 admin로 가봅시다. 2값이 admin이므로 2로 바꿔주시면 됩니다.

어차피 우리가 신경써야 할 부분은 or다음의 조건이기 때문에 or 앞에 0)은 사실 아무숫자나 와도 됩니다. 1) or no like 2 도 되고 2) or no like 2 도 되고 324) or no like 2 도 됩니다. 자 제출버튼을 눌러봅시다.

네 이것으로 문제풀이를 마치겠습니다. 감사합니다.

'Webhacking' 카테고리의 다른 글

webhacking - 47번 문제  (0) 2015.07.17
Webhacking - 33번 문제  (2) 2015.07.11
Webhacking - 문제24번  (0) 2015.07.10
Webhacking - 문제 11번  (0) 2015.07.08
webhacking시작 - 문제17번  (6) 2015.07.05
Posted by englishmath
,