Generic.Detection.log4jRCE

Detection for exploitation attempts against log4j RCE vulnerability CVE-2021-44228.

By default this artifact will search for linux path glob: /var/logs/**

For Windows hosts please change the target path. Some examples of path glob may include:

  • Specific binary: /var/logs/log.gz
  • Wildcards: /var/log/*.gz
  • More wildcards: /var/www/**/*.log
  • Multiple extentions: /var/log/**/*\.{log,gz}
  • Windows: C:/Logs/**/*.{gz,log} or **/*.{gz,log}

NOTE: this artifact runs the glob plugin with the nosymlink switch turned on. This will NOT follow any symlinks and may cause unexpected results if unknowingly targeting a folder with symlinks.


name: Generic.Detection.log4jRCE
author: Matt Green - @mgreen27
description: |
  Detection for exploitation attempts against log4j RCE
  vulnerability CVE-2021-44228.

  By default this artifact will search for linux path glob: /var/logs/**

  For Windows hosts please change the target path.
  Some examples of path glob may include:

  * Specific binary: `/var/logs/log.gz`
  * Wildcards: `/var/log/*.gz`
  * More wildcards: `/var/www/**/*.log`
  * Multiple extentions: `/var/log/**/*\.{log,gz}`
  * Windows: `C:/Logs/**/*.{gz,log}` or `**/*.{gz,log}`

  NOTE: this artifact runs the glob plugin with the nosymlink switch
  turned on.  This will NOT follow any symlinks and may cause
  unexpected results if unknowingly targeting a folder with symlinks.

reference:
  - https://github.com/Neo23x0/signature-base/blob/master/yara/expl_log4j_cve_2021_44228.yar

type: CLIENT
parameters:
  - name: PathGlob
    description: Only file names that match this glob will be scanned.
    default: /var/log/**
  - name: SizeMax
    description: maximum size of target file.
  - name: SizeMin
    description: minimum size of target file.
  - name: UploadHits
    type: bool
  - name: DateAfter
    type: timestamp
    description: "search for events after this date. YYYY-MM-DDTmm:hh:ssZ"
  - name: DateBefore
    type: timestamp
    description: "search for events before this date. YYYY-MM-DDTmm:hh:ssZ"
  - name: YaraUrl
    description: If configured will attempt to download Yara rules form Url
    default:
  - name: ShortHandYara
    description: Second option Yara choice is a Velociraptor shorthand Yara rule
    default:
  - name: YaraRule
    description: Final Yara option and the default if no other options provided.
    default: |
        rule EXPL_Log4j_CallBackDomain_IOCs_Dec21_1 {
           meta:
              description = "Detects IOCs found in Log4Shell incidents that indicate exploitation attempts of CVE-2021-44228"
              author = "Florian Roth"
              reference = "https://gist.github.com/superducktoes/9b742f7b44c71b4a0d19790228ce85d8"
              date = "2021-12-12"
              score = 60
           strings:
              $xr1  = /\b(ldap|rmi):\/\/([a-z0-9\.]{1,16}\.bingsearchlib\.com|[a-z0-9\.]{1,40}\.interact\.sh|[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}):[0-9]{2,5}\/([aZ]|ua|Exploit|callback|[0-9]{10}|http443useragent|http80useragent)\b/
           condition:
              1 of them
        }

        rule EXPL_JNDI_Exploit_Patterns_Dec21_1 {
           meta:
              description = "Detects JNDI Exploit Kit patterns in files"
              author = "Florian Roth"
              reference = "https://github.com/pimps/JNDI-Exploit-Kit"
              date = "2021-12-12"
              score = 60
           strings:
              $x01 = "/Basic/Command/Base64/"
              $x02 = "/Basic/ReverseShell/"
              $x03 = "/Basic/TomcatMemshell"
              $x04 = "/Basic/JettyMemshell"
              $x05 = "/Basic/WeblogicMemshell"
              $x06 = "/Basic/JBossMemshell"
              $x07 = "/Basic/WebsphereMemshell"
              $x08 = "/Basic/SpringMemshell"
              $x09 = "/Deserialization/URLDNS/"
              $x10 = "/Deserialization/CommonsCollections1/Dnslog/"
              $x11 = "/Deserialization/CommonsCollections2/Command/Base64/"
              $x12 = "/Deserialization/CommonsBeanutils1/ReverseShell/"
              $x13 = "/Deserialization/Jre8u20/TomcatMemshell"
              $x14 = "/TomcatBypass/Dnslog/"
              $x15 = "/TomcatBypass/Command/"
              $x16 = "/TomcatBypass/ReverseShell/"
              $x17 = "/TomcatBypass/TomcatMemshell"
              $x18 = "/TomcatBypass/SpringMemshell"
              $x19 = "/GroovyBypass/Command/"
              $x20 = "/WebsphereBypass/Upload/"

              $fp1 = "<html"
           condition:
              1 of ($x*) and not 1 of ($fp*)
        }

        rule EXPL_Log4j_CVE_2021_44228_JAVA_Exception_Dec21_1 {
           meta:
              description = "Detects exceptions found in server logs that indicate an exploitation attempt of CVE-2021-44228"
              author = "Florian Roth"
              reference = "https://gist.github.com/Neo23x0/e4c8b03ff8cdf1fa63b7d15db6e3860b"
              date = "2021-12-12"
              score = 60
           strings:
              $xa1 = "header with value of BadAttributeValueException: "

              $sa1 = ".log4j.core.net.JndiManager.lookup(JndiManager"
              $sa2 = "Error looking up JNDI resource"
           condition:
              $xa1 or all of ($sa*)
        }

        rule EXPL_Log4j_CVE_2021_44228_Dec21_Soft {
           meta:
              description = "Detects indicators in server logs that indicate an exploitation attempt of CVE-2021-44228"
              author = "Florian Roth"
              reference = "https://twitter.com/h113sdx/status/1469010902183661568?s=20"
              date = "2021-12-10"
              modified = "2021-12-13"
              score = 60
           strings:
              $x01 = "${jndi:ldap:/"
              $x02 = "${jndi:rmi:/"
              $x03 = "${jndi:ldaps:/"
              $x04 = "${jndi:dns:/"
              $x05 = "${jndi:iiop:/"
              $x06 = "${jndi:http:/"
              $x07 = "${jndi:nis:/"
              $x08 = "${jndi:nds:/"
              $x09 = "${jndi:corba:/"

              $fp1 = "<html"
           condition:
              1 of ($x*) and not 1 of ($fp*)
        }

        rule EXPL_Log4j_CVE_2021_44228_Dec21_OBFUSC {
           meta:
              description = "Detects obfuscated indicators in server logs that indicate an exploitation attempt of CVE-2021-44228"
              author = "Florian Roth"
              reference = "https://twitter.com/h113sdx/status/1469010902183661568?s=20"
              date = "2021-12-12"
              modified = "2021-12-13"
              score = 60
           strings:
              $x1 = "$%7Bjndi:"
              $x2 = "%2524%257Bjndi"
              $x3 = "%2F%252524%25257Bjndi%3A"
              $x4 = "${jndi:${lower:"
              $x5 = "${::-j}${"
              $x6 = "${${env:BARFOO:-j}"
              $x7 = "${::-l}${::-d}${::-a}${::-p}"
              $x8 = "${base64:JHtqbmRp"

              $fp1 = "<html"
           condition:
              1 of ($x*) and not 1 of ($fp*)
        }

        rule EXPL_Log4j_CVE_2021_44228_Dec21_Hard {
           meta:
              description = "Detects indicators in server logs that indicate the exploitation of CVE-2021-44228"
              author = "Florian Roth"
              reference = "https://twitter.com/h113sdx/status/1469010902183661568?s=20"
              date = "2021-12-10"
              modified = "2021-12-12"
              score = 80
           strings:
              $x1 = /\$\{jndi:(ldap|ldaps|rmi|dns|iiop|http|nis|nds|corba):\/[\/]?[a-z-\.0-9]{3,120}:[0-9]{2,5}\/[a-zA-Z\.]{1,32}\}/
              $x2 = "Reference Class Name: foo"
              $fp1r = /(ldap|rmi|ldaps|dns):\/[\/]?(127\.0\.0\.1|192\.168\.|172\.[1-3][0-9]\.|10\.)/
           condition:
              1 of ($x*) and not 1 of ($fp*)
        }

        rule SUSP_Base64_Encoded_Exploit_Indicators_Dec21 {
           meta:
              description = "Detects base64 encoded strings found in payloads of exploits against log4j CVE-2021-44228"
              author = "Florian Roth"
              reference = "https://twitter.com/Reelix/status/1469327487243071493"
              date = "2021-12-10"
              modified = "2021-12-13"
              score = 70
           strings:
              /* curl -s  */
              $sa1 = "Y3VybCAtcy"
              $sa2 = "N1cmwgLXMg"
              $sa3 = "jdXJsIC1zI"
              /* |wget -q -O-  */
              $sb1 = "fHdnZXQgLXEgLU8tI"
              $sb2 = "x3Z2V0IC1xIC1PLS"
              $sb3 = "8d2dldCAtcSAtTy0g"

              $fp1 = "<html"
           condition:
              1 of ($sa*) and 1 of ($sb*)
              and not 1 of ($fp*)
        }

        rule SUSP_JDNIExploit_Indicators_Dec21 {
           meta:
              description = "Detects indicators of JDNI usage in log files and other payloads"
              author = "Florian Roth"
              reference = "https://github.com/flypig5211/JNDIExploit"
              date = "2021-12-10"
              modified = "2021-12-12"
              score = 70
           strings:
              $xr1 = /(ldap|ldaps|rmi|dns|iiop|http|nis|nds|corba):\/\/[a-zA-Z0-9\.]{7,80}:[0-9]{2,5}\/(Basic\/Command\/Base64|Basic\/ReverseShell|Basic\/TomcatMemshell|Basic\/JBossMemshell|Basic\/WebsphereMemshell|Basic\/SpringMemshell|Basic\/Command|Deserialization\/CommonsCollectionsK|Deserialization\/CommonsBeanutils|Deserialization\/Jre8u20\/TomcatMemshell|Deserialization\/CVE_2020_2555\/WeblogicMemshell|TomcatBypass|GroovyBypass|WebsphereBypass)\//
           condition:
              filesize < 100MB and $xr1
        }

        rule SUSP_EXPL_OBFUSC_Dec21_1{
           meta:
              description = "Detects obfuscation methods used to evade detection in log4j exploitation attempt of CVE-2021-44228"
              author = "Florian Roth"
              reference = "https://twitter.com/testanull/status/1469549425521348609"
              date = "2021-12-11"
              score = 60
           strings:
              /* ${lower:X} - single character match */
              $x1 = { 24 7B 6C 6F 77 65 72 3A ?? 7D }
              /* ${upper:X} - single character match */
              $x2 = { 24 7B 75 70 70 65 72 3A ?? 7D }
              /* URL encoded lower - obfuscation in URL */
              $x3 = "$%7blower:"
              $x4 = "$%7bupper:"
              $x5 = "%24%7bjndi:"
              $x6 = "$%7Blower:"
              $x7 = "$%7Bupper:"
              $x8 = "%24%7Bjndi:"

              $fp1 = "<html"
           condition:
              1 of ($x*) and not 1 of ($fp*)
        }

        rule SUSP_JDNIExploit_Error_Indicators_Dec21_1 {
           meta:
              description = "Detects error messages related to JDNI usage in log files that can indicate a Log4Shell / Log4j exploitation"
              author = "Florian Roth"
              reference = "https://twitter.com/marcioalm/status/1470361495405875200?s=20"
              date = "2021-12-10"
              modified = "2021-12-13"
              score = 70
           strings:
              $x1 = "FATAL log4j - Message: BadAttributeValueException: "
           condition:
              $x1
        }

