Summary
=======

Rajesh Pangare discovered a null pointer dereference vulnerability in AIDE, an
advanced intrusion detection system. An attacker can crash the program during
report printing or database listing after setting extended file attributes with
an empty attribute value or with a key containing a comma. A local user might
exploit this to cause a local denial of service.

Project
=======

AIDE (https://aide.github.io)

Affected versions
=================

AIDE >= 0.13, <= 0.19.1

CVE ID
======

CVE-2025-54409

Proof of concept
================

To take advantage of the flaw the user needs write access to a mounted file
system that supports extended file attributes. aide also needs to be compiled
with --with-xattr configure flag (this is the case for most distributions).

## listing aide database with empty extended attribute value
    $ touch xattrs-file ; setfattr -n user.empty_value xattrs-file
    # aide --config <(printf -- "database_out=stdout\n$(pwd)/xattrs-file 
xattrs\n") --init | aide --config <(printf -- 
"database_in=stdin\n$(pwd)/xattrs-file xattrs\n") --list

## checking aide database with extended attribute key containing a comma
    $ touch xattrs-file ; setfattr -n user.ke,y -v value xattrs-file
    # aide --config <(printf -- "database_out=stdout\n$(pwd)/xattrs-file 
xattrs\n") --init | aide --config <(printf -- 
"database_in=stdin\n$(pwd)/xattrs-file xattrs\n") --check

Please note that the segfault only occurs on the second run of aide after the
extended file attribute has been written to the database in the first run
(provided the xattr value is shown in the report due to a change or the
database is listed via --list).

Analysis
========

The vulnerability is caused by missing error handling while decoding the base64
encoded xattr attribute from the database and incorrectly handling of empty 
xattr
attribute values and attribute keys containing a comma.

This allows a user to craft a file with an extended file attribute causing aide
to dereference a null pointer and segfault.

Mitigation
==========

Upgrade to AIDE v0.19.2 [v0.19.2]

Alternatively apply one of the provided patches:

aide-0.19_cve-2025-54409_xattr.patch for 0.19.1
aide-0.18_cve-2025-54409_xattr.patch for 0.18.8 (backported for Debian Bookworm)
aide-0.17_cve-2025-54409_xattr.patch for 0.17.4 (backported for Debian Bullseye)

If you cannot upgrade, consider removing `xattrs` group from rules matching
files on affected file systems.

[v0.19.2] https://github.com/aide/aide/releases/tag/v0.19.2

Credit
======

The issue was reported by Rajesh Pangare.
diff --git before/src/db.c after/src/db.c
index ac55f0a..ac842bc 100644
--- before/src/db.c
+++ after/src/db.c
@@ -351,17 +351,27 @@ db_line* db_char2line(char** ss, database* db){
           num = 0;
           while (num < line->xattrs->num)
           {
-            byte  *val = NULL;
-            size_t vsz = 0;
-            
             tval = strtok(NULL, ",");
             line->xattrs->ents[num].key = db_readchar(checked_strdup(tval));
             tval = strtok(NULL, ",");
-            val = base64tobyte(tval, strlen(tval), &vsz);
-            line->xattrs->ents[num].val = val;
-            line->xattrs->ents[num].vsz = vsz;
-
-            ++num;
+            if (strcmp(tval,"0") != 0) {
+                line->xattrs->ents[num].val = decode_base64(tval, strlen(tval), &line->xattrs->ents[num].vsz);
+            } else {
+                line->xattrs->ents[num].val = checked_strdup("");
+                line->xattrs->ents[num].vsz = 0;
+            }
+            if (line->xattrs->ents[num].val == NULL) {
+                LOG_DB_FORMAT_LINE(LOG_LEVEL_WARNING, "error while reading xattrs for '%s' from database (discarding extended attributes)", line->filename)
+                for (int j = num; j >= 0 ; --j) {
+                    free(line->xattrs->ents[j].key);
+                    line->xattrs->ents[j].key = NULL;
+                    free(line->xattrs->ents[j].val);
+                    line->xattrs->ents[j].val = NULL;
+                }
+                line->xattrs->num = 0;
+            } else {
+                ++num;
+            }
           }
         }
         break;
diff --git before/src/util.c after/src/util.c
index ba7359e..092457e 100644
--- before/src/util.c
+++ after/src/util.c
@@ -39,7 +39,7 @@
 #include "db_config.h"
 #include "util.h"
 
