programing

PHP 사이트에서 xss 공격을 피하기 위한 최상의 방법은 무엇입니까?

jooyons 2023. 8. 13. 09:41
반응형

PHP 사이트에서 xss 공격을 피하기 위한 최상의 방법은 무엇입니까?

저는 마법 견적이 켜져 있고 등록 글로벌이 꺼지도록 PHP를 구성했습니다.

저는 사용자 입력에서 파생된 모든 출력에 대해 항상 html 엔티티()를 호출하기 위해 최선을 다합니다.

저는 또한 가끔 제 데이터베이스에서 첨부된 xss에 사용되는 일반적인 것들을 검색합니다. 예를 들어...

<script

제가 해야 할 일은 무엇이고 어떻게 하면 제가 하려고 하는 일이 항상 이루어지도록 할 수 있을까요?

입력을 피하는 것은 성공적인 XSS 예방을 위해 할 수 있는 최선의 방법이 아닙니다.출력도 이스케이프해야 합니다. 엔진을 사용하는 경우 Smarty 엔진을 할 수 .|escape:'htmlall'모든 민감한 문자를 HTML 엔티티로 변환하는 수식자(나는 자신의 문자를 사용함)|e위의 별칭인 수식어).

입출력 보안에 대한 나의 접근 방식은 다음과 같습니다.

  • 스토어 사용자 입력이 수정되지 않음(입력 시 HTML 이스케이프 없음, PDO 준비된 문을 통해 DB-aware 이스케이프만 수행됨)
  • 사용하는 출력 형식에 따라 출력 시 이스케이프(예: HTML 및 JSON에는 서로 다른 이스케이프 규칙이 필요함)

저는 입력 중에는 아무것도 탈출해서는 안 되며 출력에만 의존해야 한다고 생각합니다.(대부분의 경우) 데이터가 어디로 가는지 알고 있다고 가정할 수 없습니다.예를 들어, 나중에 보내는 전자 메일에 표시되는 데이터를 가져오는 양식이 있는 경우 다른 이스케이프가 필요합니다(그렇지 않으면 악의적인 사용자가 전자 메일 헤더를 다시 작성할 수 있음).

즉, 데이터가 애플리케이션을 "떠나는" 마지막 순간에만 탈출할 수 있습니다.

  • 리스트 항목
  • XML 파일에 쓰기, XML에 대한 이스케이프
  • DB에 쓰기, 이스케이프(특정 DBMS의 경우)
  • 전자 메일 쓰기, 전자 메일에 대한 이스케이프
  • 기타

짧게 말하자면:

  1. 데이터가 어디로 이동하는지 알 수
  2. 데이터는 실제로 둘 이상의 위치에 배치될 수 있으며, 둘 다가 아닌 다른 탈출 메커니즘이 필요합니다.
  3. 잘못된 대상을 위해 탈출한 데이터는 정말 좋지 않습니다. (예: "Tommy\'s bar"라는 제목의 이메일을 받습니다.)

입력 계층에서 데이터를 이스케이프하는 경우(또는 이스케이프를 다시 해제해야 하는 경우 등) Esp #3이 발생합니다.

PS: 저는 magic_quote를 사용하지 않는 것에 대한 조언을 지지합니다. 그것들은 순수한 악입니다!

