생활코딩

Coding Everybody

코스 전체목록

닫기

보안

보안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. 손영민
    escaping, 웹사이트에서 엄청 중요하지만, 반면에 문제가 생기기 전까지는 아무도 신경쓰지 않는 것.
  2. 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내부적으로 스크립트 문을 받아들이지 않는 설정이 되어 있는 듯합니다. 호오...
    • 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가 빠진 경우에도 에러메시지가 출력되는 대신 빈페이지를 보이게 한다거나 하실 수 있습니다!
          대화보기
          • 광길
            보안 실습 3번 코드를 작성하고 리로드를 하면

            Notice: Undefined index: name in C:\Bitnami\wampstack-5.6.31-0\apache2\htdocs\phpjs\14.php on line 4
            //(4번줄 내용 : $name = mysqli_real_escape_string($conn, $_GET['name']);)
            Notice: Undefined index: password in C:\Bitnami\wampstack-5.6.31-0\apache2\htdocs\phpjs\14.php on line 5
            //(5번줄 내용 : $password = mysqli_real_escape_string($conn, $_GET['password']);)
            SELECT * FROM user WHERE name='' AND password='' 뉘신지?

            자꾸만 이렇게 뜹니다ㅜㅜ 데이터베이스에 이름을 다르게 저장한것도 아닌데 왜그러는 걸까요??ㅠㅠㅠ 도와주세요ㅠㅠㅠ
          • 신시내티
            수업 듣고보니 보안 전문가는 암환자를 수술하는 외과의사 같다는 생각이 드네요 ㅎㅎ
            미국에서는 금융계 회사 보안 전문가가 IT 업계에서 가장 대우받는 직업중 하나 인것 같아요.
          • 신시내티
            이고잉님 수업에는 단순한 스킬뿐 아니라,철학도 담겨있어서 좋아요. 감사합니다.
          • jhpark
            Wow, safety is vary important.
            i think, i can see that.
          • chosu1202@naver.com
            원화 표시라는 것 보다는 역슬래쉬라는 것을 아셔야 할 것 같습니다.
            Enter 바로 위에 있는 버튼 누르시면 됩니다.
            대화보기
            • 가영
              완료!
            • Jayden贤宇
              맥북은 mysql monitor에서 원화표시를 어떻게해야하죠??

              control + command + space 단축기로 원화를 넣으면 오류가 뜹니다..ㅠㅠ
            • qhdgusdndn@naver.com
              맥북은 mysql monitor에서 원화표시를 어떻게해야하죠??

              control + command + space 단축기로 원화를 넣으면 오류가 뜹니다..ㅠㅠ
            • GoldPenguin
              완료했습니다.
            • milhouse
              도움이 될지 모르겠지만 일단 작성해볼게요.^^

              -> $sql 변수에 DB안에서 실행하고 싶은 명령어를 문자열 형태로 저장한 다음

              mysqli_query 함수를 통해 DB내에서 $sql에 저장된 문자열을 전달해서

              그 문자열을 명령어로 실행시키도록 하고 있는 거라고 알고 있습니다.
              대화보기
              • Baekkyu Han
                보안
                보안1~3
                낙법 실패하는법 성공을 자신있게 도전
                복구 불가능한것은 데이터
                적절힐 비극은 엔지니어의
                좋은 엔지니어는 비극속에서 피어나는 꽃
                좋은 습관은 자신을 지킨다.

                dbase 관련 보안
              • 박예지
                완료료료
              • 김경태
                잘 봤습니다~
              • Myeongjin Ko
                완료
              • 인재진
                수강완료합니다.
              • 완료 ^^
              • fatfat
                수업 잘 들었습니다 ㅎㅎ 수업을 듣다가 궁금한게 생겼는데요!

                DB에서 가져온 내용을 화면에 표시하기 전에 script 태그를 무력화 시키는 방법은 이제 앍았습니다.

                그런데 제 생각에 DB의 내용이 공격을 당했을 수도 있으니 DB에서 가져온 내용을 좀 더 꼼꼼하게 따져봐야 하는것 아닌지 하는 괜한 걱정이 드네요..

                실제 홈페이지를 만들 때 DB에서 가져오는 내용은 script만 무력화 시켜줘도 충분한가요??
              버전 관리
              egoing
              현재 버전
              선택 버전
              graphittie 자세히 보기