-#define URL_UNSAFE " <>\"#%{}|\\^~[]`@:\033'"
+#define URL_UNSAFE " <>\"#%{}|\\^~[]`@:\033',"
 #define ISPRINT(c) (isascii(c) && isprint(c))
 
 const char* btoa(bool b) {
diff --git before/src/db.c after/src/db.c
index dfcc973..4a16236 100644
--- before/src/db.c
+++ after/src/db.c
@@ -351,17 +351,27 @@ db_line* db_char2line(char** ss, database* db){
           num = 0;
           while (num < line->xattrs->num)
           {
-            byte  *val = NULL;
-            size_t vsz = 0;
-            
             tval = strtok(NULL, ",");
             line->xattrs->ents[num].key = db_readchar(checked_strdup(tval));
             tval = strtok(NULL, ",");
-            val = base64tobyte(tval, strlen(tval), &vsz);
-            line->xattrs->ents[num].val = val;
-            line->xattrs->ents[num].vsz = vsz;
-
-            ++num;
+            if (strcmp(tval,"0") != 0) {
+                line->xattrs->ents[num].val = decode_base64(tval, strlen(tval), &line->xattrs->ents[num].vsz);
+            } else {
+                line->xattrs->ents[num].val = checked_strdup("");
+                line->xattrs->ents[num].vsz = 0;
+            }
+            if (line->xattrs->ents[num].val == NULL) {
+                LOG_DB_FORMAT_LINE(LOG_LEVEL_WARNING, "error while reading xattrs for '%s' from database (discarding extended attributes)", line->filename)
+                for (int j = num; j >= 0 ; --j) {
+                    free(line->xattrs->ents[j].key);
+                    line->xattrs->ents[j].key = NULL;
+                    free(line->xattrs->ents[j].val);
+                    line->xattrs->ents[j].val = NULL;
+                }
+                line->xattrs->num = 0;
+            } else {
+                ++num;
+            }
           }
         }
 #endif
diff --git before/src/util.c after/src/util.c
index f5c5e60..49ac5da 100644
--- before/src/util.c
+++ after/src/util.c
@@ -45,7 +45,7 @@
 #include "util.h"
 #include "errorcodes.h"
 
-#define URL_UNSAFE " <>\"#%{}|\\^~[]`@:\033'"
+#define URL_UNSAFE " <>\"#%{}|\\^~[]`@:\033',"
 #define ISPRINT(c) (isascii(c) && isprint(c))
 
 const char* btoa(bool b) {
diff --git before/src/db.c after/src/db.c
index 6675e19..375b220 100644
--- before/src/db.c
+++ after/src/db.c
@@ -374,18 +374,28 @@ db_line* db_char2line(char** ss, database* db){
           num = 0;
           while (num < line->xattrs->num)
           {
-            byte  *val = NULL;
-            size_t vsz = 0;
-            
             tval = strtok(NULL, ",");
             decode_string(tval);
             line->xattrs->ents[num].key = checked_strdup(tval);
             tval = strtok(NULL, ",");
-            val = base64tobyte(tval, strlen(tval), &vsz);
-            line->xattrs->ents[num].val = val;
-            line->xattrs->ents[num].vsz = vsz;
-
-            ++num;
+            if (strcmp(tval,"0") != 0) {
+                line->xattrs->ents[num].val = decode_base64(tval, strlen(tval), &line->xattrs->ents[num].vsz);
+            } else {
+                line->xattrs->ents[num].val = checked_strdup("");
+                line->xattrs->ents[num].vsz = 0;
+            }
+            if (line->xattrs->ents[num].val == NULL) {
+                LOG_DB_FORMAT_LINE(LOG_LEVEL_WARNING, "error while reading xattrs for '%s' from database (discarding extended attributes)", line->filename)
+                for (int j = num; j >= 0 ; --j) {
+                    free(line->xattrs->ents[j].key);
+                    line->xattrs->ents[j].key = NULL;
+                    free(line->xattrs->ents[j].val);
+                    line->xattrs->ents[j].val = NULL;
+                }
+                line->xattrs->num = 0;
+            } else {
+                ++num;
+            }
           }
         }
 #endif
diff --git before/src/db_file.c after/src/db_file.c
index e016e11..505f8af 100644
--- before/src/db_file.c
+++ after/src/db_file.c
@@ -377,7 +377,7 @@ static int str_xattr(char *str, int n, xattrs_type *xattrs) {
                 enc_key = encode_string(xattr->key);
             }
             char *enc_value = encode_base64(xattr->val, xattr->vsz);
-            m += str_format(str, n + m, ",%s,%s", enc_key?enc_key:xattr->key, enc_value);
+            m += str_format(str, n + m, ",%s,%s", enc_key?enc_key:xattr->key, enc_value?enc_value:"0");
             free(enc_key);
             free(enc_value);
             ++xattr;
diff --git before/src/util.c after/src/util.c
index 2df2c19..edc7453 100644
--- before/src/util.c
+++ after/src/util.c
@@ -48,7 +48,7 @@
 #include "util.h"
 #include "errorcodes.h"
 
-#define URL_UNSAFE " <>\"#%{}|\\^~[]`@:\033'"
+#define URL_UNSAFE " <>\"#%{}|\\^~[]`@:\033',"
 #define ISPRINT(c) (isascii(c) && isprint(c))
 
 pthread_mutex_t stderr_mutex = PTHREAD_MUTEX_INITIALIZER;

Attachment: signature.asc
Description: PGP signature

Reply via email to