Hi
I want to use lua to verify jwt token from http.uri. but I can’t found any lua function to implement it. so I wirte a c library and call c function in lua script. it works when I run a test. but I meet an error when I use this script and library in suricata.
suricata.rule:
alert http any any -> any any (msg:"nacos"; flow: established, to_server; http.uri; content:"/nacos/v1/cs/configs"; lua:./lua/nacos_default_jwt.lua; flowbits: set, nacos.1000001; flowbits: noalert; classtype:bad-unknown; sid: 1000001; rev: 1;)
nacos_default_jwt.lua:
local jwt_lib = require("jwt_library")
local nacos_default_secret="SecretKey012345678901234567890123456789012345678901234567890123456789"
local function extract_access_token(url)
local token = url:match("accessToken=([^&]+)")
return token
end
function init (args)
local needs = {}
needs["http.uri"] = tostring(true)
return needs
end
function match(args)
local http_uri = tostring(args["http.uri"])
if not http_uri then
return 0
end
local token = extract_access_token(http_uri)
if not token then
return 0
end
SCLogInfo("extract jwt token success: " .. token)
local result = jwt_lib.validate_jwt(token, nacos_default_secret)
SCLogInfo("result: " ..result)
return 0
end
return 0
jwt_library.c
// jwt_library.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/bio.h>
#include <openssl/evp.h>
#include <jwt.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
unsigned char *base64_decode(const char *base64, size_t *out_len) {
BIO *bio, *b64;
size_t len = strlen(base64);
unsigned char *decoded_data = malloc(len);
if (!decoded_data) {
perror("malloc");
exit(EXIT_FAILURE);
}
b64 = BIO_new(BIO_f_base64());
bio = BIO_new_mem_buf(base64, -1);
bio = BIO_push(b64, bio);
*out_len = BIO_read(bio, decoded_data, len);
BIO_free_all(bio);
return decoded_data;
}
int validate_jwt(const char *token, const char *base64_key) {
size_t key_len;
unsigned char *key = base64_decode(base64_key, &key_len);
jwt_t *jwt = NULL;
int ret = jwt_decode(&jwt, token, key, key_len);
free(key);
if (ret) {
return 0;
}
jwt_free(jwt);
return 1;
}
int lua_validate_jwt(lua_State *L) {
const char *token = luaL_checkstring(L, 1);
const char *base64_key = luaL_checkstring(L, 2);
int result = validate_jwt(token, base64_key);
lua_pushboolean(L, result);
return 1;
}
int luaopen_jwt_library(lua_State *L) {
static const struct luaL_Reg jwt_lib[] = {
{"validate_jwt", lua_validate_jwt},
{NULL, NULL}
};
luaL_register(L, "jwt_library", jwt_lib);
return 1;
}
suricata.log:
[8734 - Suricata-Main] 2024-07-25 21:00:36 Notice: suricata: This is Suricata version 8.0.0-dev (87c00acbd 2024-07-12) running in SYSTEM mode
[8734 - Suricata-Main] 2024-07-25 21:00:36 Info: cpu: CPUs/cores online: 1
[8734 - Suricata-Main] 2024-07-25 21:00:36 Info: suricata: Setting engine mode to IDS mode by default
[8734 - Suricata-Main] 2024-07-25 21:00:36 Info: exception-policy: master exception-policy set to: auto
[8734 - Suricata-Main] 2024-07-25 21:00:36 Info: ioctl: enp0s8: MTU 1500
[8734 - Suricata-Main] 2024-07-25 21:00:36 Info: suricata: Use pid file /var/lib/suricata/suricata.pid from config file.
[8735 - Suricata-Main] 2024-07-25 21:00:36 Info: suricata: Preparing unexpected signal handling
[8735 - Suricata-Main] 2024-07-25 21:00:36 Info: conf: Running in live mode, activating unix socket
[8735 - Suricata-Main] 2024-07-25 21:00:36 Info: logopenfile: eve-log output device (regular) initialized: alert.json
[8735 - Suricata-Main] 2024-07-25 21:00:36 Info: logopenfile: eve-log output device (regular) initialized: flow.json
[8735 - Suricata-Main] 2024-07-25 21:00:36 Info: logopenfile: eve-log output device (regular) initialized: tls.json
[8735 - Suricata-Main] 2024-07-25 21:00:36 Info: logopenfile: eve-log output device (regular) initialized: eve.json
[8735 - Suricata-Main] 2024-07-25 21:00:36 Info: logopenfile: alert-debug output device (regular) initialized: alert-debug.log
[8735 - Suricata-Main] 2024-07-25 21:00:36 Info: logopenfile: stats output device (regular) initialized: stats.log
[8735 - Suricata-Main] 2024-07-25 21:00:36 Info: classification-config: Added "43" classification types from the classification file
[8735 - Suricata-Main] 2024-07-25 21:00:36 Info: reference-config: Added "19" reference types from the reference.config file
[8735 - Suricata-Main] 2024-07-25 21:00:36 Error: detect-lua: couldn't prime file: error loading module 'jwt_library' from file '/var/lib/jwt_library.so':
/var/lib/jwt_library.so:1: unexpected symbol near '<\127>'
[8735 - Suricata-Main] 2024-07-25 21:00:36 Error: detect: error parsing signature "alert http any any -> any any (msg:"nacos"; flow: established, to_server; http.uri; content:"/nacos/v1/cs/configs"; lua:./lua/nacos_default_jwt.lua; flowbits: set, nacos.1000001; flowbits: noalert; classtype:bad-unknown; sid: 1000001; rev: 1;)" from file /home/suricata/rules/suricata.rules at line 31
[8735 - Suricata-Main] 2024-07-25 21:00:36 Warning: detect: 1 rule files specified, but no rules were loaded!
[8735 - Suricata-Main] 2024-07-25 21:00:36 Info: threshold-config: Threshold config parsed: 0 rule(s) found
[8735 - Suricata-Main] 2024-07-25 21:00:36 Info: detect: 0 signatures processed. 0 are IP-only rules, 0 are inspecting packet payload, 0 inspect application layer, 0 are decoder event only
[8735 - Suricata-Main] 2024-07-25 21:00:36 Info: runmodes: enp0s8: creating 1 thread
[8735 - Suricata-Main] 2024-07-25 21:00:36 Info: unix-manager: unix socket '/var/run/suricata/suricata-command.socket'
[8735 - Suricata-Main] 2024-07-25 21:00:36 Notice: threads: Threads created -> W: 1 FM: 1 FR: 1 Engine started.