On Thu, Feb 11, 2021 at 9:44 PM Michał Górny <mgo...@gentoo.org> wrote: > I feel that vulnerability fixes do not make it to end users fast enough.
I think that it's time to put that into perspective with past vulnerabilities. Ok, let me look at the timeline of the discussed vulnerability, ctypes CVE-2021-3177: https://python-security.readthedocs.io/vuln/ctypes-buffer-overflow-pycarg_repr.html 2021-01-16: Python issue bpo-42938 reported by Jordy Zomer ... 2021-01-18 (+2 days): commit c347cbe (branch 3.9) 2021-01-18 (+2 days): commit ece5dfd (branch 3.8) 2021-01-19 (+3 days): CVE-2021-3177 published ... 2021-02-19 (+34 days): Python 3.8.8 released 2021-02-19 (+34 days): Python 3.9.2 released Ok. What about vulnerabilities fixes released last years? "HTTP header injection in urllib, urrlib2, httplib and http.client modules" https://python-security.readthedocs.io/vuln/http-header-injection.html 2017-09-19 (+1030 days): Python 3.3.7 released "CGI directory traversal" https://python-security.readthedocs.io/vuln/cgi-directory-traversal-is_cgi.html 2011-05-09 (+1158 days): CVE-2011-1015 published 2013-04-07 (+1857 days): Python 3.2.4 released 2013-04-07 (+1857 days): Python 3.3.1 released "httplib unlimited read" https://python-security.readthedocs.io/vuln/httplib-unlimited-read.html 2011-06-11 (+652 days): Python 2.7.2 released 2011-06-11 (+652 days): Python 3.1.4 released "rgbimg and imageop overflows" https://python-security.readthedocs.io/vuln/rgbimg-imageop-overflows.html 2008-12-19 (+460 days): Python 2.5.3 released So the CVE-2021-3177 fix was delivery between 14x and 55x faster than the other listed fixes (I picked a few worst cases to put numbers in perspective). Congrats to the core developers for fixing the vulnerability in only *3* days and to release manager for releasing *4* (!) Python versions (3.6.13, 3.7.10, 3.8.8, 3.9.2) in only 34 days! I would like to highlight that exploiting a directory traversal or HTTP header injection is really trivial. Once you find a pattern to explore the filesystem / inject a HTTP header, the exploit is 100% reliable. On the other side, there is no known exploit for ctypes CVE-2021-3177 and ctypes is rarely used. I read that Django's GIS uses ctypes and floats, but so far nobody shows that PyCArg_repr() is called, and nobody published an exploit. To write a CVE-2021-3177 exploit, you must create a 64-bit floating point number (only 8 bytes!) which becomes valid machine code, and this code should allow to take control on the machine, once it's formatted as decimal. For example, PyCArg_repr(123.5) writes "123.5\0" string into the stack memory. but I don't think that it's valid x86-64 machine code. It is also hard to write a reliable exploit by injecting machine code in the stack memory. --- Nowadays it's way more difficult than 10 years ago to write an exploit using a stack overflow, C compilers provide multiple hardening layers: - FORTIFY_SOURCE, - Control flow Enforcement Technology (Intel CET), - Address Space Layout Randomization (ASLR), - stack protector, - Position Independent Executable (PIE), - etc. See https://wiki.debian.org/Hardening for example of C flags and linker flags for harderning. Did anyone notice that Red Hat Entreprise Linux 8 (RHEL) is *not* affected by the ctypes CVE-2021-3177 vulnerability thanks to hardening? "Red Hat Enterprise Linux 8: python36:3.6/python36: Not affected" and "This flaw could have had a higher Impact, however our packages are compiled with FORTIFY_SOURCE, which provides runtime protection to some memory and string functions and prevents this flaw from actually overwriting the buffer and potentially executing code." => https://access.redhat.com/security/cve/cve-2021-3177 I suggest you checking how your operating system built your Python executable, and libpython if Python is built in shared mode: hardening can prevent the ctypes vulnerabiliy, but also against *future* vulnerabilities! For example, Fedora 33 builds Python 3.9 with the following C flags: -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fcf-protection -fstack-clash-protection -fstack-protector-strong -fPIC -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 => add the -fPIE flag (...) And linker flags: -Wl,-z,now -Wl,-z,relro -specs=/usr/lib/rpm/redhat/redhat-hardened-ld => add the -pie flag (...) You can inspect hardening options on a ELF binary using hardening-check tool: $ hardening-check /usr/bin/python3.9 /usr/bin/python3.9: Position Independent Executable: yes Stack protected: no, not found! Fortify Source functions: unknown, no protectable libc functions used Read-only relocations: yes Immediate binding: yes Stack clash protection: unknown, no -fstack-clash-protection instructions found Control flow integrity: yes $ hardening-check /usr/lib64/libpython3.9.so.1.0 /usr/lib64/libpython3.9.so.1.0: Position Independent Executable: no, regular shared library (ignored) Stack protected: yes Fortify Source functions: yes (some protected functions found) Read-only relocations: yes Immediate binding: yes Stack clash protection: unknown, no -fstack-clash-protection instructions found Note: I don't know if this tool is reliable, but at least I can see that multiple hardening options are enabled ;-) On Fedora and RHEL 8, packages are built with the "annobin" extension which records C and linker flags (and much more information). So you check hardening using annocheck tool: $ annocheck /usr/lib64/libpython3.6m.so.1.0 annocheck: Version 9.50. Hardened: libpython3.6m.so.1.0: PASS. $ annocheck /usr/lib64/libpython3.6m.so.1.0 -v|grep -vE '(skip|warn|info):' annocheck: Version 9.50. Hardened: /usr/lib64/libpython3.6m.so.1.0: PASS: One dynamic section/segment found. Hardened: /usr/lib64/libpython3.6m.so.1.0: PASS: Stack not executable. Hardened: /usr/lib64/libpython3.6m.so.1.0: PASS: DT_RPATH/DT_RUNPATH absent or rooted at /usr. Hardened: /usr/lib64/libpython3.6m.so.1.0: PASS: No RWX segments found. Hardened: /usr/lib64/libpython3.6m.so.1.0: PASS: No text relocations found. Hardened: /usr/lib64/libpython3.6m.so.1.0: PASS: No thread cancellation problems. Hardened: /usr/lib64/libpython3.6m.so.1.0: PASS: GOT/PLT relocations are read only. Hardened: /usr/lib64/libpython3.6m.so.1.0: PASS. More information about annobin: https://developers.redhat.com/blog/2018/02/20/annobin-storing-information-binaries/ Victor -- Night gathers, and now my watch begins. It shall not end until my death. _______________________________________________ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-le...@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/XF33457KYRJPUZAN4C4E3KCNOA7TDL6S/ Code of Conduct: http://python.org/psf/codeofconduct/