[08] cookie 및 session 이용한 인증, SQL Injection, secure 코딩

|


- 2015.03.18 웹보안 [08]

 

 


1. SELinux 설정 해제


# vi /etc/sysconfig/selinux
      6 SELINUX=disabled

 

 

 


2. Cookie 이용한 로그인 인증


in CMD


> telnet 192.168.133.142 80   이용하면 코드가 오는 것을 확인할 수 있다.

 


1) 방식


                          id & pw
     Client               ---->              Web Server      ---->          Web app     ---->    SetCookie
Web browser        <----                  Apache        <----            php(login_check.php)  <┘
                       Set-Cookie
            (Header에 붙여서 보내줌)

 


2) 단점


Web Browser가 꺼져도 Web Temp 디렉터리에 쿠키 정보가 PC에 남음.
즉 쿠키를 이용한 인증을 사용하는 사이트의 경우, 쿠키 파일만 있으면 인증 없이 로그인할 수 있다.

 

 

 


3. Session을 이용한 로그인 인증


- session_start();
     session을 사용하려는 php 파일에서는 반드시 session_start()로 시작

 


1) 세션 이용 소스


# vi login_check.php
      1 <?
      2   session_start();
      3   $DB = mysql_connect( 'localhost', 'root', 'a' );      # mysql Server 접속
      4   $ret = mysql_select_db( 'test', $DB );                # DB 접속
      5
      6   $sql = "select * from user where id='$id' and pw=password('$pw')";    # que        ry 실행
      7   $result = mysql_query( $sql );                # 결과를 result에 저장
      8
      9 #  $row = mysql_fetch_array( $result, MYSQL_NUM );
     10
     11   $count = mysql_num_rows( $result );           # result는 몇열인가?
     12   if ( $count > 0 ) {
     13     $_SESSION['id'] = $id;                      # session 에 id 입력
     14 #    setcookie('cookie', $pw, 0, '/');          # cookie 굽기, 만료시간 없음
     15   }
     16   header('location: http://192.168.133.142/login.php');
     17
     18 ?>

 


# vi login.php
      1 <?
      2 #  if( !$_COOKIE[cookie] ) {
      3   session_start();
      4   if( !$_SESSION[id] ) {
      5 ?>
      6 <html>
      7 <head>
      8         <title> Log In </title>
      9 </head>
     10
     11 <body>
     12         <form method=POST action=login_check.php>
     13                 id <input type="text" name="id"><br>
     14                 pw <input type="password" name="pw"><br>
     15                 <input type="submit" value="Login">
     16         </form>
     17 </body>
     18 </html>
     19
     20
     21 <?
     22   }
     23   else {
     24     echo "already login...";
     25     echo "<br>";
     26     echo "<a href='logout.php'> Logout </a>";
     27   }
     28 ?>

 


# vi logout.php
      1 <?
      2 #  setcookie( 'cookie', '', 0, '/');
      3   session_start();
      4   session_destroy();
      5   header('location: http://192.168.133.142/login.php');
      6 ?>


=> 웹 브라우저가 쿠키인지, 세션인지를 알려면 WireShark를 이용해서 알 수 있다.
    같은 Cookie 필드를 통해 전달하지만 값이 다름.

 

 

 


2) 사용자 세션 정보 in Session


리눅스 서버에 사용자별 세션 정보가 남아있다.


# cd /var/lib/php/session/
# ls
sess_v456jbkagbg41dron32km4jpc3
# cat sess_v456jbkagbg41dron32km4jpc3
id|s:5:"admin";


=> 이러한 세션 정보를 헤더에 실어 보내면 공격도 가능해진다.

 

 

 


4. SQL Injection을 통한 로그인 인증 우회


1) SQL에 내가 원하는 문장을 입력하는 공격


login_check.php 안에 있는 쿼리는
"Select * from user where id=' $id ' and pw=' $pw ' " 이다.


헌데 form 안의 id 항목에 [ ' or 1=1 # ]  이라는 SQL 명령을 넣으면 바로 인증이 되어버린다.
즉, id 의 우측 싱글쿼터를 막고 or 함수와 함께 참인 값을 넣은 뒤 뒤에 내용을 주석으로 처리한다면
쿼리를 통해 돌아오는 값은 무조건 참이 되는 것이다.


이렇듯, 복잡한 코드가 생길 수록 보안에 헛점이 생긴다.

 

 


2) Tip - Injection 문제


http://flack.hkpco.kr/index.php


Level 1 : ' or 1=1 #
Level 2 : ' or 1=1 )#
Level 3 : admin' )#

 

 


* Tip [ 보안 != 공격 ]


시스템 설치 및 설정 --> 서비스 운영 --> 장애 대응 및
프로그래밍 등이 기본 밑바탕이 되어야 한다.

 

 

 


3) 해당 공격 방어


- 솔루션
     웹 방화벽


- 시큐어 코딩
     특수문자 ID 금지
     입력값 검증 등

 

 


[ 시큐어 코딩 ]


# vi login_check.php
      1 <?
      2   session_start();
      3   $DB = mysql_connect( 'localhost', 'root', 'a' );      # mysql Server 접속
      4   $ret = mysql_select_db( 'test', $DB );                # DB 접속
      5
      6   if( eregi('or', $id) || eregi('\'', $id) || eregi('#', $id) || eregi('and', $        id) ) {
      7     echo "<script> alert('invalid value'); history.back();</script>";
      8     exit;
      9   }
     10
     11   if( eregi('or', $pw) || eregi('\'', $pw) || eregi('#', $pw) || eregi('and', $        pw) ) {
     12     echo "<script> alert('invalid value'); history.back();</script>";
     13     exit;
     14   }
     15
     16   $sql = "select * from user where id='$id' and pw=password('$pw')";    # query         실행
     17   $result = mysql_query( $sql );                # 결과를 result에 저장
     18
     19 #  $row = mysql_fetch_array( $result, MYSQL_NUM );
     20
     21   $count = mysql_num_rows( $result );           # result는 몇열인가?
     22   if ( $count > 0 ) {
     23     $_SESSION['id'] = $id;                      # session 에 id 입력
     24 #    setcookie('cookie', $pw, 0, '/');          # cookie 굽기, 만료시간 없음
     25   header('location: http://192.168.65.134/login.php');
     26   }
     27   else {
     28     echo "<script> alert('login failed'); history.back();</script>";
     29     exit;
     30   }
     31 ?>

 

 

 

And