<현재 환경 세팅>
1. Virtual Box 7.1.4 + 우분투 리눅스 20.04
2. 우분투 APM (Apache2 + PHP + MySQL)
3. 기본 웹 루트 경로 /var/www/html
4. VScode SSH
5. 사진 등은 termius
☎ 기능 ☎
1) 현재 계정 회원의 아이디, 닉네임, 이메일을 form의 placeholder 방식으로 보여줌.
2) 셋 중 하나라도 수정한 정보를 입력한 뒤 제출하면 DB 데이터가 수정되고
즉시 화면의 데이터도 수정됨.
3) 비밀번호 입력란과 비밀번호 확인란에 입력한 정보가 다르거나
비밀번호 입력란의 데이터와 DB의 비밀번호(평문 비번)가 다르면 alert 표시.
☎ 구현 화면 ☎
1) 성공 시
panda 회원의 기존 정보를 placeholder 방식으로 보여주고 있다.
수정할 데이터를 입력하고 비밀번호 입력란을 채운 뒤 변경하기 버튼을 누르면
비밀번호 데이터가 DB에 있는 데이터와 일치하는지,
그리고 비밀번호 데이터와 비밀번호 확인 데이터가 서로 일치하는지 확인.
두 조건이 참일 때
곧바로 수정사항을 적용하여 화면에 보여준다.
DB 데이터도 의도대로 수정된 모습을 볼 수 있다.
1) 실패 시
DB 데이터와 비교 후 값이 서로 다를 경우
비밀번호 데이터와 비밀번호 확인 데이터가 서로 다를 경우
☎ 소스 코드(6주차) ☎
mypage.php
<?php
session_start(); //세션 적용
require 'session_init.php'; //세션 설정
require 'db_connection.php'; //DB연동
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL); //php 에러 출력
if(!isset($_SESSION['id'])) {
echo "<script>
alert('로그인이 필요한 서비스입니다.');
window.location.href = 'login.php';
</script>";
exit; //로그인 성공하지 않은 사용자는 로그인 페이지로
} else {
$user_id = $_SESSION['id']; //세션 데이터를 변수에 저장
$select_sql = "SELECT * FROM registration_list WHERE id = '$user_id'";
$result = mysqli_query($db_conn,$select_sql);
$row = mysqli_fetch_array($result);
$id = $row['id'];
$pass = $row['pass'];
$email = $row['email'];
$nick = $row['nick'];
$pass1 = $row['pass1']; //세션 데이터를 기준으로 사용자 데이터 변수 저장, placeholder출력
if (isset($_POST['submit'])) { //제출 버튼을 누르면(없으면 에러)
$mod_id = isset($_POST['mod_id'])?$_POST['mod_id']:"";
$mod_nick = isset($_POST['mod_nick'])?$_POST['mod_nick']:"";
$mod_email = isset($_POST['mod_email'])?$_POST['mod_email']:"";
$user_pw = isset($_POST['user_pw'])?$_POST['user_pw']:"";
$user_pwCheck = isset($_POST['user_pwCheck'])?$_POST['user_pwCheck']:"";
//폼에 입력한 수정 정보 변수 저장
$updateSql = "UPDATE registration_list SET ";
//업데이트문 앞부분 저장
$update_fields = []; //수정 데이터를 저장할 배열 선언
if(!empty($mod_id)) {
$update_fields[] = "id='$mod_id'";
} //아이디 수정한다카면 컬럼명='수정아이디' 형식으로 저장
if(!empty($mod_nick)) {
$update_fields[] = "nick='$mod_nick'";
} //닉넴 수정한다카면 컬럼명='수정닉넴' 형식으로 저장
if(!empty($mod_email)) {
$update_fields[] = "email='$mod_email'";
} //이멜 수정한다카면 컬럼명='수정이멜' 형식으로 저장
if(count($update_fields)>0) { //수정할 데이터가 하나라도 있으면
if($user_pw === $row['pass1']) { //일단 비번을 DB데이터랑 비교해서 같으면
if($user_pw===$user_pwCheck){ //이번엔 비번값, 비번확인값 비료해서 같으면
$updateSql .= implode(", ",$update_fields);
//업데이트문 앞부분에, 배열로 저장한 걸 이어 붙여서 하나의 문자열로 저장
$updateSql .= " WHERE id='$user_id'";
//하고 그 뒤에 조건문 붙여서 완전한 업데이트 쿼리문 완성
$updateResult = mysqli_query($db_conn,$updateSql); //업데잇 실행
if ($updateResult) { //실행 결과가 있을 때(실행 됐으면)
if(!empty($mod_id)) {
$_SESSION['id'] = $mod_id;
} //아이디 바꿨으면 그거 세션 데이터에 갱신
header("Location: mypage.php?status=success"); //수정된 마이페이지로 이동
//파라미터는 확실히 하기 위해 붙인 임의의 값. 오타나도 상관이 읍서
exit();
} else {
echo "Fail to Update :". mysqli_error($db_conn); //업데이트 안되면 에러출력해라
}
} else {
echo "<script> alert('비밀번호가 일치하지 않습니다.');</script>";
} //비밀번호 다르면 경고창 띄워라
} else {
echo "<script> alert('잘못된 비밀번호입니다.');</script>";
} //DB에 없는 비번이면 경고창 띄워라
}
}
?>
<!doctype html>
<html lang="ko">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>마이페이지_페인티</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
<link href="mypage_style.css" rel="stylesheet">
<script src="logout_func.js"></script> <!--로그아웃-->
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
<body>
<nav class="navbar navbar-expand-lg bg-body-tertiary ">
<div class="container-fluid">
<a class="navbar-brand" href="index.php">페인티</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNavDropdown">
<ul class="navbar-nav col-sm-5">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="index.php">게시판</a>
</li>
<li class="nav-item">
<a class="nav-link" href="upload.php">올리기</a>
</li>
<li class="nav-item">
<a class="nav-link" href="my_uploads.php">내 게시물</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
마이페이지
</a>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#">좋아하는 그림</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="mypage.php">회원정보</a></li>
</ul>
</li>
</ul>
<li class="navbar-nav"><?= $_SESSION['id']."님 반갑습니다."?></li>
<div class="offset-md-4">
<button type="button" class="btn btn-warning" id="logout" onclick="logout()">로그아웃</button>
</div>
</div>
</div>
</nav>
<div class="d-flex align-items-start mt-5">
<div class="tab-content container" id="v-pills-tabContent">
<div class="tab-pane fade show active" id="v-pills-profile" role="tabpanel" aria-labelledby="v-pills-profile-tab" tabindex="0">
<form method="post" action="">
<div class="row mb-3">
<label for="inputid3" class="col-sm-2 col-form-label">아이디</label>
<div class="col-sm-10">
<input type="textarea" class="form-control" id="inputPassword3" name="mod_id" placeholder="<?= $id?>">
</div>
</div>
<div class="row mb-3">
<label for="inputnick3" class="col-sm-2 col-form-label">닉네임</label>
<div class="col-sm-10">
<input type="textarea" class="form-control" id="inputPassword3" name="mod_nick" placeholder="<?= $nick?>">
</div>
</div>
<div class="row mb-3">
<label for="inputEmail3" class="col-sm-2 col-form-label">이메일</label>
<div class="col-sm-10">
<input type="email" class="form-control" id="inputEmail3" name="mod_email" placeholder="<?=$email?>">
</div>
</div>
<div class="row mb-3">
<label for="inputEmail3" class="col-sm-2 col-form-label">비밀번호</label>
<div class="col-sm-10">
<input type="password" class="form-control" id="inputEmail3" name="user_pw" placeholder="회원정보 변경을 원하시면 비밀번호를 입력해주세요." required>
</div>
</div>
<div class="row mb-3">
<label for="inputEmail3" class="col-sm-2 col-form-label">비밀번호 확인</label>
<div class="col-sm-10">
<input type="password" class="form-control" id="inputEmail3" name="user_pwCheck" placeholder="비밀번호를 한 번 더 입력해주세요." required>
</div>
</div>
<fieldset class="row mb-3">
<legend class="col-form-label col-sm-2 pt-0">윙가르디움뤠이디오박스</legend>
<div class="col-sm-10">
<div class="form-check">
<input class="form-check-input" type="radio" name="gridRadios" id="gridRadios1" value="option1" checked>
<label class="form-check-label" for="gridRadios1">
안녕하세요?
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="gridRadios" id="gridRadios2" value="option2">
<label class="form-check-label" for="gridRadios2">
이 라디오 박스는
</label>
</div>
<div class="form-check disabled">
<input class="form-check-input" type="radio" name="gridRadios" id="gridRadios3" value="option3">
<label class="form-check-label" for="gridRadios3">
장식입니다.
</label>
</div>
</div>
</fieldset>
<div class="row mb-3">
<div class="col-sm-10 offset-sm-2">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="gridCheck1">
<label class="form-check-label" for="gridCheck1">
감사합니다.
</label>
</div>
</div>
</div>
<button type="submit" class="btn btn-primary" name="submit">변경하기</button>
</form>
</div>
<div class="tab-pane fade" id="v-pills-disabled" role="tabpanel" aria-labelledby="v-pills-disabled-tab" tabindex="0">...</div>
<div class="tab-pane fade" id="v-pills-messages" role="tabpanel" aria-labelledby="v-pills-messages-tab" tabindex="0">...</div>
<div class="tab-pane fade" id="v-pills-settings" role="tabpanel" aria-labelledby="v-pills-settings-tab" tabindex="0">...</div>
</div>
</div>
</body>
</html>
<?php
}
?>
☎ 고난(까지는 아님) ☎
1) php 에러문 때문에 update 부분 실행 전에 조건을 둬야한다는 걸 알았다.
submit을 받는다든지, 서버가 post를 받았다든지 하는 조건을 먼저 두지 않으면
변수란 변수는 다 정의 안됨 상태가 된다.
2) 수정 데이터를 모두 업데이트할 필요 없도록 만들고 싶은데 어떤 방법이 좋을지 고민하다가
배열에 특정한 형태로 저장해두고 implode로 한 행을 만드는 법을 알게 되었다!
3) SQL 띄어쓰기.
UPDATE 테이블 SET 컬럼명 = '수정데이터', 컬럼명 = '수정데이터' WHERE id = '$user_id';
띄어쓰기 철저하다. 진짜 철저하다. 특히 update, set, where 이런 애들 다른 거랑 붙어있음 에러남.
4) url 파라미터가 친근해졌다. 그렇게.. 빡센 애는 아니었군.
6주차의 감상:
SQL 겁나 Injection할 수 있을 것 같이 생겼다.
7주+2일차의 감상:
의외로 쉽지 않다...
로그인으로 DB정보는 빼내겠는데 그것도 사이트 상단에 '~~님 반값습니다.'를 붙여서 알 수 있는 거고
로그인한 계정이 DB에 없으면 마이페이지에 정보가 아예 안 뜬다...
그래서 php에러 표시됨..
임의의 값을 입력하고 변경 버튼을 눌러봤자
paint에 해당하는 사용자 데이터가 DB에 없어서 업데이트할 행을 찾지 못하고
당연히 비밀번호도 잘못됐다고 표시된다.
인서트를 하면 편할텐데.. 근데 그건 너무 무적 아닌가?
게다가 DB에 내 흔적을 안 남기고 정보를 터는 게 바람직(?)할 것 같아서 사용하긴 할 지 잘 모르겠다.
모의해킹 실무에서도 ctf 풀 때처럼 로그인 가능한 아이디를 하나 받나? 아니면 계정을 만들고 시작하나??
일단 뭐 하나는 있어야 제대로 SQLi를 시험할 수 있을 것 같다. (라고 7주+2일차가 말했습니다.)
'웹 개발(초보)' 카테고리의 다른 글
웹 개발: 게시글 읽기 페이지 (1) | 2025.01.03 |
---|---|
웹 개발: 게시판 - 글 목록 (1) | 2025.01.01 |
웹 개발: 게시판 - 글 작성 (2) | 2024.11.13 |
내가 만든 사이트에 세션, 로그아웃, DB 연동 파일 분리 적용하기 (1) | 2024.11.12 |