XSS를 수행하는 방법은 여러 가지가 있습니다(http://ha.ckers.org/xss.html) 참조). 매우 어렵습니다.

사용 중인 현재 프레임워크(예: 코드 점화기)에 직접 위임합니다.완벽하지는 않지만, 제 손으로 만든 루틴보다 더 많은 것을 잡을 수도 있습니다.

이것은 훌륭한 질문입니다.

첫째, 데이터베이스에 저장하는 것과 같은 안전한 경우를 제외하고는 입력 시 텍스트를 이스케이프하지 마십시오.그 이유는 입력된 내용을 유지하여 상황에 따라 다른 방식과 장소에서 표시할 수 있기 때문입니다.여기서 변경하면 나중에 발표할 내용이 손상될 수 있습니다.

데이터를 표시하기 위해 가면 무엇이 있어서는 안 되는 것인지 필터링합니다.예를 들어, 자바스크립트가 존재할 이유가 없다면, 자바스크립트를 검색하고 제거합니다.그렇게 하는 쉬운 방법은 strip_tags 함수를 사용하고 허용하는 html 태그만 표시하는 것입니다.

다음으로, 당신이 가지고 있는 것을 가지고 html 엔티티 또는 html 특수 문자로 전달하여 거기에 있는 것을 아스키 문자로 변경합니다.상황과 얻고자 하는 내용을 기준으로 이 작업을 수행합니다.

또한, 저는 매직 쿼츠를 끄는 것을 제안합니다.PHP 6에서 제거되었으며 사용하는 것은 좋지 않은 관행으로 간주됩니다.자세한 내용은 http://us3.php.net/magic_quotes 에서 확인하십시오.

자세한 내용은 http://ha.ckers.org/xss.html 를 참조하십시오.

이는 완전한 답변은 아니지만 시작하는 데 도움이 될 수 있기를 바랍니다.

Rikh 쓰기:

저는 사용자 입력에서 파생된 모든 출력에 대해 항상 html 엔티티()를 호출하기 위해 최선을 다합니다.

이에 대한 도움은 코드를 잘못 보이게 하는 것에 대한 Joel의 에세이를 참조하십시오.

템플릿 라이브러리.또는 적어도 템플릿 라이브러리가 수행해야 하는 작업입니다.XSS를 방지하려면 모든 출력을 인코딩해야 합니다.이 작업은 주 애플리케이션/제어 로직의 작업이 아니며, 출력 방법으로만 처리해야 합니다.

코드 전체에 html 엔티티()를 뿌리면 전체 설계가 잘못됩니다.그리고 당신이 제안하는 것처럼, 당신은 한 두 자리를 놓칠 수도 있습니다.그렇기 때문에 출력 변수가 html/xml 스트림에 기록될 때 유일한 해결책은 엄격한 html 인코딩 ->입니다.

안타깝게도 대부분의 php 템플릿 라이브러리는 자체 템플릿 구문만 추가할 뿐 출력 인코딩, 현지화, HTML 유효성 검사 또는 중요한 것에는 관심이 없습니다.혹시 다른 사람이 php를 위한 적절한 템플릿 라이브러리를 알고 있는 것은 아닐까요?

저는 그것을 PHTAL에 의존합니다.

Smarty 및 일반 PHP와 달리 기본적으로 모든 출력을 이스케이프합니다.이것은 보안 측면에서 큰 승리입니다. 왜냐하면 당신이 잊어버린다면 당신의 사이트는 폭발할 수 없게 될 것이기 때문입니다.htmlspecialchars()또는|escape어딘가에.

XSS는 HTML 고유의 공격이므로 HTML 출력이 이를 방지하는 데 적합합니다.HTML을 허용하지 않지만 자체적인 위험이 있는 다른 매체에 데이터를 출력해야 할 수 있으므로 데이터베이스에서 데이터를 사전 필터링하지 마십시오.

대부분의 사이트에서는 모든 사용자 입력을 피하는 것으로 충분합니다. 세션 한또가 ID에 않도록 . 따라서 세션 ID가 URL에서 도용되지 않도록 합니다.Referer다른 사이트에 연결합니다.에는 링크가 없는지 하십시오.javascript:프로토콜 연결이 허용됩니다. 사용자가 링크를 클릭하면 바로 스크립트가 실행됩니다.

XSS 공격이 우려되는 경우 출력 문자열을 HTML로 인코딩하는 것이 해결책입니다.모든 출력 문자를 HTML 형식으로 인코딩해야 하는 경우 XSS 공격을 성공적으로 실행할 수 없습니다.

자세한 내용: 사용자 데이터 검사: 방법 및 위치

개인적으로, 저는 magic_quotes를 비활성화할 것입니다.PHP5+에서는 기본적으로 비활성화되어 있으며, 모든 것이 빠져나가지 않고 PHP6에서 제거되므로 아예 없는 것처럼 코딩하는 것이 좋습니다.

에 따라 를 들어에는 다음에 수행할 작업을 지정합니다. 예를 들어 이름과 같은 텍스트일 경우에는strip_tags(trim(stripslashes()));또는 범위를 확인하려면 정규식을 사용합니다.

값이 해당 합니다.in_array($userData, array(...))).

