[Solved in under 10 minutes]
문제가 빠르게 풀려 하나 더 풀었다.
Let's geeeeeeeeeeeet it~

<?php
include "./config.php";
login_chk();
$db = dbconnect();
if(preg_match('/prob|_|\.|\(\)/i', $_GET[no])) exit("No Hack ~_~");
if(preg_match('/\'|\"|\`/i', $_GET[no])) exit("No Quotes ~_~");
$query = "select id from prob_goblin where id='guest' and no={$_GET[no]}";
echo "<hr>query : <strong>{$query}</strong><hr><br>";
$result = @mysqli_fetch_array(mysqli_query($db,$query));
if($result['id']) echo "<h2>Hello {$result[id]}</h2>";
if($result['id'] == 'admin') solve("goblin");
highlight_file(__FILE__);
?>
코드를 보면 인자를 no로 받는다.
내가 생각하는 여기서 포인트는 id는 'guest'로 고정이다.
대충 1을 넣어보자

id가 guest고 no가 1일때 guest로 로그인이 된다.
자 다음은 뭐를 생각해봐야 할까?
id가 guest로 고정이니 admin으로 절대 로그인 할 수 없다.
고로 앞에 묶여있는 [id='guest' and no = 1] 이 부분을 전체 다 틀린다면?
그리고 뒤에 or 문을 넣어 뒤에게 맞게 한다면?
ex) (a and b) or c
이렇게 가정한다면 a 또는 b중에 하나라도 false라면 뒤에 있는 or로 c만 true로 만든다는 작전이다.
바로 해보자.

문제가 풀리지 않았다 왜그럴까?
싱글쿼터가 없기 때문이다.
삽입해보자

필터링에 막혔다 preg_match를 보자
if(preg_match('/prob|_|\.|\(\)/i', $_GET[no])) exit("No Hack ~_~");
if(preg_match('/\'|\"|\`/i', $_GET[no])) exit("No Quotes ~_~");
싱글쿼터('), 더블쿼터(") 모두 막혀있다.
그리하여 저것들을 우회하는 방법도 존재한다고 생각하지만
나는 그냥 둘 다 안쓰고 'admin'으로 입력받는 선택을 했다.
바로 ASCII코드를 입력받으면 된다.
SQL에서 ASCII코드를 받으려면 CHAR() 함수를 사용하면 된다!
바로 해보자

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ 답 ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
?no=2 or id=char(97,100,109,105,110) %23
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
를 삽입하였더니 되었다.
CHAR() 함수로 ASCII코드를 받으면 입력이 들어갈때 'admin'으로 들어가기 때문에 싱글쿼터, 더블쿼터를 신경 안써도 된다.
밑에 네모 박스와 같이 id=guest일때 no=1이니 이것을 고의로 틀리고 뒤에 or로 id='admin'을 심는 원리이다.
뒤에 %23은 습관이니 무시해도 좋다.
LoS(Lord of SQL Injection) Goblin Write-up
이상 보고 끝!