Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
Tags
- blind sql injection
- lord of sqli
- php
- Python
- CTF
- 로그인페이지
- JWT
- Los
- file upload
- csrf
- cors
- 웹개발
- css
- 게시판 만들기
- lord of sql injection
- Error based sql injection
- MySQL
- XSS
- 모의해킹
- 과제
- union sql injection
- 로그인
- 세션
- sql injection point
- cookie 탈취
- Cross Site Request Forgery
- 쿠키
- JS
- sql injection
- Reflected Xss
Archives
- Today
- Total
Almon Dev
로그인 로직 구현하기(과제) 본문
로그인 로직 구현하기
사전작업
비밀번호에 해쉬를 저장하기 위해서 varchar(512)로 최대 512바이트까지 저장하도록 변경했습니다.
alter table users modify column password varchar(512) not null;
식별 - 인증 동시
sql문에서 식별과 인증을 동시에 하는 로직입니다.
login1_proc.php
<?php
include("mysql.php");
require("jwt_auth.php");
use Firebase\JWT\JWT;
$id = $_POST["id"];
$pass = $_POST["passwd"];
$url = '/login_successful.php';
$sql = "select nickname from users where id='$id' and password='$pass';";
$sql_result = runSQL($sql);
if ($row = mysqli_fetch_array($sql_result)) {
$nick = $row['nickname'];
$update_sql = "update users set login=1 where nickname='$nick';";
runSQL($update_sql);
$token = Jwt_auth::createToken($id);
header("location:$url");
exit;
}
header('Location: login2.php?result=failed');
?>
$sql = "select nickname from users where id='$id' and password='$pass';";
이 코드처럼 where과 and를 이용해 식별과 인증을 동시에 처리합니다.
식별 - 인증 분리
login2_proc.php
<?php
include("mysql.php");
require("jwt_auth.php");
use Firebase\JWT\JWT;
$url = '/login_successful.php';
$id = $_POST["id"];
$pass = $_POST["passwd"];
$sql = "select nickname,password from users where id='$id';";
$sql_result = runSQL($sql);
if ($row = mysqli_fetch_array($sql_result)) {
$nick = $row['nickname'];
$pass_db = $row['password'];
if($pass == $pass_db) {
$update_sql = "update users set login=1 where nickname='$nick';";
runSQL($update_sql);
$token = Jwt_auth::createToken($id);
header("location:$url");
exit;
}
}
header('Location: login2.php?result=failed');
?>
$sql = "select nickname,password from users where id='$id';";
$sql_result = runSQL($sql);
if ($row = mysqli_fetch_array($sql_result)) {
$nick = $row['nickname'];
$pass_db = $row['password'];
if($pass == $pass_db) {
sql문에서 바로 비밀번호를 검사하는 게 아니라 비밀번호 값을 가져와서 사용자가 입력한 값과 비교합니다.
식별 - 인증 동시 + HASH
보안성이 뛰어나다는 argon2id 알고리즘을 사용해서 해쉬를 해보려고 했으나, argon2id나 bcrypt 알고리즘은 랜덤 한 값인 salt를 추가해서 해싱을 거치기 때문에 매번 다른 해시값이 나옵니다.
식별 - 인증을 동시에 하는 경우에는 사용하기가 힘든 것 같습니다.
signup_proc.php
<?php
include ("mysql.php");
header("Content-Type: apllication/json");
$id = $_POST['id'];
$nick = $_POST['nickname'];
$pass = $_POST['pass'];
$passCheck = $_POST['passCheck'];
$email = $_POST['email'];
$id_duple = false;
$nick_duple = false;
$pass_duple = false;
$result = false;
$sql = "select id,nickname from users where id='$id' or nickname='$nick';";
$sql_result = runSQL($sql);
if (mysqli_num_rows($sql_result) > 0) {
while ($row = mysqli_fetch_array($sql_result)) {
if ($id == $row["id"]) {
$id_duple = true;
}
if ($nick == $row['nickname']) {
$nick_duple = true;
}
}
}
if($pass != $passCheck) {
$pass_duple = true;
}
if (!$id_duple && !$pass_duple && !$nick_duple) {
$result = true;
//$pass = password_hash($pass, PASSWORD_ARGON2ID);
$pass = hash('sha256', $pass);
runSQL("insert into users values ('$id', '$nick', '$email', '$pass')");
}
echo json_encode(['result' => $result, 'id' => $id_duple, 'nick' => $nick_duple, 'pass' => $pass_duple]);
?>
$pass = hash('sha256', $pass);
runSQL("insert into users values ('$id', '$nick', '$email', '$pass')");
회원가입을 할 때 비밀번호를 sha256 알고리즘을 통해 해싱을 한 뒤 저장됩니다.
login3_proc.php
<?php
include("mysql.php");
require("jwt_auth.php");
use Firebase\JWT\JWT;
$url = '/login_successful.php';
$id = $_POST["id"];
$pass = $_POST["passwd"];
//$pass_hash = password_hash($pass, PASSWORD_ARGON2ID);
$pass_hash = hash('sha256', $pass);
$sql = "select nickname from users where id='$id' and password='$pass_hash';";
$sql_result = runSQL($sql);
if ($row = mysqli_fetch_array($sql_result)) {
$nick = $row['nickname'];
$update_sql = "update users set login=1 where nickname='$nick';";
runSQL($update_sql);
$token = Jwt_auth::createToken($id);
header("location:$url");
exit;
}
header('Location: login2.php?result=failed');
?>
입력받은 비밀번호를 해싱해서 sql문의 where에 삽입합니다.
식별 - 인증 분리 + HASH
signup_proc.php
<?php
include ("mysql.php");
header("Content-Type: apllication/json");
$id = $_POST['id'];
$nick = $_POST['nickname'];
$pass = $_POST['pass'];
$passCheck = $_POST['passCheck'];
$email = $_POST['email'];
$id_duple = false;
$nick_duple = false;
$pass_duple = false;
$result = false;
$sql = "select id,nickname from users where id='$id' or nickname='$nick';";
$sql_result = runSQL($sql);
if (mysqli_num_rows($sql_result) > 0) {
while ($row = mysqli_fetch_array($sql_result)) {
if ($id == $row["id"]) {
$id_duple = true;
}
if ($nick == $row['nickname']) {
$nick_duple = true;
}
}
}
if($pass != $passCheck) {
$pass_duple = true;
}
if (!$id_duple && !$pass_duple && !$nick_duple) {
$result = true;
$pass = password_hash($pass, PASSWORD_ARGON2ID);
runSQL("insert into users values ('$id', '$nick', '$email', '$pass', '0')");
}
echo json_encode(['result' => $result, 'id' => $id_duple, 'nick' => $nick_duple, 'pass' => $pass_duple]);
?>
$pass = password_hash($pass, PASSWORD_ARGON2ID);
runSQL("insert into users values ('$id', '$nick', '$email', '$pass', '0')");
argon2id 알고리즘을 이용해서 비밀번호를 저장합니다.
login4_proc.php
<?php
include("mysql.php");
require("jwt_auth.php");
use Firebase\JWT\JWT;
$url = '/login_successful.php';
$id = $_POST["id"];
$pass = $_POST["passwd"];
$sql = "select nickname,password from users where id='$id';";
$sql_result = runSQL($sql);
if ($row = mysqli_fetch_array($sql_result)) {
$nick = $row['nickname'];
$pass_db = $row['password'];
if(password_verify( $pass, $pass_db)) {
$update_sql = "update users set login=1 where nickname='$nick';";
runSQL($update_sql);
$token = Jwt_auth::createToken($id);
header("location:$url");
exit;
}
}
header('Location: login2.php?result=failed');
?>
$pass = $_POST["passwd"];
$sql = "select nickname,password from users where id='$id';";
$sql_result = runSQL($sql);
if ($row = mysqli_fetch_array($sql_result)) {
$nick = $row['nickname'];
$pass_db = $row['password'];
if(password_verify( $pass, $pass_db)) {
password_verify 함수는 db에 저장된 비밀번호의 salt를 추출한 뒤, 사용자에게 입력받은 비밀번호인 $pass에 추출한 salt를 추가하여 argon2id 알고리즘으로 해싱해서 검사합니다.
마무리
insert into users values ('test_hash', 'test_hash', 'test_hash@google.com', '$argon2id$v=19$m=65536,t=4,p=1$ZktUSEY5cFVnWjJXRS5RMQ$v7HpyL7siKDXwis35fU39E8pdpIiCCa7iDWyHd4nTUs', '0')
select nickname from users where id='test_hash' and password='$argon2id$v=19$m=65536,t=4,p=1$UHIualFMUGo5WU5LMjVVRQ$88i1WqH9z6gd2E891XWkihpz70ZOrVxwoNIuuI37rZY'
정말로 다른 해시가 생성되는지 확인하기 위해 식별 - 인증 동시방법을 사용했을 때 로그에 남은 sql문입니다.
salt를 추가하는 방식은 같은 비밀번호를 입력하더라도 다른 해시가 나오기 때문에 최근에 사용되는 비밀번호 알고리즘들은 기본적으로 salt를 사용하고 있습니다. 그렇기에 식별 - 인증 분리방법이 더 자주 사용됩니다.
salt 구별
$argon2id$v=19$m=65536,t=4,p=1$UHIualFMUGo5WU5LMjVVRQ$ argon2id에서 salt는 $salt$처럼 $안에 있습니다.
'모의해킹 > 웹 개발' 카테고리의 다른 글
게시판 만들기 #2 (게시글 작성) (0) | 2024.11.11 |
---|---|
게시판 만들기 #1 (0) | 2024.11.11 |
JWT로 로그인 구현하기 (1) | 2024.11.03 |
세션으로 로그인 구현하기(모의해킹 공부) (0) | 2024.11.01 |
쿠키로 로그인 구현하기 (모의해킹 공부) (0) | 2024.10.31 |