안녕하세요. 오늘은 webhacking 35번 문제를 풀어보겠습니다.

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

문제를 낸 사람은 HellSonic분인 것 같네요. 일단 index.phps를 눌러봅시다.

당연하지만 이런 소스에서는 solve를 먼저 봐야 합니다. 

if($admin_ck[ip]==$_SERVER[REMOTE_ADDR])
{

@solve();

admin_ck[ip]의 값이 SERVER[REMOTE_ADDR] 라면 해결된다는 군요. SERVER[REMOTE_ADDR]는 자신의 ip주소를 불러오라는 함수입니다.

그러면 admin_ck[ip]가 뭔지 알아야겠죠.

$admin_ck=mysql_fetch_array(mysql_query("select ip from challenge35_list where id='admin' and ip='$_SERVER[REMOTE_ADDR]'"));

mysql_fetch_array 이란 DB의 레코드셋을 PHP배열로 가져오는 함수입니다. 레코드셋이란 쉽게 말하면 레코드들의 집합이라 보시면 됩니다. 그렇다면 가져올려는 레코드셋을 한 번 봅시다.

mysql_query("select ip from challenge35_list where id='admin' and ip='$_SERVER[REMOTE_ADDR]'")

mysql_query는 php에서 데이터베이스(MySQL)에게 SQL 명령어를 실행시키기 위해서 쓰는 함수입니다. 명령문을 보시면 select ip = ip를 검색하라

from challenge35_list = challenge35_list란 테이블에서, where은 조건입니다. 그렇다면

id가 admin이고 ip가 SERVER[REMOTE_ADDR]인 ip를 challenge35_list에서 검색한 값을 php배열로 가져온다 라는 뜻이 되겠네요. 여기까지 됐으면 자 이제 처음부터 차례대로 해석해봅시다.

if($_GET[phone])
{
if(
eregi("%|\*|/|=|from|select|x|-|#|\(\(",$_GET[phone])) exit("no hack");

eregi는 문자열을 찾는 함수입니다. phone값을 받았는데 이 값에서 

% * / = from select x - # ( 가 있을 경우 참을 반환하여 exit(no hack)를 실행한다는군요. 즉 우리는 phone값에 % * / from select (을 넣을 수 없습니다. 그 다음 걸 봅시다.

@mysql_query("insert into challenge35_list(id,ip,phone) values('$_SESSION[id]','$_SERVER[REMOTE_ADDR]',$_GET[phone])") or die("query error");

앞에 붙은 @는 함수의 오류를 출력하지 않겠다라는 소리입니다. 뒤의 query는 앞서 설명했다 시피 sql 명령어를 실행시키기 위한 함수입니다. 명령문을 보시면 insert = 삽입하라.

into challenge35_list(id,ip,phone) = challenge35_list테이블의 id,ip,phone 컬럼(필드)에

values('$_SESSION[id]','$_SERVER[REMOTE_ADDR]',$_GET[phone]) = $_SESSION[id]','$_SERVER[REMOTE_ADDR]',$_GET[phone]의 값을

즉 정리하면 challenge35_list테이블의 id,ip,phone 컬럼(필드)에 $_SESSION[id]','$_SERVER[REMOTE_ADDR]',$_GET[phone]의 값을 삽입하라는 소리입니다. 뒤의 or die("query error");는 앞의 명령이 실패했을 경우 query error를 내보내라 라는 뜻입니다.

이 함수가 다 끝나면 id는 id란 세션의 값, ip는 SERVER[REMOTE_ADDR]의 값 

phone에는 GET[phone]의 값이 들어가 있겠군요.

자 이제 해석이 끝났으니 정리를 해봅시다.

1. 해결을 위해서는 admin_ck[ip]의 값이 자신의 ip주소여야 한다.

2. admin_ck는 id가 admin인 자신의 ip주소를 가져온다.

3. id의 값에는 SESSION[id]의 값이 들어간다.

4. 우리가 만질 수 있는 부분은 GET[phone]뿐이다.

우리가 바꿀수 있는 부분은 GET[phone]인데 정작 우리는 id의 값을 바꿔야 합니다. 왜냐하면 id의 값이 admin인 자신의 ip주소를 갖고 오기 때문에 ip주소가 똑같아도 id값이 admin이 아니면 백날 가져오지 않습니다. 그러면 우리는 GET[phone]을 이용해 id의 값까지 바꿔봅시다. 이러한 문제를 풀 경우에는 특수문자가 거의 필수로 들어갑니다.

phone 값에 1),('admin','자신의 IP값',2

를 넣어줍시다. 데이터 유형이 문자유형일 경우 '를 입력해야 합니다. 숫자는 상관없습니다. 그러면

@mysql_query("insert into challenge35_list(id,ip,phone) values('$_SESSION[id]','$_SERVER[REMOTE_ADDR]',1),('admin','IP',2)") or die("query error"); 이렇게 되겠지요.

사실 values(값1,값2,값3)는 values(값1,값2,값3),(값4,값5,값6)으로 써도 작동이 됩니다.

다만 후자의 경우에는 값1,값2,값3이 먼저 들어가고 값4,값5,값6이 들어가기 때문에 값1,값2,값3은 덮어져 버립니다. 즉 값4,값5,값6만 남아있게 되는 것이지요. 이렇게 함으로써 우리가 id,ip,phone 값을 전부 수정할 수 있게 됩니다.

방금 쓴 것대로 넣어주시면 id에는 admin이 ip에는 자신의 ip주소가 들어가게 됩니다. 즉 문제가 해결되지요. phone값은 상관이 없으므로 아무거나 넣어주셔도 됩니다. 앞쪽 phone값도 어차피 덮어져 버리기 때문에 아무값이나 넣어도 상관없습니다.그러면 입력해봅시다.

음 쿼리에러가 떴네요. 문법은 맞습니다. 그럼 뭐가 문제일까요? no hack이 뜬게 아닌 걸로 보아 eregi에 걸린 것은 아닙니다. 

알아보니 php에는 magic_quotes_gpc라는 함수가 존재한답니다. 이 함수는 '(홑따옴표), "(큰따옴표), \(이스케이프), %00(null) 값에 대해 앞에 \ 문자를 붙임으로써 공격을 방지하는 기능을 가지고 있답니다. 만약 이 함수가 실행되었다면 우리가 입력한 

1),('admin','자신의 IP값',2 의 값은 1),(\'admin\',\'자신의 IP값\',2 이 되버려 쿼리에러가 되버립니다. 그렇다면 '를 대체할 무언가가 필요합니다. '는 문자를 입력하기 위한 기호이니까 '대신 문자를 쓸 수 있도록 해주는 것을 써야 합니다. 바로 char함수이죠. char함수는 아스키코드를 문자로 바꿔주는 함수입니다. 즉 id의 admin도 아스키코드로 써야 하며 자신의 ip주소도 아스키코드로 써야합니다. 참고로 .은 46입니다. 자 그럼 아래와 같이 써주세요.

add 버튼을 눌러주세요.

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




'Webhacking' 카테고리의 다른 글

webhacking - 46번 문제  (0) 2015.08.01
webhacking - 36번 문제  (0) 2015.07.30
webhacking - 32번 문제  (0) 2015.07.29
webhacking - 56번문제  (1) 2015.07.19
webhacking - 47번 문제  (0) 2015.07.17
Posted by englishmath
,