'cookie'에 해당되는 글 2건

  1. 2015.05.07 [08] cookie 및 session 이용한 인증, SQL Injection, secure 코딩
  2. 2015.05.07 [07] php 셋팅, mysql 연동, 계정 인증, Web 인증방식, cookie 이용 인증 및 logout

[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


[07] php 셋팅, mysql 연동, 계정 인증, Web 인증방식, cookie 이용 인증 및 logout

|


- 2015.03.17

 


1. php 연동


1) php.ini 파일 수정


# vi /etc/php.ini
    457 register_globals = On
    462 register_long_arrays = On


# service httpd restart


* register_globals : 전역변수 사용 가능 설정 - $id, $pw 등을 사용하기 위함

 

 


2) php 기본 사용법


<?
     $var = 0;     # 변수 선언 시 $ 를 붙이면 된다. type 지정 및 선언 필요 없음


?>    #  <-  이 안에 php 내용 삽입

 

 


3) 출력 확인


변수를 받아 출력 되는지 확인


# vi login_check.php
      1 <?
      2
      3   echo "id: $id";
      4   echo "<br>";
      5   echo "pw: $pw";
      6
      7 ?>


login.html 에서 확인 해보면 정상적으로 작동한다.

 

 


4) php변수


- 글로별 변수 : get, post 방식 상관 없이 처리 가능
- $_GET[] : get 방식으로 데이터가 전달 된 경우
- $_POST[] : post 방식으로 데이터가 전달 된 경우

 

 


[ 예제 ]


# vi login_check.php
      1 <?
      2
      3   echo "id: $id";
      4   echo "<br>";
      5   echo "pw: $pw";
      6
      7   echo "<br>";
      8   echo "<br>";
      9
     10   echo "id: $_GET[id]";
     11   echo "<br>";
     12   echo "pw: $_GET[pw]";
     13
     14   echo "<br>";
     15   echo "<br>";
     16
     17   echo "id: $_POST[id]";
     18   echo "<br>";
     19   echo "pw: $_POST[pw]";
     20
     21 ?>

 


- POST 방식


http://192.168.133.142/login_check.php 에서 전송하면 POST 결과 확인 가능

 


- GET 방식


현재 login.html 소스코드가 POST 방식이기 때문에 아래 url을 통해 확인 가능


http://192.168.133.142/login_check.php?id=asdf&pw=asdf

 


* Tip


php 는 컴파일이 없기 때문에 에러메세지가 따로 나오지 않는다.
눈으로 소스코드를 찾아보거나 명령어 방법으로 에러를 찾아야 한다.

 

 

 

 


2. php와 mysql


1) mysql 관련 library in php


- mysql_connect() : mysql server 접속
     server : localhost
     username : root
     password : xxxx


- mysql_select_db() : 사용할 DB 선택
     DB_name : test
     file descriptor : DB id - mysql_connect() 를 통해 반환됨


- mysql_query() : 쿼리 전송
     query : 실행할 쿼리


- mysql_fetch_array() : 쿼리 결과를 배열 형태로 반환
     result : 쿼리 실행 결과
     상수 : 배열의 형태
                    MYSQL_NUM         - 숫자로 가져옴
                    MYSQL_ASSOC     - field 값으로 가져옴
                    MYSQL_BOTH        - 둘 다로 가져옴

 


* 쿼리 실행 결과를 가져올 수 있는 또 다른 함수


- mysql_fetch_row()
- mysql_fetch_assoc()

 


ex)


# vi login_check.php
      1 <?
      2   $DB = mysql_connect( 'localhost', 'root', 'a' );
      3   mysql_select_db( 'test', $DB );
      4
      5 ?>


=>
# mysql -u root -p
mysql> use test;


까지 진행 된 상황.

 

 


[ 예제 ]


# vi login_check.php
      1 <?
      2   $DB = mysql_connect( 'localhost', 'root', 'a' );      # mysql Server 접속
      3   $ret = mysql_select_db( 'test', $DB );                # DB 접속
      4
      5   $sql = "select * from user";                          # query 실행
      6   $result = mysql_query( $sql );                        # 결과를 result에 저장
      7
      8   while( $row = mysql_fetch_array( $result, MYSQL_NUM ) ) {     # row에 NULL값이 들어갈 때까지 반복
      9     echo "num: $row[0] name: $row[1] id: $row[2] pw: $row[3]";  # 반복문 없다면 첫번째 열만 출력함
     10     echo "<br>";
     11   }
     12
     13 ?>

 

 

 


2) 인증 예제


id & pw 인증


# vi login_check.php
      1 <?
      2   $DB = mysql_connect( 'localhost', 'root', 'a' )                                   ;      # mysql Server 접속
      3   $ret = mysql_select_db( 'test', $DB );                                                      # DB 접속
      4
      5   $sql = "select * from user where id='$id' and pw=password('$pw')";       # query 실행
      6   $result = mysql_query( $sql );                                                                 # 결과를 result에 저장
      7
      8   #$row = mysql_fetch_array( $result, MYSQL_NUM );
      9
     10   $count = mysql_num_rows( $result );                                                     # result는 몇열인가?
     11   echo $count;                                                                                           # 조건 맞는 열의 개수 저장하여 출력
     12
     13 ?>


=> http://192.168.133.142/login_check.php?id=admin&pw=xxxx   확인 시 1 이 나온다. 이를 이용하여 아래처럼 꾸며보자.

 


# vi login_check.php
      1 <?
      2   $DB = mysql_connect( 'localhost', 'root', 'a' );                                            # mysql Server 접속
      3   $ret = mysql_select_db( 'test', $DB );                                                         # DB 접속
      4
      5   $sql = "select * from user where id='$id' and pw=password('$pw')";           # query 실행
      6   $result = mysql_query( $sql );                                                                     # 결과를 result에 저장
      7
      8   #$row = mysql_fetch_array( $result, MYSQL_NUM );
      9
     10   $count = mysql_num_rows( $result );                                                         # result는 몇열인가?
     11   if ( $count > 0 ) {
     12     header('location: http://192.168.133.142/login.html');
     13   }
     14   else {
     15     echo "authentication fail... ";
     16   }
     17
     18 ?>


=> 인증은 된다. but 일반적으론 tcp 세션이 끊기기 전까지 인증이 유지되어야 하는데 여기선 그렇지 못하다.

 

 

 


3. Web 인증 방식


1) TCP 통신


연결을 계속 유지시키지는 않음
세션을 맺고 페이지를 모두 받아오면 바로 세션을 끊는다.

 

 


2) cookie, session


인증된 사용자임을 알기 위해 서버가 제공해주는 것들

 


* php 내의 이미 선언 되어 있는 변수


$_COOKIE[]
$_SESSION[]

 

 


3) cookie 굽기


- setcookie()
     cookie name
     cookie value
     expire time
     path
     (option) domain
     (option) security

 


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

 


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


html 파일을 php로 바꿔준다.


# mv login.html login.php


# vi index.html
     17                                         <li> <a href="login.php">Log In</a> <        /li>

 

 


4) logout


아래와 같이 Logout 버튼을 만들 수 있다.


# vi login.php
     21   else {
     22     echo "already login...";
     23     echo "<br>";
     24     echo "<a href='logout.php'> Logout </a>";
     25   }

 


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


=> cookie의 value를 초기화해서 쓸모 없는 cookie로 바꿔버림.


 

 

And


prev | 1 | next