2009-04-09 11 views
1

저는 포럼이나 블로그 같은 웹 소프트웨어를 작성하는 데 항상 관심이있었습니다. HTML로 다시 작성하기 위해 제한된 마크 업을 사용하는 것입니다. 하지만 최근에는 PHP에 대해 "PHP BBCode 파서 -PEAR"로 인터넷 검색을 시도해 보았습니다. 비효율적 인 혼란을 겪었거나 XSS 구멍이있는 코드가 여기 저기에 나옵니다.정규 표현식과 XSS의 "전쟁"

가난한 BBCode 파서의 앞에서 언급 한 예를 사용하면 어떻게 XSS를 피할 수 있습니까? 이제 링크 처리에 대한 일반적인 정규 표현식을 사용하고, 그것이 얼마나 취약하고 어떻게 피할 수 있는지 언급 할 수 있습니다.

// Assume input has already been encoded by htmlspecialchars with ENT_QUOTES 
$text = preg_replace('#\[url\](.*?)\[/url\]#i','<a href="\1">\1</a>', $text); 
$text = preg_replace('#\[url=(.*?)\](.*?)\[/url\]#i','<a href="\1">\2</a>', $text); 

처리 이미지 태그는 이것보다 안전하지 않습니다.

그래서 몇 가지 구체적인 질문이 있습니다. 대부분 PHP 구현에만 해당됩니다.

  1. 이 예에서는 uri/url 유효성 검증 식을 사용하여 일치시키는 것이 더 좋습니까? 또는 (.*?) 및 콜백을 사용하는 것이 더 좋으며 입력이 유효한 링크인지 여부를 확인 하시겠습니까? 위에서 분명히 알 수 있듯이 javascript:alert('XSS!')은 위의 URL 태그에서 작동하지만 uri 일치가 완료되면 실패합니다.
  2. 콜백 내에서 urlencode()과 같은 기능은 무엇입니까 (URI 표준이 적용되는 한) 어떤 억지력이나 문제점입니까?
  3. 풀 스택 파서를 작성하는 것이 더 안전할까요? 또는 페이지 당 여러 항목을 처리하는 데 너무 많은 것을 개발하고 사용하는 데 필요한 시간과 처리 능력이 있습니까?

필자의 예는 많은 것 중 하나이며, 어떤 것보다 구체적입니다. 그러나, 자신의 제공을 회피하지 마십시오. 그래서 저는 텍스트 파싱 상황에서 XSS 보호를위한 원칙과 모범 사례 및 일반적인 권장 사항을 찾고 있습니다.

답변

4

테스트 밖으로 몇 가지 경우 중 하나 비효율적 인 혼란을 얻을, 또는 XSS 구멍

지옥 그래와 가난한 코드를 얻을. 아직 XSS에 취약하지 않은 bbcode 구현을 만났습니다.

'<a href="\1">\1</a>' 

좋은 번호 :., '<'탈출을 HTML로 '&'와 ' "'문자를 실패

가 더 잘 연습이 예에서는, 단지 URI를 사용하여 일치/(. *?) 및 콜백을 사용하여 올바른 입력인지 여부를 확인하는 것이 좋습니다.

콜백이 필요합니다. 어쨌든 콜백이 필요합니다. HTML 이스케이프 처리, pos가 아닙니다. 간단한 문자열 교체만으로 보안을 유지할 수 있습니다. 네가하는 동안 sanitisation을 버려라.

무엇 콜백 내를 urlencode 같은 함수()에 대한

거의; 실제로 htmlspecialchars()가 필요합니다. urlencode()는 쿼리 매개 변수를 인코딩하는 것에 관한 것으로 여기서는 필요하지 않습니다.

전체 스택 구문 분석기를 작성하는 것이 더 안전할까요?

예.

bbcode는 재귀 태그 기반 언어 (정규식도 구문 분석 할 수없는 XML과 같은)이기 때문에 정규식 파싱에 실제로 적합하지 않습니다. 많은 bbcode 구멍은 중첩 및 잘못 된 문제로 인해 발생합니다. 예를 들어 :

[url]http://www.example.com/[i][/url]foo[/i] 

다양한 BBCode의 구현에 (AN 포함 XSS 구멍까지) 깨진 코드를 생성하는 다른 많은 함정이있다

<a href="http://www.example.com/&lt;i>">foo</i> 

같은으로 나올 수 없습니다.

당신이 정규식 수있는 BBCode는 같은 언어가 필요하면 내가 원칙과 모범 사례

을 찾고 있어요

, 당신은 필요 :

  • 가능한 태그의 수를 감소 다른 태그 안에 넣을 수 있습니다. 임의의 중첩을 실제로 지원할 수는 없습니다.
  • HTML 태그 구분 기호 '<'및 '>'에 특수 문자를 사용하여 텍스트에 실제 꺽쇠 괄호를 구분할 수 있습니다. 나는 ASCII 제어 코드를 사용한다. (이전에 사용자 입력 단계에서 제어 문자를 필터링했다.)
  • 이 두 제어 문자 사이의 내용에 대해 이러한 제어 문자로 처리되는 문자열을 분할하여 태그 안이나 태그 경계 위로 bbcode 범위를 도달하게하지 마십시오.
  • 태그 테두리를 통해 도달하는 bbcode 범위가 외부에서 작동하지 않기 때문에 큰 블록 요소를 먼저 수행하고 내부적으로 링크로 작업하고 마지막으로 굵게 기울임 꼴로 작업 할 수 있기 때문입니다.
  • 을 입력하십시오. 한 번에 한 블록 씩 처리하십시오. 예. 이중 새 라인에 새로운 < p>를 시작하는 경우 bbcode 태그가 두 개의 개별 블록 사이에 걸쳐있을 수 없습니다.

여전히 옳다는 것은 여전히 ​​어렵습니다. 적절한 파서는 방수가 될 가능성이 훨씬 큽니다.

+0

흠, 나는 당신이 말한 것에 동의하지만 적절한 파서를 만드는 데 많은 기술이 없었습니다. XML 형식의 구문 분석을위한 적절한 튜토리얼을 알고 있습니까? 나는 지나치게 복잡하지는 않지만 아직 필요한 스킬 레벨에있는 좋은 것을 찾기가 어렵다는 것을 알게되었습니다. –

+0

필요에 맞는 타사 파서 라이브러리를 찾을 수없는 경우 수동으로 수행 할 수 있습니다. 먼저 '\ [[^ \]] + \]'같은 문자열로 preg_split-with-PREG_SPLIT_DELIM_CAPTURE를 태그를 선택하고 열린 태그 스택을 유지하면서 목록을 살펴보십시오. – bobince

+0

(목록의 짝수 번호는 텍스트이고, 홀수 번호의 태그입니다. 일반적으로 텍스트는 HTML 이스케이프가 발생하고, 스마일 리어를 자동으로 배치 할 수 있지만 일부 태그는이를 변경할 수 있습니다.) – bobince