숫자를 확인하는 경우 is_numeric을 사용하여 정수를 적용하거나 특정 유형으로 캐스트하면 문자열을 전송하려는 사람이 방지됩니다.

만약 당신이 PHP 5.2+를 가지고 있다면, 필터()보고 이메일 주소를 포함한 다양한 데이터 유형을 필터링할 수 있는 확장자를 사용하는 것을 고려해보세요.문서화는 특별히 좋은 것은 아니지만 개선되고 있습니다.

HTML을 처리해야 한다면 PHP Input Filter 또는 HTML Refiner와 같은 것을 고려해야 합니다.또한 HTML 정화 장치는 HTML의 적합성을 검증합니다.입력 필터가 아직 개발 중인지 잘 모르겠습니다.둘 다 사용할 수 있는 태그 집합과 허용되는 속성을 정의할 수 있습니다.

무엇을 결정하든 항상 기억하세요. 사용자(자신 포함!)로부터 PHP 스크립트로 들어오는 어떤 것도 절대 신뢰하지 마십시오.

이 모든 답변은 훌륭하지만 근본적으로 XSS에 대한 해결책은 문자열 조작에 의한 HTML 문서 생성을 중단하는 것입니다.

입력을 필터링하는 것은 모든 응용 프로그램에 대해 항상 좋은 생각입니다.

htmlentity()와 친구를 사용하여 출력을 이스케이프하는 것은 제대로 사용되는 한 작동해야 하지만, 이것은 mysql_real_escape_string($var)과 문자열을 연결하여 SQL 쿼리를 생성하는 HTML과 같습니다. 즉, 매개 변수화된 쿼리를 사용하는 접근 방식에 비해 작동해야 하지만 작업을 검증할 수 있는 것은 더 적습니다.

장기적인 해결책은 애플리케이션이 DOM과 같은 표준 인터페이스를 사용하여 내부적으로 페이지를 구성한 다음 라이브러리(libxml과 같은)를 사용하여 XHTML/HTML/등에 대한 직렬화를 처리하는 것입니다.물론, 우리는 그것이 대중적이고 충분히 빠르기까지는 아직 멀었지만, 그 동안 우리는 문자열 작업을 통해 HTML 문서를 만들어야 하며, 그것은 본질적으로 더 위험합니다.

"매직 인용"은 설계상 잘못된 입력의 모든 것을 회피함으로써 작동하는 최악의 XSS 결함에 대한 완화책입니다.사용하고 싶은 유일한 경우는 XSS와 관련하여 부주의하게 작성된 것으로 알려진 기존 PHP 응용 프로그램을 사용해야 하는 경우입니다. (이 경우 "마법 인용문"으로도 심각한 문제에 직면하게 됩니다.)자체 응용프로그램을 개발할 때는 "매직 인용문"을 사용하지 않도록 설정하고 대신 XSS 안전 관행을 따라야 합니다.

