progress
This commit is contained in:
parent
80504583a4
commit
d3b949949c
417
src/main.c
417
src/main.c
@ -384,7 +384,7 @@ int search_in_string(char* raw_string, char* search_string) {
|
|||||||
// https://stackoverflow.com/questions/5901181/c-string-append
|
// https://stackoverflow.com/questions/5901181/c-string-append
|
||||||
void annotate_entry(int index, char* annotation_string) {
|
void annotate_entry(int index, char* annotation_string) {
|
||||||
if (index >= 0 && index < total_entries) {
|
if (index >= 0 && index < total_entries) {
|
||||||
if (all_entries[index].annotation== NULL){
|
if (all_entries[index].annotation[0] == '\0'){
|
||||||
strncpy(all_entries[index].annotation, annotation_string, sizeof(all_entries[index].annotation) - 1);
|
strncpy(all_entries[index].annotation, annotation_string, sizeof(all_entries[index].annotation) - 1);
|
||||||
all_entries[index].annotation[sizeof(all_entries[index].annotation) - 1] = '\0';
|
all_entries[index].annotation[sizeof(all_entries[index].annotation) - 1] = '\0';
|
||||||
all_entries[index].annotated_flag = 1;
|
all_entries[index].annotated_flag = 1;
|
||||||
@ -392,8 +392,9 @@ void annotate_entry(int index, char* annotation_string) {
|
|||||||
char * new_str ;
|
char * new_str ;
|
||||||
if((new_str = malloc(strlen(all_entries[index].annotation)+strlen(",")+strlen(annotation_string)+1)) != NULL){
|
if((new_str = malloc(strlen(all_entries[index].annotation)+strlen(",")+strlen(annotation_string)+1)) != NULL){
|
||||||
new_str[0] = '\0'; // ensures the memory is an empty string
|
new_str[0] = '\0'; // ensures the memory is an empty string
|
||||||
strcat(new_str,",");
|
strcat(new_str, all_entries[index].annotation);
|
||||||
strcat(new_str,annotation_string);
|
strcat(new_str, ",");
|
||||||
|
strcat(new_str, annotation_string);
|
||||||
strncpy(all_entries[index].annotation, new_str, sizeof(all_entries[index].annotation) - 1);
|
strncpy(all_entries[index].annotation, new_str, sizeof(all_entries[index].annotation) - 1);
|
||||||
all_entries[index].annotation[sizeof(all_entries[index].annotation) - 1] = '\0';
|
all_entries[index].annotation[sizeof(all_entries[index].annotation) - 1] = '\0';
|
||||||
free(new_str);
|
free(new_str);
|
||||||
@ -415,224 +416,183 @@ void annotate_suspicious_entries(struct log_entry* dataset) {
|
|||||||
all_entries[i].annotation[0] = '\0';
|
all_entries[i].annotation[0] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
int is_suspicious = 0; // Flag um zu verfolgen ob bereits annotiert
|
// 1. PAYLOAD-GRÖßE: Sehr lange Requests
|
||||||
|
|
||||||
// 1. PAYLOAD-GRÖßE: Sehr lange Requests (bereits vorhanden, aber verbessert)
|
|
||||||
int url_length = strlen(all_entries[i].url_path);
|
int url_length = strlen(all_entries[i].url_path);
|
||||||
if (url_length > SUSPICIOUS_REQUEST_LEN_THRESHOLD) {
|
if (url_length > SUSPICIOUS_REQUEST_LEN_THRESHOLD) {
|
||||||
annotate_entry(i, "Long Payload");
|
annotate_entry(i, "Long Payload");
|
||||||
suspicious_patterns_count++;
|
suspicious_patterns_count++;
|
||||||
is_suspicious = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. PFAD-BASIERTE ANGRIFFE: Häufige Angriffsziele und sensible Pfade
|
// 2. PFAD-BASIERTE ANGRIFFE: Häufige Angriffsziele und sensible Pfade
|
||||||
if (!is_suspicious) {
|
// Git-Repository Zugriffe (häufig bei Recon)
|
||||||
// Git-Repository Zugriffe (häufig bei Recon)
|
if (search_in_string(all_entries[i].url_path, ".git/") ||
|
||||||
if (search_in_string(all_entries[i].url_path, ".git/") ||
|
search_in_string(all_entries[i].url_path, "/.git")) {
|
||||||
search_in_string(all_entries[i].url_path, "/.git")) {
|
annotate_entry(i, "Git Access");
|
||||||
annotate_entry(i, "Git Access");
|
suspicious_patterns_count++;
|
||||||
suspicious_patterns_count++;
|
}
|
||||||
is_suspicious = 1;
|
|
||||||
}
|
// Environment-Dateien (kritische Konfigurationsdateien)
|
||||||
// Environment-Dateien (kritische Konfigurationsdateien)
|
if (search_in_string(all_entries[i].url_path, ".env") ||
|
||||||
else if (search_in_string(all_entries[i].url_path, ".env") ||
|
search_in_string(all_entries[i].url_path, ".config") ||
|
||||||
search_in_string(all_entries[i].url_path, ".config") ||
|
search_in_string(all_entries[i].url_path, "config.php")) {
|
||||||
search_in_string(all_entries[i].url_path, "config.php")) {
|
annotate_entry(i, "Config Access");
|
||||||
annotate_entry(i, "Config Access");
|
suspicious_patterns_count++;
|
||||||
suspicious_patterns_count++;
|
}
|
||||||
is_suspicious = 1;
|
|
||||||
}
|
// WordPress Admin-Bereiche (häufig attackiert)
|
||||||
// WordPress Admin-Bereiche (häufig attackiert)
|
if (search_in_string(all_entries[i].url_path, "wp-admin") ||
|
||||||
else if (search_in_string(all_entries[i].url_path, "wp-admin") ||
|
search_in_string(all_entries[i].url_path, "wp-login") ||
|
||||||
search_in_string(all_entries[i].url_path, "wp-login") ||
|
search_in_string(all_entries[i].url_path, "wp-config")) {
|
||||||
search_in_string(all_entries[i].url_path, "wp-config")) {
|
annotate_entry(i, "WP Attack");
|
||||||
annotate_entry(i, "WP Attack");
|
suspicious_patterns_count++;
|
||||||
suspicious_patterns_count++;
|
}
|
||||||
is_suspicious = 1;
|
|
||||||
}
|
// Database Management Tools
|
||||||
// Database Management Tools
|
if (search_in_string(all_entries[i].url_path, "phpmyadmin") ||
|
||||||
else if (search_in_string(all_entries[i].url_path, "phpmyadmin") ||
|
search_in_string(all_entries[i].url_path, "phpMyAdmin") ||
|
||||||
search_in_string(all_entries[i].url_path, "phpMyAdmin") ||
|
search_in_string(all_entries[i].url_path, "adminer")) {
|
||||||
search_in_string(all_entries[i].url_path, "adminer")) {
|
annotate_entry(i, "DB Tool Access");
|
||||||
annotate_entry(i, "DB Tool Access");
|
suspicious_patterns_count++;
|
||||||
suspicious_patterns_count++;
|
}
|
||||||
is_suspicious = 1;
|
|
||||||
}
|
// Admin/Management Interfaces
|
||||||
// Admin/Management Interfaces
|
if (search_in_string(all_entries[i].url_path, "/admin") ||
|
||||||
else if (search_in_string(all_entries[i].url_path, "/admin") ||
|
search_in_string(all_entries[i].url_path, "/manager") ||
|
||||||
search_in_string(all_entries[i].url_path, "/manager") ||
|
search_in_string(all_entries[i].url_path, "/console")) {
|
||||||
search_in_string(all_entries[i].url_path, "/console")) {
|
annotate_entry(i, "Admin Access");
|
||||||
annotate_entry(i, "Admin Access");
|
suspicious_patterns_count++;
|
||||||
suspicious_patterns_count++;
|
|
||||||
is_suspicious = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. DIRECTORY TRAVERSAL: Pfad-Traversal Versuche
|
// 3. DIRECTORY TRAVERSAL: Pfad-Traversal Versuche
|
||||||
if (!is_suspicious) {
|
if (search_in_string(all_entries[i].url_path, "../") ||
|
||||||
if (search_in_string(all_entries[i].url_path, "../") ||
|
search_in_string(all_entries[i].url_path, "..\\") ||
|
||||||
search_in_string(all_entries[i].url_path, "..\\") ||
|
search_in_string(all_entries[i].url_path, "%2e%2e%2f") ||
|
||||||
search_in_string(all_entries[i].url_path, "%2e%2e%2f") ||
|
search_in_string(all_entries[i].url_path, "%2e%2e%5c")) {
|
||||||
search_in_string(all_entries[i].url_path, "%2e%2e%5c")) {
|
annotate_entry(i, "Path Traversal");
|
||||||
annotate_entry(i, "Path Traversal");
|
suspicious_patterns_count++;
|
||||||
suspicious_patterns_count++;
|
|
||||||
is_suspicious = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. SQL INJECTION: SQL-Keywords in URLs
|
// 4. SQL INJECTION: SQL-Keywords in URLs
|
||||||
if (!is_suspicious) {
|
if (search_in_string(all_entries[i].url_path, "select%20") ||
|
||||||
if (search_in_string(all_entries[i].url_path, "select%20") ||
|
search_in_string(all_entries[i].url_path, "union%20") ||
|
||||||
search_in_string(all_entries[i].url_path, "union%20") ||
|
search_in_string(all_entries[i].url_path, "insert%20") ||
|
||||||
search_in_string(all_entries[i].url_path, "insert%20") ||
|
search_in_string(all_entries[i].url_path, "delete%20") ||
|
||||||
search_in_string(all_entries[i].url_path, "delete%20") ||
|
search_in_string(all_entries[i].url_path, "drop%20") ||
|
||||||
search_in_string(all_entries[i].url_path, "drop%20") ||
|
search_in_string(all_entries[i].url_path, "' or ") ||
|
||||||
search_in_string(all_entries[i].url_path, "' or ") ||
|
search_in_string(all_entries[i].url_path, "' and ") ||
|
||||||
search_in_string(all_entries[i].url_path, "' and ") ||
|
search_in_string(all_entries[i].url_path, "1=1") ||
|
||||||
search_in_string(all_entries[i].url_path, "1=1") ||
|
search_in_string(all_entries[i].url_path, "1' or '1'='1")) {
|
||||||
search_in_string(all_entries[i].url_path, "1' or '1'='1")) {
|
annotate_entry(i, "SQL Injection");
|
||||||
annotate_entry(i, "SQL Injection");
|
suspicious_patterns_count++;
|
||||||
suspicious_patterns_count++;
|
|
||||||
is_suspicious = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. XSS ATTEMPTS: Cross-Site-Scripting Versuche
|
// 5. XSS ATTEMPTS: Cross-Site-Scripting Versuche
|
||||||
if (!is_suspicious) {
|
if (search_in_string(all_entries[i].url_path, "<script") ||
|
||||||
if (search_in_string(all_entries[i].url_path, "<script") ||
|
search_in_string(all_entries[i].url_path, "%3cscript") ||
|
||||||
search_in_string(all_entries[i].url_path, "%3cscript") ||
|
search_in_string(all_entries[i].url_path, "javascript:") ||
|
||||||
search_in_string(all_entries[i].url_path, "javascript:") ||
|
search_in_string(all_entries[i].url_path, "onerror=") ||
|
||||||
search_in_string(all_entries[i].url_path, "onerror=") ||
|
search_in_string(all_entries[i].url_path, "onload=") ||
|
||||||
search_in_string(all_entries[i].url_path, "onload=") ||
|
search_in_string(all_entries[i].url_path, "alert(")) {
|
||||||
search_in_string(all_entries[i].url_path, "alert(")) {
|
annotate_entry(i, "XSS Attempt");
|
||||||
annotate_entry(i, "XSS Attempt");
|
suspicious_patterns_count++;
|
||||||
suspicious_patterns_count++;
|
|
||||||
is_suspicious = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6. BACKUP/SENSITIVE FILE ACCESS: Backup-Dateien und sensible Extensions
|
// 6. BACKUP/SENSITIVE FILE ACCESS: Backup-Dateien und sensible Extensions
|
||||||
if (!is_suspicious) {
|
if (search_in_string(all_entries[i].url_path, ".bak") ||
|
||||||
if (search_in_string(all_entries[i].url_path, ".bak") ||
|
search_in_string(all_entries[i].url_path, ".old") ||
|
||||||
search_in_string(all_entries[i].url_path, ".old") ||
|
search_in_string(all_entries[i].url_path, ".backup") ||
|
||||||
search_in_string(all_entries[i].url_path, ".backup") ||
|
search_in_string(all_entries[i].url_path, ".sql") ||
|
||||||
search_in_string(all_entries[i].url_path, ".sql") ||
|
search_in_string(all_entries[i].url_path, ".log") ||
|
||||||
search_in_string(all_entries[i].url_path, ".log") ||
|
search_in_string(all_entries[i].url_path, ".key") ||
|
||||||
search_in_string(all_entries[i].url_path, ".key") ||
|
search_in_string(all_entries[i].url_path, ".pem")) {
|
||||||
search_in_string(all_entries[i].url_path, ".pem")) {
|
annotate_entry(i, "Sensitive File");
|
||||||
annotate_entry(i, "Sensitive File");
|
suspicious_patterns_count++;
|
||||||
suspicious_patterns_count++;
|
|
||||||
is_suspicious = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 7. BOT/SCANNER DETECTION: Verdächtige User-Agents
|
// 7. BOT/SCANNER DETECTION: Verdächtige User-Agents
|
||||||
if (!is_suspicious) {
|
if (search_in_string(all_entries[i].user_agent, "nmap") ||
|
||||||
if (search_in_string(all_entries[i].user_agent, "nmap") ||
|
search_in_string(all_entries[i].user_agent, "sqlmap") ||
|
||||||
search_in_string(all_entries[i].user_agent, "sqlmap") ||
|
search_in_string(all_entries[i].user_agent, "nikto") ||
|
||||||
search_in_string(all_entries[i].user_agent, "nikto") ||
|
search_in_string(all_entries[i].user_agent, "dirb") ||
|
||||||
search_in_string(all_entries[i].user_agent, "dirb") ||
|
search_in_string(all_entries[i].user_agent, "gobuster") ||
|
||||||
search_in_string(all_entries[i].user_agent, "gobuster") ||
|
search_in_string(all_entries[i].user_agent, "whatweb") ||
|
||||||
search_in_string(all_entries[i].user_agent, "whatweb") ||
|
search_in_string(all_entries[i].user_agent, "masscan") ||
|
||||||
search_in_string(all_entries[i].user_agent, "masscan") ||
|
search_in_string(all_entries[i].user_agent, "python-requests") ||
|
||||||
search_in_string(all_entries[i].user_agent, "python-requests") ||
|
search_in_string(all_entries[i].user_agent, "curl/") ||
|
||||||
search_in_string(all_entries[i].user_agent, "curl/") ||
|
search_in_string(all_entries[i].user_agent, "wget/")) {
|
||||||
search_in_string(all_entries[i].user_agent, "wget/")) {
|
annotate_entry(i, "Scanner/Bot");
|
||||||
annotate_entry(i, "Scanner/Bot");
|
suspicious_patterns_count++;
|
||||||
suspicious_patterns_count++;
|
|
||||||
is_suspicious = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8. EXCESSIVE URL ENCODING: Verdächtig hohe Anzahl von URL-Encoding
|
// 8. EXCESSIVE URL ENCODING: Verdächtig hohe Anzahl von URL-Encoding
|
||||||
if (!is_suspicious) {
|
char *url = all_entries[i].url_path;
|
||||||
char *url = all_entries[i].url_path;
|
int encoding_count = 0;
|
||||||
int encoding_count = 0;
|
char *pos = url;
|
||||||
char *pos = url;
|
while ((pos = strstr(pos, "%")) != NULL) {
|
||||||
while ((pos = strstr(pos, "%")) != NULL) {
|
encoding_count++;
|
||||||
encoding_count++;
|
pos++;
|
||||||
pos++;
|
}
|
||||||
}
|
// Wenn mehr als 10 URL-Encodings in einer URL, verdächtig
|
||||||
// Wenn mehr als 10 URL-Encodings in einer URL, verdächtig
|
if (encoding_count > 10) {
|
||||||
if (encoding_count > 10) {
|
annotate_entry(i, "Heavy Encoding");
|
||||||
annotate_entry(i, "Heavy Encoding");
|
suspicious_patterns_count++;
|
||||||
suspicious_patterns_count++;
|
|
||||||
is_suspicious = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 9. ATYPICAL HTTP METHODS: Ungewöhnliche oder fehlerhafte HTTP-Methoden
|
// 9. ATYPICAL HTTP METHODS: Ungewöhnliche oder fehlerhafte HTTP-Methoden
|
||||||
if (!is_suspicious) {
|
if (strcmp(all_entries[i].request_method, "ATYPICAL") == 0) {
|
||||||
if (strcmp(all_entries[i].request_method, "ATYPICAL") == 0) {
|
annotate_entry(i, "Malformed Request");
|
||||||
annotate_entry(i, "Malformed Request");
|
suspicious_patterns_count++;
|
||||||
suspicious_patterns_count++;
|
}
|
||||||
is_suspicious = 1;
|
// Seltene aber potentiell gefährliche HTTP-Methoden
|
||||||
}
|
else if (strcmp(all_entries[i].request_method, "PROPFIND") == 0 ||
|
||||||
// Seltene aber potentiell gefährliche HTTP-Methoden
|
strcmp(all_entries[i].request_method, "MKCOL") == 0 ||
|
||||||
else if (strcmp(all_entries[i].request_method, "PROPFIND") == 0 ||
|
strcmp(all_entries[i].request_method, "COPY") == 0 ||
|
||||||
strcmp(all_entries[i].request_method, "MKCOL") == 0 ||
|
strcmp(all_entries[i].request_method, "MOVE") == 0 ||
|
||||||
strcmp(all_entries[i].request_method, "COPY") == 0 ||
|
strcmp(all_entries[i].request_method, "LOCK") == 0) {
|
||||||
strcmp(all_entries[i].request_method, "MOVE") == 0 ||
|
annotate_entry(i, "Rare Method");
|
||||||
strcmp(all_entries[i].request_method, "LOCK") == 0) {
|
suspicious_patterns_count++;
|
||||||
annotate_entry(i, "Rare Method");
|
|
||||||
suspicious_patterns_count++;
|
|
||||||
is_suspicious = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 10. STATUS CODE ANOMALIES: Verdächtige Status-Code Muster
|
// 10. STATUS CODE ANOMALIES: Verdächtige Status-Code Muster
|
||||||
if (!is_suspicious) {
|
// 403 auf sensible Pfade könnte Angriffserkennung bedeuten
|
||||||
// 403 auf sensible Pfade könnte Angriffserkennung bedeuten
|
if (all_entries[i].status_code == 403 &&
|
||||||
if (all_entries[i].status_code == 403 &&
|
(search_in_string(all_entries[i].url_path, "admin") ||
|
||||||
(search_in_string(all_entries[i].url_path, "admin") ||
|
search_in_string(all_entries[i].url_path, ".git") ||
|
||||||
search_in_string(all_entries[i].url_path, ".git") ||
|
search_in_string(all_entries[i].url_path, ".env"))) {
|
||||||
search_in_string(all_entries[i].url_path, ".env"))) {
|
annotate_entry(i, "Blocked Access");
|
||||||
annotate_entry(i, "Blocked Access");
|
suspicious_patterns_count++;
|
||||||
suspicious_patterns_count++;
|
}
|
||||||
is_suspicious = 1;
|
// 429 Too Many Requests - Rate Limiting aktiviert
|
||||||
}
|
if (all_entries[i].status_code == 429) {
|
||||||
// 429 Too Many Requests - Rate Limiting aktiviert
|
annotate_entry(i, "Rate Limited");
|
||||||
else if (all_entries[i].status_code == 429) {
|
suspicious_patterns_count++;
|
||||||
annotate_entry(i, "Rate Limited");
|
|
||||||
suspicious_patterns_count++;
|
|
||||||
is_suspicious = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 11. CREDENTIAL STUFFING: Wiederholte Login-Versuche mit verschiedenen Credentials
|
// 11. CREDENTIAL STUFFING: Wiederholte Login-Versuche mit verschiedenen Credentials
|
||||||
if (!is_suspicious) {
|
if ((search_in_string(all_entries[i].url_path, "login") ||
|
||||||
if ((search_in_string(all_entries[i].url_path, "login") ||
|
search_in_string(all_entries[i].url_path, "signin") ||
|
||||||
search_in_string(all_entries[i].url_path, "signin") ||
|
search_in_string(all_entries[i].url_path, "auth")) &&
|
||||||
search_in_string(all_entries[i].url_path, "auth")) &&
|
(all_entries[i].status_code == 401 || all_entries[i].status_code == 403)) {
|
||||||
(all_entries[i].status_code == 401 || all_entries[i].status_code == 403)) {
|
annotate_entry(i, "Failed Auth");
|
||||||
annotate_entry(i, "Failed Auth");
|
suspicious_patterns_count++;
|
||||||
suspicious_patterns_count++;
|
|
||||||
is_suspicious = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 12. SHELL/WEBSHELL ACCESS: Verdächtige Shell-bezogene Pfade
|
// 12. SHELL/WEBSHELL ACCESS: Verdächtige Shell-bezogene Pfade
|
||||||
if (!is_suspicious) {
|
if (search_in_string(all_entries[i].url_path, ".php?") ||
|
||||||
if (search_in_string(all_entries[i].url_path, ".php?") ||
|
search_in_string(all_entries[i].url_path, "shell") ||
|
||||||
search_in_string(all_entries[i].url_path, "shell") ||
|
search_in_string(all_entries[i].url_path, "backdoor") ||
|
||||||
search_in_string(all_entries[i].url_path, "backdoor") ||
|
search_in_string(all_entries[i].url_path, "cmd=") ||
|
||||||
search_in_string(all_entries[i].url_path, "cmd=") ||
|
search_in_string(all_entries[i].url_path, "exec=") ||
|
||||||
search_in_string(all_entries[i].url_path, "exec=") ||
|
search_in_string(all_entries[i].url_path, "system=")) {
|
||||||
search_in_string(all_entries[i].url_path, "system=")) {
|
annotate_entry(i, "Shell Access");
|
||||||
annotate_entry(i, "Shell Access");
|
suspicious_patterns_count++;
|
||||||
suspicious_patterns_count++;
|
|
||||||
is_suspicious = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 13. API ABUSE: Verdächtige API-Zugriffe
|
// 13. API ABUSE: Verdächtige API-Zugriffe
|
||||||
if (!is_suspicious) {
|
if (search_in_string(all_entries[i].url_path, "/api/") &&
|
||||||
if (search_in_string(all_entries[i].url_path, "/api/") &&
|
(all_entries[i].status_code >= 400 && all_entries[i].status_code < 500)) {
|
||||||
(all_entries[i].status_code >= 400 && all_entries[i].status_code < 500)) {
|
annotate_entry(i, "API Error");
|
||||||
annotate_entry(i, "API Error");
|
suspicious_patterns_count++;
|
||||||
suspicious_patterns_count++;
|
|
||||||
is_suspicious = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1382,8 +1342,20 @@ void format_iso8601_time(struct simple_time time, char* buffer, int buffer_size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Export in Timesketch-kompatiblem Format
|
//Export in Timesketch-kompatiblem Format
|
||||||
|
void write_csv_field(FILE* file, const char* field) {
|
||||||
|
fprintf(file, "\"");
|
||||||
|
for (const char* p = field; *p; p++) {
|
||||||
|
if (*p == '"') {
|
||||||
|
fprintf(file, "\"\"");
|
||||||
|
} else {
|
||||||
|
fprintf(file, "%c", *p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf(file, "\"");
|
||||||
|
}
|
||||||
|
|
||||||
void export_filtered_entries(char *filepath) {
|
void export_filtered_entries(char *filepath) {
|
||||||
//90 chars + delimiter
|
// 90 chars +delimiter
|
||||||
char filename[91];
|
char filename[91];
|
||||||
if (filepath == NULL) {
|
if (filepath == NULL) {
|
||||||
printf("Dateiname für Timesketch-Export eingeben (ohne .csv): ");
|
printf("Dateiname für Timesketch-Export eingeben (ohne .csv): ");
|
||||||
@ -1396,7 +1368,7 @@ void export_filtered_entries(char *filepath) {
|
|||||||
strncpy(filename, filepath, sizeof(filename) - 1);
|
strncpy(filename, filepath, sizeof(filename) - 1);
|
||||||
filename[sizeof(filename) - 1] = '\0';
|
filename[sizeof(filename) - 1] = '\0';
|
||||||
}
|
}
|
||||||
// Dateiendung
|
|
||||||
strcat(filename, ".csv");
|
strcat(filename, ".csv");
|
||||||
printf("\nINFO: Schreibe Datei %s...\n", filename);
|
printf("\nINFO: Schreibe Datei %s...\n", filename);
|
||||||
FILE* file = fopen(filename, "w");
|
FILE* file = fopen(filename, "w");
|
||||||
@ -1415,44 +1387,56 @@ void export_filtered_entries(char *filepath) {
|
|||||||
if (passes_filter(i)) {
|
if (passes_filter(i)) {
|
||||||
format_iso8601_time(all_entries[i].time, iso_datetime, sizeof(iso_datetime));
|
format_iso8601_time(all_entries[i].time, iso_datetime, sizeof(iso_datetime));
|
||||||
|
|
||||||
// https://stackoverflow.com/questions/5901181/c-string-append
|
// Tags werden von Timesketch in diesem Format erwartet: [ "tag1","tag2" ]
|
||||||
// https://www.quora.com/How-can-we-count-the-number-of-special-characters-in-a-string-in-the-C-language-using-fgets
|
char tag_str[256] = "";
|
||||||
char* tag_str;
|
if (strlen(all_entries[i].annotation) > 0) {
|
||||||
int num_delimiters = 0;
|
// Create a working copy for strtok (it modifies the string)
|
||||||
int c=0;
|
char annotation_copy[64];
|
||||||
while(all_entries[i].annotation[c]!='\0'){
|
strncpy(annotation_copy, all_entries[i].annotation, sizeof(annotation_copy) - 1);
|
||||||
num_delimiters++;
|
annotation_copy[sizeof(annotation_copy) - 1] = '\0';
|
||||||
}
|
|
||||||
if (tag_str=malloc(sizeof(all_entries[i].annotation)+sizeof("[ ]")+(sizeof(','))*num_delimiters)+1)!=NULL){
|
|
||||||
tag_str[0] = '\0';
|
|
||||||
|
|
||||||
|
|
||||||
char* token = strtok(all_entries[i].annotation, ",");
|
|
||||||
if (!token) return;
|
|
||||||
strcat(tag_str, "[ ");
|
strcat(tag_str, "[ ");
|
||||||
for (i=0;i<num_delimiters;i++){
|
// https://stackoverflow.com/questions/5901181/c-string-append
|
||||||
|
// https://www.quora.com/How-can-we-count-the-number-of-special-characters-in-a-string-in-the-C-language-using-fgets
|
||||||
|
char* token = strtok(annotation_copy, ",");
|
||||||
|
int first = 1;
|
||||||
|
while (token != NULL) {
|
||||||
|
if (!first) {
|
||||||
|
strcat(tag_str, ",");
|
||||||
|
}
|
||||||
strcat(tag_str, "\"");
|
strcat(tag_str, "\"");
|
||||||
strcat(tag_str, strtok(NULL, ","));
|
strncat(tag_str, token, sizeof(tag_str) - strlen(tag_str) - 3);
|
||||||
strcat(tag_str, '"');
|
strcat(tag_str, "\"");
|
||||||
|
first = 0;
|
||||||
|
token = strtok(NULL, ",");
|
||||||
}
|
}
|
||||||
strcat(tag_str, " ]");
|
strcat(tag_str, " ]");
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(file, "\"%s\",\"%s\",\"HTTP Access Log\",\"%s\",\"%s\",\"%s\",%d,%d,\"%s\",\"%s\",\"%s\"\n",
|
// Write CSV row with proper escaping
|
||||||
iso_datetime, // datetime
|
write_csv_field(file, iso_datetime);
|
||||||
all_entries[i].source_file, // message
|
fprintf(file, ",");
|
||||||
all_entries[i].ip_address,
|
write_csv_field(file, all_entries[i].source_file);
|
||||||
all_entries[i].request_method,
|
fprintf(file, ",");
|
||||||
all_entries[i].url_path,
|
write_csv_field(file, "HTTP Access Log");
|
||||||
all_entries[i].status_code,
|
fprintf(file, ",");
|
||||||
all_entries[i].bytes_sent,
|
write_csv_field(file, all_entries[i].ip_address);
|
||||||
all_entries[i].user_agent,
|
fprintf(file, ",");
|
||||||
all_entries[i].parsing_timestamp,
|
write_csv_field(file, all_entries[i].request_method);
|
||||||
tag_str
|
fprintf(file, ",");
|
||||||
//all_entries[i].annotation // tag
|
write_csv_field(file, all_entries[i].url_path);
|
||||||
);
|
fprintf(file, ",");
|
||||||
free(tag_str);
|
fprintf(file, "%d", all_entries[i].status_code);
|
||||||
tag_str=NULL;
|
fprintf(file, ",");
|
||||||
|
fprintf(file, "%d", all_entries[i].bytes_sent);
|
||||||
|
fprintf(file, ",");
|
||||||
|
write_csv_field(file, all_entries[i].user_agent);
|
||||||
|
fprintf(file, ",");
|
||||||
|
write_csv_field(file, all_entries[i].parsing_timestamp);
|
||||||
|
fprintf(file, ",");
|
||||||
|
write_csv_field(file, tag_str);
|
||||||
|
fprintf(file, "\n");
|
||||||
|
|
||||||
exported_count++;
|
exported_count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3033,8 +3017,8 @@ void print_help(char* binary) {
|
|||||||
printf(" 0.0.0.0 - - [31/Aug/2025:00:11:42 +0000] \"GET /.git/config HTTP/1.1\" 400 255 \"-\" \"Mozilla/5.0\" \"-\"\n");
|
printf(" 0.0.0.0 - - [31/Aug/2025:00:11:42 +0000] \"GET /.git/config HTTP/1.1\" 400 255 \"-\" \"Mozilla/5.0\" \"-\"\n");
|
||||||
|
|
||||||
printf("\nCSV-Export (Timesketch-kompatibel):\n");
|
printf("\nCSV-Export (Timesketch-kompatibel):\n");
|
||||||
printf(" Spalten: datetime, timestamp_desc, ip_address, method, url_path, status_code,\n");
|
printf(" Spalten: datetime, message timestamp_desc, ip_address, method, url_path, status_code,\n");
|
||||||
printf(" bytes_sent, user_agent, source_file, parsing_timestamp, annotation\n");
|
printf(" bytes_sent, user_agent, source_file, parsing_timestamp, tag\n");
|
||||||
|
|
||||||
printf("\nAnnotationen:\n");
|
printf("\nAnnotationen:\n");
|
||||||
printf(" - Automatische Erkennung verdächtiger Muster (z.B. 'Long Payload')\n");
|
printf(" - Automatische Erkennung verdächtiger Muster (z.B. 'Long Payload')\n");
|
||||||
@ -3045,7 +3029,6 @@ void print_help(char* binary) {
|
|||||||
printf(" - Parser erwartet das obige Standardformat. Abweichungen können zum Abbruch führen.\n");
|
printf(" - Parser erwartet das obige Standardformat. Abweichungen können zum Abbruch führen.\n");
|
||||||
printf(" - Zeitzone aus dem Log wird gelesen, aber intern als einfache Felder verarbeitet.\n");
|
printf(" - Zeitzone aus dem Log wird gelesen, aber intern als einfache Felder verarbeitet.\n");
|
||||||
printf(" - ATYPICAL-Methode: für fehlerhafte/binäre Requests innerhalb der \"request\"-Spalte.\n");
|
printf(" - ATYPICAL-Methode: für fehlerhafte/binäre Requests innerhalb der \"request\"-Spalte.\n");
|
||||||
printf(" - Komplexe Zeitraum-Filter sind vollständig über Kommandozeile verfügbar.\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user