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 |
'컴퓨터 > 웹 개발' 카테고리의 다른 글
[코딩야학] ~ 라이브러리 1 - 19일차 (0) | 2018.03.05 |
---|---|
[코딩야학] ~ 관계형DB실습 - 17일차 (0) | 2017.08.11 |
[코딩야학] ~ MySQL실습 - 16일차 (0) | 2017.08.10 |
[코딩야학] ~ DB이론 - 15일차 (0) | 2017.08.08 |
[코딩야학] ~ PHP 실습 - 13,14일차 (0) | 2017.08.08 |