]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
pgsql: add query keyword 13331/head
authorJuliana Fajardini <jufajardini@oisf.net>
Sun, 25 May 2025 21:58:40 +0000 (18:58 -0300)
committerVictor Julien <victor@inliniac.net>
Wed, 28 May 2025 17:08:07 +0000 (19:08 +0200)
Add the `pgsql.query` rule keyword to match on PGSQL's query
request message contents. This currently matches on the EVE field:

pgsql.request.simple_query

`pgsql.query` is a sticky buffer and can be used as a fast_pattern.

Task #6259

doc/userguide/rules/index.rst
doc/userguide/rules/pgsql-keywords.rst [new file with mode: 0644]
rust/src/pgsql/detect.rs [new file with mode: 0644]
rust/src/pgsql/mod.rs
rust/src/pgsql/pgsql.rs
src/detect-engine-register.c

index c4b42fa2d88a4e39a2678b5a178921192eff79fb..a1192741c92f5e1e97deb5c8e8f90109867d22f2 100644 (file)
@@ -53,5 +53,6 @@ Suricata Rules
    tag
    vlan-keywords
    ldap-keywords
+   pgsql-keywords
    rule-types
    email-keywords
diff --git a/doc/userguide/rules/pgsql-keywords.rst b/doc/userguide/rules/pgsql-keywords.rst
new file mode 100644 (file)
index 0000000..8c63233
--- /dev/null
@@ -0,0 +1,33 @@
+PGSQL Keywords
+##############
+
+.. role:: example-rule-emphasis
+
+pgsql.query
+***********
+
+This keyword is a sticky buffer that allows matching on the contents of
+PostgreSQL's `query` request messages parsed by the engine. Note that this
+buffer inspects only the `string` portion of the PostgreSQL message, skipping
+other fields such as identifier and length, and focusing on the query itself.
+
+Currently, it exposes the contents of the ``pgsql.request.simple_query`` field
+from EVE output.
+
+``pgsql.query`` can be used as a ``fast_pattern``
+(see :ref:`rules-keyword-fast_pattern`).
+
+Use ``nocase`` with this keyword to avoid case sensitivity for the matches.
+
+Examples
+========
+
+.. container:: example-rule
+
+    alert pgsql any any -> any any (msg:"Simple SELECT rule";
+    :example-rule-emphasis:`pgsql.query; content:"SELECT \*";` sid:1;)
+
+.. container:: example-rule
+
+    alert pgsql any any -> any any (msg:"Simple delete rule";
+    :example-rule-emphasis:`pgsql.query; content:"delete"; nocase` sid:2;)
diff --git a/rust/src/pgsql/detect.rs b/rust/src/pgsql/detect.rs
new file mode 100644 (file)
index 0000000..de58f8a
--- /dev/null
@@ -0,0 +1,76 @@
+/* Copyright (C) 2025 Open Information Security Foundation
+ *
+ * You can copy, redistribute or modify this Program under the terms of
+ * the GNU General Public License version 2 as published by the Free
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+// written by Juliana Fajardini <jufajardini@oisf.net>
+
+use super::pgsql::{PgsqlTransaction, ALPROTO_PGSQL};
+use crate::pgsql::parser::PgsqlFEMessage;
+use crate::core::{STREAM_TOSERVER};
+use crate::detect::{helper_keyword_register_sticky_buffer, SigTableElmtStickyBuffer};
+use suricata_sys::sys::{
+    DetectEngineCtx, SCDetectBufferSetActiveList, SCDetectHelperBufferMpmRegister, SCDetectSignatureSetAppProto,
+    Signature,
+};
+use std::os::raw::{c_int, c_void};
+
+static mut G_PGSQL_QUERY_BUFFER_ID: c_int = 0;
+
+unsafe extern "C" fn pgsql_detect_query_setup(
+    de: *mut DetectEngineCtx, s: *mut Signature, _raw: *const std::os::raw::c_char,) -> c_int
+{
+    if SCDetectSignatureSetAppProto(s, ALPROTO_PGSQL) != 0 {
+        return - 1;
+    }
+    if SCDetectBufferSetActiveList(de, s, G_PGSQL_QUERY_BUFFER_ID) < 0 {
+        return - 1;
+    }
+    0
+}
+
+unsafe extern "C" fn pgsql_detect_query_get_data(
+    tx: *const c_void, _flags: u8, buffer: *mut *const u8, buffer_len: *mut u32,
+) -> bool {
+    let tx = cast_pointer!(tx, PgsqlTransaction);
+
+    if let Some(PgsqlFEMessage::SimpleQuery(ref query)) = &tx.request {
+        *buffer = query.payload.as_ptr();
+        *buffer_len = query.payload.len() as u32;
+        return true;
+    }
+
+    *buffer = std::ptr::null();
+    *buffer_len = 0;
+    false
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn SCDetectPgsqlRegister() {
+    let kw = SigTableElmtStickyBuffer {
+        name: String::from("pgsql.query"),
+        desc: String::from("match PGSQL  query request content"),
+        url: String::from("/rules/pgsql-keywords.html#pgsql.query"),
+        setup: pgsql_detect_query_setup,
+    };
+    let _g_pgsql_query_kw_id = helper_keyword_register_sticky_buffer(&kw);
+    G_PGSQL_QUERY_BUFFER_ID = SCDetectHelperBufferMpmRegister(
+        b"pgsql.query\0".as_ptr() as *const libc::c_char,
+        b"pgsql query request content\0".as_ptr() as *const libc::c_char,
+        ALPROTO_PGSQL,
+        STREAM_TOSERVER,
+        Some(pgsql_detect_query_get_data),
+    );
+}
index a4c79c03192f9dbae20241712ee36abfeb2f262b..3c329139381fc5976ea6c96c66251d68070217a8 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2022 Open Information Security Foundation
+/* Copyright (C) 2022-2025 Open Information Security Foundation
  *
  * You can copy, redistribute or modify this Program under the terms of
  * the GNU General Public License version 2 as published by the Free
@@ -19,6 +19,7 @@
 //!
 //! written by Juliana Fajardini <jufajardini@oisf.net>
 
+pub mod detect;
 pub mod logger;
 pub mod parser;
 pub mod pgsql;
index 14d5f09f4f6c9ed2f1e98d3e3a16eb0dbe0dd45e..eba26cbebd548a5c2cda455a2a5d5886005b3f84 100644 (file)
@@ -34,7 +34,7 @@ use suricata_sys::sys::AppProto;
 
 pub const PGSQL_CONFIG_DEFAULT_STREAM_DEPTH: u32 = 0;
 
-static mut ALPROTO_PGSQL: AppProto = ALPROTO_UNKNOWN;
+pub(crate) static mut ALPROTO_PGSQL: AppProto = ALPROTO_UNKNOWN;
 
 static mut PGSQL_MAX_TX: usize = 1024;
 
index 741baffdc42652d38b3f3d3470a2cdcd1cd65df2..a5899f33377c8a070c73b57be97f158eac8a0d5e 100644 (file)
@@ -772,6 +772,7 @@ void SigTableSetup(void)
     SCDetectLdapRegister();
     SCDetectSdpRegister();
     SCDetectDNSRegister();
+    SCDetectPgsqlRegister();
 
     for (size_t i = 0; i < preregistered_callbacks_nb; i++) {
         PreregisteredCallbacks[i]();