생활코딩

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. 완료!
  2. skekogo
    오늘도 감사합니다!
  3. 이희태
    6/24일 보안 강의 수강완료하였습니다. 하.... 다른분들 존경합니다
  4. 웹초보
    codeanywhere 에서는 자체적으로 escaping 처리를 함으로써 쓰기 페이지에서 스크립트 코드의 입력을 막는 조치를 한 듯 합니다.

    db에 값이 추가가 안되는 것을 보니 post로 전송할 때 혹은 db에 insert 할 때 값을 조사해서 스크립트 코드가 있으면 실행이 안되도록 한 것 같습니다.
  5. 정미정
    감사해요! 잘들었습니다!
  6. 헬리사우드
    저는 제가 제 웹사이트를 해킹하면서 그부분을 고치려는방법으로 보안을 높입니다.
    이런식으로 보안을 높여도 돼는건가요?
  7. booski
    같은 문제인데 이미 다른분이 질문하신게 있어서 복붙해서 올려봅니다..
    ---
    안녕하세요 질문있습니다.
    2번 강의에서 본문에 자바스크립트 내용을 입력하고 제출하면 데이터베이스에 추가가 안됩니다.
    유저 테이블에 새로운 id가 등록되긴 하는데 topic테이블에는 추가가 안되네요.
    본문에 그냥 일반 문서를 치면 잘 업데이트가 되는데 자바스크립트 내용을 쓰면 안됩니다.
    이건 왜 그런건가요?
  8. 김민성
    감사합니다 잘들었습니다
  9. huni
    저도 아랫분처럼 데이터베이스부터 속도를 못 따라가겠네요.
    차라리 데이터 베이스는 잠시 쉬고 다음 강의를 넘어가도 될런지 모르겠습니다.
    아직은 데이터베이스까지 논스톱으로 이해하기 벅차네요
  10. seetower
    mysql 부터 멘붕이 오기 시작하더니 보안에서는 외계어를 듣는 듯 합니다..

    이해를 전혀 못하고 있네요..

    어떻게 해야 하나요?? ㅜ ㅜ;;
  11. 유혀누
    잘들었습니다.
  12. 나효진
    보안 마무리
  13. 개구리
    사용자의 입력을 받는 부분에 <xmp> <pre> <code>등의 태그를
    응용해도 스크립트 입력 방지 가능할 듯도 생각되네요.
    pre : 타자로 입력한 그대로 공백, 줄 바꿈 포함해서 출력, 단 태그는 적용된다.
    xmp : 타자로 입력한 그대로 공백, 줄 바꿈 포함해서 출력, 태그도 무시하고 그대로 출력된다.
    code : 말 그대로 코드를 그대로 출력한다. 태그 스크립트 적용되지 않는다.
  14. 삼나무숲
    객체지향으로 하는 것은 어떻게 하는 걸까요?
  15. Seo Yun Seok Tudoistube
    HTML Entity 라는 단어랑 'OR 1=1의 위험성과 역슬래시 Escaping 을 이제야 좀 알겠네요. 감사합니다^_____^
  16. 공삼이육
    강의시간 보다 오타 내서 헤매는 게 더 오래 걸린 것 같아요..ㅋㅋㅋ 재밌게 잘 봤습니다!
  17. 우탄
    재미따리 재미따~
  18. 14번째
    4.3.
  19. 보안까지 챙겨주셔서 감사합니다~
    역시 아무리 강조해도 지나치지 않네요.. ^^
  20. 세번째 영상의 2:13초에 패스워드를 asdfdsa' or 로 치면

    오류가 나는 sql문이 된다고 하셨잖아요.

    그러면 $result값이 NULL이 되고 if문 안의 값도 NULL이 되어서

    else에 해당하는 안녕하세요 주인님이 나오게 되는건가요?
  21. publicum
    혹시 다른 브라우저를 쓰시는 분들 참고하시라고 남겨드립니다.

    이고잉님께서 3번째 영상 중에 공격자가 URL 조작으로 SQL에 항상 참인 호출을 넣는 사례를 보여주셨는데, 기존 URL 뒤에 한칸 띄어서 OR를 붙이는 공격예제를 일부 브라우져에서는 제대로 인식하지 않고 잘못된 주소로 처리해서 구글 검색으로 넘어가버립니다. 찾아보니 본래 URL에서의 스페이스는 '+'기호나 '%20'로 표시되는 군요. 즉, 한칸띄기 대신 +를 입력하시면 똑같은 효과로 예제를 따라가실 수 있어요.
  22. Jaeeui Kwon
    20170317
  23. 170307
    감사합니다.
  24. <script>
    </script>
  25. 강경호
    감사합니다
    170228
  26. Gunho Lee
    안녕하세요 질문있습니다.
    2번 강의에서 본문에 자바스크립트 내용을 입력하고 제출하면 데이터베이스에 추가가 안됩니다.
    유저 테이블에 새로운 id가 등록되긴 하는데 topic테이블에는 추가가 안되네요.
    본문에 그냥 일반 문서를 치면 잘 업데이트가 되는데 자바스크립트 내용을 쓰면 안됩니다.
    이건 왜 그런건가요?
  27. egoing
    여기까지 오셨으면 여기서 멈추셔도 괜찮습니다. 이미 덜 중요하고 훨씬 어려운 개념들의 구간에 들어서셨거든요~
    대화보기
    • 가뭉멍
      여기까지 잘 달려왔는데... 비록... 3개월이나 걸렸지만... ㅠㅠ 생초보에게는 데이터베이스 이후로 갑자기 너무 진행이 빠르고 어려워지는 느낌이예요.. 보안 강의만 대여섯번씩 다시보는 중..그래도 끝까지 포기 안하렵니다..!!
    • 아니먼데
      잘됬는데 위에코드 복사해서 넣으니까 자꾸 이상한거나옴
      경고 : mysqli_fetch_assoc ()는 매개 변수 1 부울에 주어진, mysqli_result 될 것으로 예상 D : Bitnami \ wampstack-5.6.29-0 \ 아파치 \ htdocs에 \ index.php에 \ 라인 (36)
      이거뜨면서 자꾸 않나옴 전엔잘됬는데 2번쨰 index.php복붙했더니 이럼
      36번쨰라인
      $row = mysqli_fetch_assoc($result);이거임
    • 문돌이
      object(mysqli_result)#2 (5) { ["current_field"]=> int(0) ["field_count"]=> int(3) ["lengths"]=> NULL ["num_rows"]=> int(1) ["type"]=> int(0) } 주인님 환영합니다

      http://localhost......111

      주신 코드를 넣어보니 저한테는 나타나는 것을 보니, 제 생각에는 코드의 문제가 아니라 설정의 문제 같습니다.
      어렵네요..ㅠ
      대화보기
      • 호미타
        <?php
        $conn = mysqli_connect("localhost", "root", "문자로된비번");
        mysqli_select_db($conn, "opentutorials");
        $sql = "SELECT * FROM user WHERE name='".$_GET['name']."'AND password='".$_GET['password']."'";
        $result = mysqli_query($conn, $sql);
        var_dump($result);
        ?>
        입력한 코드입니다ㅜ echo로 sql문 작동 확인했을 때는 잘 작동했는데, 결과 값이 안나오네요ㅠㅠ

        http://localhost......111
        주소창에 넣은 입력 값이구요..
        object(mysqli_result)#2 (0) { } 뉘신지?
        이게 출력된 내용입니다;ㅁ;
        뭐가 문제인지 모르겠어서 헤매이고있습니다ㅠㅠ
        대화보기
        • 문돌이
          혹시 그 이전 코드랑 크롬 주소창에 적으신 데이터를 보여주실 수 있나요..?
          데이터가 입력되는 활동이 일어나지 않아서..그런 것 같기도 하구요..
          대화보기
          • 호미타
            질문자님은 아니지만 질문자님과 똑같은 문제로 고민중인데요, echo 출력 구문을 지워도
            var_dump의 값이
            object(mysqli_result)#2 (0) { } 뉘신지?
            이렇게만 뜹니다. 아무리 찾아봐도 모르겠네요ㅠㅠ
            대화보기
            • 노노재노재노창
              재밌는걸~
            • 문돌이
              echo sql; 이것 지워보시는 건 어떠신가요..?
              대화보기
              • 나홀로문도리
                좋은 강의 감사합니다~!
                잘 들었습니다!
              • 이성진
                수강 완료!
                좋은 강의 항상 감사 드립니다~
              • write.php에서 비밀번호 입력하는 부분이 원래 있어야 하나요?
              • 보안3 강의에서요.
                $sql = "SELECT * FROM user WHERE name ='".$_GET['name']."'AND password='".$_GET['password']."'";
                echo $sql;
                $result = mysqli_query($conn,$sql);
                var_dump($result);

                이렇게 php 코딩을 했는데 출력되는 $sql은 제대로 나오는데
                var_dump($result); 이 부분이 동영상과는 다르게
                object(mysqli_result)#2 (0) { } 이렇게만 떠요.. 왜그럴까요ㅜ
              • 열공인
                안녕하세요. 이제까지 잘 써왔는데요. 어제 컴퓨터 시작할 때 패스워드를 바꿨네요. 그것 때문인지 오늘 cmd에서 mysql들어 가려고 하니, the system cannot find the path 라고 나오네요. 그런데 실습 프로그램은 또 작동을 하는 것 같아요. cmd에서만 들어갈 수가 없는 상황?? 제가 잘 몰라서 상황이 어떤지도 솔직히 파악을 못하겠는데요. bitnami를 다시 설치해야 할까요? 감사합니다.
              • 김종엽
                2016.08.10 완료 !
              • 구녹수수
                근데 phpjs에서 8.php를 한게 아니고 8-1과 8-2로 나눠서 하지 않았나요??
                똑같이 8.php를 만들어서 해보니까
                undefined index : password라고 뜨는데
                이고잉님 처럼
                localhost/phpjs/8.php를 하면 저런 오류가 뜹니다.
                아무것도 넘기지 않았는데 뉘신지 가 안뜨고 오류가 뜨는데
                어떻게 해야하나요???
              • 차누
                수강완료
              • Wookiiis
                잘 보았습니다. :)
              • 김유성
                너무 재밌네요. 감사합니다.

                다른 분들을 위해 조금 남겨 해봅니다.

                url에 추가한 ' or '1'='1' 문을 ' or '1'로 해도 됩니다.
                '1'='1' 은 항상 true 인데, '1' 자체로도 항상 true 이니까요.
              • JustStudy
                고맙습니다 2.
              • 이주환
                2016. 4. 14.
                정독했습니다.
                보안의 중요성은 숙지할수밖에 없는 사항이죠.
              • JustStudy
                고맙습니다
              • 반가운 C 개발자네요.
                C언어는 절차지향적 성격이 강하지만,
                C언어를 더 깊이 파시다 보면 객체지향도 알게 될겁니다.
                (물론, 다중패러다임 언어인 C++이나 순수객체지향 언어인 Java를 배우신다면
                제대로 된 객체지향을 배우시겠지만요.)

                객체지향적 디자인은 프로그래밍에 있어 매우 중요하고 유용하기 때문에,
                C언어에서도 언어적으로 지원되진 않지만 라이브러리나 프레임워크를 통해
                "일부" 구현하는 모습을 종종 볼 수 있습니다(매크로의 힘은 무한합니다).

                예로, 윈도우즈 커널드라이버 프레임워크는 성능문제 때문에 C언어를 채택했지만
                (유저드라이버 프레임웤은 C++ API를 지원합니다.)
                객체지향적 API를 제공하지요.

                C언어는 그 역사만큼 굉장한 깊이가 있기 때문에
                꾸준히 공부하신다면 무한한 재미를 느끼실 수 있을겁니다.
                대화보기
                • 3번강의 수강하시는 분들이 약간 헷갈릴 수 있을 것 같아 덧붙이자면,
                  name='egoing' AND password='111111' OR '1'='1'

                  이부분 설명하실 때 앞에서는 비밀번호가 '111111'이 참이거나 '1'이 '1'이 참이면 참이라고 설명하시고
                  뒤에서는 OR 앞 전체와 뒤 전체 중에 하나가 참이면 참이라고 하셨습니다.

                  예제에서는 뒤에 설명하신게 맞고,
                  그 이유는 연산자들의 우선순위 때문입니다.
                  괄호가 없을 때, 기본적으로 각 연산자(==, >=, OR, AND 이런 것들)들 끼리 약속된 우선순위가 있는데요

                  수학에서도 곱하기가 더하기보다 먼저인것처럼
                  비교연산(부등호/등호) -> AND -> OR 순으로 우선순위가 높습니다.
                  그렇기 때문에 이름과 비밀번호가 AND로 먼저 묶이고,
                  이후에 뒤 식과 OR가 되게 됩니다.
                버전 관리
                egoing
                현재 버전
                선택 버전
                graphittie 자세히 보기