Last active
January 17, 2022 12:01
-
-
Save righettod/ce1570954242de2f8772c6f25eece77d to your computer and use it in GitHub Desktop.
Script to identify Log4J affected class for CVE-2021-44228 in a collection of ear/war/jar files
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
#!/bin/bash | |
######################################################################################################### | |
# Script to identify Log4J affected class for CVE-2021-44228 in a collection of EAR/WAR/JAR files | |
# Based on this script: | |
# https://github.com/righettod/toolbox-pentest-web/blob/master/scripts/identify-class-location.sh | |
######################################################################################################### | |
if [ "$#" -lt 1 ]; then | |
script_name=$(basename "$0") | |
echo "Usage:" | |
echo " $script_name [BASE_SEARCH_FOLDER]" | |
echo "" | |
echo "Call example:" | |
echo " $script_name /apps" | |
exit 1 | |
fi | |
# Constants | |
JAR_FOUND=0 | |
TARGET_CLASS_NAME="org/apache/logging/log4j/core/lookup/JndiLookup.class" | |
APP_LIBS_FOLDER=$1 | |
WORK_FOLDER=/tmp/work | |
JAR_WORK_FOLDER=/tmp/jarwork | |
NESTED_JAR_WORK_FOLDER=/tmp/nestedjarwork | |
CDIR=$(pwd) | |
# See https://unix.stackexchange.com/a/9499 | |
OIFS="$IFS" | |
IFS=$'\n' | |
# Utility functions | |
inspect_folder (){ | |
folder_location=$1 | |
for jar_lib in $(find "$folder_location" -type f -iname "*.jar") | |
do | |
inspect_jar_file "$jar_lib" | |
done | |
} | |
inspect_jar_file(){ | |
jar_file_location=$1 | |
find=$(unzip -l "$jar_file_location" | grep -c "$TARGET_CLASS_NAME") | |
if [ $find -ne 0 ] | |
then | |
JAR_FOUND=1 | |
echo "" | |
echo -e "\e[91m[!] Class found in the file '$jar_file_location'.\e[0m" | |
echo -e "\e[93m[+] Try to find the Maven artefact version...\e[0m" | |
rm -rf "$JAR_WORK_FOLDER" 2>/dev/null | |
mkdir "$JAR_WORK_FOLDER" | |
unzip -q -d "$JAR_WORK_FOLDER" "$jar_file_location" | |
chmod -R +r "$JAR_WORK_FOLDER" | |
cd $JAR_WORK_FOLDER | |
for f in $(grep -r "groupId\s*=\s*org.apache.logging.log4j" *) | |
do | |
file_loc=$(echo $f | cut -d":" -f1) | |
artefact_version=$(grep -Po "version\s*=\s*.*" "$file_loc" | sed 's/version=//g') | |
echo "File : $jar_file_location" | |
echo "Metadata file : $file_loc" | |
echo "Log4J version : $artefact_version" | |
done | |
cd $CDIR | |
rm -rf $JAR_WORK_FOLDER 2>/dev/null | |
fi | |
# Handle nested jar case | |
has_nested_jar=$(unzip -l "$jar_file_location" | grep "\.jar$" | grep -cv "Archive:") | |
if [ $has_nested_jar -ne 0 ] | |
then | |
nestedjar_lib_name="$(basename "$jar_file_location")_$RANDOM" | |
mkdir -p "$NESTED_JAR_WORK_FOLDER/$nestedjar_lib_name" | |
unzip -q -d "$NESTED_JAR_WORK_FOLDER/$nestedjar_lib_name" "$jar_file_location" | |
chmod -R +r "$NESTED_JAR_WORK_FOLDER/$nestedjar_lib_name" | |
inspect_folder "$NESTED_JAR_WORK_FOLDER/$nestedjar_lib_name" | |
fi | |
} | |
echo -e "\e[93m[+] Searching class '$TARGET_CLASS_NAME' across '$APP_LIBS_FOLDER' folder...\e[0m" | |
for lib in $(find "$APP_LIBS_FOLDER" -type f -iname "*.jar" -o -iname "*.war" -o -iname "*.ear") | |
do | |
filename=$(basename "$lib") | |
filename="$filename" | |
extension="${filename##*.}" | |
printf "\r[*] Inspecting file: %-80s" $filename | |
if [ $extension == "ear" ] | |
then | |
rm -rf $WORK_FOLDER 2>/dev/null | |
mkdir $WORK_FOLDER | |
unzip -q -d $WORK_FOLDER "$lib" | |
chmod -R +r $WORK_FOLDER | |
for war_lib in $(find $WORK_FOLDER -type f -iname "*.war") | |
do | |
war_lib_name="$(basename "$war_lib")_$RANDOM" | |
war_lib_folder="$WORK_FOLDER/$war_lib_name" | |
mkdir "$war_lib_folder" | |
unzip -q -d "$war_lib_folder" "$war_lib" | |
chmod -R +r "$war_lib_folder" | |
done | |
inspect_folder "$WORK_FOLDER" | |
rm -rf "$WORK_FOLDER" 2>/dev/null | |
fi | |
if [ $extension == "war" ] | |
then | |
rm -rf $WORK_FOLDER 2>/dev/null | |
war_lib_name="$(basename "$lib")_$RANDOM" | |
war_lib_folder=$WORK_FOLDER/$war_lib_name | |
mkdir -p "$war_lib_folder" | |
unzip -q -d "$war_lib_folder" "$lib" | |
chmod -R +r "$war_lib_folder" | |
inspect_folder "$WORK_FOLDER" | |
rm -rf $WORK_FOLDER 2>/dev/null | |
fi | |
if [ $extension == "jar" ] | |
then | |
inspect_jar_file "$lib" | |
fi | |
done | |
printf "\r%-100s" " " | |
if [ $JAR_FOUND -eq 0 ] | |
then | |
echo -e "\r\e[92m[V] Inspection finished - Class not found!\e[0m\n" | |
else | |
echo -ne "\r\e[91m[!] Inspection finished - Class found!\e[0m\n" | |
fi | |
IFS="$OIFS" | |
rm -rf "$NESTED_JAR_WORK_FOLDER" 2>/dev/null | |
exit $JAR_FOUND |
@tbird5 Thank you very much for the feedback I will work on it to address the issues raised 👍
@tbird5 New version published with the issues mentioned normally fixed (at least using my test cases) 👍
From now I will manage the script and the analysis content here.
It will facilitate the issue handling, sharing, publishing and backup of the content.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Note about formatMsgNoLookups bypass
ℹ️ This bypass was bring by the CVE-2021-45046.
Below is a POC from LunaSecIO showing the vulnerability and its exploitation context:
Source: https://twitter.com/LunaSecIO/status/1470871128843251716
A unit tests suite was created and used to perform some tests for the bypass of
log4j2.formatMsgNoLookups=true
:Version 2.14.1 seems to be exposed to the bypass:
Version 2.15.0 do not seems to be exposed to the bypass:
Note that a usage of the
printf()
function, like for examplevictim.printf(Level.INFO,"%s",TEST_PAYLOAD)
, have the same effect that using theThreadContext
combined with a expression in the log pattern:On version 2.15.0 - By default:
Regarding LDAP(S), a bypass of the validation against allowed hosts was identified: https://twitter.com/pwntester/status/1471465662975561734