4.10. 다시 보내질 수도 있는 HTML/URIs 를 필터링해라

Cross-site malicious content 를 예방해야 하는 한가지 특별한 경우는 한 사용자로부터 HTML 또는 XHTML 을 받아 이를 다른 사용자에게 전달하도록 설계된 웹 애플리케이션이다 (이에 대한 더욱 자세한 정보는 6.13절 을 보라). 다음 하부 절은 이러한 특정 종류의 입력을 필터링하는 것이 공통 요구사항이기 때문에 이에 대해 논의한다.

4.10.1. 몇몇 HTML 데이타를 제거 및 금지해라

모든 가능한 (X)HTML 태그가 어떤 것이라도 영향을 끼칠 수 없도록 이를 제거하는 것이 가장 안전한데 이의 제거는 비교적 쉽다. 위에서 언급했듯이 합법적인 문자 목록을 확인해서 목록에 없는 그러한 문자들을 거절 또는 제거해야 한다. 이 필터에서 합법적인 문자 목록에 있는 다음 문자는 다만 포함시키지 마라: ``<", ``>" 와 ``&" (속성에 사용된다면 이중 인용부호 ``quot;"). 브라우저가 HTML 스펙에 따라 작동한다면 ``>" 는 제거될 필요는 없지만 실제로는 제거되어야 한다. 이는 어떤 브라우저는 페이지 저자가 실제로 시작 ``<" 태그를 놓아 ``도움이 되도록" 하나를 끼워넣었다고 가정하기 때문으로 공격자는 이 동작을 악용하여 바람직하지 못한 ``<" 를 만들기 위해 ``>" 를 사용할 수 있다.

보통 HTML 전송에 사용되는 문자셋은 ISO-8859-1 (국제화 텍스트를 보낼 때에도) 이며 따라서 필터는 또한 대부분의 제어 문자 (개행과 탭은 무방하다) 및 고차 (high-order) 비트가 설정되어 있는 문자를 제거해야 한다.

이러한 접근방법의 문제점은 실제로 사용자를 놀라게 할 수 있다는 것으로 모든 국제화 텍스트가 말없이 제거된다면 이를 적은 사람은 당혹스러울 것이다. 무효한 문자가 경고없이 조용히 제거된다면 그 데이타는 돌이킬 수 없이 분실되어 추후 다시 얻을 수 없을 것이다. 한가지 대안은 그러한 문자를 금지하여 이 문자를 사용하려고 하는 사용자에게 에러 메세지를 되돌려 보내는 것이다. 이는 적어도 사용자에게 경고를 하지만 사용자들이 찾는 기능성을 주지는 않는다. 다른 대안은 이 데이타를 인코딩 또는 유효화하는 것이다.

4.10.2. HTML 데이타 인코딩

거의 안전한 대안은 결정적인 문자를 변환시켜 이들이 HTML 에서 통상적인 의미를 가질 수 없도록 하는 것이다. 이는 모든 "<", ">" 와 "&" 를 각각 "&lt;", "&gt;" 와 "&amp;" 로 변환시킴으로써 행해질 수 있다. 임의의 국제화 문자는 "&#value;" 포맷을 이용하여 Latin-1 으로 인코딩될 수 있다 - 마지막의 세미콜론을 잊지 마라. 국제화 문자를 인코딩한다는 것은 물론 입력 인코딩이 무엇인지를 알아야 함을 의미한다.

여기서 한가지 가능한 위험은 이러한 인코딩이 우연히 두번 해석된다면 공격당하기 쉬울 것이라는 것이다. 그러나 적어도 이 접근 방법은 추후 사용자에게 입력의 "의도" 를 볼 수 있도록 허용한다.

4.10.3. HTML 데이타 확인

어떤 애플리케이션이 여하튼 작동하기 위해서는 제 삼자로부터 HTML 을 받아들여 이를 사용자들에게 전송해야 한다. 주의 - 이 시점에서 위험한 곳을 걷고있다 ; 실제로 이를 행하길 원하는지를 확신해라. 임의의 곳에서 온 HTML 을 받아들인다는 아이디어는 이를 올바르게 이해하는 것이 무척 어렵기 때문에 상당한 보안 견습자들 사이에서도 의견이 분분하다.

그러나 애플리케이션이 HTML 을 받아들여야 하고 이럴만한 가치가 있다고 믿는다면 적어도 안전한 HTML 명령 목록을 확인하여 단지 이들만을 허용해라.

