문제 설명
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를 획득할 수 있다.

댓글남기기