간단한 로그인 페이지만 존재한다. admin 계정으로 로그인을 성공하면 flag를 얻을 수 있다.

아이디와 비밀번호를 기준으로 유저를 찾는다. 여기서 SQL 평문이 그대로 들어가므로 주석을 이용해서 password를 찾는 과정을 없앨 수 있다.
userid에 admin"--을 입력할 경우 --뒤의 명령어는 주석처리 되므로 실제 SQL은 select * from users where userid="admin"만 실행된다. password는 아무거나 입력해도 된다.
노노그램을 풀고 나면 랭킹 등록창이 나오고 자신과 같은 정답을 적은 사람들을 볼 수 있다. 아무런 설명도 없어서 당황스러웠지만 SQL Injection을 이용해서 모든 컬럼 값을 뽑아오면 된다.
소스를 보여주지 않았지만 아마 이런 SQL이 있을 것으로 예상된다.
$result = mysqli_query($db,"select * from chall3 where answer ='$answer' and ip='$ip'");

answer 값은 hidden으로 보내주고 있으므로 위 값에 SQL Injection을 통해 조건절을 모두 우회하면 된다.
value에 'or 1=1-- (마지막 공백 포함)를 넣으면 admin의 secret data를 볼 수 있다.
소스를 보면 admin의 no는 2이고, admin으로 로그인하면 성공이다. 하지만 sql에는 where id='guest'가 있어서 2를 입력해도 admin으로 로그인할 수 없다. 게다가 SQL Injection에 사용되는 대부분의 글자들을 검열시켜놓았다.
where절을 우회하기 위해서는 다음과 같은 sql이 실행되도록 해야한다.
select id from chall18 where id='guest' and no=0 or id='admin'
이렇게 하면 id가 guest이고 no가 0이거나, id가 admin인 데이터를 가져온다. guest의 no는 1이므로 결과가 출력되지 않을 것이고, 최종적으로 admin만 나올 것이다. 하지만 코드에서는 공백을 검열하므로 그대로 0 or id='admin'를 입력할 수 없다.
SQL에서는 TAB 역시 공백으로 인식한다. 하지만 위 코드에서는 TAB을 검열하지 않으므로 공백 대신 TAB의 URL 인코딩 값인 %09를 넣어서 해결했다.
no=0%09or%09id='admin'
old-18과 비슷하게 필터링을 우회해서 어드민으로 로그인하면 된다.
이 문제에서는 공백 뿐만 아니라 =역시 검열한다. 따라서 SQL에서 =대신 사용할 수 있는 like 키워드를 사용할 것이다.
최종적으로 실행할 SQL은
select id from chall27 where id='guest' and no=(0) or id='admin'-- )
이 될것이다. 따라서 no=0)%09or%09id%09like%09%27admin%27%09--%09을 입력해야한다.
마지막에 주석을 넣은 이유
기존 코드가
select id from chall27 where id='guest' and no=({$_GET['no']})이므로 뒤에 닫힌 괄호를 무시하기 위해 주석을 넣었다. 그리고 sql 주석은 무조건 한칸의 공백을 두고 사용해야하므로 --%09를 추가한 것이다.