added cli flags functionality

This commit is contained in:
Vomitblood 2025-02-13 02:44:44 +08:00
parent 59832d8e11
commit 9caedb4480
8 changed files with 89 additions and 19 deletions

2
server/build.sh Executable file
View file

@ -0,0 +1,2 @@
#!/bin/bash
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o server main.go

View file

@ -0,0 +1,24 @@
package cli
import (
"flag"
"fmt"
"os"
"github.com/Vomitblood/cspj-application/server/internal/config"
)
func GetFlags() {
logDir := flag.String("l", "", "Path to the log directory")
flag.Parse()
// check if the -l flag is provided
if flag.Lookup("l").Value.String() == "" {
fmt.Println("Error: The -l flag (log directory) is required.")
os.Exit(1)
}
// store the value in a globally accessible config package
config.LogDirectory = *logDir
}

View file

@ -0,0 +1,3 @@
package config
var LogDirectory string

View file

@ -87,6 +87,7 @@ func SetupDemoDb(w http.ResponseWriter, r *http.Request) {
// avoid duplicate entries and specify roles
insertDataSQL := `
INSERT INTO users (email, password, role) VALUES
('asdf@gmail.com', 'asdf', 'user'),
('alice@example.com', 'asdfalicepassword', 'user'),
('bob@example.com', 'asdfbobpassword', 'user'),
('charlie@example.com', 'asdfcharliepassword', 'admin')
@ -152,7 +153,6 @@ func FetchEmails() (map[string]bool, error) {
emails[email] = true
}
log.Println("Fetched emails:", emails)
return emails, nil
}

View file

@ -3,16 +3,17 @@ package log_backup
import (
"fmt"
"log"
"path/filepath"
"github.com/Vomitblood/cspj-application/server/internal/config"
"github.com/Vomitblood/cspj-application/server/internal/webdav"
"github.com/studio-b12/gowebdav"
)
// TODO: use values from config file
var localLogPaths = []string{
"/home/vomitblood/build/cspj-application/docker/chungus/logs/host-fs-accesslog.log",
"/home/vomitblood/build/cspj-application/docker/chungus/logs/host-fs-auditlog.log",
"/home/vomitblood/build/cspj-application/docker/chungus/logs/host-fs-errorlog.log",
filepath.Join(config.LogDirectory, "host-fs-accesslog.log"),
filepath.Join(config.LogDirectory, "host-fs-auditlog.log"),
filepath.Join(config.LogDirectory, "host-fs-errorlog.log"),
}
var remoteFiles = []string{

View file

@ -5,17 +5,14 @@ import (
"encoding/json"
"log"
"os"
"path/filepath"
"github.com/Vomitblood/cspj-application/server/internal/config"
"github.com/Vomitblood/cspj-application/server/internal/telegram"
"github.com/fsnotify/fsnotify"
tg "github.com/go-telegram-bot-api/telegram-bot-api/v5"
)
const (
// TODO: add config for user to specify log location
modsecLogFile = "/home/vomitblood/build/cspj-application/docker/chungus/logs/host-fs-auditlog.log"
)
var lastReadPosition int64 = 0
type LogEntry struct {
@ -25,16 +22,18 @@ type LogEntry struct {
}
func WatchFile(bot *tg.BotAPI) {
modsecLogFile := filepath.Join(config.LogDirectory, "host-fs-auditlog.log")
log.Println("Watching logfile directory:", config.LogDirectory)
watcher, err := fsnotify.NewWatcher()
if err != nil {
log.Fatal("Failed to initialize watcher:", err)
log.Fatal("Failed to initialize watcher: ", err)
}
defer watcher.Close()
// add log file to watcher
err = watcher.Add(modsecLogFile)
if err != nil {
log.Fatal("Failed to watch log file:", err)
log.Fatal("Failed to watch log file: ", err)
}
log.Println("Monitoring log file for changes...")
@ -54,15 +53,16 @@ func WatchFile(bot *tg.BotAPI) {
if !ok {
return
}
log.Println("Watcher error:", err)
log.Println("Watcher error: ", err)
}
}
}
func readNewLines(bot *tg.BotAPI) {
modsecLogFile := filepath.Join(config.LogDirectory, "host-fs-auditlog.log")
file, err := os.Open(modsecLogFile)
if err != nil {
log.Println("Failed to reopen log file:", err)
log.Println("Failed to reopen log file: ", err)
return
}
defer file.Close()
@ -77,7 +77,7 @@ func readNewLines(bot *tg.BotAPI) {
// try to parse json
if err := json.Unmarshal([]byte(line), &logEntry); err != nil {
log.Println("⚠️ Failed to parse JSON:", err)
log.Println("⚠️ Failed to parse JSON: ", err)
// skip invalid json lines
// very crucial as modsecurity does not respect the json spec
continue
@ -93,6 +93,6 @@ func readNewLines(bot *tg.BotAPI) {
lastReadPosition, _ = file.Seek(0, os.SEEK_CUR)
if err := scanner.Err(); err != nil {
log.Println("Error reading log file:", err)
log.Println("Error reading log file: ", err)
}
}

View file

@ -1,6 +1,7 @@
package sql_injection
import (
"bytes"
"context"
"encoding/json"
"fmt"
@ -134,6 +135,7 @@ func SecureRegisterSql(w http.ResponseWriter, r *http.Request) {
}
func UnsecureLoginSql(w http.ResponseWriter, r *http.Request) {
log.Println("/unsecure-login-sql hit")
// decode the json body
var requestData struct {
Email string `json:"email"`
@ -175,12 +177,18 @@ func UnsecureLoginSql(w http.ResponseWriter, r *http.Request) {
// very secure login endpoint
func SecureLoginSql(w http.ResponseWriter, r *http.Request) {
// decode the json body
log.Println("/secure-login-sql hit")
var requestData struct {
Email string `json:"email"`
Password string `json:"password"`
}
type AIResponse struct {
Confidence float64 `json:"confidence"`
Query string `json:"query"`
Result string `json:"result"`
}
// declare new json decoder with custom property
jsonDecoder := json.NewDecoder(r.Body)
// rejects any unknown fields in the json, more strict
@ -214,6 +222,35 @@ func SecureLoginSql(w http.ResponseWriter, r *http.Request) {
return
}
// make insecure sql command just to send to ai model to check
insecureQuery := fmt.Sprintf("SELECT id, email, password FROM users WHERE email = '%s' AND password = '%s'", requestData.Email, requestData.Password)
// send the query to the ai model server
aiReqBody, _ := json.Marshal(map[string]string{"query": insecureQuery})
aiResp, err := http.Post("http://127.0.0.1:5000/predict", "application/json", bytes.NewBuffer(aiReqBody))
if err != nil {
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
log.Println("Failed to reach AI model:", err)
return
}
defer aiResp.Body.Close()
var aiResponse AIResponse
if err := json.NewDecoder(aiResp.Body).Decode(&aiResponse); err != nil {
http.Error(w, "Failed to decode AI response", http.StatusInternalServerError)
log.Println("Error decoding AI response:", err)
return
}
log.Println("AI Response:", aiResponse.Result)
// reject the original request if ai result is fail
if aiResponse.Result == "fail" {
http.Error(w, "Potential SQL injection detected", http.StatusForbidden)
log.Println("AI detected SQL injection attempt")
return
}
// retrieve the email and password from the database
var id int
var email string

View file

@ -3,6 +3,8 @@ package main
import (
"log"
"github.com/Vomitblood/cspj-application/server/internal/cli"
"github.com/Vomitblood/cspj-application/server/internal/config"
"github.com/Vomitblood/cspj-application/server/internal/db"
"github.com/Vomitblood/cspj-application/server/internal/http_server"
"github.com/Vomitblood/cspj-application/server/internal/log_watcher"
@ -11,6 +13,9 @@ import (
)
func main() {
cli.GetFlags()
log.Printf("Log directory set to: %s", config.LogDirectory)
var err error
db.DbPool, err = db.ConnectToDb()
if err != nil {
@ -27,7 +32,5 @@ func main() {
// start log watcher
go log_watcher.WatchFile(tgBot)
//
http_server.ServeApi()
}