그누보드에서 소홀히 하고 있는 아주 중요한 허점 - PHP 끝 태그 '?>'의 남용 > 그누보드5 팁자료실

그누보드5 팁자료실

그누보드에서 소홀히 하고 있는 아주 중요한 허점 - PHP 끝 태그 '?>'의 남용 정보

그누보드에서 소홀히 하고 있는 아주 중요한 허점 - PHP 끝 태그 '?>'의 남용

첨부파일

2020-11-24_15-07-21.png (46.0K) 2회 다운로드 2020-11-24 15:27:33
2020-11-24_15-11-46.png (53.6K) 0회 다운로드 2020-11-24 15:27:33
2020-11-24_15-13-56.png (56.0K) 0회 다운로드 2020-11-24 15:27:33
sample.zip (32.8K) 17회 다운로드 2020-11-24 15:27:33

본문

그누보드의 지속적인 발전을 기대하는 php전문가입니다.
이미 세계적으로 유명한 Acunetix 소프트웨어를 이용해 그누보드의 취약성 등급을 추정한바 있습니다.
[https://sir.kr/g5_tip/14784] 여길 잠간 봐주시면 저의 노력 아시게 됩니다.

이 시간에는
그누보드소스에서 공통적이면서도 무시되고 있는 중요한 허점에 대하여 논하려고 합니다.
php코드는 당연히 <?php로 시작해서 ?>로 끝내야 합니다.
그러나 php업체의 공개문서에 따르면 오직 php코드만 있는 코드파일에서는 끝 태그인 '?>'을 사용하지 않는것이 매우 중요함을 알수 있습니다.
아래에 해당 부분 발췌하였습니다.
If a file contains only PHP code, it is preferable to omit the PHP closing tagat the end of the file. This prevents accidental whitespace or new linesbeing added after the PHP closing tag, which may cause unwanted effectsbecause PHP will start output buffering when there is no intention fromthe programmer to send any output at that point in the script.
간단히 역하면, php코드만 있는 파일에서 끝 태그 ?> 다음에 공백문자나 빈 행바꾸기 등이 삽입되어 있는 경우 최종 코드 실행후 출력 값이 프로그래머가 원하는 값이 아니될수 있다는것입니다.
그럼 간단한 예로 이 부분 이해해보기로 하겠습니다.
3개 파일 준비하겠습니다. 첨부파일로 전체 코드 올렸습니다.

common.php
<?php
function checkPassword($val) {
    /*
    * 디비 조회하여 비번 비교 한 결과를 부울린 타입으로 리턴한다고 가정!!!
    * 현재는 true로 매번 리턴!!!
    */
    return true; // 또는 false
}
/*
 * 주의!!!
 * ?> 기호 다음에 빈 행 2개 추가 되었음!!!
 */
?>




test.php
<?php
require_once 'common.php';

$password = $_POST['password'];

$result = checkPassword($password); // 현재는 checkPassword()함수가 true만을 리턴하므로 '성공' 출력!

if($result) {
    echo '성공';
} else {
    echo '실패';
}

/*
 * 주의!!!
 * ?> 기호 다음에 탭 문자열 삽입 되었음!!!
 */
?> 

index.html파일을 작성합니다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <script type="text/javascript" src="jquery-3.2.1.min.js"></script>

    <script>
        function getData() {
            $.ajax({
                url: "test.php",
                type: "POST",
                data: {password: '123'},
                success: function (result) {
                    console.log(result);
                    if(result == '성공') {
                        alert('비번 통과 성공!');
                    } else {
                        alert('비번 통과 실패!'); // 왜 test.php에서는 '성공'문자열을 리턴해주는데 여기에 걸릴가??????????????????????
                    }
                }
            });
        }

        $(document).ready(function() {
            getData(); // test.php에 요청
        });
    </script>
</head>
<body>

</body>
</html>

이제 웹 브라우저에서 http://localhost/sample/index.html 링크 테스트합니다.
당연히 '성공' 값이 리턴되어 '비번 통과 성공!' 메시지 뜰것이라 믿는 분 계실겁니다.
그런데 실제 보면 test.php가 출력한 값은 빈 행 3개와 뒤끝에 탭이 하나 더 추가된 문자열 즉


'성공'
로, 우리가 원하는 결과값의 앞과 뒤에 빈 행과 탭이 추가되었습니다.
꼭 ajax로 요청보내서 리턴값을 확인해보세요.

예를 통해 보는것 처럼, php 끝 태그 ?> 다음에 눈에는 보이지 않는 공백, 행바꾸기, 탭 등이 있다면 최종 출력값에 이 공백, 행바꾸기 같은것들이 함께 삽입되어 리턴됩니다.
위의 예에서 '성공' 문자열이 리턴 되었지만 사실상 그 앞에 빈 행이 추가되었기 때문에 if(result == '성공') 결과값 비교가 실패하여 alert('비번 통과 실패!');가 작동하게 됩니다.

이렇게 우리는 ?> 태그 다음에 삽입된 공백이나 행바꾸기, 탭 등이 얼마나 큰 허점을 발생시키는지 알게 되었습니다.

php개발과정에 이 문제를 소홀히 하시면 도무지 알수 없는 결과에 당황해져 그 디버깅에 아까운 시간 소모하시게 됩니다.
저도 이런 문제 한번 당했는데, 호상 연동하는 파일들이 너무 많으니 어디서 문제가 발생하고 있는지 몰라서, 끝내 찾아내지 못하구, 결과값을 리턴하기 전에 ob_end_clean()함수를 써서 모면했더랬는데... 바로 이 문제였거든요, 그래서 차후로는 절대 php 끝 기호 ?> 을 망탕 쓰지 않습니다.
php는 php코드로만 작성된 파일에서 끝 기호 ?> 가 없으면 자동적으로 코드마감을 인지하여 처리함으로써 개발자들이 위의 문제에 집중하지 않도록 해줍니다.

그누보드가 바로 이 허점 소홀히 하는거 같아요.
1000개 이상이나 되는 php파일들이 모두 ?> 기호를 사용하였고, ?> 기호 다음에 빈 행이 들어간것도 많고요...
ajax기능도 사용했는데 위의 예처럼 된 부분 있으면 정말 안타까운 문제를 당하고 맙니다.
때문에 그누보드의 모든 php코드파일들 전부 이 문제 고려해서 시급히 수정할것을 정중히 제의드리는 바입니다.

/theme/basic/head.php 파일처럼 php코드와 html, 자바스크립트가 엉킨 코드파일은 이 문제 제기되지 않으니 염려마시고요, 오직 php코드만으로 작성된 코드파일들은 php 끝 기호 ?> 를 제거함이 깨끗한 코드품질을 담보하는것이라 얘기마치게 됩니다.
그리고 그누보드 아름답게 확장하시는 모든 개발자분들도 위의 규칙 고려하여 배포해주세요.

마지막까지 보아주신 여러분께 감사드립니다.
추천
19

댓글 19개

글잘봤습니다 다만 제가 이걸 읽고 의문이 드는것은 ?>가 그렇게 큰 허점인가? 입니다
보시면 ajax에서 echo로 처리하여 비교 결과값에 공백또는 탭값이 추가되어 비교결과값이 일치하게 되지않는 다는 점밖에 보이지않는데요

이경우에 php에서 echo말고 die로만 처리해도 해결될 문제라고 생각되어지네요
물론 ?>뒤에 값(공백이든 탭이든)이 오는건 문제가 된다고 생각되어지네요 그래서 ?>제거가 오는 이점은 분명 있다고 생각되어집니다
php특성을 또 무시할 수 없을것같네요 여기저기 사이사이에 끼일수있는 언어다보니 php를 다루는사람들은 거의 반사적으로 ?>를 쓰는것같습니다 ㅎㅎㅎ
아니면 오류나니깐요 ㅠㅠ
그래서 head.php같은 파일까지 ?>를 제거하기보다는 지금 문제되는것이 ajax에서 결과값이 상이해지는 것때문인데 ajax파일에서만 ?>를 제거하는것도 나쁘지 않다고 생각됩니다

물론 개인적인 의견입니다 하하.. 작성자분 덕분에 여러생각들을 하게 되네요
재밌네요 감사합니다
저런문제때문에 PHP 코딩표준규칙인 PSR-12에서 PHP파일만있을때는 종료태그 삭제하라고 한거죠

그누는 PHP 코딩표준도 안지키는..

PHP 프레임워크들은 다지켜요
좋은 댓글 감사합니다.
그누보드 소스의 전반적인 문제인지라 여기에 게시함을 양해바랍니다.
먼저 Policia님이 얘기하신 echo 말고 die로만 처리해도 된다고 하신데 대해 답을 드린다면...
인클루드 되어진 라이브러리 코드파일에 빈 행이 있다면 그것을 불러들인데서 die로 결과값 출력해도 빈행은 그대로 삽입되어집니다.
첨부파일 샘플코드에서 test.php코드에서 echo '성공' 대신 die('성공')으로 해도 아마 결과 같은거예요.
그리고 그렇게 큰 문제인가 하는것인데...
이런 점 놓치구 그냥 코딩하시면 결과파싱할 때 발생하는 오류 해석이 자연 힘들어집니다.
가령 파일을 다운로드하는 코드에 이 문제 섞여 있으문 어카지요? 다운로드 할 파일내용앞에 빈행이 붙어 깨진 파일로 로컬에 다운로드 될것입니다.
결과값을 JSON타입으로 리턴해주는 코드라고 할때 거기에 빈 행, 탭이 끼우면, 말단에서 JSON파싱할때 오류 산출 될겁니다.
그누보드에 잠재하고 있는 실제 이 문제를 찾아내어 연재글 올리려고 합니다. 다음번 연재에서는 이 문제 해소하는 프로그램을 함께 올리려고 합니다.
그누보드의 전반적인 품질상향 문제라 주제분류에 맞지 않는 게시글 다시금 양해구합니다.
$_SERVER['HTTP_X_REQUESTED_WITH'] ajax가 아닌지 맞는지 판별해서 아닐땐 die 시키는것도 해야되지 않나요? 그거랑 또 csrf 방지 하는거랑.. 저는 독학으로 이렇게 처리하면된다고 배웠는데 이거 외에 다른 방법도 써야되는지 궁금합니다.
감사합니다. 관심주셔서..
개발자님이 꼭 ajax에 대해서만 작동하게 하시려면...
function isAjax()
    {
        if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && ($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest')) {
            // this is ajax request, do something
            return true;
        }
        return false;
    }
와 같이 만들어 사용하시면 된다고 보아집니다.
그리구, CSRF방지문제는 별개의 문제로, 수많은 공격패턴들을 안전하게 처리할수 있는 필터를 만들고 디비에 저장하거나 또는 말단에 리턴해줄 때 이 필터를 통과시켜 주면 됩니다.
공격패턴들이 대체 특수기호를 많이 활용하기때문,, 저는 아래와 같은 필터를 사용하군 합니다.
function escape($val)
    {
        $search = array("\\", "\0", "\x1a", "\x8");
        $replace= array("\\\\", "\\0", "\\Z", "\\b");
        return str_replace($search, $replace, $val);
    }
function safeEncode($val)
    {
return escape(htmlspecialchars($input, ENT_QUOTES, 'UTF-8'));
    }
safeEncode($input);//

감사합니다...
php 코드로 끝나는 파일은 마지막에 ?>는 생략하는게 좋지요.

라이브러리 같은경우 header 보다 먼저 공백이 출력되는 부분도 있고,

php 코딩 스타일 가이드에서도 PHP 파일은 마지막에 ?>를 쓰지 않는걸 권장합니다.
저도 PHP만 있는 경우 ?>은 생략합니다.
뭐, 저는 phpcs 쓰고 있어서 알아서 잡아주긴 하지만요.

XSS 필터


public function setXSS($data)
    {
        $data = str_replace(array('&amp;','&lt;','&gt;'), array('&amp;amp;','&amp;lt;','&amp;gt;'), $data);
        $data = preg_replace('/(&#*\w+)[\x00-\x20]+;/u', '$1;', $data);
        $data = preg_replace('/(&#x*[0-9A-F]+);*/iu', '$1;', $data);
        $data = html_entity_decode($data, ENT_COMPAT, 'UTF-8');
        $data = preg_replace('#(<[^>]+?[\x00-\x20"\'])(?:on|xmlns)[^>]*+>#iu', '$1>', $data);
        $data = preg_replace('#([a-z]*)[\x00-\x20]*=[\x00-\x20]*([`\'"]*)[\x00-\x20]*j[\x00-\x20]*a[\x00-\x20]*v[\x00-\x20]*a[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2nojavascript...', $data);
        $data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*v[\x00-\x20]*b[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2novbscript...', $data);
        $data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*-moz-binding[\x00-\x20]*:#u', '$1=$2nomozbinding...', $data);
        $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?expression[\x00-\x20]*\([^>]*+>#i', '$1>', $data);
        $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?behaviour[\x00-\x20]*\([^>]*+>#i', '$1>', $data);
        $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:*[^>]*+>#iu', '$1>', $data);
        $data = preg_replace('#</*\w+:\w[^>]*+>#i', '', $data);

        do {
            $Temporary = $data;
            $data = preg_replace('#</*(?:applet|b(?:ase|gsound|link)|embed|frame(?:set)?|i(?:frame|layer)|l(?:ayer|ink)|meta|object|s(?:cript|tyle)|title|xml)[^>]*+>#i', '', $data);
        } while ($Temporary !== $data);

        return trim($data);
    }
PHP 8.0에서도 여전해요 젠드엔진이 그모양이라..
오죽하면 PHP 코딩스탠다드인 PSR-12에 까지 이 항목이 들어갔을까요 ㅠ

PSR 한국어 번역본
https://psr.kkame.net/accepted/psr-12-extended-coding-style-guide#2-2-files
php 엔진 자체에세 해결해 주면 좋을텐데
닫음 태그가 없을땐 왠지 초조함과 불안감이 같이 오더라구요 ^^;;; 
어색하기도 하구

글 잘 읽었습니다  :  )
전체 2,412 |RSS
그누보드5 팁자료실 내용 검색

회원로그인

(주)에스아이알소프트 / 대표:홍석명 / (06211) 서울특별시 강남구 역삼동 707-34 한신인터밸리24 서관 1404호 / E-Mail: admin@sir.kr
사업자등록번호: 217-81-36347 / 통신판매업신고번호:2014-서울강남-02098호 / 개인정보보호책임자:김민섭(minsup@sir.kr)
© SIRSOFT