본문 바로가기

개발과제

[노말틱 모의 해킹 취업반 4주차 개발과제 (2/2)] 회원가입 만들기-2

보안 강화를 하겠습니다!

process_join.php 파일 열기 전에

 

LOGIN_INFO 데이터베이스에 주소까지 넣을 수 있는 칸을 만들겠습니다.

 

phpmyadmin 통해 접속하겠습니다

 

그리고 테이블에 새로운 칼럼 추가 하겠습니다!

 

phpmyadmin 위에 '구조'이라고 있습니다 거기서 작업하겠습니다

 

그리고 중간에 보시면 

 

 

실행!

 

칼럼 추가 하겠습니다

 

이름은 adr text 하겠습니다.

 

이렇게요!

 

 

굳이 주소 입력 안 해도 되게 NULL에 체크했습니다!

 

 

저장하고 나면 테이블에 추가된 게 보이실 겁니다.

 

좋습니다

이제 process join.php 로 가겠습니다.

 

그리고 추가

 

$adr = mysqli_real_escape_string($conn,$_POST['address']);

 

mysqli_real_escaspe_string 굳이 안 해도 됩니다. 애초에 작성을 못하게 했으니깐요!

 

근데 혹시나 해서 적어는 놨습니다.

 

있으면 좋잖아요!

 

trim()은 빈칸을 없애주는 함수입니다

 

그리고 주소를 해쉬 함수 이용해서 저장하겠습니다!

 

주소는 password_hash() 쓰기엔 부적절합니다. 이유는 이 해쉬 함수는 저장할 때 랜덤의 솔트 값을 주고 암호화하는데

즉 이 말은 같은 비밀번호여도 암호화될 때 전혀 다르게 나오게 됩니다.

 

근데 주소는 아니죠. 만약 저희가 주소 같은 사람들끼리 모아서 출력을 하고 싶은데 저 솔트값으로 해싱되어서

전부 다르게 나오니 일일이 꺼내봐야 됩니다! 그럼 매우 까다로워지겠죠?

 

그러니 php에 제공되는 암호화인 openssl을 이용하겠습니다

.

.

.

.

 

이렇게요

 

//암호화 키
    $encryption_key = 'my_secret_key';
    
//주소는 암호화
    $encrypted_address = openssl_encrypt($adr, 'aes-256-cbc', $encryption_key, OPENSSL_RAW_DATA, '1234567890123456');

 

보시면 aes-256-cbc는 암호화 알고리즘입니다.

그리고 OPENSSL_RAW_DATA는 복호화할 때 반환된 데이터가 바이트 단위로 반환되는 것입니다.

123456789012356은 초기화 벡터입니다. 각 암호화에 사용되는 문자열이라고 합니다!

 

만약 이 초기화 벡터가 다르면 같은 주소여도 초기화 벡터가 달라서 다른 암호 값이 나오게 됩니다

 

 

그리고 sql 실행되는 문을 수정하겠습니다

 

 

//중복이 아닐때
//새로운 사용자를 데이터베이스에 삽입문
$sql = "INSERT INTO LOGIN_INFO (id, pw, adr)
VALUES ('$login_id','$hashed_pw','$encrypted_address')";

 

그리고 메인페이지에 주소값까지 나오게 하겠습니다

 

only_login.php 에 수정하겠습니다.

 

php문만 수정하겠습니다

        <?php 
            include 'DB_INFO.php'; //데이터 베이스 정보

            //데이터베이스 연결
            $conn = mysqli_connect($host,$username,$password,$dbname);

            session_start(); //세션 시작

            if(!isset($_SESSION['login_id'])) {
                //로그인하지 않은 사용자
                header("Location: login.php"); //login 화면으로 바꾼다
                exit(); //이 페이지를 바로 닫는다
            }
            
            $login_id = $_SESSION['login_id']; // 사용자 ID 저장
            
            //주소 값 찾기
            $sql = "SELECT adr from LOGIN_INFO WHERE id='$login_id'";

            //쿼리 실행
            $result = mysqli_query($conn, $sql);
            $row = mysqli_fetch_array($result); //결과 값
            $adr = $row['adr']; //결과 배열중 adr 가져온다

            if($adr!= NULL) {
                $encryption_key = 'my_secret_key'; //암호화 키
                //복호화
                $decrypted_address = openssl_decrypt($encrypted_address, 'aes-256-cbc', $encryption_key, OPENSSL_RAW_DATA, '1234567890123456');
                echo "당신은 ", $_SESSION['login_id'], " 입니다!", $decrypted_address ,"에 사시군요 환영합니다! HAPPYHACKING!!";
            } else {
                echo "당신은 ", $_SESSION['login_id'], " 입니다! 환영합니다! HAPPYHACKING!!";
            }
        ?>

 

