프로그래밍 입문

보안

토픽 프로그래밍 입문 > 웹 어플리케이션 만들기 > 웹 어플리케이션 만들기

보안1

보안2

php/5.php

사용자가 입력한 script 태그를 무력화시키는 방법. (참고 : htmlspecialchars)

<html>
  <head>
    <title></title>
  </head>
  <body>
    <?php
       echo htmlspecialchars('<script>alert(1);</script>');
    ?>
  </body>
</html>

index.php

<?php
$conn = mysqli_connect("localhost", "root", 111111);
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="http://localhost/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="http://localhost/index.php">JavaScript</a></h1>
  </header>
	<nav>
		<ol>
    <?php
    while( $row = mysqli_fetch_assoc($result)){
      echo '<li><a href="http://localhost/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="http://localhost/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>

보안3

/phpjs/14.php

<?php
$conn = mysqli_connect("localhost", "root", 111111);
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>

process.php

원래는 process.php 파일에도 보안을 적용해야 합니다. 하지만 우리수업에서는 수업 시간을 줄이기 위해서 생략합니다. 참고로 아래와 같이 process.php  개선할 수 있습니다. 아래 파일을 그대로 적용해주세요.
<?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');
?>

소스코드

github

참고

보안의 중요한 주제인 암호화에 대해서 궁금하신 분은 아래 수업을 참고해주세요.

암호화를 이용한 보편적이지 않은 코딩

댓글

댓글 본문
  1. James Hanjoo Park
    하기와 같은 문제가 발생했는데...14.php 파일의 18번째줄은 하기와 같은데...뭐가 문제인가요?
    강의화면 같은 MySQL문이 나와야 하는데......

    echo "누구세요?";


    Parse error: syntax error, unexpected end of file, expecting variable (T_VARIABLE) or quoted-string and whitespace (T_ENCAPSED_AND_WHITESPACE) or ${ (T_DOLLAR_OPEN_CURLY_BRACES) or {$ (T_CURLY_OPEN) in C:\Bitnami\wampstack-5.4.40-0\apache2\htdocs\phpjs\14.php on line 18
  2. 박병진
    2020.11.25 완료
  3. 10/14
  4. PARK
    2020.10.08
  5. 100억
    보안3 동영상에 나오는 phpjs/8.php파일은 존재하지않고 8-1.php, 8-2.php파일이 존재합니다
  6. 허우룩
    2020.09.16
  7. HyeonHui Jeong
    5/17
  8. 열심히사는사람
    복습을 해야겠네요 완료
  9. 산노을
    감사!!!!!!!!!!!!
  10. myjin
    완료!!
  11. 엄청잘될꺼야
    감사합니다. 완료
  12. 들국화
    완료 감사합니다
  13. 왜 이래 답변
    $conn = mysqli_connect("localhost", "root", 111111);
    에서 알파벳+숫자 가 비번이신 분은 따옴표를 붙여서 쓰시면 되요.
    이렇게
    $conn = mysqli_connect("localhost", "root", "1234abc");
    대화보기
    • 왜 이래
      아니
      $conn = mysqli_connect("localhost", "root", 111111);
      이 부분에서 알파벳과 숫자가 같이 있으면 작동이 안되네요. ex) 1234abcd
      제 비번이 그래서 작동이 안 돼요.. 심지어 그냥 1111이나 214124 이나 alkekf 같이 막 쓰면 그게 작동이 되네요..
      이거 왜 이런건가요?
    • 초심자
      Trying to get property 'num_rows' of non-object in C:\Bitnami\wampstack-7.3.6-1\apache2\htdocs\php\phpjs\14.php on line 16

      if($result->num_rows == "0"){
      여기서 막혔는데 어쩌나요?
      if (!empty($result) && $result->num_rows == "0"){
      이렇게 바꾸라는데 왜 이렇게 해결해야하는지
      저는왜 그부분에서 에러가나는지 모르겠어요.
      버전이 올라가면서 문법이 완성이 안되면 에러나게 바뀌었나요?
    • 셜리
      어려워서인지 뒤로 갈수록 시간이 걸립니다. ㅎㅎ 완료!
    • Fsor
      참 고맙습니다.
    • 손영민
      escaping, 웹사이트에서 엄청 중요하지만, 반면에 문제가 생기기 전까지는 아무도 신경쓰지 않는 것.
    • Comtroll
      view-source:http://localhost:8080/write.php

      write.php 페이지에서 소스 확인해보시면 패스워드 노출 안됩니다.
      잘 생각해보면 알 수 있죠
      대화보기
      • Comtroll
        port 문제가 얽혀서 헤매시는 분들 많을 것 같네요.

        강의에서는 80 port로 서버를 진행하고 있어서 접속 주소에 localhost:8080로 포트를 표시하는 부분이 없습니다.
        http에서는 port가 명시되지 않으면 규약인 80이 포트로 사용됩니다.

        Linux에서는 현재 well known port (0~1023) 로 서버를 여는데는 sudo 권한이 필요한 것 같습니다.
        그래서 bitnami configure에서 apache server의 port를 80으로 설정해도 안되죠.

        강의자분처럼 root 디렉토리 bitnami를 설치하거나, 모든 주소에 :8080을 붙여서 사용하시면 될 것 같네요.
        데이터베이스 주소는 데이터베이스 port로 사용하셔야 하고요.
        mysqli에서 default로 쓰는 port는 3306 이라, 3306으로 사용 중이면 주소에 :3306 안해도 됩니다.
      • 조동재
        htmlspecialchars($row['title']) 에서 $row['title']은 문자열 값을 가지고 있는 거 아닌가요?
        그러면 htmlspecialchars('$row['title']') 이 되야 하는 거 아닌가요...? 부족한 질문이지만.. 감사합니다
      • 김민환
        어려운 내용이라서 개념만 대충 배워갑니다. 복습이 중요하군요. 복습... ^^;
        항상 감사합니다.
      • 슝태
        20180119
      • PassionOfStudy
        18-01-09 11일차 - 2번째 강의

        수강완료!


        ----------------------------------------------------------------------------------
        본래 보안에 관심이 있는 1인으로서 신기하고 재미있네요~

        Secure Coding이라는게 이런 것을 생각함으로써 시작하는 것일까요???
      • hanulsso
        반복학습이 필요한 수업이네요
        여러번 복습하겠습니다.
        저런게 보안이었군요 재밌습니다 어렵지만
      • 이근환
        2017-12-12 수강 15일차

        수강완료하였습니다.

        htmlspecialchars와 strip tags, mysqli_real_escape_string을 배우고

        또 보안에 대해서 생각해보는 시간을 가지게 되어서 뜻 깊은 강의였습니다!
      • jkedu714@gmail.com
        와.... 난이도가 급 올라가는 듯한 느낌이네요 ㅠㅠ
        매우 어렵습니다 ;;;
      • remake
        비트나미 설치 시 오류로 MAMP(https://www.mamp.info/en/)를 깔아서 실습하고 있는데, 보안2의 예제
        alert(merong)이 아예 데이터베이스로 전달되지 않네요. 실습해보고 싶었는데 뭔가 AMP내부적으로 스크립트 문을 받아들이지 않는 설정이 되어 있는 듯합니다. 호오...
      • JIbt
        OWASP10 중에서 몇가지 내용이네요!
        정말 대단하십니다.. 보안 공부하면서 뭔가 와닿지 않았던 내용인데
        이렇게 직접 보여주시니깐 정말 머리에 쏙쏙 박히네요 ㅎㅎㅎ
      • 박인호
        11-28
        수강완료.
        상당히 중요할 수 있는 내용이군요, 감사합니다.
      • 서성진
        ㅠㅠ 많이 어렵고, 또 이번엔 졸음이 쏟아져서..
        절대 재미없거나 흥미가 없어서는 아닌데,,
        어려워서 그랬던 것 같습니다. 정신 차려가면서 끝까지 맨정신으로 보느라 힘들었네요. ㅎㅎ
        그래도 본 보람은 있었네요.
        감사합니다. 잘 봤습니다.
      • 효천
        어렵네요
        하지만 중요한 부분 같습니다.
      • 유상원
        2017-11-11 완료!
      • I love computer
        아우 어렵다ㅠㅠㅠ
      • JH Chae
        수강 완료했습니다 감사합니다!!

        한가지 여쭤볼 것이 있는데요,

        $conn = mysqli_connect("localhost", "root", 111111);
        위에서 해당 서버에 접속하면서 password를 입력하게 되는데 프로그래밍하는 입장에선 내부적으로 바로 드러나는데
        외부에서는 볼 수 없나요?
      • Michael
        완료~!
        감사합니다.~!
      • 송성태
        알고 보니까 섬뜩합니다.
        보안이 없으면 그냥 정보를 공개하는 것과 마찬가지군요.
        뭐하나 그냥 넘어갈 내용이 없군요.
        잘 보았습니다.
      • hunter10
        완료
      • 왓떠뻐꺼
        완료했습니다. 감사합니다.
      • var_dump 해서 나온 값이 항상 6이 나오는데 뭐가 잘못된걸까요?ㅠ
      • kulung
        process.php 코드내에 password 도
        $password = mysqli_real_escape_string($conn, $_POST['password']); 를 넣어줘서
        조건문을 $sql = "INSERT INTO user (name, password) VALUES('".$author."', ".$password")";
        하면안..되는건지요? @@ 어렵네용
      • Gyoil Gu
        여러번 돌려봤어요! 보안은 어렵고 중요하네요.
      • 다시시작
        완료
      • jayxwoo
        잘봤습니다^^ 이런식으로 escaping을 한다는 감각을 조금은 알 것 같네요. 감사합니다~
      • jayxwoo
        설명을 잘 못드린 것 같네요. (정확하진 않다고 말씀드리긴 했지만..)
        보안3 동영상을 보니 원화 표시는 역슬래시를 사용하는 것 같네요. 보안3 동영상 25분20초 부터 한번 보세요. ^^
        대화보기
        • jayxwoo
          맥os에서는..
          - 원화(₩) 표시 대신 키보드버튼 1 왼쪽에 위치한 ` 버튼을 사용하는 것으로 알고 있습니다.
          - 원화 표시를 해야 할 경우 키보드 인풋을 한글로 변경하신 후 위와 동일한 버튼 ` 을 누르시면 원화로 표시됩니다.

          (정확하진 않지만 한번 해보세요.)
          대화보기
          • forest
            완료
          • thank you so much ^^
          • 김태윤
            봤어요.. 근데 어렵네요. --;
          • Narrativi
            $_GET[] 으로 받으려고 하는 name과 password를 찾을 수 없다는 뜻입니다.
            아마 주소에 ?name=egoing&password=111111 를 덧붙이는걸 깜박하신 것 같네요!

            localhost/phpjs/14.php 로 이동하면 보시는 에러메시지가 뜨고
            localhost/phpjs/14.php?name=ㅁㄴㅇㄹ&password=ㅁㄴㅇㄹ 로 이동하시면, ㅁㄴㅇㄹ에 입력한 내용에 따라 '반갑습니다' 또는 '뉘신지'가 뜨게 됩니다.

            if문을 응용하시면 name 또는 password가 빠진 경우에도 에러메시지가 출력되는 대신 빈페이지를 보이게 한다거나 하실 수 있습니다!
            대화보기