slimm609 / checksec.sh

Checksec.sh
https://slimm609.github.io/checksec.sh/
Other
1.99k stars 299 forks source link

Different results between v2.6.0 and v2.7.0 #246

Closed voxik closed 3 months ago

voxik commented 3 months ago

Using checksec to check fortification of Ruby in Fedora, the check passes with v2.6.0 while it fails with v2.7.0. The main difference is that FORTIFY reports Yes for the former while No for the latter. Here are some details:

2.6.0

$ checksec --version
WARNING: 'openssl' not found! It's required for most checks.

WARNING: Not all necessary commands found. Some tests might not work!

checksec v2.6.0, Brian Davis, github.com/slimm609/checksec.sh, Dec 2015
Based off checksec v1.5, Tobias Klein, www.trapkit.de, November 2011

$ checksec --file=redhat-linux-build/libruby.so.3.3.1 
WARNING: 'openssl' not found! It's required for most checks.

WARNING: Not all necessary commands found. Some tests might not work!

RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH  Symbols     FORTIFY Fortified   Fortifiable FILE
Full RELRO      Canary found      NX enabled    DSO             No RPATH   No RUNPATH   33201 Symbols     Yes   11      28      redhat-linux-build/libruby.so.3.3.1

$ checksec --fortify-file=redhat-linux-build/libruby.so.3.3.1 
WARNING: 'openssl' not found! It's required for most checks.

WARNING: Not all necessary commands found. Some tests might not work!

* FORTIFY_SOURCE support available (libc)    : Yes
* Binary compiled with FORTIFY_SOURCE support: Yes

 ------ EXECUTABLE-FILE ------- . -------- LIBC --------
 Fortifiable library functions | Checked function names
 -------------------------------------------------------
 strlcpy_chk                    | __strlcpy_chk
 strlcpy                        | __strlcpy_chk
 strlcpy_chk                    | __strlcpy_chk
 strlcpy                        | __strlcpy_chk
 poll                           | __poll_chk
 poll                           | __poll_chk
 realpath                       | __realpath_chk
 realpath                       | __realpath_chk
 stpcpy                         | __stpcpy_chk
 stpcpy                         | __stpcpy_chk
 getlogin_r                     | __getlogin_r_chk
 getlogin_r                     | __getlogin_r_chk
 printf_chk                     | __printf_chk
 printf_chk                     | __printf_chk
 getgroups                      | __getgroups_chk
 getgroups_chk                  | __getgroups_chk
 getgroups                      | __getgroups_chk
 getgroups_chk                  | __getgroups_chk
 longjmp_chk                    | __longjmp_chk
 longjmp                        | __longjmp_chk
 longjmp_chk                    | __longjmp_chk
 longjmp                        | __longjmp_chk
 ppoll                          | __ppoll_chk
 ppoll                          | __ppoll_chk
 explicit_bzero_chk             | __explicit_bzero_chk
 explicit_bzero_chk             | __explicit_bzero_chk
 memcpy_chk                     | __memcpy_chk
 memcpy                         | __memcpy_chk
 memcpy_chk                     | __memcpy_chk
 memcpy                         | __memcpy_chk
 vfprintf_chk                   | __vfprintf_chk
 vfprintf_chk                   | __vfprintf_chk
 vsnprintf_chk                  | __vsnprintf_chk
 vsnprintf_chk                  | __vsnprintf_chk
 memmove                        | __memmove_chk
 memmove_chk                    | __memmove_chk
 memmove                        | __memmove_chk
 memmove_chk                    | __memmove_chk
 fprintf_chk                    | __fprintf_chk
 fprintf_chk                    | __fprintf_chk
 fread                          | __fread_chk
 fread                          | __fread_chk
 strlcat                        | __strlcat_chk
 strlcat                        | __strlcat_chk
 memset                         | __memset_chk
 memset_chk                     | __memset_chk
 memset                         | __memset_chk
 memset_chk                     | __memset_chk
 getcwd                         | __getcwd_chk
 getcwd                         | __getcwd_chk
 read                           | __read_chk
 read                           | __read_chk
 pread                          | __pread_chk
 pread                          | __pread_chk
 readlink                       | __readlink_chk
 readlink                       | __readlink_chk

