Tech/web

XSS Mitigation

XSS...?

사이트 간 스크립팅(또는 크로스 사이트 스크립팅, 영문 명칭 cross-site scripting, 영문 약어 XSS)은 웹 애플리케이션에서 많이 나타나는 취약점의 하나로 웹사이트 관리자가 아닌 이가 웹 페이지에 악성 스크립트를 삽입할 수 있는 취약점이다.

Environment

일반적인 사이트에서 공격을 시도하면 안 되기 때문에 간단하게 취약한 게시판을 구현한 후 이를 통해 진행한다.

취약한 게시판은 다음과 같이 스크립트를 포함한 글을 등록한 후

해당 게시판을 확인하면 다음과 같이 스크립트가 작동하도록 구축하였다.

XSS Mitigation

XSS 공격에 대한 보호기법은 CSP, X-XSS-Protection 등 다양한 보호 기법이 존재하지만 PHP를 통해 직접 적용시킨 후 어떠한 변화가 나타나는지 확인하기 위해 다음 두 가지를 적용한다.

Escape

사용자가 입력한 값 중 '<', '>' 와 같은 특수문자가 HTML 태그로 인식하는 것이 아닌 단순한 문자로 인식하기 위해 HTML Entity로 변환하여 스크립트가 작동되지 않도록 적용한다.

htmlentities

htmlentities ( string $string , int $flags = ENT_COMPAT , string|null $encoding = null ,
 bool $double_encode = true ) : string
  • htmlentities 함수는 모든 문자를 HTML entities 로 변환한다.
  • 인자
    • string : 변환할 문자열
    • flags : 따옴표나 변환할 문서 유형을 설정한다. (기본적으로 ENT_COMPAT | ENT_HTML401 설정되어 있다)
      • ENT_COMPAT : 큰 따옴표만 변환한다.
      • ENT_QUOTES : 큰, 작은 따옴표 둘 다 변환한다.
      • ENT_NOQUOTES : 큰, 작은 따옴표 둘 다 변환하지 않는다.
    • encoding : 문자열 변환 시 사용할 인코딩 유형을 설정할 수 있다. (기본적으로 UTF-8로 설정되어 있다)
    • double_encode : false로 설정 시 문자열을 html entity로 변환하지 않는다.
  • 코드 적용
echo htmlentities($row['title']);
echo htmlentities($row['contents']);

적용 시 다음 그림과 같이 스크립트가 페이지에 삽입되는 것이 아니라 단순한 문자로 보이는 것을 확인할 수 있다.

htmlspecialchars

htmlspecialchars ( string $string , int $flags = ENT_COMPAT , 
string|null $encoding = null , bool $double_encode = true ) : string
  • htmlspecialchars 함수는 다음과 같이 특정 문자를 HTML entities 로 변환한다.
    • &(ampersand) → &
    • "(double quote) → "
    • '(single quote) → ' (for ENT_HTML401)
    • <(less than) → <
    • (greater than) → >
  • 인자
    • htmlentities와 동일하다.
  • 적용
echo htmlspecialchars($row['title']);
echo htmlspecialchars($row['contents']);

적용 시 htmlentities 함수와 같은 모습이 보여지는 것을 확인할 수 있다.

strip_tags

strip_tags ( string $string , array|string|null $allowed_tags = null ) : string
  • strip_tags 함수는 문자열에 포함된 HTML, PHP 태그를 제거한다.
  • 인자
    • string : 태그를 제거할 문자열
    • allowed_tags : 제거하지 않을 태그
  • 적용
echo strip_tags($row['title']);
echo strip_tags($row['contents']);

적용 시 다음과 같이 'script' 태그만 제거되어 alert`xss` 만 남아있는 것을 확인할 수 있다.

Filtering

사용자가 입력한 값 중 'script', 'alert()', 'onerror=' 와 같이 악의적인 행동을 위해 사용하는 태그, 함수, 이벤트 등을 필터링하여 입력할 수 없도록 적용한다.

str_replace

str_replace ( array|string $search , array|string $replace , 
string|array $subject , int &$count = null ) : string|array
  • str_replace 함수는 검색하려는 문자열 모두를 특정 문자열로 교체한다.
  • 인자
    • search : 변경할 대상인 값
    • replace : 검색된 값을 변경할 값
    • subject : 대상 문자열
    • count : 매칭된 대상을 변경하지 않고 넘어갈 횟수

preg_replace

preg_replace ( string|array $pattern , string|array $replacement , 
string|array $subject , int $limit = -1 , int &$count = null ) : string|array|null
  • preg_replace 함수는 정규표현식을 사용하여 문자를 찾아 변경한다.
  • 인자
    • pattern : 문자 탐색을 위한 정규표현식
    • replacement : 검색된 값을 변경할 값
    • subject : 대상 문자열
    • limit : 패턴에 매칭 할 최대 수. 기본적으로 -1(제한 없음)으로 설정되어 있다.
    • count : 매칭된 대상을 변경하지 않고 넘어갈 횟수
  • 적용
$contents = str_replace("<\script>", "_", $contents); //<\script> \ 제외
$contents = preg_replace("/onerror\s*=/i", "_", $contents);

적용 후 다음과 같이 대/소문자 둘 다 포함한 글을 적는다면

다음과 같이 str_replace 함수는 대/소문자를 다르게 적용되기 때문에 'SCRIPT'는 필터링되지 않지만 preg_replace 함수는 대/소문자 모두 필터링되는 것을 확인할 수 있다.

Reference

'Tech > web' 카테고리의 다른 글

WSL2에서 Burp Suite의 Proxy 기능 사용  (0) 2021.04.08