[ 환경 ]
DVWA | v1.9 |
Burp Suite | Community Edition v2024.11.2 |
이 코드는 사용자가 자신의 현재 비밀번호를 확인한 후 새 비밀번호로 변경할 수 있는 기능을 제공하며, Anti-CSRF 토큰 검증, 현재 비밀번호 확인, 새 비밀번호 일치 확인, 데이터베이스 업데이트의 과정을 포함한다.
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
$pass_curr = $_GET[ 'password_current' ];
$pass_new = $_GET[ 'password_new' ];
$pass_conf = $_GET[ '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 );
$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();
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 = 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 );
$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();
generateSessionToken();
아래는 앞서 살펴본 코드를 개선한 코드의 예제로 보안 강화와 기능 개선을 목표로 기존 코드의 한계를 극복하고, 더욱 안전한 구현을 제공한다. 주요 개선 사항은 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>";
}
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
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()]);
1. POST 요청 사용
2. 강력한 비밀번호 암호화
3. SQL 인젝션 방지
4. CSRF 방어
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 |