SUMMARY:

* Number of checked functions in libc                : 83
* Total number of library functions in the executable: 35355
* Number of Fortifiable functions in the executable : 56
* Number of checked functions in the executable      : 22
* Number of unchecked functions in the executable    : 34

2.7.0

$ checksec --version
WARNING: 'openssl' not found! It's required for most checks.

WARNING: Not all necessary commands found. Some tests might not work!

checksec v2.7.0, Brian Davis, github.com/slimm609/checksec.sh, Dec 2015
Based off checksec v1.5, Tobias Klein, www.trapkit.de, November 2011

$ checksec --file=redhat-linux-build/libruby.so.3.3.1 
WARNING: 'openssl' not found! It's required for most checks.

WARNING: Not all necessary commands found. Some tests might not work!

RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH  Symbols     FORTIFY Fortified   Fortifiable FILE
Full RELRO      Canary found      NX enabled    DSO             No RPATH   No RUNPATH   33201 Symbols     No    11      28      redhat-linux-build/libruby.so.3.3.1

$ checksec --fortify-file=redhat-linux-build/libruby.so.3.3.1 
WARNING: 'openssl' not found! It's required for most checks.

WARNING: Not all necessary commands found. Some tests might not work!

* FORTIFY_SOURCE support available (libc)    : Yes
* Binary compiled with FORTIFY_SOURCE support: Yes

 ------ EXECUTABLE-FILE ------- . -------- LIBC --------
 Fortifiable library functions | Checked function names
 -------------------------------------------------------
 explicit_bzero_chk             | __explicit_bzero_chk
 fprintf_chk                    | __fprintf_chk
 fread                          | __fread_chk
 getcwd                         | __getcwd_chk
 getgroups                      | __getgroups_chk
 getgroups_chk                  | __getgroups_chk
 getlogin_r                     | __getlogin_r_chk
 longjmp                        | __longjmp_chk
 longjmp_chk                    | __longjmp_chk
 memcpy                         | __memcpy_chk
 memcpy_chk                     | __memcpy_chk
 memmove                        | __memmove_chk
 memmove_chk                    | __memmove_chk
 memset                         | __memset_chk
 memset_chk                     | __memset_chk
 poll                           | __poll_chk
 ppoll                          | __ppoll_chk
 pread                          | __pread_chk
 printf_chk                     | __printf_chk
 read                           | __read_chk
 readlink                       | __readlink_chk
 realpath                       | __realpath_chk
 stpcpy                         | __stpcpy_chk
 strlcat                        | __strlcat_chk
 strlcpy                        | __strlcpy_chk
 strlcpy_chk                    | __strlcpy_chk
 vfprintf_chk                   | __vfprintf_chk
 vsnprintf_chk                  | __vsnprintf_chk

SUMMARY:

* Number of checked functions in libc                : 83
* Total number of library functions in the executable: 14093
* Number of Fortifiable functions in the executable : 28
* Number of checked functions in the executable      : 11
* Number of unchecked functions in the executable    : 17
teoberi commented 3 months ago

See here. Try 2.7.1 from here. After accepting Pull requests from here, it will be OK for processes as well.

voxik commented 3 months ago

Thx for all the pointers 👏

voxik commented 3 months ago

Trying with 2.7.1, these are the results now:

$ checksec --version
WARNING: 'openssl' not found! It's required for most checks.

WARNING: Not all necessary commands found. Some tests might not work!

checksec v2.7.1, Brian Davis, github.com/slimm609/checksec.sh, Dec 2015
Based off checksec v1.5, Tobias Klein, www.trapkit.de, November 2011

 checksec --file=redhat-linux-build/libruby.so.3.3.1
WARNING: 'openssl' not found! It's required for most checks.

WARNING: Not all necessary commands found. Some tests might not work!

RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH  Symbols     FORTIFY Fortified   Fortifiable FILE
Full RELRO      Canary found      NX enabled    DSO             No RPATH   No RUNPATH   33201 Symbols     Partial   11      28      redhat-linux-build/libruby.so.3.3.1

$ checksec --fortify-file=redhat-linux-build/libruby.so.3.3.1 
WARNING: 'openssl' not found! It's required for most checks.

WARNING: Not all necessary commands found. Some tests might not work!

