문제 설명
you need login with "admin"s id!
===========================
create table tmitter_user(
idx int auto_increment primary key,
id char(32),
ps char(32)
);
풀이
문제 설명을 읽어보면 admin의 id로 로그인해야 한다고 되어있다. 접속해보면 tmitter은 twitter의 가짜가 아니라고 한다.
Sign Up 버튼을 누르면 아래와 같은 join.php가 나오고 소스 코드를 분석해보았다.
join.php
의 소스코드는 아래와 같고 POST 메소드로 id
와 ps
를 입력받고 chk()
함수를 실행한다. 이 함수는 id의 길이는 4보다 크고, ps의 길이는 7보다 커야 한다.
<script>
function chk(f){
if(f.id.value.length<4){alert("chk id"); return false;}
if(f.ps.value.length<7){alert("chk ps"); return false;}
return true;
}
</script>
<form onsubmit="return chk(this);" method="post">
<table>
<tbody><tr><td>ID</td><td><input type="text" name="id" maxlength="32"></td><td class="ex">at least 4char</td></tr>
<tr><td>PS</td><td><input type="password" name="ps" maxlength="32"></td><td class="ex">at least 7char</td></tr>
<tr><td colspan="2"><input type="submit" value="join"></td></tr>
</tbody></table>
</form>
2
그래서 id와 ps를 각각 admin
, admin12
를 넣어 가입해보면 admin은 이미 존재한다고 출력된다.
Sign in 소스 코드는 아래와 같고 loginf()
함수를 사용중이다.
<div class="cont">
have an account? <input type="button" onclick="loginf();" value="Sign in">
</div>
<script>
function loginf() {
var ab = document.getElementById("loginform");
//ab.style.left=event.x;
ab.style.left = 0;
//ab.style.top=event.y;
ab.style.top = 0;
ab.style.display = "block";
}
</script>
그래서 일단 계정을 guest
, guestguest
를 넣고 가입한 후 로그인을 시도해 보니 tmitter.php
로 이동된 것을 볼 수 있다.
이 문제를 다시 한 번 살펴보면 id와 ps의 길이를 32로 제한하고 있는 것을 볼 수 있다. 처음 문제 설명에서 보았듯이 이 id와 ps는 char
이라는 자료형을 통해 값을 저장하게 되는데, 우리는 SQL을 처음 배울 때 varchar
함수를 사용했을 것이다. 따라서 char
자료형의 취약점을 통해서 익스플로잇을 할 수 있는데 char
자료형은 고정 문자열이기 때문에 사용자가 입력한 문자열을 제외하고는 공백으로 처리된다.
<form onsubmit="return chk(this);" method="post">
<table>
<tbody><tr><td>ID</td><td><input type="text" name="id" maxlength="32"></td><td class="ex">at least 4char</td></tr>
<tr><td>PS</td><td><input type="password" name="ps" maxlength="32"></td><td class="ex">at least 7char</td></tr>
<tr><td colspan="2"><input type="submit" value="join"></td></tr>
</tbody></table>
</form>
create table tmitter_user(
idx int auto_increment primary key,
id char(32),
ps char(32)
);
따라서 이 32자를 넘어서 123을 입력하면 어떻게 될까? admin 123
을 입력한다고 했을 때 123이 33자리부터 입력되었다고 치면 요청되는 쿼리 부분에서는 동일하게 admin
을 입력한 것과 똑같다. 따라서 이를 이용해 32자를 넘고 아무 문자나 숫자를 입력한 후 가입하면 flag를 획득할 수 있다.
admin과 공백 후 1자리를 1로 설정하기 위해 maxlength
값을 32에서 33으로 늘렸다. 따라서 스페이스바로 그냥 쭉 늘린 후 백스페이스하고 1을 입력하면 33자리를 입력할 수 있는 것이다. 비밀번호는 최소 7자리 이므로 1234567을 입력하였다.
위에서 말했던 것처럼 요청되는 쿼리는 admin으로 인식하기 때문에 admin
, 1234567
을 입력해주면 flag를 획득할 수 있다.
댓글남기기