왜 Evil Regexes가 문제입니까?
컴퓨터는 사용자가 말한대로 정확히 수행하기 때문에 그것이 의미하는 바가 아니거나 완전히 불합리한 경우에도 마찬가지입니다. Regex 엔진에 주어진 입력에 대해 주어진 패턴과 일치하는 것이 있는지 여부를 증명하도록 요청하면 엔진은 얼마나 많은 다른 조합을 테스트해야하는지에 관계없이이를 시도합니다.
다음은 OP 게시물의 첫 번째 예제에서 영감을 얻은 간단한 패턴입니다.
^((ab)*)+$
입력이 주어지면 :
아바 바바 바바 바바 바바 바바 바브
정규식 엔진은 다음과 같은 것을 시도 (abababababababababababab)
하고 첫 번째 시도에서 일치하는 항목을 찾습니다.
그러나 우리는 원숭이 렌치를 넣습니다.
abababababababababababab a
엔진이 먼저 시도 (abababababababababababab)
하지만 추가로 인해 실패합니다 a
. 이것은 우리의 패턴이 (ab)*
선의의 표시로 캡처 중 하나를 해제하고 ( "뒤로") 외부 패턴이 다시 시도하도록 하기 때문에 치명적인 bracktracking을 유발 합니다. 정규식 엔진의 경우 다음과 같습니다.
(abababababababababababab)
-아니오
(ababababababababababab)(ab)
-아니오
(abababababababababab)(abab)
-아니오
(abababababababababab)(ab)(ab)
-아니오
(ababababababababab)(ababab)
-아니오
(ababababababababab)(abab)(ab)
-아니오
(ababababababababab)(ab)(abab)
-아니오
(ababababababababab)(ab)(ab)(ab)
-아니오
(abababababababab)(abababab)
-아니오
(abababababababab)(ababab)(ab)
-아니오
(abababababababab)(abab)(abab)
-아니오
(abababababababab)(abab)(ab)(ab)
-아니오
(abababababababab)(ab)(ababab)
-아니오
(abababababababab)(ab)(abab)(ab)
-아니오
(abababababababab)(ab)(ab)(abab)
-아니오
(abababababababab)(ab)(ab)(ab)(ab)
-아니오
(ababababababab)(ababababab)
-아니오
(ababababababab)(abababab)(ab)
-아니오
(ababababababab)(ababab)(abab)
-아니오
(ababababababab)(ababab)(ab)(ab)
-아니오
(ababababababab)(abab)(abab)(ab)
-아니오
(ababababababab)(abab)(ab)(abab)
-아니오
(ababababababab)(abab)(ab)(ab)(ab)
-아니오
(ababababababab)(ab)(abababab)
-아니오
(ababababababab)(ab)(ababab)(ab)
-아니오
(ababababababab)(ab)(abab)(abab)
-아니오
(ababababababab)(ab)(abab)(ab)(ab)
-아니오
(ababababababab)(ab)(ab)(ababab)
-아니오
(ababababababab)(ab)(ab)(abab)(ab)
-아니오
(ababababababab)(ab)(ab)(ab)(abab)
-아니오
(ababababababab)(ab)(ab)(ab)(ab)(ab)
-아니오
...-
(ab)(ab)(ab)(ab)(ab)(ab)(ab)(ab)(abababab)
아니오
(ab)(ab)(ab)(ab)(ab)(ab)(ab)(ab)(ababab)(ab)
-아니오
(ab)(ab)(ab)(ab)(ab)(ab)(ab)(ab)(abab)(abab)
-아니오
(ab)(ab)(ab)(ab)(ab)(ab)(ab)(ab)(abab)(ab)(ab)
-아니오
(ab)(ab)(ab)(ab)(ab)(ab)(ab)(ab)(ab)(ababab)
-아니오
(ab)(ab)(ab)(ab)(ab)(ab)(ab)(ab)(ab)(abab)(ab)
-아니오
(ab)(ab)(ab)(ab)(ab)(ab)(ab)(ab)(ab)(ab)(abab)
-아니오
(ab)(ab)(ab)(ab)(ab)(ab)(ab)(ab)(ab)(ab)(ab)(ab)
-아니오
가능한 조합의 수는 입력의 길이에 따라 기하 급수적으로 확장되며, 정규식 엔진은 가능한 모든 용어 조합을 다 사용하고 결국 포기할 때까지이 문제를 해결하려는 모든 시스템 리소스를 소모합니다. "일치하는 항목이 없습니다."라고보고합니다. 한편 서버는 타는 금속 더미로 변했습니다.
악한 정규식을 찾는 방법
실제로 매우 까다 롭습니다. 나는 그들이 무엇인지 그리고 일반적으로 그들을 피하는 방법을 알고 있지만 몇 가지를 직접 썼습니다. 놀랍도록 오래 걸리는 Regex를 참조하십시오 . 원자 그룹에 가능한 모든 것을 래핑 하면 역 추적 문제를 방지하는 데 도움이 될 수 있습니다. 기본적으로 정규식 엔진에 주어진 표현식을 다시 방문하지 않도록 지시합니다. "첫 번째 시도에서 일치하는 항목을 잠급니다". 그러나 원자 식은 식 내 에서 역 추적을 방지하지 않으므로 ^(?>((ab)*)+)$
여전히 위험하지만 ^(?>(ab)*)+$
안전합니다 (일치 (abababababababababababab)
한 다음 일치하는 문자를 포기하는 것을 거부하여 치명적인 역 추적을 방지 함).
불행히도 일단 작성되면 실제로 문제 정규식을 즉시 또는 빠르게 찾는 것이 매우 어렵습니다. 결국, 잘못된 정규식을 인식하는 것은 다른 잘못된 코드를 인식하는 것과 같습니다 . 많은 시간과 경험 및 / 또는 단일 재앙적인 이벤트가 필요합니다.
흥미롭게도이 답변이 처음 작성 되었기 때문에 텍사스 대학교 오스틴의 한 팀은 이러한 "악한"패턴을 찾기위한 명시적인 목적으로 정규식의 정적 분석을 수행 할 수있는 도구의 개발을 설명하는 논문을 발표했습니다. 이 도구는 Java 프로그램을 분석하기 위해 개발되었지만 앞으로 몇 년 동안 특히 ReDoS 공격 비율이 계속 증가 함에 따라 JavaScript 및 기타 언어에서 문제 패턴을 분석하고 감지하는 데 더 많은 도구가 개발 될 것으로 예상 됩니다.
정규식
Valentin Wüstholz, Oswaldo Olivo, Marijn JH Heule 및 Isil Dillig 를 사용하는 프로그램에서 DoS 취약성의 정적 감지
The University of Texas at Austin