다음은 애플리케이션 (게스트북과 같은) 에 유용할 수 있는 최소한의 안전한 HTML 태그셋이다: <p> (paragraph), <b> (bold), <i> (italics), <em> (emphasis), <strong> (strong emphasis), <pre> (preformatted text), <br> (forced line break - 마침 태그가 필요하지 않음을 주목해라) 과 이들의 마침 태그들.

단지 적은 일련의 ``안전한" HTML 명령들만이 수용됨을 보증할 필요가 있을뿐 아니라 이들이 적절히 포개지고 닫힘을 보증할 필요가 있다. XML 에서는 이를 ``well-formed" 데이타라고 한다. 표준 HTML (<p> 앞에 제공되지 않은 내포된 </p> 를 지원하는 것은 무방할 것이다) 을 수용하려면 약간의 예외가 있을 수 있지만 완전히 일반적인 HTML 을 수용하려고 하는 것은 대부분의 애플리케이션에서 필요하지 않다. 실로 HTML 대신 XHTML 을 고수하려고 한다면 well-formedness 가 요구된다. 또한 HTML 태그는 대소문자 구분을 하지 않는데 태그는 대문자, 소문자 또는 이들의 조합일 수 있다. 그러나 XHTML 을 수용하려고 한다면 모든 태그를 소문자로 표현할 필요가 있다 (XML 은 대소문자를 구분하는데 XML 을 사용하는 XHTML 은 소문자로 태그를 표현해야 한다).

다음은 이를 위해 임의로 뽑은 약간의 팁이다. 제공된 텍스트가 메인 사이트로부터의 (변조를 예방하기 위해) 텍스트로 잘못 해석될 수 없도록 보통 무엇이 HTML 텍스트와 허용 태그셋을 둘러쌀지를 설계해야 한다. 속성 형태와 그 값을 검사하지 않는다면 모든 속성을 수용하지 마라; 사용자들에게 문제를 야기할 수 있는 자바스크립트와 같은 것을 지원하는 많은 속성들이 있다. 위 목록에서 저자가 어떠한 속성도 포함하지 않았음을 알아차렸을 것이다. 이는 가장 안전한 방침이다. 불안전한 태그가 사용되면 될 수 있는 한 경고 메세지를 주어야 하지만 실제로 쓸모있는 것이 아니라면 중대한 문자를 인코딩 (예, "<" 는 "&lt;" 로) 함으로써 사용자를 안전하게 보호함과 동시에 데이타 손실을 예방한다.

4.10.4. 하이퍼텍스트 링크 (URIs/URLs) 확인

주의깊은 독자라면 저자가 하이퍼텍스트 링크 태그 <a> 를 안전한 HTML 태그로 포함하지 않았음을 알아차렸을 것이다. 분명히 <'a href="safe URI"> (하이퍼텍스트 링크) 를 안전한 목록 (속성의 내용을 검사하지 않았다면 다른 모든 속성을 허용하지 않으며) 에 추가할 수 있을 것이다. 애플리케이션이 이를 필요로 한다면 그렇게 해라. 그러나 제삼자에게 링크 생성을 허용하는 것은 안전한 URI [1] 를 정의하는 것이 매우 힘든 것으로 알려져 있기 때문에 비교적 덜 안전하다. 많은 브라우저는 사용자에게 위험할 수 있는 모든 종류의 URI 를 받아들인다. 이 절은 다른 사용자에게 다시 건네줄 제삼자로부터의 URI 를 확인하는 방법을 HTML 내로 병합된 URI 를 포함해서 논의한다.

우선 다양한 스펙에 정의된 것과 같이 URI 구문을 간략히 살펴보자. URIs 는 절대적 또는 상대적일 수 있다. 절대적 URI 의 구문은 다음과 같다:

scheme://authority[path][?query][#fragment]

URI 는 "http" 와 같은 스킴 이름, "://" 문자, "www.dwheeler.com" 과 같은 authority, 디렉토리 또는 파일 이름과 같이 보이는 경로, 질의 앞의 물음표 및 단락 (fragment) 식별자 앞의 해시 ("#") 로 시작한다. 각괄호는 선택적인 부분을 둘러싼다 - 예로 많은 URIs 는 실제로 질의 또는 단락을 포함하지는 않는다. 몇몇 스킴은 데이타중 일부를 허용하지 않을 수 있으나 (예, 경로, 질의 또는 단락) 많은 스킴은 그 고유의 추가적인 요건을 갖는다. 많은 스킴은 authority 필드가 다음 구문을 사용하여 선택적인 사용자 이름, 패스워드 및 포트를 식별할 수 있게 한다:

 [username[:password]@]host[:portnumber]