sources:
  - query: |
      -- check which Yara to use
      LET yara = SELECT * FROM if(condition=YaraUrl,
            then= { SELECT Content FROM http_client( url=YaraUrl, method='GET') },
            else= if(condition=ShortHandYara,
                then= { SELECT ShortHandYara as Content FROM scope() },
                else= { SELECT YaraRule as Content FROM scope() }))

      -- time testing
      LET time_test(stamp) =
            if(condition= DateBefore AND DateAfter,
                then= stamp < DateBefore AND stamp > DateAfter,
                else=
            if(condition=DateBefore,
                then= stamp < DateBefore,
                else=
            if(condition= DateAfter,
                then= stamp > DateAfter,
                else= True
            )))

      -- first find all matching glob
      LET files = SELECT FullPath, Name, Size , Mtime, Atime, Ctime, Btime
        FROM glob(globs=PathGlob,nosymlink='True')
        WHERE
          NOT IsDir AND NOT IsLink
          AND if(condition=SizeMin,
            then= SizeMin < Size,
            else= True)
          AND if(condition=SizeMax,
            then=SizeMax > Size,
            else= True)
          AND
             ( time_test(stamp=Mtime)
            OR time_test(stamp=Atime)
            OR time_test(stamp=Ctime)
            OR time_test(stamp=Btime))

      LET hits = SELECT * FROM foreach(row=files,
            query={
                SELECT
                    url(parse=FileName).Path as FullPath,
                    Size,
                    Mtime, Atime, Ctime, Btime,
                    Rule, Tags, Meta,
                    str(str=String.Data) AS HitContext,
                    String.Offset AS HitOffset
                FROM yara(rules=yara.Content[0],files=url(path=FullPath, scheme="file"), accessor='gzip')
                LIMIT 1
            })

      -- upload files that have hit
      LET upload_hits=SELECT *,
            upload(file=FullPath) AS Upload
        FROM hits

      -- return rows
      SELECT * FROM if(condition=UploadHits,
        then=upload_hits,
        else=hits)