* FORTIFY_SOURCE support available (libc)    : Yes
* Binary compiled with FORTIFY_SOURCE support: Yes

 ------ EXECUTABLE-FILE ------- . -------- LIBC --------
 Fortifiable library functions | Checked function names
 -------------------------------------------------------
 explicit_bzero_chk             | __explicit_bzero_chk
 fprintf_chk                    | __fprintf_chk
 fread                          | __fread_chk
 getcwd                         | __getcwd_chk
 getgroups                      | __getgroups_chk
 getgroups_chk                  | __getgroups_chk
 getlogin_r                     | __getlogin_r_chk
 longjmp                        | __longjmp_chk
 longjmp_chk                    | __longjmp_chk
 memcpy                         | __memcpy_chk
 memcpy_chk                     | __memcpy_chk
 memmove                        | __memmove_chk
 memmove_chk                    | __memmove_chk
 memset                         | __memset_chk
 memset_chk                     | __memset_chk
 poll                           | __poll_chk
 ppoll                          | __ppoll_chk
 pread                          | __pread_chk
 printf_chk                     | __printf_chk
 read                           | __read_chk
 readlink                       | __readlink_chk
 realpath                       | __realpath_chk
 stpcpy                         | __stpcpy_chk
 strlcat                        | __strlcat_chk
 strlcpy                        | __strlcpy_chk
 strlcpy_chk                    | __strlcpy_chk
 vfprintf_chk                   | __vfprintf_chk
 vsnprintf_chk                  | __vsnprintf_chk

SUMMARY:

* Number of checked functions in libc                : 83
* Total number of library functions in the executable: 14093
* Number of Fortifiable functions in the executable : 28
* Number of checked functions in the executable      : 11
* Number of unchecked functions in the executable    : 17

So the FORTIFY changed from No to Partial.

However now I am puzzled how to interpret the results. I guess the reason for Partial is the "* Number of unchecked functions in the executable : 17". Is there something to do about them?

teoberi commented 3 months ago

The coded cases can now be: https://github.com/slimm609/checksec.sh/blob/a5819f3c4e424f46a1a8c33b19c1ad1f09cb6689/src/functions/filecheck.sh#L144

Better Partial than No or worse Yes depends on the case! https://github.com/slimm609/checksec.sh/issues/235#issuecomment-2092442077

voxik commented 3 months ago

Better Partial than No or worse Yes depends on the case!

👍

I think I start to understand what is going on. Looking back at the 2.6.0 outputs, this:

FORTIFY Fortified   Fortifiable
Yes 11      28

correlates with the:

* Number of Fortifiable functions in the executable : 28
* Number of checked functions in the executable      : 11
* Number of unchecked functions in the executable    : 17

In 2.7, this was changed that the FORTIFY == Yes only when the result would be:

* Number of Fortifiable functions in the executable : 28
* Number of checked functions in the executable      : 28
* Number of unchecked functions in the executable    : 0

And FORTIFY == No for the following case

* Number of Fortifiable functions in the executable : 28
* Number of checked functions in the executable      : 0
* Number of unchecked functions in the executable    : 28

All in between is Partial.

Just let me explain the context why I am using checksec. This started with Fedora introducing fortification flags. My memory is a bit hazy, but I believe that either there was some issue and despite Fedora setting the fortification, Ruby was not fortified. Or maybe I just wanted to be sure that I won't mess up. Therefore I have added the checksec into the mix, while I can't say I really know what I am doing.

Based on this: 1) I'd still rather use checksec naively, i.e. ensuring there are no changes between Ruby builds. If there are changes, make sure I know about them and asking experts for help. 2) The output of the tool could be more helpful (and yes, it seems that the Partial intends to improve this 👍). Up until now, I had no idea what the Fortified / Fortifiable fields means and that they are actually used to derive the FORTIFY value. In retrospect, checking the Fortified / Fortifiable fields and ignoring the FORTIFY value altogether would make more sense for my case. Maybe all these fields should have been combined into one field or either the numbers or just the FORTIFY status displayed based on the --verbose / --extended flags. Alternatively, this could be better captured in documentation / manpages

Nevertheless, I am closing this ticket, because my original concern was addressed. Thank you for your support.