Last active
December 29, 2021 22:29
-
-
Save JamoCA/6a8c612645b1b7c47eba8e317ad51d23 to your computer and use it in GitHub Desktop.
Log4j Exploit Pattern Detection Using ColdFusion\CFML
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!--- getRequestAsText() and containsLog4jExploit() ColdFusion UDF proof-of-concept | |
2021-12-21 | |
by James Moberg https://www.sunstarmedia.com/ | |
https://gist.github.com/JamoCA/6a8c612645b1b7c47eba8e317ad51d23 | |
Tested on CF2016+ and Lucee (using TryCF.com). | |
---> | |
<cfscript> | |
string function getRequestAsText() output=false hint="I return HTTP header, url and form data as text" { | |
var response = getHttpRequestData(); | |
var responseText = []; | |
var temp = {"lf":chr(10)}; | |
for (temp.header in response.headers){ | |
arrayAppend(responseText, "#temp.header#: #response.headers[temp.header]#"); | |
} | |
responseText = arrayToList(responseText, temp.lf); | |
responseText = responseText & temp.lf & "ip: " & cgi.remote_addr; | |
for (temp.field in URL){ | |
responseText = responseText & temp.lf & "url-#temp.field#: " & URL[temp.field]; | |
} | |
for (temp.field in FORM){ | |
if (temp.field neq "FIELDNAMES") responseText = responseText & temp.lf & "form-#temp.field#: " & FORM[temp.field]; | |
} | |
return trim(responseText); | |
} | |
boolean function containsLog4jExploit(string inputString="") output=false hint="I sanitize string and perform regex to identify exploit" { | |
local.pattern = "(?i)j1n2d3i5\:(ldap|rmi|ldaps|dns)"; | |
local.text = canonicalize(arguments.inputString, false, false); | |
local.text = local.text.replaceAll("\s", ""); | |
local.text = local.text.replaceAll("\$\{\:{1,2}\-([a-zA-Z]+)?\}", "$1"); | |
local.text = local.text.replaceAll("\$\{\:\-\:\}", "\:"); | |
local.text = local.text.replaceAll("\$\{(upper|lower)\:(.+?)\}", "$2"); | |
local.text = local.text.replaceAll("(?i)\$\{(env|sys)\:.*?\:\-(.+?)\}", "$2"); | |
local.text = local.text.replaceAll("(?i)\$\{date\:\'(.+?)\'\}", "$1"); | |
local.text = local.text.replaceAll("(?i)\$\{[a-zA-z_0-9]+\:[a-zA-z_0-9]+\:\-(.+?)\}", "$1"); | |
return javacast("boolean", reFindNoCase(local.pattern.replaceAll("\d",""), local.text)); | |
} | |
// Unit test samples are from https://github.com/Puliczek/CVE-2021-44228-PoC-log4j-bypass-words | |
// and https://log4j-tester.trendmicro.com/ | |
tests = [ | |
"1. System variables": "${${env:EN_AME:-j}ndi${env:EN_AME:-:}${env:EN_AME:-l}dap${env:EN_AME:-:}//127.0.0.1/z}" | |
,"2. Lower lookup": "${${lower:j}n" & "di:${lower:l}${lower:d}a${lower:p}://127.0.0.1/z}" | |
,"2. Upper lookup": "${${upper:j}n" & "di:${upper:l}${upper:d}a${upper:p}://127.0.0.1/z}" | |
,"3. '::-' notation": "${${::-j}${::-n}${::-d}${::-i}:${::-l}${::-d}${::-a}${::-p}://127.0.0.1/z}" | |
,"4. Invalid Unicode characters with upper": "${jnd${upper:ı}:ldap://127.0.0.1/z}" | |
,"5. System properties": "${jnd${sys:SYS_NAME:-i}:ldap:/127.0.0.1/z}" | |
,"6. ':' notation": "${j${${:-l}${:-o}${:-w}${:-e}${:-r}:n}di:ldap://127.0.0.1/z}" | |
,"7. Date": "${${date:'j'}${date:'n'}${date:'d'}${date:'i'}:${date:'l'}${date:'d'}${date:'a'}${date:'p'}://127.0.0.1/z}" | |
,"8. HTML URL Encoding": "%24%7Bjn" & "di%3A" & "ldap://127.0.0.1/z%7D" | |
,"9. Non-existent lookup": "${${what:ever:-j}${some:thing:-n}${other:thing:-d}${and:last:-i}:ldap://127.0.0.1/z}" | |
,"11. Unicode Characters": "${\u006a\u006e\u0064\u0069:ldap://127.0.0.1/z}" | |
,"12. Trick with ## (works on log4j 2.15)": "$" & "{" & "jndi" & ":ldap://127.0.0.1##baddomain.com/z}" | |
,"13. DoS attack": "${${::-${::-$${::-j}}}}" // not currently supported. may be too difficult to sanitize/detect. | |
,"TrendMicro-system environment": "${${env:3910238:-j}ndi${env:3910238:-:}${env:3910238:-l}dap${env:3910238:-:}//127.0.0.1/z}" | |
,"TrendMicro-system properties": "${${sys:3910238:-j}ndi${sys:3910238:-:}${sys:3910238:-l}dap${sys:3910238:-:}//127.0.0.1/z}" | |
,"TrendMicro-lower special": "${j${${:-l}${:-o}${:-w}${:-e}${:-r}:n}${:-d}${:-i}${:-:}${:-l}${:-d}${:-a}${:-p}${:-:}${:-/}${:-/}127.0.0.1/z}" | |
,"Current Header/URL/Form": getRequestAsText() | |
]; | |
</cfscript> | |
<h2>Log4j Detection Unit Tests</h2> | |
<cfset cr = 0> | |
<cfoutput> | |
<cfloop collection="#tests#" item="test"> | |
<cfset cr += 1> | |
<cfset isBad = containsLog4jExploit(tests[test])> | |
<fieldset><legend<cfif isBad> style="color:red;"</cfif>>[#cr#/#structCount(tests)#] #test# = <b>#isBad#</b></legend> | |
<pre>#encodeForHTML(tests[test])#</pre> | |
</fieldset> | |
</cfloop> | |
</cfoutput> |
Updated on 12/29/2021 to block rmi, ldaps & dns (versus only ldap) based on feedback from Google Cloud:
https://cloud.google.com/blog/products/identity-security/recommendations-for-apache-log4j2-vulnerability
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Updated on 12/29/2021 to remove spaces prior to performing regex replacements.