-
[web hacking] login filtering 풀이해킹/wargame 2023. 2. 28. 14:36
https://dreamhack.io/wargame/challenges/336/
[wargame.kr] login filtering
Description text I have accounts. but, it's blocked. can you login bypass filtering?
dreamhack.io
wargame.kr 에 있던 문제입니다.
코드 분석
<?php if (isset($_GET['view-source'])) { show_source(__FILE__); exit(); } /* create table user( idx int auto_increment primary key, id char(32), ps char(32) ); */ if(isset($_POST['id']) && isset($_POST['ps'])){ include("./lib.php"); # include for $FLAG, $DB_username, $DB_password. $conn = mysqli_connect("localhost", $DB_username, $DB_password, "login_filtering"); mysqli_query($conn, "set names utf8"); $id = mysqli_real_escape_string($conn, trim($_POST['id'])); $ps = mysqli_real_escape_string($conn, trim($_POST['ps'])); $row=mysqli_fetch_array(mysqli_query($conn, "select * from user where id='$id' and ps=md5('$ps')")); if(isset($row['id'])){ if($id=='guest' || $id=='blueh4g'){ echo "your account is blocked"; }else{ echo "login ok"."<br />"; echo "FLAG : ".$FLAG; } }else{ echo "wrong.."; } } ?> <!DOCTYPE html> <style> * {margin:0; padding:0;} body {background-color:#ddd;} #mdiv {width:200px; text-align:center; margin:50px auto;} input[type=text],input[type=[password] {width:100px;} td {text-align:center;} </style> <body> <form method="post" action="./"> <div id="mdiv"> <table> <tr><td>ID</td><td><input type="text" name="id" /></td></tr> <tr><td>PW</td><td><input type="password" name="ps" /></td></tr> <tr><td colspan="2"><input type="submit" value="login" /></td></tr> </table> <div><a href='?view-source'>get source</a></div> </form> </div> </body> <!-- you have blocked accounts. guest / guest blueh4g / blueh4g1234ps -->
id와 ps를 post 방식으로 받아와서 데이터베이스에 존재하는지 확인하고,
존재한다면 아이디가 guest 또는 blueh4g인지 필터링합니다.
아이디가 guest나 blueh4g가 아닌 다른 것이라면 정상적으로 로그인이 되고 flag 값을 출력해줍니다.
이 문제는 sql injection을 사용할 수도 있을 것 같지만, mysqli_real_escape_string이라는 함수가 걸립니다.
mysqli_real_escape_string
post 방식으로 인자 그대로 받아오지 않고, sql injection을 대비하기 위해 ' 또는 " 등의 문자를 필터링을 걸친 후 escaped string을 전달해주는 함수입니다.
escaped string은 \n, \t와 같이 escape된 문자열을 의미합니다.
문제에서 id와 ps가 이 함수를 통해 escaped돼서 전달되기 때문에 특수문자를 활용한 sql injection은 어려워 보입니다.
해결법
문제에 대한 답은 생각보다 간단합니다. php에서는 대소문자 구분을 하고, 쿼리문에서는 대소문자 구분이 없다는 점을 이용하면 됩니다.
문제에서는 우선 쿼리문을 통해 계정 정보가 있는지 확인하고, 이후 그 계정에 대한 id가 guest 또는 blueh4g인지 확인합니다.
따라서 아이디를 guest가 아닌 Guest, gUest 등 대소문자를 섞어서 주게 되면, 쿼리문에서는 대소문자 비교를 하지 않기 때문에 GUEST라는 id의 계정정보가 있는지 확인하고, 정보가 있으므로 문자열 비교 필터링으로 들어가게 되는데,
이 때는 Guest == guest는 false를 반환하기 때문에 로그인 필터링에 걸리지 않고 flag 값을 얻어낼 수 있습니다.
취약점 보완법
login filtering을 할 때, id로 Guest나 gUESt등 대소문자가 섞여서 들어올 수 있다고 생각하고 필터링 코드를 작성하면 됩니다.
'해킹 > wargame' 카테고리의 다른 글
[webhacking] XSS-1 / XSS-2 문제 풀이 (0) 2023.03.05 [webhacking] cookie, session- basic 풀이 (0) 2023.03.03 [web hacking] strcmp 풀이 (0) 2023.02.28