데이터베이스 연결하고 sql로 adr을 찾습니다

만약 adr 값이 NULL이 아니면 주소 출력하고 아니면 그냥 id만 출력되게 했습니다

그리고 암호화 키 입력 후 복호화 진행하여 출력하겠습니다!

 

이제 회원가입부터 해보겠습니다

 

 

대충 적었습니다

 

실행하면!

 

 

그럼 그렇지

 

왤까요? 한번 에러 코드 찾아봤습니다

 

#cat /var/log/apache2/error.log

 

으음...

 

뭔가 adr에서 문자 형식이 안 맞다고 나오네요. 이때 의심 되는 건 크기가 안 맞는 것일 수도 있습니다!

 

한 번 주소 암호화 할 때 OPENSSL_RAW_DATA 대신에 OPENSSL_ZERO_PADDING을 이용하겠습니다

 

OPEN_ZERO_PADDING 이용하면 알아서 블록의 크기를 맞춰서 저장을 해주는 것입니다.

 

이제 되길 바래야죠

 

됬네요!

 

phpmyadmin 통해 확인해 보겠습니다

 

됬네요! 암호화&nbsp; 까지

 

좋아요!

 

이제 로그인하기 전에 only_login.php 에도 고치겠습니다.

 

이렇게요!

 

로그인해보겠습니다

 

 

다행이다!

 

잘 나오네요!! 사실 굳이 주소가 이 메인페이지에 나오게 할 이유는 없습니다. 그래서

주소 확인하는 코딩 부분은 다음 글을 쓸 땐 지워져 있을 겁니다.

이렇게 하는 것은 이렇게 확인이 가능하다는 걸 확인 하는 용이었습니다!

 

그냥 지금 지우겠습니다. 예전처럼 돌아가기만 하면 됩니다!

 

다시 돌아온 그..

 

좋아요! 근데 여기서 확실하게 아셔야 하는 점이 있습니다.

 

암호키 즉 $encryption_key = 'my_secret_key'; 이 것은 당연히 따로 파일을 만들어서 안전하게 보관을 해야 되고요!

'1234567890123456' 이 초기화 벡터도 마찬가지입니다!

 

데이터베이스 정보 저장할 때. env 하는 것처럼 나중에 보안으로 따로 저장하는 과정을 설명해 드리겠습니다!

 

오늘은 이 글로 마치겠습니다.

 

다음글은 게시판을 본격적으로 만들겠습니다!

.

.

.

.

 

감사합니다

 

-process_join.php

 

<?php
    include 'DB_INFO.php'; //데이터 베이스 정보

    session_start(); //세션 시작

    //데이터베이스 연결
    $conn = mysqli_connect($host,$username,$password,$dbname);

    //데이터베이스 오류시 종료
    if(mysqli_connect_errno()) {
        die("데이터 베이스 오류: ". mysqli_connect_error());
    }
    
    
    //POST로 전달된 정보 받기
    $login_id = mysqli_real_escape_string($conn,$_POST['id']);
    $login_pw = mysqli_real_escape_string($conn,$_POST['pw']);
    $adr = trim(mysqli_real_escape_string($conn,$_POST['address']));
    
    //비밀번호는 해싱
    $hashed_pw = password_hash($login_pw, PASSWORD_DEFAULT);

    //암호화 키
    $encryption_key = 'my_secret_key';
    
    //주소는 암호화
    $encrypted_address = openssl_encrypt($adr, 'aes-256-cbc', $encryption_key, OPENSSL_ZERO_PADDING, '1234567890123456');

    //ID 중복 검사용 sql문
    $check_id = "SELECT id FROM LOGIN_INFO WHERE id='$login_id' ";

    //중복 검사 sql문 실행
    $result_id = mysqli_query($conn, $check_id);

    if(mysqli_num_rows($result_id) > 0 ) { 
        //중복이 있을때
        $_SESSION['join_error'] = '아이디가 중복입니다!';
        header("Location: join.php");
    } else {
        //중복이 아닐때
        //새로운 사용자를 데이터베이스에 삽입문
        $sql = "INSERT INTO LOGIN_INFO (id, pw, adr)
        VALUES ('$login_id','$hashed_pw','$encrypted_address')";

        //sql문 실행
        if(mysqli_query($conn,$sql)) {
            $_SESSION['join_error'] = '회원가입이 완료되었습니다!';
            header("Location: join.php");
        } else {
            $_SESSION['join_error'] = '회원가입 오류가 발생하였습니다.';
            header("Location: join.php");
        }

    }

    //회원가입 후 닫기
    exit();
?>