diff options
author | Hugo SIMELIERE <hsimeliere.opensource@witekio.com> | 2024-04-11 13:36:08 +0200 |
---|---|---|
committer | Steve Sakoman <steve@sakoman.com> | 2024-04-13 04:51:47 -0700 |
commit | b6f7111caf9da963f868cdb588b065f8bc936b1e (patch) | |
tree | fe61676a9925d8560e9bd8a6a21e5fcada1eba0c /meta | |
parent | b027cb1af8e5e19059eef63684db1edefef2bb54 (diff) | |
download | poky-b6f7111caf9da963f868cdb588b065f8bc936b1e.tar.gz |
shadow: fix CVE-2023-4641
Upstream-Status: Backport [https://github.com/shadow-maint/shadow/commit/65c88a43a23c2391dcc90c0abda3e839e9c57904]
(From OE-Core rev: d1f74ec0419dd13a23549cfdc228b91602bfb065)
Signed-off-by: Hugo SIMELIERE <hsimeliere.opensource@witekio.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
Diffstat (limited to 'meta')
-rw-r--r-- | meta/recipes-extended/shadow/files/CVE-2023-4641.patch | 146 | ||||
-rw-r--r-- | meta/recipes-extended/shadow/shadow.inc | 1 |
2 files changed, 147 insertions, 0 deletions
diff --git a/meta/recipes-extended/shadow/files/CVE-2023-4641.patch b/meta/recipes-extended/shadow/files/CVE-2023-4641.patch new file mode 100644 index 0000000000..75dbbad299 --- /dev/null +++ b/meta/recipes-extended/shadow/files/CVE-2023-4641.patch | |||
@@ -0,0 +1,146 @@ | |||
1 | From 51731b01fd9a608397da22b7b9164e4996f3d4c6 Mon Sep 17 00:00:00 2001 | ||
2 | From: Alejandro Colomar <alx@kernel.org> | ||
3 | Date: Sat, 10 Jun 2023 16:20:05 +0200 | ||
4 | Subject: [PATCH] gpasswd(1): Fix password leak | ||
5 | |||
6 | CVE: CVE-2023-4641 | ||
7 | Upstream-Status: Backport [https://github.com/shadow-maint/shadow/commit/65c88a43a23c2391dcc90c0abda3e839e9c57904] | ||
8 | |||
9 | How to trigger this password leak? | ||
10 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
11 | |||
12 | When gpasswd(1) asks for the new password, it asks twice (as is usual | ||
13 | for confirming the new password). Each of those 2 password prompts | ||
14 | uses agetpass() to get the password. If the second agetpass() fails, | ||
15 | the first password, which has been copied into the 'static' buffer | ||
16 | 'pass' via STRFCPY(), wasn't being zeroed. | ||
17 | |||
18 | agetpass() is defined in <./libmisc/agetpass.c> (around line 91), and | ||
19 | can fail for any of the following reasons: | ||
20 | |||
21 | - malloc(3) or readpassphrase(3) failure. | ||
22 | |||
23 | These are going to be difficult to trigger. Maybe getting the system | ||
24 | to the limits of memory utilization at that exact point, so that the | ||
25 | next malloc(3) gets ENOMEM, and possibly even the OOM is triggered. | ||
26 | About readpassphrase(3), ENFILE and EINTR seem the only plausible | ||
27 | ones, and EINTR probably requires privilege or being the same user; | ||
28 | but I wouldn't discard ENFILE so easily, if a process starts opening | ||
29 | files. | ||
30 | |||
31 | - The password is longer than PASS_MAX. | ||
32 | |||
33 | The is plausible with physical access. However, at that point, a | ||
34 | keylogger will be a much simpler attack. | ||
35 | |||
36 | And, the attacker must be able to know when the second password is being | ||
37 | introduced, which is not going to be easy. | ||
38 | |||
39 | How to read the password after the leak? | ||
40 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
41 | |||
42 | Provoking the leak yourself at the right point by entering a very long | ||
43 | password is easy, and inspecting the process stack at that point should | ||
44 | be doable. Try to find some consistent patterns. | ||
45 | |||
46 | Then, search for those patterns in free memory, right after the victim | ||
47 | leaks their password. | ||
48 | |||
49 | Once you get the leak, a program should read all the free memory | ||
50 | searching for patterns that gpasswd(1) leaves nearby the leaked | ||
51 | password. | ||
52 | |||
53 | On 6/10/23 03:14, Seth Arnold wrote: | ||
54 | > An attacker process wouldn't be able to use malloc(3) for this task. | ||
55 | > There's a handful of tools available for userspace to allocate memory: | ||
56 | > | ||
57 | > - brk / sbrk | ||
58 | > - mmap MAP_ANONYMOUS | ||
59 | > - mmap /dev/zero | ||
60 | > - mmap some other file | ||
61 | > - shm_open | ||
62 | > - shmget | ||
63 | > | ||
64 | > Most of these return only pages of zeros to a process. Using mmap of an | ||
65 | > existing file, you can get some of the contents of the file demand-loaded | ||
66 | > into the memory space on the first use. | ||
67 | > | ||
68 | > The MAP_UNINITIALIZED flag only works if the kernel was compiled with | ||
69 | > CONFIG_MMAP_ALLOW_UNINITIALIZED. This is rare. | ||
70 | > | ||
71 | > malloc(3) doesn't zero memory, to our collective frustration, but all the | ||
72 | > garbage in the allocations is from previous allocations in the current | ||
73 | > process. It isn't leftover from other processes. | ||
74 | > | ||
75 | > The avenues available for reading the memory: | ||
76 | > - /dev/mem and /dev/kmem (requires root, not available with Secure Boot) | ||
77 | > - /proc/pid/mem (requires ptrace privileges, mediated by YAMA) | ||
78 | > - ptrace (requires ptrace privileges, mediated by YAMA) | ||
79 | > - causing memory to be swapped to disk, and then inspecting the swap | ||
80 | > | ||
81 | > These all require a certain amount of privileges. | ||
82 | |||
83 | How to fix it? | ||
84 | ~~~~~~~~~~~~~~ | ||
85 | |||
86 | memzero(), which internally calls explicit_bzero(3), or whatever | ||
87 | alternative the system provides with a slightly different name, will | ||
88 | make sure that the buffer is zeroed in memory, and optimizations are not | ||
89 | allowed to impede this zeroing. | ||
90 | |||
91 | This is not really 100% effective, since compilers may place copies of | ||
92 | the string somewhere hidden in the stack. Those copies won't get zeroed | ||
93 | by explicit_bzero(3). However, that's arguably a compiler bug, since | ||
94 | compilers should make everything possible to avoid optimizing strings | ||
95 | that are later passed to explicit_bzero(3). But we all know that | ||
96 | sometimes it's impossible to have perfect knowledge in the compiler, so | ||
97 | this is plausible. Nevertheless, there's nothing we can do against such | ||
98 | issues, except minimizing the time such passwords are stored in plain | ||
99 | text. | ||
100 | |||
101 | Security concerns | ||
102 | ~~~~~~~~~~~~~~~~~ | ||
103 | |||
104 | We believe this isn't easy to exploit. Nevertheless, and since the fix | ||
105 | is trivial, this fix should probably be applied soon, and backported to | ||
106 | all supported distributions, to prevent someone else having more | ||
107 | imagination than us to find a way. | ||
108 | |||
109 | Affected versions | ||
110 | ~~~~~~~~~~~~~~~~~ | ||
111 | |||
112 | All. Bug introduced in shadow 19990709. That's the second commit in | ||
113 | the git history. | ||
114 | |||
115 | Fixes: 45c6603cc86c ("[svn-upgrade] Integrating new upstream version, shadow (19990709)") | ||
116 | Reported-by: Alejandro Colomar <alx@kernel.org> | ||
117 | Cc: Serge Hallyn <serge@hallyn.com> | ||
118 | Cc: Iker Pedrosa <ipedrosa@redhat.com> | ||
119 | Cc: Seth Arnold <seth.arnold@canonical.com> | ||
120 | Cc: Christian Brauner <christian@brauner.io> | ||
121 | Cc: Balint Reczey <rbalint@debian.org> | ||
122 | Cc: Sam James <sam@gentoo.org> | ||
123 | Cc: David Runge <dvzrv@archlinux.org> | ||
124 | Cc: Andreas Jaeger <aj@suse.de> | ||
125 | Cc: <~hallyn/shadow@lists.sr.ht> | ||
126 | Signed-off-by: Alejandro Colomar <alx@kernel.org> | ||
127 | Signed-off-by: Hugo SIMELIERE <hsimeliere.opensource@witekio.com> | ||
128 | --- | ||
129 | src/gpasswd.c | 1 + | ||
130 | 1 file changed, 1 insertion(+) | ||
131 | |||
132 | diff --git a/src/gpasswd.c b/src/gpasswd.c | ||
133 | index 4d75af96..a698b32a 100644 | ||
134 | --- a/src/gpasswd.c | ||
135 | +++ b/src/gpasswd.c | ||
136 | @@ -918,6 +918,7 @@ static void change_passwd (struct group *gr) | ||
137 | strzero (cp); | ||
138 | cp = getpass (_("Re-enter new password: ")); | ||
139 | if (NULL == cp) { | ||
140 | + memzero (pass, sizeof pass); | ||
141 | exit (1); | ||
142 | } | ||
143 | |||
144 | -- | ||
145 | 2.42.0 | ||
146 | |||
diff --git a/meta/recipes-extended/shadow/shadow.inc b/meta/recipes-extended/shadow/shadow.inc index 2ecab5073d..c16292c38a 100644 --- a/meta/recipes-extended/shadow/shadow.inc +++ b/meta/recipes-extended/shadow/shadow.inc | |||
@@ -16,6 +16,7 @@ SRC_URI = "https://github.com/shadow-maint/shadow/releases/download/${PV}/${BP}. | |||
16 | file://shadow-relaxed-usernames.patch \ | 16 | file://shadow-relaxed-usernames.patch \ |
17 | file://CVE-2023-29383.patch \ | 17 | file://CVE-2023-29383.patch \ |
18 | file://0001-Overhaul-valid_field.patch \ | 18 | file://0001-Overhaul-valid_field.patch \ |
19 | file://CVE-2023-4641.patch \ | ||
19 | " | 20 | " |
20 | 21 | ||
21 | SRC_URI_append_class-target = " \ | 22 | SRC_URI_append_class-target = " \ |