"host" 는 이름 ("www.dwheeler.com") 또는 IPv4 숫자 주소 (127.0.0.1) 일 수 있다. 상대적 URI 는 현재 객체에 대해 한 객체를 참조하며 구문은 파일 이름과 같이 보인다:

path[?query][#fragment]

대부분의 URI 에서 허용된 문자는 제한된 수로 따라서 이 문제를 피하기 위해서는 다른 8-비트 문자를 %hh 와 같이 URL 인코드할 수도 있다 (hh 는 8비트 문자의 16진법 값이다). 유효한 URIs 에 대한 더욱 세부적인 정보는 IEFT RFC 2396 및 관련 스펙을 보라.

URIs 의 구문을 보았기 때문에 각 부분의 위험을 조사해보자:

물론 단순함과의 절충이 있다. 간단한 패턴이 이해하기 더욱 쉽지만 그다지 세련되지는 않다 (따라서 세련된 패턴에 비해 너무 허가적이거나 너무 제한적일 수 있다). 복잡한 패턴은 더욱 엄격할 수 있지만 더욱 많은 에러를 가질 것 같이 보이며 사용하기 위해 더 많은 성능을 필요로 하며 어떤 상황에 있어 구현하기 어렵다.

다음은 매우 간단하며 직접 손으로 또는 정규 표현식을 통해 구현될 수 있는 "간단하고 일반적으로 안전한 (simple mostly safe)" URI 패턴에 대한 저자의 제안이다; 다음 패턴을 허용해라:

(http|ftp|https)://[-A-Za-z0-9._/]+

이 패턴은 질의, 단락, 포트 또는 상대 URIs 와 같이 많은 잠재적으로 위험한 능력을 허용하지 않으며 단지 약간의 스킴만을 허용한다. 이는 URL 이스케이프 및 서버가 다룰 수 없을 수도 있는 문자를 지정하기 위해 사용될 수 있는 "%" 문자의 사용을 금지한다. 이는 ":" 또는 URL 이스케이프를 허용하지 않기 때문에 포트 넘버 지정을 허용하지 않으며 이를 이용해서 더욱 위험한 URI 로 리디렉션시키는 것은 어려울 것이다 (이스케이프 문자가 없기 때문에). 또한 많은 다른 문자의 사용을 예방한다: 많은 서툴리 설계된 웹 애플리케이션은 많은 예기치 못한 문자를 다룰 수 없을 것이다.

그럼에도 불구하고 "일반적으로 안전한 (mostly safe)" URI 는 하부 디렉토리 ("/" 를 통해) 와 상위 디렉토리로 올라가려는 시도 (".." 를 통해) 와 같은 많은 의심스러운 URIs 를 허용한다; 이러한 종류의 비합법적인 질의는 서버가 잡아야한다. 저자가 이러한 비합법적인 질의가 보안 약점인 경우를 모름에도 불구하고 이는 어떤 비합법적인 호스트 식별자 (예, "20.20") 를 허용한다. 어떤 웹 애플리케이션은 하부 디렉토리를 질의 데이타로 처리한다 (더 나쁘게는 명령 데이타로); 이는 모든 서투르게 설계된 웹 애플리케이션을 발견할 수는 때문에 일반적으로 예방하기 힘들다. 여러분이 모든 경로의 사용을 금지할 수도 있지만 이는 대부분의 인터넷 정보를 참조하는 것을 불가능하게 만들 것이다. 패턴은 지역적 서버 정보에 대한 참조 ("http:///", "http://localhost/" 와 "http://127.0.0.1" 과 같은 패턴을 통해) 및 내부 네트워크상의 서버에 접근하는 것을 허용한다; 4.11절 에 권고된바와 같이 resulting HTTP Get 요청을 동작에 대한 요청이 아닌 정보에 대한 요청으로만 정확히 해석하는 서버에 의존해야 할 것이다. 이 패턴은 질의 폼을 허용하지 않기 때문에 많은 경우에 있어 이는 충분해야 한다.

불행히도 "일반적으로 안전한" 패턴은 또한 많은 수의 규칙에 맞고 유용한 URIs 를 막는다. 예를 들어, 많은 웹사이트는 "?" 문자를 사용하여 특정 문서를 식별한다 (예, 뉴스 사이트상의 기사들). "#" 문자는 문서의 특정 절을 지정하는데 유용하며 상대 URIs 를 허용하는 것은 논의에서 다뤄질 것이다. 다양한 허용 문자와 URL 이스케이프는 "일반적으로 안전한" 패턴에 포함되어 있지 않다. 예를 들어 URL 이스케이프를 허용하지 않는다면 많은 비영어권 페이지를 접근하는 것은 어렵다. 정말로 그런 기능성을 필요로 한다면 사용자로 하여금 더욱 높은 위험에 노출되도록 하는 반면 더욱 많은 기능성을 주고 있음을 깨달으면서 덜 안전한 패턴을 사용할 수 있다.

질의를 허용하지만 적어도 사용되는 프로토콜과 포트를 제한하는 한 패턴은 다음과 같은데 필자는 이를 "간단하고 어느정도 안전한 패턴 (simple somewhat safe pattern)" 이라고 부를 것이다:

 (http|ftp|https)://[-A-Za-z0-9._]+(\/([A-Za-z0-9\-\_\.\!\~\*\'\(\)\%\?]+))*/?

이 패턴은 비합법적인 이스케이프, 다중 질의, ftp 에서의 질의 등을 허용하기 때문에 실제로 효과적이지는 않다. 이는 비교적 간단한 것을 이용한다.

실제로 URIs 를 합법적인 값으로 제한하는 "어느정도 안전한 (somewhat safe)" 패턴을 생성하는 것은 꽤 어렵다. 다음은 저자가 "복잡하지만 어느정도 안전한 패턴 (sophisticated somewhat safe pattern)" 이라도 부르는 패턴으로 공백은 무시되며 주석은 "#" 으로 시작된다:

 (
 (
  # Handle http, https, and relative URIs:
  ((https?://([A-Za-z0-9][A-Za-z0-9\-]*(\.[A-Za-z0-9][A-Za-z0-9\-]*)*\.?))|
    ([A-Za-z0-9\-\_\.\!\~\*\'\(\)]|(%[2-9A-Fa-f][0-9a-fA-F]))+)?
  ((/([A-Za-z0-9\-\_\.\!\~\*\'\(\)]|(%[2-9A-Fa-f][0-9a-fA-F]))+)*/?) # path
   (\?(                                                              # query:
       (([A-Za-z0-9\-\_\.\!\~\*\'\(\)\+]|(%[2-9A-Fa-f][0-9a-fA-F]))+=
        ([A-Za-z0-9\-\_\.\!\~\*\'\(\)\+]|(%[2-9A-Fa-f][0-9a-fA-F]))+
        (\&([A-Za-z0-9\-\_\.\!\~\*\'\(\)\+]|(%[2-9A-Fa-f][0-9a-fA-F]))+=
         ([A-Za-z0-9\-\_\.\!\~\*\'\(\)\+]|(%[2-9A-Fa-f][0-9a-fA-F]))+)*)
       |
       (([A-Za-z0-9\-\_\.\!\~\*\'\(\)\+]|(%[2-9A-Fa-f][0-9a-fA-F]))+  # isindex
       )
   ))?
   (\#([A-Za-z0-9\-\_\.\!\~\*\'\(\)\+]|(%[2-9A-Fa-f][0-9a-fA-F]))+)? # fragment
  )|
 # Handle ftp:
 (ftp://([A-Za-z0-9][A-Za-z0-9\-]*(\.[A-Za-z0-9][A-Za-z0-9\-]*)*\.?)
  ((/([A-Za-z0-9\-\_\.\!\~\*\'\(\)]|(%[2-9A-Fa-f][0-9a-fA-F]))+)*/?) # path
  (\#([A-Za-z0-9\-\_\.\!\~\*\'\(\)\+]|(%[2-9A-Fa-f][0-9a-fA-F]))+)? # fragment
  )
 )

위와 같은 복잡한 패턴도 모든 비합법적인 URIs 를 금지하지는 않는다. 예를 들어 다시 "20.20" 은 합법적인 도메인 이름이 아니지만 패턴은 이를 허용한다; 그러나 저자가 아는한 이는 어떠한 보안 문제도 야기하지 않는다. 복잡한 패턴은 제어문자를 나타내는 URL 이스케이프를 금지한다 (예, $1F 를 통해 %00) - 허용된 가장 작은 이스케이프 값은 %20 (아스키 스페이스) 이다. 제어 문자를 금지함으로써 어떤 문제를 예방하지만 또한 제한적이다; 모든 제어 문자를 임의의 웹 애플리케이션으로 전송하는 것을 지원하려면 "2-9" 를 "0-9" 로 변경해라. 이 패턴은 경로에 모든 다른 URL 이스케이프 값을 허용하는데 국제화 문자에 유용하지만 이를 다룰 수 없는 약간의 시스템에서 문제를 야기할 수 있다. 패턴은 적어도 공백, 개행, 이중인용부호 및 다른 위험한 문자가 URI 에 사용됨을 금지하며 따라서 URI 를 생성 문서에 병합할 때 다른 종류의 공격을 예방한다. 많은 곳에서 패턴이 "+" 를 허용함을 주목해라. 실제적으로 "+" 는 종종 질의와 단락에서 공백 문자 대신 사용된다.

불행히 위에서 언급했듯이 질의 데이타를 허용하는 모든 기법을 통해 작동할 수 있는 공격이 있는데 질의가 허용되어 있다면 이에 대해 실제적으로 훌륭한 방어는 없을 것 같다. 그래서 위 패턴에서 질의 데이타의 사용을 제거할 수 있지만 "복잡하고 일반적으로 안전한 (sophisticated mostly safe)" 패턴을 산출하는 다른 폼을 허용해야 한다.

 (
 (
  # Handle http, https, and relative URIs:
  ((https?://([A-Za-z0-9][A-Za-z0-9\-]*(\.[A-Za-z0-9][A-Za-z0-9\-]*)*\.?))|
    ([A-Za-z0-9\-\_\.\!\~\*\'\(\)]|(%[2-9A-Fa-f][0-9a-fA-F]))+)?
  ((/([A-Za-z0-9\-\_\.\!\~\*\'\(\)]|(%[2-9A-Fa-f][0-9a-fA-F]))+)*/?) # path
   (\#([A-Za-z0-9\-\_\.\!\~\*\'\(\)\+]|(%[2-9A-Fa-f][0-9a-fA-F]))+)? # fragment
  )|
 # Handle ftp:
 (ftp://([A-Za-z0-9][A-Za-z0-9\-]*(\.[A-Za-z0-9][A-Za-z0-9\-]*)*\.?)
  ((/([A-Za-z0-9\-\_\.\!\~\*\'\(\)]|(%[2-9A-Fa-f][0-9a-fA-F]))+)*/?) # path
  (\#([A-Za-z0-9\-\_\.\!\~\*\'\(\)\+]|(%[2-9A-Fa-f][0-9a-fA-F]))+)? # fragment
  )
 )

저자가 말할 수 있는 건 단지 이러한 패턴이 사용자에 의해 선택된 하이퍼텍스트 앵커 (<a> 태그) 를 검사하기 위해서만 사용된다면 이 접근 방법은 또한 웹 버그의 삽입을 예방한다. 웹 버그는 메인 페이지를 생성한 웹서버 이외의 누군가에게 누가 컨텐트를 읽었는지 및 언제 읽었는지와 같은 정보를 추적할 수 있도록 하는 단순한 텍스트이다 - 더욱 자세한 정보는 7.6절 을 보라. 이는 동일한 검사 규칙을 갖고서 <img> (이미지) 태그를 사용한다면 그렇지 않다 - 이미지 태그는 즉각적으로 로드되어 누군가에게 웹 버그를 추가할 수 있도록 한다. 다시 한번 말해서 이는 어떠한 속성도 허용하지 않았다고 추정한다; 많은 속성들은 꽤 위험하며 여러분이 제공하려고 하는 보안을 돌파할 수 있다

이러한 모든 패턴들은 전체 URI 가 패턴과 일치함을 요구함을 주목하기 바란다. 이러한 패턴들의 부적절함은 이들이 많은 유용한 패턴을 금지하는 방식으로 허용가능한 패턴을 제한한다는 것이다 (예, 이들은 새로운 URI 스킴의 사용을 방해한다). 또한 어떤 패턴도 어떤 웹사이트가 질의를 받았을 때 이 이상으로 수행하는 실제적인 문제를 예방할 수는 없다 - 그리고 이러한 웹사이트는 조직에 내부적이다. 그 결과로 GET 질의를 action 으로 받아들이는 웹사이트가 있어야만 URI 가 실제로 안전할 것이다 (4.11절을 보라). 합법적인 URLs/URIs 에 대한 더욱 자세한 정보는 IEFT RFC 2396 을 보라; 도메인 네임 구문은 IEFT RFC 1034 에서 더욱 심도있게 논의되고 있다.

4.10.5. 다른 HTML 태그

아마도 더욱 많은 HTML 태그의 지원을 고려할 수도 있다. 명백한 다음 선택은 <ol> (ordered list), <ul> (unordered list) 및 <li> (list item) 과 같은 리스트 지향 태그들이다. 그러나 어떤 시점 후에는 실제로 완전한 출판 관련 태그를 허용하고 있다 (이런 경우 제공자를 신뢰하거나 여기 논의될 것보다 더욱 엄격한 검사를 수행할 필요가 있다). 더욱더 중요하게 추가되는 모든 새로운 기능성은 에러에 대한 기회를 생성한다 (또한 악용될 수도 있다).

다른 예로는 동일한 URI 패턴을 갖고 <img> 태그를 허용할 수 있을 것이다. 이는 제삼자에게 문서를 누가 언제 읽었는지 식별할 수 있는 웹 버그를 문서에 끼워넣는 것을 허용하기 때문에 대체로 덜 안전하다고 알려져 있다. 웹 버그에 대해 더욱 자세한 정보는 7.6절 을 보라.

4.10.6. 관련 쟁점

웹 애플리케이션은 명시적으로 문자셋 (보통 ISO-8859-1) 을 지정해야 하며 신뢰되지 않은 사용자로부터의 데이타가 사용된다면 다른 문자를 허용하지 않아야 한다. 더욱 자세한 정보를 얻기 위해서는 8.5절 을 보라.

이러한 종류의 입력을 필터링하는 것이 잘못되는 것은 쉽기 때문에 다른 대안들도 또한 논의되어 왔다. 한가지 옵션은 사용자들에게 HTML 보다 더욱 간단한 여러분이 설계한 다른 언어를 사용할 것인지 묻는 것이다 - 그 언어에는 매우 제한된 기능성을 부여한다. 다른 접근 방법은 HTML 을 어떤 내부의 "안전한" 포맷으로 분석한 후 그 안전한 포맷을 다시 HTML 으로 전환하는 것이다

입력, 출력 또는 둘 모두에 대해 필터링을 행할 수 있다. CERT 는 데이타가 동적 페이지의 일부분이 되기 전인 출력 동안에 데이타를 필터링하도록 권고한다. 이는 올바르게 행해진다면 이러한 접근 방법이 모든 동적 컨텐트가 필터링됨을 보장하기 때문이다. CERT 는 동적 컨텐트가 HTTP 이외의 다른 방법을 통해 웹사이트의 데이타베이스에 들어갈 수 있기때문에 입력 시의 필터링은 그다지 효과적이지 않으며 이런 경우에 있어 웹 서버는 입력 프로세스의 일부분으로의 데이타를 전혀 볼 수 없을 것이라고 믿고 있다. 동적 페이지가 들어가는 모든 곳에서 필터링이 구현되지 않는다면 데이타 요소는 손상된 채로 남아있을 수도 있다.

그러나 저자는 모든 경우에 대해 이점에 대해 CERT 에 동의하지 않는다. 문제는 입력만큼 모든 출력을 필터링하는 것을 잊는 것은 쉬우며 손상된 입력을 시스템으로 넣는 것을 허용하는 것은 어쨋든 일어나길 기다리는 재앙이라는 것이다. 보안적인 프로그램은 그 입력을 어쨋든 필터링해야하며 따라서 입력 필터링의 일부분으로 모든 이러한 검사를 포함하는 것이 때때로 더욱 좋다 (그래서 관리자는 규칙이 실제로 무엇임을 볼 수 있을 것이다). 마지막으로 어떤 보안적인 프로그램에서 값을 출력할 수 있는 많은 다른 프로그램 위치가 있지만 데이타가 입력으로 들어갈 수 있는 방식과 위치는 몇가지 만이 있다는 것이다.; 이러한 경우에 있어서 입력 필터링을 하는 것이 더욱 좋은 견해일 것이다.

주석

[1]

기술적으로 하이퍼텍스트 링크는 모든 "uniform resource identifier" (URI) 일 수 있다. "Uniform Resource Locator" (URL) 은 이름 또는 자원의 어떤 다른 속성에 의해 자원을 식별한다기 보다는 URI 의 기본 접근 메카니즘 (예, 네트워크 "location") 의 표현을 통해 자원을 식별하는 URIs 의 부분 집합을 참조한다. 많은 사람들은 URLs 이 가장 널리 사용되고 있는 URI 의 유형이기 때문에 "URL" 을 "URI" 와 동의어로서 사용하고 있다. 예를 들어 URIs 에서 사용된 인코딩은 실제로 "URL 인코딩" 이라고 부른다.