XSS, 사이트 간 스크립팅 취약성은 응용 프로그램이 외부 소스의 문자열(사용자 입력, 다른 웹 사이트에서 가져온 문자열 등)을 [X]에 포함할 때 발생합니다.적절한 이스케이프 없이 HTML, CSS, ECMAscript 또는 기타 브라우저에서 구문 분석된 출력으로, (X]HTML에서)보다 작음, 단일 또는 이중 따옴표(ECMAscript)와 같은 특수 문자가 나타나지 않기를 바랍니다.이에 대한 적절한 해결책은 출력 언어의 규칙에 따라 항상 문자열을 이스케이프하는 것입니다: [X]의 엔티티 사용HTML, ECMA 스크립트의 백슬래시 등.

신뢰할 수 없는 것을 추적하는 것이 어려울 수 있고 탈출해야 하기 때문에 HTML과 같은 언어의 "마크업이 있는 텍스트"와는 반대로 "텍스트 문자열"인 모든 것을 항상 탈출하는 것이 좋습니다. 일부 프로그래밍 환경은 "스트링"(일반 텍스트),"HTML 문자열"(HTML 마크업) 등.그런 식으로, "string"에서 "HTML string"으로 직접적인 암시적 변환은 불가능할 것이고, 문자열이 HTML 마크업이 될 수 있는 유일한 방법은 이스케이프 함수를 통해 전달하는 것입니다.

"글로벌 등록"은 이를 비활성화하는 것이 분명 좋은 생각이지만 XSS와는 전혀 다른 문제를 다루고 있습니다.

이 기능을 사용하면 가능한 많은 xss 공격을 제거하는 데 도움이 됩니다.

<?php

function h($string, $esc_type = 'htmlall')
{
    switch ($esc_type) {
        case 'css':
            $string = str_replace(array('<', '>', '\\'), array('&lt;', '&gt;', '&#47;'), $string);
            // get rid of various versions of javascript
            $string = preg_replace(
                    '/j\s*[\\\]*\s*a\s*[\\\]*\s*v\s*[\\\]*\s*a\s*[\\\]*\s*s\s*[\\\]*\s*c\s*[\\\]*\s*r\s*[\\\]*\s*i\s*[\\\]*\s*p\s*[\\\]*\s*t\s*[\\\]*\s*:/i',
                    'blocked', $string);
            $string = preg_replace(
                    '/@\s*[\\\]*\s*i\s*[\\\]*\s*m\s*[\\\]*\s*p\s*[\\\]*\s*o\s*[\\\]*\s*r\s*[\\\]*\s*t/i',
                    'blocked', $string);
            $string = preg_replace(
                    '/e\s*[\\\]*\s*x\s*[\\\]*\s*p\s*[\\\]*\s*r\s*[\\\]*\s*e\s*[\\\]*\s*s\s*[\\\]*\s*s\s*[\\\]*\s*i\s*[\\\]*\s*o\s*[\\\]*\s*n\s*[\\\]*\s*/i',
                    'blocked', $string);
            $string = preg_replace('/b\s*[\\\]*\s*i\s*[\\\]*\s*n\s*[\\\]*\s*d\s*[\\\]*\s*i\s*[\\\]*\s*n\s*[\\\]*\s*g:/i', 'blocked', $string);
                return $string;

        case 'html':
            //return htmlspecialchars($string, ENT_NOQUOTES);
            return str_replace(array('<', '>'), array('&lt;' , '&gt;'), $string);

        case 'htmlall':
            return htmlentities($string, ENT_QUOTES);
        case 'url':
            return rawurlencode($string);
        case 'query':
            return urlencode($string);

        case 'quotes':
            // escape unescaped single quotes
            return preg_replace("%(?<!\\\\)'%", "\\'", $string);

        case 'hex':
            // escape every character into hex
            $s_return = '';
            for ($x=0; $x < strlen($string); $x++) {
                $s_return .= '%' . bin2hex($string[$x]);
            }
            return $s_return;

        case 'hexentity':
            $s_return = '';
            for ($x=0; $x < strlen($string); $x++) {
                $s_return .= '&#x' . bin2hex($string[$x]) . ';';
            }
            return $s_return;

        case 'decentity':
            $s_return = '';
            for ($x=0; $x < strlen($string); $x++) {
                $s_return .= '&#' . ord($string[$x]) . ';';
            }
            return $s_return;

        case 'javascript':
            // escape quotes and backslashes, newlines, etc.
            return strtr($string, array('\\'=>'\\\\',"'"=>"\\'",'"'=>'\\"',"\r"=>'\\r',"\n"=>'\\n','</'=>'<\/'));

        case 'mail':
            // safe way to display e-mail address on a web page
            return str_replace(array('@', '.'),array(' [AT] ', ' [DOT] '), $string);

        case 'nonstd':
            // escape non-standard chars, such as ms document quotes
            $_res = '';
            for($_i = 0, $_len = strlen($string); $_i < $_len; $_i++) {
                $_ord = ord($string{$_i});
                // non-standard char, escape it
                if($_ord >= 126){ 
                    $_res .= '&#' . $_ord . ';'; 
                } else {
                    $_res .= $string{$_i};
                }
            }
               return $_res;

        default:
            return $string;
    }
}
    
