상세 컨텐츠

본문 제목

DVWA : CSRF - Impossible level

Vulnerability Assessment/Web Application

by DarkSoul.Story 2025. 1. 1. 19:20

본문

반응형

[ 환경 ]

DVWA v1.9
Burp Suite Community Edition v2024.11.2

1. Source code analysis

[그림 1] Impossible level Source code

 

이 코드는 사용자가 자신의 현재 비밀번호를 확인한 후 새 비밀번호로 변경할 수 있는 기능을 제공하며, Anti-CSRF 토큰 검증, 현재 비밀번호 확인, 새 비밀번호 일치 확인, 데이터베이스 업데이트의 과정을 포함한다.

Anti-CSRF 토큰 검증

checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
  • 사용자가 전송한 토큰( $_REQUEST'user_token' ] )과 세션에 저장된 토큰( $_SESSION'session_token' ] )을 비교한다.
  • 토큰이 일치하지 않으면 checkToken(  ) index.php로 리디렉션하거나 요청을 차단한다.

사용자 입력값 가져오기

$pass_curr = $_GET[ 'password_current' ];
$pass_new  = $_GET[ 'password_new' ];
$pass_conf = $_GET[ 'password_conf' ];
  • password_current: 현재 비밀번호
  • password_new: 새 비밀번호
  • password_conf: 새 비밀번호 확인값

현재 비밀번호 처리 (입력값 정제)

$pass_curr = stripslashes( $pass_curr );
$pass_curr = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass_curr ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
$pass_curr = md5( $pass_curr );
  • stripslashes ) : 백슬러시(\)를 제거하여 입력값을 정재한다.
  • mysqli_real_escape_string  ) : SQL 인젝션(SQL Injection)을 방지하기 위해 데이터베이스 쿼리에 안전하도록 입력값을 이스케이프 처리한다.
  • 입력된 새 비밀번호를 md5 해시 알고리즘으로 암호화하고,암호화된 비밀번호를 데이터베이스에 저장한다.
  • md5는 더 이상 안전하지 않은 해시 알고리즘으로, rainbow table 공격 및 GPU 기반 크래킹 공격에 취약하다.

현재 비밀번호 처리 (현재 비밀번호 검증)

$data = $db->prepare( 'SELECT password FROM users WHERE user = (:user) AND password = (:password) LIMIT 1;' );
$current_user = dvwaCurrentUser();
$data->bindParam( ':user', $current_user, PDO::PARAM_STR );
$data->bindParam( ':password', $pass_curr, PDO::PARAM_STR );
$data->execute();
  • 현재 사용자의 비밀번호가 데이터베이스에 저장된 값과 일치하는지 확인한다.
  • :user:password 매개변수에 현재 사용자 이름 $current_user)과 현재 비밀번호( $pass_cur) 값을 바인딩한다.
  • SQL 인젝션 방지를 위해 PDO의 bindParam(  ) 을 사용한다.
더보기

bindParam()는 PHP에서 PDO (PHP Data Objects)를 사용하여 SQL 쿼리에 변수 값을 안전하게 바인딩하기 위해 제공되는 메서드로 이를 통해 SQL Injection과 같은 보안 문제를 방지할 수 있다.

 

기본역할 : bindParam() 메서드는 값의 참조(reference)를 바인딩한다. 이 값은 SQL 실행 시점에서 평가되며, 주로 prepare() 메서드와 함께 사용되어 prepared SQL 문에 변수를 안전하게 연결한다.

 

ㅁ bindParam( ) vs bindValue( )

특징  bindParam( ) vs bindValue( )
값 전달 방식 변수의 참조를 방인딩 즉시 값을 복사
변경된 값 반영 SQL 실행 전에 변수 값이 변경되면 반영 SQL 실행 전에 변수 값 변경이 반영되지 않음
사용 예시 동적으로 값이 변경될 경우 적합 값이 고정적일 경우 적합

새 비밀번호 처리 및 검증 (새 비밀번호 검증)

if( ( $pass_new == $pass_conf ) && ( $data->rowCount() == 1 ) ) {
  • 새 비밀번호( $pass_new )와 비밀번호 확인값( $pass_conf )이 동일한지 확인한다.
  • rowCount( )가 1이면 현재 비밀번호가 데이터베이스의 값과 일치한다는 의미

새 비밀번호 처리 및 검증 (새 비밀번호 처리)

$pass_new = stripslashes( $pass_new );
$pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
$pass_new = md5( $pass_new );
  • stripslashes : 백슬러시(\)를 제거하여 입력값을 정재한다.
  • mysqli_real_escape_string  : SQL 인젝션(SQL Injection)을 방지하기 위해 데이터베이스 쿼리에 안전하도록 입력값을 이스케이프 처리한다.
  • 입력된 새 비밀번호를 md5 해시 알고리즘으로 암호화하고,암호화된 비밀번호를 데이터베이스에 저장한다.

데이터베이스 업데이트

$data = $db->prepare( 'UPDATE users SET password = (:password) WHERE user = (:user);' );
$data->bindParam( ':password', $pass_new, PDO::PARAM_STR );
$current_user = dvwaCurrentUser();
$data->bindParam( ':user', $current_user, PDO::PARAM_STR );
$data->execute();
  • 새 비밀번호르 ㄹ업데이트하는 SQL 쿼리를 준비한다.
  • :password :user 매개변수에 새 비밀번호( $pass_new )와 현재 사용자( $current_user )값을 바인딩한다.
  • execute( )를 통해 SQL 쿼리를 실행한다.

Anti-CSRF 토큰 생성

generateSessionToken();
  • 새로운 Anti-CSRF 토큰을 생성하여 세션 변수( $_SESSION'session_token' ] )에 저장한다.

 

