해당 포스트는 소스코드만 다룹니다
개념 설명은 이전 포스트를 참고해주세요
2024.11.27 - [모의해킹/SegFault 7기] - 로그인 로직 이해하기 - 식별과 인증, 그리고 해시 (Hash)
▲ 이전 포스트 확인
먼저, 해싱하지 않은 두 가지의 테스트 버전에 대한 데이터베이스이다. 소스코드에서는 평문으로 저장된 암호를 불러와 비교한다.
식별/인증 동시
<?php
session_start();
$db_conn = mysqli_connect("localhost", "root", "root", "test_db");
if (!$db_conn) {
die("Connection failed: " . mysqli_connect_error());
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = $_POST['id'] ?? '';
$password = $_POST['pass'] ?? '';
// 식별과 인증 동시에 처리
$sql = $db_conn->prepare("SELECT * FROM user WHERE id = ? AND pw = ?");
$sql->bind_param("ss", $username, $password);
$sql->execute();
$result = $sql->get_result();
if ($result->num_rows > 0) {
$_SESSION['login_success'] = true;
$_SESSION['username'] = $username;
} else {
$_SESSION['login_success'] = false;
$_SESSION['message'] = "Wrong ID or password!";
}
header("Location: login.php");
exit();
}
mysqli_close($db_conn);
?>
식별/인증 분리
<?php
session_start();
$db_conn = mysqli_connect("localhost", "root", "root", "test_db");
if (!$db_conn) {
die("Connection failed: " . mysqli_connect_error());
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = $_POST['id'] ?? '';
// 식별: 사용자 존재 여부 확인
$sql = $db_conn->prepare("SELECT * FROM user WHERE id = ?");
$sql->bind_param("s", $username);
$sql->execute();
$result = $sql->get_result();
if ($result->num_rows > 0) {
// 인증: 비밀번호 확인
$user = $result->fetch_assoc();
$password = $_POST['pass'] ?? '';
if ($user['pw'] === $password) {
$_SESSION['login_success'] = true;
$_SESSION['username'] = $username;
} else {
$_SESSION['login_success'] = false;
$_SESSION['message'] = "Wrong ID or password!";
}
}
header("Location: login.php");
exit();
}
mysqli_close($db_conn);
?>
이제 데이터베이스에 저장된 암호 또한 해싱한 후 코드를 적용해보자.
기존 데이터베이스를 몇 가지 수정해준다.
- pw 길이 수정 → ALTER TABLE user MODIFY pw VARCHAR(64);
- 기존 평문 암호 해싱하여 저장 → UPDATE `user` SET `pw` =' hashed pw**'** WHERE `user`**.**`id` = '**id**'
import hashlib
pw = "your_password"
hashed_pw = hashlib.sha256(pw.encode()).hexdigest()
print(hashed_pw)
테스트 테이블이라 값이 많지 않아 파이썬 코드로 구해서 값을 바꿔 저장했다. 동일한 해시 함수를 사용한다면 python에서 실행한 결과와 php에서 실행한 결과는 동일하다.
- 해시 함수 SHA256으로 설정
해시를 적용한 두 가지 코드의 테스트 버전에 대한 데이터베이스를 구성했다.
이어서 진행하는 실습에 대해서는 해당 테이블을 계속 사용한다. (평문 암호 저장하지 않음)
식별/인증 동시 with Hash
<?php
session_start();
$db_conn = mysqli_connect("localhost", "root", "root", "test_db");
if (!$db_conn) {
die("Connection failed: " . mysqli_connect_error());
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = $_POST['id'] ?? '';
$password = $_POST['pass'] ?? '';
// 사용자가 입력한 비밀번호를 SHA-256으로 해싱
$hashedInputPassword = hash('sha256', $password);
// 식별과 인증 동시에 처리 (비밀번호는 해시된 상태로 비교)
$sql = $db_conn->prepare("SELECT * FROM user WHERE id = ? AND pw = ?"); // 사용자 검색
$sql->bind_param("ss", $username, $hashedInputPassword);
$sql->execute();
$result = $sql->get_result();
if ($result->num_rows > 0) {
$_SESSION['login_success'] = true; // 로그인 성공 상태 저장
$_SESSION['username'] = $username; // 사용자 이름 저장
} else {
$_SESSION['login_success'] = false;
$_SESSION['message'] = "Wrong ID or password!";
}
header("Location: login.php"); // 로그인 페이지로 리다이렉트
exit();
}
mysqli_close($db_conn);
?>
식별/인증 동시 with Hash
<?php
session_start();
$db_conn = mysqli_connect("localhost", "root", "root", "test_db");
if (!$db_conn) {
die("Connection failed: " . mysqli_connect_error());
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = $_POST['id'] ?? '';
// 식별: 사용자 존재 여부 확인
$sql = $db_conn->prepare("SELECT * FROM user WHERE id = ?");
$sql->bind_param("s", $username);
$sql->execute();
$result = $sql->get_result();
if ($result->num_rows > 0) {
// 인증: 사용자 존재
$user = $result->fetch_assoc();
$password = $_POST['pass'] ?? '';
$hashedInputPassword = hash('sha256', $password); // 입력 비밀번호 해싱
// 인증: 해시된 비밀번호 비교
if ($user['pw'] === $hashedInputPassword) {
$_SESSION['login_success'] = true; // 로그인 성공
$_SESSION['username'] = $username; // 사용자 이름 저장
} else {
$_SESSION['login_success'] = false;
$_SESSION['message'] = "Wrong ID or password!";
}
}
header("Location: login.php"); // 로그인 페이지로 리다이렉트
exit();
}
mysqli_close($db_conn);
?>
네 가지 경우에 대해서 정상적으로 로그인이 가능한 것을 테스트하였다. 이어서 하는 실습에는 최종적으로 식별/인증 동시 with Hash 코드를 사용할 것이다. 이를 위해, 추후 데이터베이스에 저장되는 가입자의 암호도 해시가 적용되도록 회원가입 코드도 수정한다.
- register.php 수정 항목
// 모든 검증 통과 시 데이터베이스에 사용자 추가
if (empty($error_messages['id']) && empty($error_messages['password']) && empty($error_messages['email']) && empty($error_messages['phone'])) {
// 비밀번호를 SHA-256으로 해싱
$hashedPassword = hash('sha256', $password);
$query = $db_conn->prepare("INSERT INTO user (id, pw, username, phone, email) VALUES (?, ?, ?, ?, ?)");
$query->bind_param("sssss", $id, $hashedPassword, $name, $phone, $email);
if ($query->execute()) {
// 회원가입 완료 후 로그인 페이지로 리다이렉트
header("Location: login.php");
exit();
} else {
$error_messages['id'] = "Failed to create an account. Please try again.";
}
}
코드 테스트를 위해 새 계정인 google을 회원가입 페이지에서 만들었다.
새 데이터가 정상적으로 데이터베이스에 저장되었으며, 비밀번호는 해싱된 값만이 저장된 것을 볼 수 있다.
로그인 또한 정상적으로 실행된다.
'모의해킹 > 웹해킹스터디' 카테고리의 다른 글
Burp Suite 사용법 (0) | 2024.11.27 |
---|---|
쿠키(Cookie)와 세션(Session) (0) | 2024.11.27 |
로그인 로직 이해하기 - 식별과 인증, 그리고 해시 (Hash) (1) | 2024.11.27 |
데이터베이스와 SQL (3) | 2024.11.27 |
[macOS] MAMP로 PHP 웹 개발 환경 세팅 (1) | 2024.11.27 |