?>

원천

HttpOnly를 사용하는 세션 쿠키(또는 모든 쿠키)를 만듭니다.이 경우 대부분의 브라우저는 쿠키 값을 JavaScript에서 숨깁니다.사용자가 수동으로 쿠키를 복사할 수는 있지만 이렇게 하면 직접 스크립트 액세스를 방지할 수 있습니다.StackOverflow에서 베타를 실행하는 동안 이 문제가 발생했습니다.

이건 해결책이 아니라 벽에 있는 또 다른 벽돌일 뿐입니다.

  • 사용자 입력을 신뢰하지 않음
  • 모든 자유 텍스트 출력 이스케이프
  • magic_quotes를 사용하지 말고 DBMS 고유의 변형이 있는지 확인하거나 PDO를 사용합니다.
  • 세션을 하이잭킹할 수 있는 악성 스크립트를 방지하기 위해 가능한 경우 HTTP 전용 쿠키 사용을 고려합니다.

데이터베이스에 들어가는 모든 데이터의 유효성을 검사해야 합니다.또한 데이터베이스에서 나가는 모든 데이터의 유효성을 검사합니다.

mysql_real_escape_string은 SQL 주입을 방지하는 데 좋지만 XSS가 더 까다롭습니다.가능한 경우 preg_match, stip_tags 또는 htmlentity를 사용해야 합니다!

현재 PHP 애플리케이션에서 XSS를 방지하는 가장 좋은 방법은 HTML 청정기(http://htmlpurifier.org/) 입니다.한 가지 작은 단점은 라이브러리가 상당히 크고 APC와 같은 운영 코드 캐시와 함께 사용하는 것이 가장 좋다는 것입니다.신뢰할 수 없는 콘텐츠가 화면으로 출력되는 모든 위치에서 이 기능을 사용합니다.html 엔티티, html 특수 문자, filter_input, filter_var, strip_tags 등보다 훨씬 철저합니다.

기존 사용자 입력 검사 라이브러리를 사용하여 모든 사용자 입력을 치료합니다.여러분이 많은 노력을 기울이지 않는 한, 스스로 실행하는 것은 결코 효과가 없을 것입니다.

가장 좋은 방법은 코드를 바인딩할 수 있는 클래스를 사용하여 데이터를 수동으로 유출할 염려가 없도록 하는 것입니다.

오경보가 발생하지 않는 사이트에서는 철저한 sql injection/xss injection 방지를 구현하기 어렵습니다.CMS에서 최종 사용자가 사용하기를 원할 수 있습니다.<script>또는<object>다른 사이트의 항목에 연결합니다.

나는 모든 사용자들이 스크립트가 없는 파이어폭스를 설치하도록 권장합니다 ;-)

언급URL : https://stackoverflow.com/questions/71328/what-are-the-best-practices-for-avoiding-xss-attacks-in-a-php-site

반응형