2. Source code improvements

아래는 앞서 살펴본 코드를 개선한 코드의 예제로 보안 강화와 기능 개선을 목표로 기존 코드의 한계를 극복하고, 더욱 안전한 구현을 제공한다. 주요 개선 사항은 POST 요청 사용, 강력한 비밀번호 암호화, SQL 인젝션 방지이다.

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    checkToken($_POST['user_token'], $_SESSION['session_token'], 'index.php');

    $pass_curr = $_POST['password_current'];
    $pass_new = $_POST['password_new'];
    $pass_conf = $_POST['password_conf'];

    if ($pass_new === $pass_conf) {
        $stmt = $db->prepare('SELECT password FROM users WHERE user = :user');
        $stmt->execute([':user' => dvwaCurrentUser()]);
        $stored_hashed_password = $stmt->fetchColumn();

        if (password_verify($pass_curr, $stored_hashed_password)) {
            $hashed_new_password = password_hash($pass_new, PASSWORD_BCRYPT);

            $stmt = $db->prepare('UPDATE users SET password = :password WHERE user = :user');
            $stmt->execute([':password' => $hashed_new_password, ':user' => dvwaCurrentUser()]);
            echo "<pre>Password Changed.</pre>";
        } else {
            echo "<pre>Current password is incorrect.</pre>";
        }
    } else {
        echo "<pre>Passwords do not match.</pre>";
    }
}

POST 요청 확인

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
  • HTTP 요청 메서드가 POST인지 확인하며, GET 요청 대신 POST 요청을 사용하여 비밀번호와 같은 민감한 데이터가 URL에 노출되지 않도록 한다.

현재 비밀번호 검증

if (password_verify($pass_curr, $stored_hashed_password)) {
  • password_verify( ) : 사용자가 입력한 현재 비밀번호($pass_curr)와 데이터베이스에 저장된 암호화된 비밀번호($stored_hashed_password)를 비교하며, 비밀번호가 일치하지 않으면 오류 메시지를 출력한다.

새 비밀번호 암호화

$hashed_new_password = password_hash($pass_new, PASSWORD_BCRYPT);
  • password_hash( ) 새 비밀번호를 안전하게 암호화한다.
  • PASSWORD_BCRYPT 옵션을 사용하여 강력한 해시 알고리즘을 적용합니다.
  • 이 방식은 md5나 sha1에 비해 훨씬 안전하며, 비밀번호 검증에 password_verify( )를 사용한다.

데이터베이스 업데이트

$stmt = $db->prepare('UPDATE users SET password = :password WHERE user = :user');
$stmt->execute([':password' => $hashed_new_password, ':user' => dvwaCurrentUser()]);
  • 현재 사용자의 비밀번호를 새 암호화된 비밀번호로 업데이트한다.
  • Prepared Statement 사용 : SQL 인젝션 방지를 위해 :password와 :user 매개변수로 데이터를 바인딩한다.
  • execute()를 통해 쿼리를 실행하고, 비밀번호를 업데이트한다.

개선된 코드의 주요 기능

1. POST 요청 사용

  • GET 대신 POST 요청을 사용하여 민감한 데이터가 URL에 노출되지 않도록 함

2. 강력한 비밀번호 암호화

  • password_hash( )를 사용하여 안전한 암호화
  • password_verify( )를 사용해 암호화된 비밀번호 검증

3. SQL 인젝션 방지

  • PDO의 Prepared Statements를 사용하여 SQL 쿼리를 안전하게 처리

4. CSRF 방어

  • Anti-CSRF 토큰 검증으로 CSRF 공격 방지
반응형

'Vulnerability Assessment > Web Application' 카테고리의 다른 글

DVWA : File Inclusion - Medium level  (1) 2025.01.03
DVWA : File Inclusion - Low level  (1) 2025.01.02
DVWA : CSRF - High level  (0) 2025.01.01
DVWA : CSRF - Medium level  (0) 2025.01.01
DVWA : CSRF - Low level  (0) 2024.12.30

관련글 더보기