Skip to content

Instantly share code, notes, and snippets.

@tomgidden
Last active May 10, 2024 15:18
Show Gist options
  • Save tomgidden/b2ee71c0c9056ebfb39a53ab5c77956d to your computer and use it in GitHub Desktop.
Save tomgidden/b2ee71c0c9056ebfb39a53ab5c77956d to your computer and use it in GitHub Desktop.
Shell Script or Ansible playbook to mitigate issues with CVE-2024-2961
#!/bin/sh
# Test if CN-EXT charsets are enabled
if ( iconv -l | egrep -q 'CN-?EXT' ); then
# Comment out CN-EXT charsets in gconv-modules config
find /usr/lib* \( -path '*/gconv-modules' -o -path '*/gconv-modules-extra.conf' \) \
-exec sed '/^\([^#].*\)\?\(CNEXT\|CN-EXT\)/ s/^/###mitigate_CVE-2024-2961: /g' -i {} \;
# Rebuild gconv-modules.cache
iconvconfig
# Re-test if CN-EXT charsets are still enabled
if ( iconv -l | egrep -q 'CN-?EXT' ); then
echo "CN-EXT charsets are still enabled. Manual review might be needed."
exit 1
else
echo "CN-EXT charsets are now disabled."
fi
else
echo "CN-EXT charsets are already disabled."
fi
---
- name: Check iconv installation and disable CN-EXT charsets (gconv-modules)
hosts: all
become: True
gather_facts: no
tasks:
- name: Find CN-EXT charsets with iconv -l
shell: iconv -l | egrep 'CN-?EXT'
register: cn_ext_charsets
failed_when: cn_ext_charsets.rc != 0
- name: Find gconv-modules config files
shell: "find /usr/lib* -path '*/gconv-modules' -o -path '*/gconv-modules-extra.conf'"
register: gconv_modules_find
when: cn_ext_charsets.rc == 0
- fail: msg="gconv-modules configuration file not found. Check paths."
when: gconv_modules_find.rc != 0
- name: Disable CN-EXT charsets in gconv-modules
replace:
path: "{{ item }}"
regexp: "^([^#].*CN-?EXT.*)$"
replace: '###mitigate_CVE-2024-2961: \1'
register: lineinfile_result
loop: "{{ gconv_modules_find.stdout_lines }}"
when: gconv_modules_find.rc == 0
- fail: msg="No CN-EXT charsets found in existing gconv-modules config file. Manual review might be needed."
when: lineinfile_result.changed == False and gconv_modules_find.rc == 0
- name: (Re)generate gconv-modules cache
command: iconvconfig
when: lineinfile_result.changed == True
- name: Verify CN-EXT charsets are disabled (fail if present)
shell: iconv -l | egrep 'CN-?EXT'
register: cn_ext_charsets_after
failed_when: cn_ext_charsets_after.rc == 0
when: lineinfile_result.changed == True
# This tests PHP CLI. Run the same code on an active webserver to test properly. On an old apache2/php-fpm
# a restart doesn't seem necessary.
php -r 'error_reporting(-1); echo iconv("UTF-8","ISO-2022-CN-EXT","X")=="X"?"FAILED\n":"OKAY\n";'
@tomgidden
Copy link
Author

This follows steps given in https://garrettmills.dev/blog/2024/04/22/Mitigating-the-iconv-Vulnerability-for-PHP-CVE-2024-2961/

It seems to work for my test machine where the config is in /usr/lib/x86_64-linux-gnu/gconv/gconv-modules, but it looks like /usr/lib/x86_64-linux-gnu/gconv/gconv-modules.d/... and /etc/conf.d/... may be possible too.

I haven't tested to see if it actually fixes the vulnerability; once the exploit is known, maybe it can be included in this playbook.

@tomgidden
Copy link
Author

tomgidden commented Apr 29, 2024

Tried on a newer server, and there both gconv-modules and gconv-modules.d/... existed, so I've updated above to do all matched files, not just the first. And, (re)generation of the cache is now unconditional. It seems to work.

Note, it unconditionally disables CN-EXT encodings, regardless of the version of glibc / iconv. I suppose it'd be worth adding a step to check glibc version as in Garrett Mills' notes above, but I haven't bothered here.

@tomgidden
Copy link
Author

tomgidden commented Apr 29, 2024

Rewritten as script to allow for running locally without Ansible. Relatively untested.

Also, ref: https://rockylinux.org/news/glibc-vulnerability-april-2024/ -- both script and playbook check both /usr/lib and /usr/lib64.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment