Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(checker): Detect OpenSSL 0.9.x, as found in msys/cygwin #4735

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

qmfrederik
Copy link
Contributor

@qmfrederik qmfrederik commented Jan 31, 2025

As a side-effect, this also finds OpenSSL in a bunch of other libraries.

@qmfrederik
Copy link
Contributor Author

@terriko I've updated the tests; would you mind re-approving this workflow?

@terriko
Copy link
Contributor

terriko commented Feb 11, 2025

Pinging @ffontaine -- I know you've been working on reducing false positives in this particular pattern, is this update going to cause you problems?

@ffontaine
Copy link
Contributor

Thanks a lot @terriko for pinging me.
Indeed, merging this PR will put back many false positives.
Why?
Because of OPENSSL_VERSION_TEXT that is commonly used by packages depending on openssl.

For example libssh uses this piece of code to log the version of openssl that was used to compile the library:

    if (OpenSSL_version_num() != OPENSSL_VERSION_NUMBER){
        SSH_LOG(SSH_LOG_WARNING, "libssh compiled with %s "
            "headers, currently running with %s.",
            OPENSSL_VERSION_TEXT,
            OpenSSL_version(OpenSSL_version_num())
        );
    }

This is an interesting information but libssh.so is a shared library, not a static one. It doesn't embed any code from openssl and so is not affected by any CVEs related to openssl. Moreover, it doesn't mean that the final openssl library that will be embedded in the system has the same version (e.g. libssh could have been compiled with openssl 3.3.2 and the final openssl version installed on the system could be openssl 3.3.4). This would be odd but could be seen on embedded systems.

You can easily reproduce this false positive by compiling this simple main program:

#include <openssl/crypto.h>

int main()
{
    printf("%s\n", OPENSSL_VERSION_TEXT);
    return 0;
}

If this PR is merged as it is, cve-bin-tool will (wrongly) detect openssl inside this binary.

@qmfrederik
Copy link
Contributor Author

Thanks @ffontaine . The approach taken by cve-bin-tool relies on looking for version information in strings embedded in binaries. If your application includes a version string of another component, that would result in a false positive. That's not specific to OpenSSL; that's a consequence of the approach taken by this tool.

You could argue that including OPENSSL_VERSION_TEXT in your executable is a bug, likely to print out the wrong information (as you've pointed out), and what you should be doing instead is calling SSLeay_version so you get the correct version information at runtime (and don't embed SSL version strings in your application), sidestepping this issue.

What I found was that the tool currently does not detect OpenSSL as built by old versions of MSYS or GnuWin32. Those versions merely contain this version string: OpenSSL 0.9.8h 28 May 2008, without any extra information. You can inspect that by checking out this branch and analyzing test/condensed-downloads/openssl-0.9.8h-1-bin.zip.tar.gz or looking at http://downloads.sourceforge.net/gnuwin32/openssl-0.9.8h-1-bin.zip .

I think a false negative on an old version of OpenSSL would be an important limitation (that GnuWin32 build is unfortunately still used). Is there another approach you would suggest which would avoid this false negative?

@ffontaine
Copy link
Contributor

ffontaine commented Feb 12, 2025

Hi @qmfrederik, using latest main, I added openssl-0.9.8h-1-bin.zip to test/test_data/openssl.py

    {
        "url": "http://downloads.sourceforge.net/gnuwin32/",
        "package_name": "openssl-0.9.8h-1-bin.zip",
        "product": "openssl",
        "version": "0.9.8h",
    },

I then run LONG_TESTS=1 pytest test/test_scanner.py -k openssl -v and test was successful.

I double checked by running cve-bin-tool on openssl-0.9.8h-1-bin.zip and it correctly detects 0.9.8h inside openssl.exe and libeay32.dll.

So I'm not able to reproduce your issue, can you provide additional details (e.g. other binaries)?

@qmfrederik
Copy link
Contributor Author

Ah - good catch, thanks. Let me see if I can find another package on Windows which is representative.

@qmfrederik
Copy link
Contributor Author

@ffontaine Here's another example: https://ftp-stud.hs-esslingen.de/pub/Mirrors/sources.redhat.com/cygwin/x86_64/release/openssl10/libssl1.0/libssl1.0-1.0.2t-1.tar.xz

The version string is embedded like this:

strings usr/bin/cygcrypto-1.0.0.dll | grep "OPENSSLDIR" -B 3
OpenSSL 1.0.2t  10 Sep 2019
built on: reproducible build, date unspecified
platform: Cygwin-x86_64
OPENSSLDIR: "/etc/pki/tls"

I have another example which reads like this:

OpenSSL 1.1.1  11 Sep 2018
platform: mingw64
OPENSSLDIR: "C:/building/msys64/mingw64/ssl"

And then there's the interesting example of nodejs, which (usually) contains a static copy of OpenSSL: https://github.com/nodejs/node/blob/main/doc/contributing/maintaining/maintaining-openssl.md#L3 .

@ffontaine
Copy link
Contributor

1.0.2t is correctly detected in libssl1.0-1.0.2t-1.tar.xz (i.e. in cygssl-1.0.0.dll):

{
        "url": "https://ftp-stud.hs-esslingen.de/pub/Mirrors/sources.redhat.com/cygwin/x86_64/release/openssl10/libssl1.0/",
        "package_name": "libssl1.0-1.0.2t-1.tar.xz",
        "product": "openssl",
        "version": "1.0.2t",
        "other_products": ["gcc"],
},

This is not surprising as the current multiline pattern will be triggered on OPENSSLDIR.

Concerning nodejs, do you have a concrete example of a nodejs package statically linked with openssl?
I quickly checked node_v8.16.1-1_x86_64.ipk and it is dynamically linked to openssl:

readelf -d node_v8.16.1-1_x86_64.ipk_extract/gzip.uncompressed_extract/data.tar.gz_extract/gzip.uncompressed_extract/usr/bin/node|grep "libssl\|crypto"
 0x0000000000000001 (NEEDED)             Shared library: [libcrypto.so.1.1]
 0x0000000000000001 (NEEDED)             Shared library: [libssl.so.1.1]

@qmfrederik
Copy link
Contributor Author

When I use main, OpenSSL is not detected in cygcrypto-1.0.0.dll. The text

OpenSSL 1.0.2t  10 Sep 2019
built on: reproducible build, date unspecified
platform: Cygwin-x86_64

includes an underscore (via Cygwin-x86_64) which is not matched by the OpenSSL ([0-9]+\.[0-9]+\.[0-9]+[a-z]*) [a-zA-Z0-9 ]+\r?\n(?:%s \(Library: %s\)|[a-zA-Z0-9:, \.\-\r\n]*OPENSSLDIR|ssl) pattern (but adding a _ is an easy fix there).

For node, yes, I'm using libnode72 which is part of Ubuntu 24.04 (http://security.ubuntu.com/ubuntu/pool/universe/n/nodejs/libnode72_12.22.9~dfsg-1ubuntu3.6_amd64.deb).

That does not dynamically link with OpenSSL:

ldd /usr/lib/x86_64-linux-gnu/libnode.so.72 
        linux-vdso.so.1 (0x00007fc1d14a1000)
        libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007fc1ced19000)
        libuv.so.1 => /lib/x86_64-linux-gnu/libuv.so.1 (0x00007fc1cece7000)
        libbrotlidec.so.1 => /lib/x86_64-linux-gnu/libbrotlidec.so.1 (0x00007fc1cecd9000)
        libbrotlienc.so.1 => /lib/x86_64-linux-gnu/libbrotlienc.so.1 (0x00007fc1cec48000)
        libcares.so.2 => /lib/x86_64-linux-gnu/libcares.so.2 (0x00007fc1cec31000)
        libnghttp2.so.14 => /lib/x86_64-linux-gnu/libnghttp2.so.14 (0x00007fc1cec05000)
        libicui18n.so.70 => /lib/x86_64-linux-gnu/libicui18n.so.70 (0x00007fc1ce8d6000)
        libicuuc.so.70 => /lib/x86_64-linux-gnu/libicuuc.so.70 (0x00007fc1ce6db000)
        libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fc1ce4af000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fc1ce3c8000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fc1ce3a8000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc1ce17d000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fc1d14a3000)
        libbrotlicommon.so.1 => /lib/x86_64-linux-gnu/libbrotlicommon.so.1 (0x00007fc1ce15a000)
        libicudata.so.70 => /lib/x86_64-linux-gnu/libicudata.so.70 (0x00007fc1cc53c000)

and the OpenSSL version string and the other keywords the regex is looking for appear to be pretty far from each other.

@ffontaine
Copy link
Contributor

Yes, adding _ in the pattern makes sense to catch the version in cygcrypto-1.0.0.dll.

Concerning nodejs, thanks for your link, this is an interesting topic.

When I grep for OpenSSL, it indeeds contains OpenSSL 1.1.1m 14 Dec 2021, this is really "frightening" that this old, unsecure and unmaintained (1.1.1 is EOL since September 2023) openssl version is embedded inside an Ubuntu 24.04 security nodejs release but this is another story and that's why cve-bin-tool is so useful ...

Basically, I see two approaches:

  • Do not update cve-bin-tool pattern: openssl will not be detected but the openssl fork used by nodejs has quite diverged from upstream openssl. 2505 commits above and 6070 commits behind official openssl repo on 3.1.7 branch: https://github.com/quictls/openssl.
  • Update the openssl pattern, for example by adding [a-zA-Z0-9/ \.\r\n]* before ssl to catch:
OpenSSL 1.1.1m  14 Dec 2021
DTLSv0.9
../deps/openssl/openssl/ssl/ssl_mcnf.c

I don't have any strong opinion, I'll let @terriko read all our messages. I'm quite confident that she will have helpful advice.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants