일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- cors
- 웹개발
- union sql injection
- css
- 과제
- lord of sqli
- Error based sql injection
- Los
- MySQL
- XSS
- 쿠키
- file upload
- 로그인
- 세션
- Reflected Xss
- JS
- lord of sql injection
- 모의해킹
- cookie 탈취
- php
- csrf
- 로그인페이지
- CTF
- sql injection point
- blind sql injection
- Python
- 게시판 만들기
- sql injection
- Cross Site Request Forgery
- JWT
- Today
- Total
Almon Dev
모의해킹 공부 정리 7일차 (mysql 적용) 본문
오늘은 드디어 mysql을 이용해서 users.txt를 대체할 겁니다.
mysql을 사용하기 위해 여기저기서 사용될
db에 접속해서 sql문을 실행하는 동작을 함수로 만들어서 mysql.php에 저장했습니다.
mysql.php
<?php
function runSQL($sql) {
$host = "localhost";
$id = "root";
$password = "admin1234";
$dbname = "almond";
$conn = mysqli_connect($host, $id, $password, $dbname);
if (!$conn) {
die("mysql 연결 에러 : ". mysqli_connect_error());
}
$result = mysqli_query($conn, $sql);
if (!$result) {
die("쿼리문 에러 : " . mysqli_error($conn));
}
mysqli_close($conn);
return $result;
}
?>
$conn = mysqli_connect($host, $id, $password, $dbname);
conn이라는 변수에 db에 접속한 mysqli 객체를 저장합니다. 실패 시에는 false가 저장됩니다.
if (!$conn) {
die("mysql 연결 에러 : ". mysqli_connect_error());
}
if (!$result) {
die("쿼리문 에러 : " . mysqli_error($conn));
}
이 부분은 mysql 커넥션과 쿼리문의 응답이 제대로 왔는지 검사하는 부분입니다.
$result = mysqli_query($conn, $sql);
mysqli_query 함수로 sql문을 실행한 뒤 $result 변수에 저장합니다.
mysqli_close($conn);
mysqli_close로 mysql과의 연결을 종료합니다.
return $result;
$result에 담긴 값을 리턴합니다.
/test/sql_test.php
<?php
include ("../mysql.php");
$sql = "select * from users;";
$result = runSQL($sql);
echo "$result";
?>
include로 만들어둔 mysql.php를 불러옵니다.
에러가 났는데 상태코드가 500이네요
500은 서버에서 생긴 문제이므로 로그를 확인해 봅시다.
<?php
include ("../mysql.php");
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
$sql = "select * from users;";
$result = runSQL($sql);
echo "$result";
?>
ini_set('display_errors', 1); 에러를 화면에 출력하도록 변경합니다.
ini_set('display_startup_errors', 1); php 초기화 과정에서 발생하는 에러를 출력합니다. ex) 모듈, 환경설정
error_reporting(E_ALL); 출력할 에러의 종류를 의미합니다. E_ALL은 모든 에러를 뜻합니다.
Fatal error
: Uncaught Error: Object of class mysqli_result could not be converted to string in /home/almond/WebDev/test/sql_test.php:17 Stack trace: #0 {main} thrown in
/home/almond/WebDev/test/sql_test.php
on line
17
오류 코드인데 Uncaught Error: Object of class mysqli_result could not be converted to string 부분을 보면
mysqli_result 객체를 문자열로 변경할 수 없다는 뜻입니다.
echo "$result";에서 echo 문자열이나 문자열로 변환 가능한 데이터만 출력이 가능해서 에러가 난 것 같습니다.
mysqli_result 객체를 문자열로 변환하는 과정을 거쳐야 할 것 같습니다.
테스트를 위해 값을 하나 추가해 줍니다.
insert into users values('admin', 'Almond Dev', 'admin@naver.com', 'admin1234');
/test/sql_test.php파일을 수정해 줍니다.
<?php
include ("../mysql.php");
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
$sql = "select * from users;";
$result = runSQL($sql);
$row = null;
if (mysqli_num_rows($result) > 0) {
while ($row = mysqli_fetch_array($result)) {
printf("ID : %s \nPassword : %s \nname : %s \nEmail : %s",
$row['id'], $row['password'], $row['nickname'], $row['email']);
}
}
?>
while ($row = mysqli_fetch_array($result)) {
$result에 담긴 mysqli_result 객체를 mysqli_fetch_array함수로 array로 변환하며 $row에 한 줄씩 넣습니다.
printf("ID : %s \nPassword : %s \nname : %s \nEmail : %s",
$row['id'], $row['password'], $row['nickname'], $row['email']);
printf함수를 사용해서 각 내용을 출력해 줍니다.
printf문의 %s는 문자열을 의미합니다.
, 뒤에 넣은 변수를 순서대로 %s에 포맷팅합니다.
이제 users.txt로 만들었던 로직을 수정할 시간입니다.
로그인
login_proc2.php
<?php
include("mysql.php");
$id = $_POST["id"];
$pass = $_POST["passwd"];
$url = '/login_successful.php';
$sql = 'select id,password,nickname from users;';
$sql_result = runSQL($sql);
$result = false;
if (mysqli_num_rows($sql_result) > 0) {
while ($row = mysqli_fetch_array($sql_result)) {
if ($id == $row['id'] && $pass == $row['password']) {
$nickname = $row['nickname'];
echo "<form id='redirection-form' action='$url' method='post'>";
echo "<input type='hidden' name='nickname' value='$nickname'>";
echo "</form>";
echo "<script>document.getElementById('redirection-form').submit()</script>";
$result = true;
}
}
if(!$result) {
header('Location: login2.php?result=failed');
}
}
?>
include("mysql.php");
$sql = 'select id,password,nickname from users;';
$sql_result = runSQL($sql);
mysql.php에 만들어둔 runSQL 함수를 이용해서 db에 저장되어 있는아이디, 비밀번호 닉네임을 받아옵니다.
if ($id == $row['id'] && $pass == $row['password']) {
$nickname = $row['nickname'];
echo "<form id='redirection-form' action='$url' method='post'>";
echo "<input type='hidden' name='nickname' value='$nickname'>";
echo "</form>";
echo "<script>document.getElementById('redirection-form').submit()</script>";
$result = true;
}
유저의 입력값과 비교해서 로그인에 성공하면
닉네임값을 login_successful.php로 post 메서드를 이용해서 전송합니다.
if(!$result) {
header('Location: login2.php?result=failed');
}
실패 시 다시 로그인 페이지로 돌아가며, 로그인 실패 메시지를 띄우게 됩니다.
if (!$result) {
header('Location: login2.php? result=failed');
}
본래는 if문이 없고 while문이 끝나고 header('Location: login2.php?result=failed');로 리다이렉션 하도록 했으나
로그인이 실패를 해도 성공을 해도 이 부분이 실행되어서 계속 실패메시지가 떠서 수정했습니다
회원가입
sign_up.php
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>회원가입</title>
<link rel="stylesheet" href="/css/sign_up.css">
<script src="/script/duplicate_check.js" defer></script>
</head>
<body>
<container class="signup-container">
<form action="sign_up_proc.php" method="post" class="signup-form">
<div class="logo-container">
<a href="/login2.php"><img src="/imgs/almond.png" alt="logo" class="logo"></a>
</div>
<h2>Almond</h2>
<input type="text" name="id" placeholder="아이디" class="signup-input id-input" required>
<input type="password" name="pass" placeholder="비밀번호" class="signup-input pass-input" required>
<input type="password" name="passCheck" placeholder="비밀번호 확인" class="signup-input pass-input-check" required>
<input type="text" name="nickname" placeholder="닉네임" class="signup-input nickname-input" required>
<input type="email" name="email" placeholder="이메일" class="signup-input email-input" required>
<div class="agreement">
<input type="checkbox" id="sign_up_agreement" required>
<label for="sign_up_agreement">회원가입에 동의합니다.</label>
</div>
<button type="submit" class="signup-submit">회원가입</button>
</form>
</container>
</body>
</html>
<input type="email" name="email" placeholder="이메일" class="signup-input email-input" required>
이메일 입력을 위한 input을 추가했습니다.
sign_up_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 * from users;";
$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;
runSQL("insert into users values ('$id', '$nick', '$email', '$pass')");
}
echo json_encode(['result' => $result, 'id' => $id_duple, 'nick' => $nick_duple, 'pass' => $pass_duple]);
?>
기존 users.txt로 하던 부분을 mysql로 대체했습니다. 달라진 점은
$sql = "select * from users;";
$sql_result = runSQL($sql);
almond db의 users테이블의 모든 데이터를 읽어옵니다.
while ($row = mysqli_fetch_array($sql_result)) {
mysqli_fetch_array로 sqli_result(DB에서 가져온 데이터) 객체를 array형태로 변환시킵니다.
그 이후 while문을 돌면서 $sql_result값을 한줄씩 $row에 저장합니다.
if ($id == $row["id"]) {
$id_duple = true;
}
if ($nick == $row['nickname']) {
$nick_duple = true;
}
if문으로 유저가 입력한 아이디와 닉네임의 중복을 확인합니다.
if($pass != $passCheck) {
$pass_duple = true;
}
유저가 입력한 비밀번호와 비밀번호 확인의 값이 동일한지 확인합니다.
if (!$id_duple && !$pass_duple && !$nick_duple) {
$result = true;
runSQL("insert into users values ('$id', '$nick', '$email', '$pass')");
}
모든 검사를 통과하면 users 테이블에 insert into를 이용해서 유저가 입력한 값을 삽입합니다.
코드들을 계속해서 수정하고 다시 만들고를 반복하다 보니 점점 폴더도 코드내용도 복잡해집니다.
그래서 요즘 주석의 중요함을 느끼고 있습니다.
db를 사용하는 것도 고쳐야 될 점이 많이 보입니다.
mysql.php는 sql문을 하나 실행할 때마다 db와 연결했다 끊었다를 반복하고 있습니다.
회원가입과 로그인은 모든 데이터를 db에서 서버로 불러와서 검사를 하고 있어서
이 사이트는 상관없지만 데이터가 많은 사이트에서는 성능적으로 절대 쓰면 안 될 거 같습니다.
'모의해킹 > 웹 개발' 카테고리의 다른 글
모의해킹 공부 정리 9일차 (로그아웃) (0) | 2024.10.25 |
---|---|
모의해킹 공부 정리 8일차 (과제) (1) | 2024.10.24 |
모의해킹 공부 정리 4,5,6 일차 (mysql 설정) (3) | 2024.10.22 |
모의해킹 공부 정리 3일차 (회원가입 페이지) (0) | 2024.10.19 |
모의해킹 공부 정리 2일차 (과제) (2) | 2024.10.18 |