22. 보안

https://www.opentutorials.org/course/1688/9471



1) 보안 1

최고의 보안 담당자는 우리 시스템에 침입한 크래커


최고의 보안전문가만이 시스템을 지킬 수 있을까?

- 보안의 중요성과 보안에 대한 좋은 습관을 가질 필요가 있다.

- 좋은 습관을 가지고 몇 가지 지침들만 잘 따라주면 수많은 외부적 공격으로부터 시스템을 보호하는 효과를 가질 수 있다.



2) 보안 2 (escaping)

자바스크립트는 중요한 정보들을 탈취해서 몰래 자신들의 서버에 전송하는 능력을 가지고 있다.


사용자가 잘못된 사이트에 입력하는 정보를 알아내서 사용자의 내밀한 정보를 캐내는 나쁜 짓을 할 수 있다.

→ 피싱


문제해결 방법

- 사용자가 등록한 정보 안에는 스크립트 코드를 입력할 수 없음

- 입력한 정보가 HTML로 표현되게 하는 기법 사용


         

- 사용자가 스크립트 코드를 입력하면 그대로 실행되는 문제 발생


HTML Entity : https://dev.w3.org/html5/html-author/charref


htmlspecialchars()

- 자동변환 내장함수

- HTML의 코드로 인식될 수 있는 문자열의 일부내용을 HTML Entity로 변환하여 출력

- 보안을 높이는데 사용되는 중요한 API

- 사용자가 입력한 스크립트 코드를 무력화시키고, 화면에 출력할 수 있음


php/5.php

1
2
3
4
5
6
7
8
9
10
11
<html>
  <head>
    <meta charset = "utf-8">
    <title></title>
  </head>
  <body>
    <?php
       echo htmlspecialchars('<script>alert(1);</script>');
    ?>
  </body>
</html>
cs


- javascript를 실행하지 않는다.


사용자가 입력한 정보는 모두 공격의 대상이 될 수 있으므로 htmlspecialchars()로 감싸줘야 한다.

index.php

    


- 원하지 않는 태그들까지 HTML Entity로 변환되는 문제 발생

ex) <H2>, <ul>, <li>, <a> 등

- strip_tags() API로 해결


strip_tags()

http://php.net/manual/kr/function.strip-tags.php

- 주어진 str에서 모든 HTML과 PHP 태그를 제거한 문자열을 반환

- 선택적인 두번째 인수로 제거하지 않을 태그를 지정할 수 있음


index.php (escaping 기법 추가)

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<?php
  $conn = mysqli_connect('localhost''root''');
  mysqli_select_db($conn'opentutorials');
  $result = mysqli_query($conn'SELECT * FROM topic');
?>
 
<!DOCTYPE html>
<html>
  <head>
    <meta charset = "utf-8">
    <link rel="stylesheet" type="text/css" href="/style.css">
  </head>
  <body id="target">
    <header>
      <img src="https://s3.ap-northeast-2.amazonaws.com/opentutorials-user-file/course/94.png" alt="생활코딩">
      <h1><a href="/index.php">JavaScript</a></h1>
    </header>
    <nav>
      <ol>
      <?php
        while($row=mysqli_fetch_assoc($result)) {
          echo '<li><a href="/index.php?id='.$row['id'].'">'.htmlspecialchars($row['title']).'</a></li>'."\n";
        }
      ?>
      </ol>  
    </nav>
    <div id="control">
      <input type="button" value="white" onclick="document.getElementById('target').className='white'"/>
      <input type="button" value="black" onclick="document.getElementById('target').className='black'"/>
      <a href="write.php">쓰기</a
    </div>
    <article>
      <?php
        if(empty($_GET['id']) === false) {
          $sql='SELECT topic.id, title, name, description FROM topic LEFT JOIN user ON topic.author = user.id WHERE topic.id='.$_GET['id'];
          $result = mysqli_query($conn,$sql);
          $row = mysqli_fetch_assoc($result);
          echo '<h2>'.htmlspecialchars($row['title']).'</h2>';
          echo'<p>'.htmlspecialchars($row['name']).'</p>';
          echo strip_tags($row['description'], '<a><h1><h2><h3><h4><h5><ul><ol><li>');
        }
      ?>
    </article>
  </body>
</html>
cs




3) 보안 3 

SQL Injection

- '1=1' 이라는 조건은 무조건 참



- ' or 1=1 로 인해 무조건 참이 되면서 로그인 성공


mysqli_real_escape_string()

- SQL문 안에서 특수한 기호가 있는 정보가 포함되어 있다면, 그 앞에 escape(역슬래시)를 붙여줌

- MySQL 서버는 역슬래스가 붙어있는 기호를 SQL문의 특수한 키워드로 생각하지 않고 문자로 처리


/phpjs/14.php

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
<?php
  $conn = mysqli_connect('localhost''root''');
  mysqli_select_db($conn'opentutorials');
  $name = mysqli_real_escape_string($conn$_GET['name']);
  $password = mysqli_real_escape_string($conn$_GET['password']);
  $sql = "SELECT * FROM user WHERE name='".$name."' AND password='".$password."'";
  echo $sql;
  $result = mysqli_query($conn$sql);
?>
 
<!DOCTYPE html>
<html>
  <head>
    <meta charset = "utf-8">
  </head>
  <body>
    <?php
      if($result->num_rows == "0"){
        echo "뉘신지?";
      } else {
        echo "안녕하세요. 주인님";
      }
    ?>
  </body>
</html>
cs





※ process.php 개선

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
  $conn = mysqli_connect("localhost""root"111111);
  mysqli_select_db($conn"opentutorials");
 
  $title = mysqli_real_escape_string($conn$_POST['title']);
  $author = mysqli_real_escape_string($conn$_POST['author']);
  $description = mysqli_real_escape_string($conn$_POST['description']);
 
  $sql = "SELECT * FROM user WHERE name='".$author."'";
  $result  = mysqli_query($conn$sql);
  if($result->num_rows == 0){
    $sql = "INSERT INTO user (name, password) VALUES('".$author."', '111111')";
    mysqli_query($conn$sql);
    $user_id = mysqli_insert_id($conn);
  } else {
    $row = mysqli_fetch_assoc($result);
    $user_id = $row['id'];
  }
  $sql = "INSERT INTO topic (title,description,author,created) VALUES('".$title."', '".$description."', '".$user_id."', now())";
  $result = mysqli_query($conn$sql);
  header('Location: http://localhost/index.php');
?>
cs




+ Recent posts