본문 바로가기
드림핵

[드림핵][wargame.kr] md5 password 풀이

by jwcs 2024. 2. 23.
728x90

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

 

[wargame.kr] md5 password

Description md5('value', true);

dreamhack.io

 

/

첫 페이지다. 패스워드를 입력하라고 한다.

 

소스를 보며 분석해보자.

 

<?php
 if (isset($_GET['view-source'])) {
  show_source(__FILE__);
  exit();
 }

 if(isset($_POST['ps'])){
  sleep(1);
  include("./lib.php"); # include for $FLAG, $DB_username, $DB_password.
  $conn = mysqli_connect("localhost", $DB_username, $DB_password, "md5_password");
  /*
  
  create table admin_password(
   password char(64) unique
  );
  
  */

  $ps = mysqli_real_escape_string($conn, $_POST['ps']);
  $row=@mysqli_fetch_array(mysqli_query($conn, "select * from admin_password where password='".md5($ps,true)."'"));
  if(isset($row[0])){
   echo "hello admin!"."<br />";
   echo "FLAG : ".$FLAG;
  }else{
   echo "wrong..";
  }
 }
?>
<style>
 input[type=text] {width:200px;}
</style>
<br />
<br />
<form method="post" action="./index.php">
password : <input type="text" name="ps" /><input type="submit" value="login" />
</form>
<div><a href='?view-source'>get source</a></div>

전체 소스다. 중요한 부분만 빼서 확인해보겠다.

 

비밀번호 입력과정

비밀번호 검색하는 과정이다. `md5($ps, true)`에 대해서 알아야한다.

md5() 함수는 md5 해싱하는 함수이다. 뒤에 true는 바이너리 값으로 리턴할 것인지에 대한 것이다. 기본값은 false다.

 

이 부분에서 취약점이 발생한다. 바이너리 데이터를 입력하면 아마 utf-8로 인코딩할 것이다. 그럼 우리는 인코딩 시 `'='`가 되는 값을 찾아야한다.

 

왜 `'='`인지 궁금할 수 있으니 적어보겠다.

select * from admin_password where password=' [입력값] '

이다. 만약 입력값이 `aaa' = 'bbb`인 상황을 가정해보자.

select * from admin_password where password= 'aaa' = 'bbb'; 일 것이다.

 

password = 'aaa' 에서 false

false = 'bbb'는 false다.

따라서 false = false이기 때문에 true가 되어 문제가 풀리게 된다.

이것을 false injection이라고 한다. 이번 문제를 풀며 알게됐다.

https://jwcs.tistory.com/93

 

mysql boolean 비교 시 동작 방식과 false injection

출처 https://mysqlcode.com/mysql-bool-boolean/ MySQL BOOL, BOOLEAN - A Complete Guide - MySQLCode In this tutorial, we will learn the MySQL data type BOOL and BOOLEAN. We will also be learning how to implement boolean in the queries and some exceptions y

jwcs.tistory.com

참고하자

 

그럼 `'='`을 가지는 해싱값을 찾아보자.

import hashlib

for i in range(100000000):
    password = hashlib.md5(str(i).encode()).hexdigest()

    if '273d27' in password:
        print(i)

이러한 코드로 찾아보자. 27은 따옴표이고, 3d는 `=`이다.

 

찾은 값들

`83245200`을 입력해보겠다. 실제로 어떤 값은 flag를 출력해주고 어떤 값은 출력해주지 않을 것이다

flag

짜잔

 

방어 방법

 

바이너리 형식으로 데이터를 보냈는데, DBMS에서 이를 인코딩 하는 과정에서 취약점이 발생했다.

이진 데이터로 저장하려는 의도는 저장 공간을 효율적으로 사용하기 위함일 것이다. md5를 이진 데이터로 저장한다면 16바이트만큼 차지하지만, 16진수 형태의 문자열로 이를 저장하려 한다면 32바이트만큼 차지한다. 따라서 이를 base64로 인코딩하여 저장한다면 안전하고 효율적인 저장의 이점을 가져갈 수 있을 것이다.

 + 찾아보니 `binary`라는 키워드와 함께 사용하면 utf-8로 인코딩이 되지 않고 연산이 수행된다고 한다. 따라서 이러한 방법도 좋을 것같다.

728x90
반응형

'드림핵' 카테고리의 다른 글

[드림핵] BypassIF 풀이  (0) 2024.02.25
[wargame.kr] dun worry about the vase 풀이  (1) 2024.02.24
[드림핵] web-deserialize-python 풀이  (1) 2024.02.12
[드림핵] funjs 풀이  (1) 2024.02.11
[드림핵] crawling 풀이  (0) 2024.02.11