Compare commits
	
		
			No commits in common. "fb1e39ed1c8852000f3b1e5e9edf6da91314f3d8" and "4a1187c3a969e13da1199e222840974ea5b9d753" have entirely different histories.
		
	
	
		
			fb1e39ed1c
			...
			4a1187c3a9
		
	
		
							
								
								
									
										10
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								README.md
									
									
									
									
									
								
							| 
						 | 
					@ -1,15 +1,5 @@
 | 
				
			||||||
# CSPJ Application
 | 
					# CSPJ Application
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Setup
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
### Requirements
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
User to be added into `docker` group.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
```bash
 | 
					 | 
				
			||||||
sudo usermod -aG docker $USER
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## Services
 | 
					## Services
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- 3331: Apache + ModSecurity
 | 
					- 3331: Apache + ModSecurity
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,7 @@ import { Box, Stack } from "@mui/material";
 | 
				
			||||||
import { WindowButtons } from "./WindowButtons";
 | 
					import { WindowButtons } from "./WindowButtons";
 | 
				
			||||||
import { NavigationButtons } from "./NavigationButtons";
 | 
					import { NavigationButtons } from "./NavigationButtons";
 | 
				
			||||||
import { RouteDisplay } from "./RouteDisplay";
 | 
					import { RouteDisplay } from "./RouteDisplay";
 | 
				
			||||||
 | 
					import { Testing } from "../Testing/Testing";
 | 
				
			||||||
import { ServerStatus } from "./ServerStatus";
 | 
					import { ServerStatus } from "./ServerStatus";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const HeaderBar = () => {
 | 
					export const HeaderBar = () => {
 | 
				
			||||||
| 
						 | 
					@ -72,6 +73,7 @@ export const HeaderBar = () => {
 | 
				
			||||||
          }}
 | 
					          }}
 | 
				
			||||||
        >
 | 
					        >
 | 
				
			||||||
          <ServerStatus />
 | 
					          <ServerStatus />
 | 
				
			||||||
 | 
					          <Testing />
 | 
				
			||||||
          <WindowButtons />
 | 
					          <WindowButtons />
 | 
				
			||||||
        </Stack>
 | 
					        </Stack>
 | 
				
			||||||
      </Box>
 | 
					      </Box>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
import { Box, Button, Chip, CircularProgress, Popover, Stack } from "@mui/material";
 | 
					import { Box, Button, Chip, CircularProgress, Popover, Stack } from "@mui/material";
 | 
				
			||||||
import { fetch } from "@tauri-apps/plugin-http";
 | 
					import { fetch } from "@tauri-apps/plugin-http";
 | 
				
			||||||
import { useAtom } from "jotai";
 | 
					import { useAtom } from "jotai";
 | 
				
			||||||
import { MouseEvent, useCallback, useEffect, useState } from "react";
 | 
					import { MouseEvent, useEffect, useState } from "react";
 | 
				
			||||||
import { serverConnectionAtom, serverUrlAtom } from "../../lib/jotai";
 | 
					import { serverConnectionAtom, serverUrlAtom } from "../../lib/jotai";
 | 
				
			||||||
import { defaultSettings } from "../../lib/settings";
 | 
					import { defaultSettings } from "../../lib/settings";
 | 
				
			||||||
import { ServerUrlInput } from "./ServerUrlInput";
 | 
					import { ServerUrlInput } from "./ServerUrlInput";
 | 
				
			||||||
| 
						 | 
					@ -24,7 +24,7 @@ export const ServerStatus = () => {
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // function to check server health
 | 
					  // function to check server health
 | 
				
			||||||
  const checkServerConnection = useCallback(async () => {
 | 
					  const checkServerConnection = async () => {
 | 
				
			||||||
    setServerConnection("connecting");
 | 
					    setServerConnection("connecting");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // remove trailing slash
 | 
					    // remove trailing slash
 | 
				
			||||||
| 
						 | 
					@ -42,7 +42,7 @@ export const ServerStatus = () => {
 | 
				
			||||||
      await sleep(500);
 | 
					      await sleep(500);
 | 
				
			||||||
      setServerConnection("disconnected");
 | 
					      setServerConnection("disconnected");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }, [serverUrl, setServerConnection, setServerUrl]);
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const chipProps = {
 | 
					  const chipProps = {
 | 
				
			||||||
    color: serverConnection === "connected" ? "success" : serverConnection === "disconnected" ? "error" : "warning",
 | 
					    color: serverConnection === "connected" ? "success" : serverConnection === "disconnected" ? "error" : "warning",
 | 
				
			||||||
| 
						 | 
					@ -64,7 +64,7 @@ export const ServerStatus = () => {
 | 
				
			||||||
        clearInterval(intervalId);
 | 
					        clearInterval(intervalId);
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }, [checkServerConnection, serverConnection, serverUrl]);
 | 
					  }, [serverConnection, serverUrl]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <Box
 | 
					    <Box
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,28 +0,0 @@
 | 
				
			||||||
import { Grid2 } from "@mui/material";
 | 
					 | 
				
			||||||
import { FC } from "react";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type SetupLogItemProps = {
 | 
					 | 
				
			||||||
  children?: string;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const SetupLogItem: FC<SetupLogItemProps> = ({ children }) => {
 | 
					 | 
				
			||||||
  return (
 | 
					 | 
				
			||||||
    <Grid2
 | 
					 | 
				
			||||||
      color="lightgreen"
 | 
					 | 
				
			||||||
      container
 | 
					 | 
				
			||||||
      fontFamily="JetBrainsMono"
 | 
					 | 
				
			||||||
      fontSize="0.9rem"
 | 
					 | 
				
			||||||
      spacing={1}
 | 
					 | 
				
			||||||
    >
 | 
					 | 
				
			||||||
      <Grid2 size="auto">></Grid2>
 | 
					 | 
				
			||||||
      <Grid2
 | 
					 | 
				
			||||||
        size="grow"
 | 
					 | 
				
			||||||
        sx={{
 | 
					 | 
				
			||||||
          wordBreak: "break-word",
 | 
					 | 
				
			||||||
        }}
 | 
					 | 
				
			||||||
      >
 | 
					 | 
				
			||||||
        {children}
 | 
					 | 
				
			||||||
      </Grid2>
 | 
					 | 
				
			||||||
    </Grid2>
 | 
					 | 
				
			||||||
  );
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
| 
						 | 
					@ -3,14 +3,13 @@ import { Box, Divider, Tab, useTheme } from "@mui/material";
 | 
				
			||||||
import { useState } from "react";
 | 
					import { useState } from "react";
 | 
				
			||||||
import { SqlInjectionLogin } from "./SqlInjectionLogin";
 | 
					import { SqlInjectionLogin } from "./SqlInjectionLogin";
 | 
				
			||||||
import { SqlInjectionRegister } from "./SqlInjectionRegister";
 | 
					import { SqlInjectionRegister } from "./SqlInjectionRegister";
 | 
				
			||||||
import { SqlInjectionSetup } from "./SqlInjectionSetup";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const SqlInjection = () => {
 | 
					export const SqlInjection = () => {
 | 
				
			||||||
  // contexts
 | 
					  // contexts
 | 
				
			||||||
  const theme = useTheme();
 | 
					  const theme = useTheme();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // states
 | 
					  // states
 | 
				
			||||||
  const [subTabValue, setSubTabValue] = useState("setup");
 | 
					  const [subTabValue, setSubTabValue] = useState("register");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // logic for switching tabs
 | 
					  // logic for switching tabs
 | 
				
			||||||
  const subTabChangeEvent = (newTabValue: string) => {
 | 
					  const subTabChangeEvent = (newTabValue: string) => {
 | 
				
			||||||
| 
						 | 
					@ -38,7 +37,7 @@ export const SqlInjection = () => {
 | 
				
			||||||
      >
 | 
					      >
 | 
				
			||||||
        <TabContext value={subTabValue}>
 | 
					        <TabContext value={subTabValue}>
 | 
				
			||||||
          <TabList
 | 
					          <TabList
 | 
				
			||||||
            onChange={(_, value) => {
 | 
					            onChange={(e, value) => {
 | 
				
			||||||
              subTabChangeEvent(value);
 | 
					              subTabChangeEvent(value);
 | 
				
			||||||
            }}
 | 
					            }}
 | 
				
			||||||
            scrollButtons={true}
 | 
					            scrollButtons={true}
 | 
				
			||||||
| 
						 | 
					@ -47,10 +46,6 @@ export const SqlInjection = () => {
 | 
				
			||||||
            }}
 | 
					            }}
 | 
				
			||||||
            variant="standard"
 | 
					            variant="standard"
 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
            <Tab
 | 
					 | 
				
			||||||
              label="Setup"
 | 
					 | 
				
			||||||
              value="setup"
 | 
					 | 
				
			||||||
            />
 | 
					 | 
				
			||||||
            <Tab
 | 
					            <Tab
 | 
				
			||||||
              label="Register"
 | 
					              label="Register"
 | 
				
			||||||
              value="register"
 | 
					              value="register"
 | 
				
			||||||
| 
						 | 
					@ -71,12 +66,6 @@ export const SqlInjection = () => {
 | 
				
			||||||
              width: "100%",
 | 
					              width: "100%",
 | 
				
			||||||
            }}
 | 
					            }}
 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
            <TabPanel
 | 
					 | 
				
			||||||
              sx={{ p: 2 }}
 | 
					 | 
				
			||||||
              value="setup"
 | 
					 | 
				
			||||||
            >
 | 
					 | 
				
			||||||
              <SqlInjectionSetup />
 | 
					 | 
				
			||||||
            </TabPanel>
 | 
					 | 
				
			||||||
            <TabPanel
 | 
					            <TabPanel
 | 
				
			||||||
              sx={{ p: 2 }}
 | 
					              sx={{ p: 2 }}
 | 
				
			||||||
              value="register"
 | 
					              value="register"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,120 +0,0 @@
 | 
				
			||||||
import { LoadingButton } from "@mui/lab";
 | 
					 | 
				
			||||||
import { Box, FormControlLabel, Grid, Grid2, Switch, TextField, Typography } from "@mui/material";
 | 
					 | 
				
			||||||
import { fetch } from "@tauri-apps/plugin-http";
 | 
					 | 
				
			||||||
import { useAtom } from "jotai";
 | 
					 | 
				
			||||||
import { useState } from "react";
 | 
					 | 
				
			||||||
import { useNotification } from "../../../contexts/NotificationContext";
 | 
					 | 
				
			||||||
import { serverUrlAtom } from "../../../lib/jotai";
 | 
					 | 
				
			||||||
import { HeaderLogo } from "../../Generic/HeaderLogo";
 | 
					 | 
				
			||||||
import { SetupLogItem } from "./SetupLogItem";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const SqlInjectionSetup = () => {
 | 
					 | 
				
			||||||
  // contexts
 | 
					 | 
				
			||||||
  const { openNotification } = useNotification();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // atoms
 | 
					 | 
				
			||||||
  const [serverUrl, setServerUrl] = useAtom(serverUrlAtom);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // states
 | 
					 | 
				
			||||||
  const [logs, setLogs] = useState<string[]>([]);
 | 
					 | 
				
			||||||
  const [loading, setLoading] = useState<boolean>(false);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  const setupClickEvent = async () => {
 | 
					 | 
				
			||||||
    setLoading(true);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    try {
 | 
					 | 
				
			||||||
      const response = await fetch(serverUrl + "/nuke-db", {
 | 
					 | 
				
			||||||
        method: "POST",
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
      const responseText = await response.text();
 | 
					 | 
				
			||||||
      if (!response.ok) {
 | 
					 | 
				
			||||||
        openNotification("Nuke failed: " + responseText);
 | 
					 | 
				
			||||||
      } else {
 | 
					 | 
				
			||||||
        openNotification("Nuke successful");
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      setLogs((prevLogs) => [...prevLogs.slice(-5), responseText]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      const response2 = await fetch(serverUrl + "/setup-demo-db", {
 | 
					 | 
				
			||||||
        method: "POST",
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
      const responseText2 = await response2.text();
 | 
					 | 
				
			||||||
      if (!response.ok) {
 | 
					 | 
				
			||||||
        openNotification("Setup demo DB failed: " + responseText2);
 | 
					 | 
				
			||||||
      } else {
 | 
					 | 
				
			||||||
        openNotification("Demo database setup successful");
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      setLogs((prevLogs) => [...prevLogs.slice(-5), responseText2]);
 | 
					 | 
				
			||||||
    } catch (e) {
 | 
					 | 
				
			||||||
      // log the error and handle failure
 | 
					 | 
				
			||||||
      console.log("Request failed", e);
 | 
					 | 
				
			||||||
    } finally {
 | 
					 | 
				
			||||||
      // stop loading indicator regardless of success/failure
 | 
					 | 
				
			||||||
      setLoading(false);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return (
 | 
					 | 
				
			||||||
    <>
 | 
					 | 
				
			||||||
      <Box
 | 
					 | 
				
			||||||
        alignItems="center"
 | 
					 | 
				
			||||||
        display="flex"
 | 
					 | 
				
			||||||
        flexDirection="row"
 | 
					 | 
				
			||||||
        sx={{
 | 
					 | 
				
			||||||
          mb: 2,
 | 
					 | 
				
			||||||
        }}
 | 
					 | 
				
			||||||
      >
 | 
					 | 
				
			||||||
        <HeaderLogo />
 | 
					 | 
				
			||||||
        <Typography
 | 
					 | 
				
			||||||
          sx={{
 | 
					 | 
				
			||||||
            color: "grey",
 | 
					 | 
				
			||||||
          }}
 | 
					 | 
				
			||||||
          variant="h6"
 | 
					 | 
				
			||||||
        >
 | 
					 | 
				
			||||||
           Setup
 | 
					 | 
				
			||||||
        </Typography>
 | 
					 | 
				
			||||||
      </Box>
 | 
					 | 
				
			||||||
      <Box
 | 
					 | 
				
			||||||
        sx={{
 | 
					 | 
				
			||||||
          display: "flex",
 | 
					 | 
				
			||||||
          flexDirection: "column",
 | 
					 | 
				
			||||||
          maxHeight: "100%",
 | 
					 | 
				
			||||||
        }}
 | 
					 | 
				
			||||||
      >
 | 
					 | 
				
			||||||
        <Typography variant="body2">
 | 
					 | 
				
			||||||
          Click on the 'Setup/reset DB' button below to initialize or reset your database.
 | 
					 | 
				
			||||||
        </Typography>
 | 
					 | 
				
			||||||
        <Typography variant="body2">
 | 
					 | 
				
			||||||
          If you get an error, make sure you have set the correct server URL (check the chip at the top right).
 | 
					 | 
				
			||||||
        </Typography>
 | 
					 | 
				
			||||||
        <Typography variant="body2">
 | 
					 | 
				
			||||||
          Demo email:{" "}
 | 
					 | 
				
			||||||
          <b>
 | 
					 | 
				
			||||||
            <code style={{ fontFamily: "JetBrainsMono" }}>asdf@gmail.com</code>
 | 
					 | 
				
			||||||
          </b>
 | 
					 | 
				
			||||||
        </Typography>
 | 
					 | 
				
			||||||
        <Typography variant="body2">
 | 
					 | 
				
			||||||
          Demo password:{" "}
 | 
					 | 
				
			||||||
          <b>
 | 
					 | 
				
			||||||
            <code style={{ fontFamily: "JetBrainsMono" }}>asdf</code>
 | 
					 | 
				
			||||||
          </b>
 | 
					 | 
				
			||||||
        </Typography>
 | 
					 | 
				
			||||||
        <LoadingButton
 | 
					 | 
				
			||||||
          loading={loading}
 | 
					 | 
				
			||||||
          onClick={setupClickEvent}
 | 
					 | 
				
			||||||
          size="small"
 | 
					 | 
				
			||||||
          sx={{
 | 
					 | 
				
			||||||
            my: 2,
 | 
					 | 
				
			||||||
          }}
 | 
					 | 
				
			||||||
          variant="contained"
 | 
					 | 
				
			||||||
        >
 | 
					 | 
				
			||||||
          Setup/reset DB
 | 
					 | 
				
			||||||
        </LoadingButton>
 | 
					 | 
				
			||||||
        {logs.map((log, index) => (
 | 
					 | 
				
			||||||
          <SetupLogItem key={index}>{log}</SetupLogItem>
 | 
					 | 
				
			||||||
        ))}
 | 
					 | 
				
			||||||
      </Box>
 | 
					 | 
				
			||||||
    </>
 | 
					 | 
				
			||||||
  );
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
							
								
								
									
										10
									
								
								client/src/components/Pages/Xss/Xss.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								client/src/components/Pages/Xss/Xss.tsx
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,10 @@
 | 
				
			||||||
 | 
					import { Box } from "@mui/material";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const Xss = () => {
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <Box>
 | 
				
			||||||
 | 
					      <h1>XSS</h1>
 | 
				
			||||||
 | 
					      <p>Cross-site scripting (XSS) is a type of security vulnerability</p>
 | 
				
			||||||
 | 
					    </Box>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										74
									
								
								client/src/components/Testing/Testing.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								client/src/components/Testing/Testing.tsx
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,74 @@
 | 
				
			||||||
 | 
					import { BugReportOutlined } from "@mui/icons-material";
 | 
				
			||||||
 | 
					import { Box, Button, IconButton, useTheme } from "@mui/material";
 | 
				
			||||||
 | 
					import { fetch } from "@tauri-apps/plugin-http";
 | 
				
			||||||
 | 
					import { useAtom } from "jotai";
 | 
				
			||||||
 | 
					import { useState } from "react";
 | 
				
			||||||
 | 
					import { serverUrlAtom } from "../../lib/jotai";
 | 
				
			||||||
 | 
					import { defaultSettings } from "../../lib/settings";
 | 
				
			||||||
 | 
					import { FloatingDialog } from "../Generic/FloatingDialog";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const Testing = () => {
 | 
				
			||||||
 | 
					  // contexts
 | 
				
			||||||
 | 
					  const theme = useTheme();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // atoms
 | 
				
			||||||
 | 
					  const [serverUrl, setServerUrl] = useAtom(serverUrlAtom);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // states
 | 
				
			||||||
 | 
					  const [openState, setOpenState] = useState(false);
 | 
				
			||||||
 | 
					  const [maximisedState, setMaximisedState] = useState(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // functions
 | 
				
			||||||
 | 
					  const close = () => setOpenState(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const testing = () => {
 | 
				
			||||||
 | 
					    fetch(serverUrl + "/nuke-db").then((response) => {
 | 
				
			||||||
 | 
					      console.log(response);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    fetch(serverUrl + "/setup-demo-db").then((response) => {
 | 
				
			||||||
 | 
					      console.log(response);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <FloatingDialog
 | 
				
			||||||
 | 
					      body={
 | 
				
			||||||
 | 
					        <Box
 | 
				
			||||||
 | 
					          sx={{
 | 
				
			||||||
 | 
					            border: "1px solid " + theme.palette.grey[700],
 | 
				
			||||||
 | 
					            borderRadius: defaultSettings.style.radius + "px",
 | 
				
			||||||
 | 
					            display: "flex",
 | 
				
			||||||
 | 
					            flexDirection: "column",
 | 
				
			||||||
 | 
					            flexGrow: 1,
 | 
				
			||||||
 | 
					            my: 2,
 | 
				
			||||||
 | 
					            overflow: "hidden",
 | 
				
			||||||
 | 
					            p: 0,
 | 
				
			||||||
 | 
					          }}
 | 
				
			||||||
 | 
					        >
 | 
				
			||||||
 | 
					          <Box>
 | 
				
			||||||
 | 
					            <Button
 | 
				
			||||||
 | 
					              onClick={() => {
 | 
				
			||||||
 | 
					                testing();
 | 
				
			||||||
 | 
					              }}
 | 
				
			||||||
 | 
					            >
 | 
				
			||||||
 | 
					              test
 | 
				
			||||||
 | 
					            </Button>
 | 
				
			||||||
 | 
					          </Box>
 | 
				
			||||||
 | 
					        </Box>
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      close={close}
 | 
				
			||||||
 | 
					      maximisedState={maximisedState}
 | 
				
			||||||
 | 
					      openButton={
 | 
				
			||||||
 | 
					        <IconButton
 | 
				
			||||||
 | 
					          onClick={() => setOpenState(true)}
 | 
				
			||||||
 | 
					          size="small"
 | 
				
			||||||
 | 
					        >
 | 
				
			||||||
 | 
					          <BugReportOutlined />
 | 
				
			||||||
 | 
					        </IconButton>
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      openState={openState}
 | 
				
			||||||
 | 
					      setMaximisedState={setMaximisedState}
 | 
				
			||||||
 | 
					      title="Testing"
 | 
				
			||||||
 | 
					    />
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -2,7 +2,6 @@ services:
 | 
				
			||||||
  postgres:
 | 
					  postgres:
 | 
				
			||||||
    image: postgres:latest
 | 
					    image: postgres:latest
 | 
				
			||||||
    container_name: postgres_db
 | 
					    container_name: postgres_db
 | 
				
			||||||
    restart: unless-stopped
 | 
					 | 
				
			||||||
    environment:
 | 
					    environment:
 | 
				
			||||||
      POSTGRES_USER: asdfuser
 | 
					      POSTGRES_USER: asdfuser
 | 
				
			||||||
      POSTGRES_PASSWORD: asdfpassword
 | 
					      POSTGRES_PASSWORD: asdfpassword
 | 
				
			||||||
| 
						 | 
					@ -15,7 +14,7 @@ services:
 | 
				
			||||||
  modsecurity:
 | 
					  modsecurity:
 | 
				
			||||||
    image: owasp/modsecurity-crs:apache-alpine
 | 
					    image: owasp/modsecurity-crs:apache-alpine
 | 
				
			||||||
    container_name: modsecurity
 | 
					    container_name: modsecurity
 | 
				
			||||||
    restart: unless-stopped
 | 
					    restart: always
 | 
				
			||||||
    environment:
 | 
					    environment:
 | 
				
			||||||
      BACKEND: "http://localhost:80"
 | 
					      BACKEND: "http://localhost:80"
 | 
				
			||||||
      SERVER_NAME: "localhost"
 | 
					      SERVER_NAME: "localhost"
 | 
				
			||||||
| 
						 | 
					@ -37,27 +36,9 @@ services:
 | 
				
			||||||
  dvwa:
 | 
					  dvwa:
 | 
				
			||||||
    image: vulnerables/web-dvwa
 | 
					    image: vulnerables/web-dvwa
 | 
				
			||||||
    container_name: dvwa
 | 
					    container_name: dvwa
 | 
				
			||||||
    restart: unless-stopped
 | 
					    restart: always
 | 
				
			||||||
    ports:
 | 
					    ports:
 | 
				
			||||||
      - "80:80"
 | 
					      - "80:80"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  cspj-server:
 | 
					 | 
				
			||||||
    image: cspj-server
 | 
					 | 
				
			||||||
    container_name: cspj-server
 | 
					 | 
				
			||||||
    restart: unless-stopped
 | 
					 | 
				
			||||||
    network_mode: host
 | 
					 | 
				
			||||||
    depends_on:
 | 
					 | 
				
			||||||
      - postgres
 | 
					 | 
				
			||||||
    volumes:
 | 
					 | 
				
			||||||
      - "/home/vomitblood/build/cspj-application/docker/chungus/logs/:/tmp"
 | 
					 | 
				
			||||||
    command: ["server", "-l", "/tmp"]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  cspj-ml-server:
 | 
					 | 
				
			||||||
    image: cspj-ml-server
 | 
					 | 
				
			||||||
    container_name: cspj-ml-server
 | 
					 | 
				
			||||||
    restart: unless-stopped
 | 
					 | 
				
			||||||
    ports:
 | 
					 | 
				
			||||||
      - "5000:5000"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
volumes:
 | 
					volumes:
 | 
				
			||||||
  postgres_data:
 | 
					  postgres_data:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1 +0,0 @@
 | 
				
			||||||
docker container rm modsecurity suricata dvwa postgres_db
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,11 +1,7 @@
 | 
				
			||||||
mkdir logs
 | 
					mkdir logs
 | 
				
			||||||
 | 
					 | 
				
			||||||
touch ./logs/host-fs-auditlog.log
 | 
					touch ./logs/host-fs-auditlog.log
 | 
				
			||||||
touch ./logs/host-fs-errorlog.log
 | 
					touch ./logs/host-fs-errorlog.log
 | 
				
			||||||
touch ./logs/host-fs-accesslog.log
 | 
					touch ./logs/host-fs-accesslog.log
 | 
				
			||||||
 | 
					 | 
				
			||||||
chmod 777 ./logs/host-fs-auditlog.log
 | 
					chmod 777 ./logs/host-fs-auditlog.log
 | 
				
			||||||
chmod 777 ./logs/host-fs-errorlog.log
 | 
					chmod 777 ./logs/host-fs-errorlog.log
 | 
				
			||||||
chmod 777 ./logs/host-fs-accesslog.log
 | 
					chmod 777 ./logs/host-fs-accesslog.log
 | 
				
			||||||
 | 
					 | 
				
			||||||
docker compose up
 | 
					 | 
				
			||||||
| 
						 | 
					@ -14,5 +14,5 @@ services:
 | 
				
			||||||
    volumes:
 | 
					    volumes:
 | 
				
			||||||
      - ./suricata/etc:/etc/suricata
 | 
					      - ./suricata/etc:/etc/suricata
 | 
				
			||||||
      - ./suricata/logs:/var/log/suricata
 | 
					      - ./suricata/logs:/var/log/suricata
 | 
				
			||||||
      # - ./suricata/lib:/var/lib/suricata
 | 
					      - ./suricata/lib:/var/lib/suricata
 | 
				
			||||||
    command: ["-c", "/etc/suricata/suricata.yaml", "--af-packet"]
 | 
					    command: ["-c", "/etc/suricata/suricata.yaml", "--af-packet"]
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,11 +0,0 @@
 | 
				
			||||||
FROM python:3.11.6-slim
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
WORKDIR /app
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
COPY requirements.txt .
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
RUN pip install --no-cache-dir -r requirements.txt
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
COPY main.py .
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CMD ["python", "main.py"]
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,46 +0,0 @@
 | 
				
			||||||
# Test Cases
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## 1. Basic test cases
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[Good] `SELECT _ FROM users WHERE id = 1`  
 | 
					 | 
				
			||||||
[Bad] `SELECT _ FROM users WHERE id = 1 OR 1=1`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## 2. Authentication bypass cases
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[Bad] `SELECT _ FROM users WHERE username = 'admin' --`  
 | 
					 | 
				
			||||||
[Bad] `SELECT _ FROM users WHERE username = 'admin' #`  
 | 
					 | 
				
			||||||
[Bad] `SELECT \* FROM users WHERE username = 'admin' OR '1'='1'`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## 3. Union based injection cases
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[Bad] `SELECT id, username FROM users WHERE id = 1 UNION SELECT null, 'hacker'`  
 | 
					 | 
				
			||||||
[Bad] `SELECT id, username FROM users WHERE id = 1 UNION SELECT 1, 'hacked' FROM dual`  
 | 
					 | 
				
			||||||
[Bad] `SELECT database() UNION SELECT 1`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## 4. Error based injection cases
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[Bad] `SELECT _ FROM users WHERE id = 1 AND (SELECT 1 FROM users WHERE id=2)=1`  
 | 
					 | 
				
			||||||
[Bad] `SELECT _ FROM users WHERE id = (SELECT COUNT(\*) FROM users)`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## 5. Blind SQL injection cases
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[Bad] `SELECT _ FROM users WHERE id = 1; WAITFOR DELAY '00:00:10' --`  
 | 
					 | 
				
			||||||
[Bad] `SELECT _ FROM users WHERE username = 'admin' AND 1=1`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## 6. Hex and Base64 encoded injection cases
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[Bad] `SELECT _ FROM users WHERE username = 0x61646D696E`  
 | 
					 | 
				
			||||||
[Bad] `SELECT _ FROM users WHERE username = 'YWRtaW4='`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## 7. False positives cases
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[Good] `SELECT _ FROM users WHERE id = 5`  
 | 
					 | 
				
			||||||
[Good] `SELECT users.name, orders.amount FROM users JOIN orders ON users.id = orders.user_id`  
 | 
					 | 
				
			||||||
[Good] `SELECT _ FROM users WHERE username = ? AND password = ?`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## 8. Edge cases
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[Good] `""`  
 | 
					 | 
				
			||||||
[Bad] `'; --`  
 | 
					 | 
				
			||||||
[Good] `12345`  
 | 
					 | 
				
			||||||
[Good] `asdkjhasdkjh`
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,7 +0,0 @@
 | 
				
			||||||
services:
 | 
					 | 
				
			||||||
  cspj-ml-server:
 | 
					 | 
				
			||||||
    image: cspj-ml-server
 | 
					 | 
				
			||||||
    container_name: cspj-ml-server
 | 
					 | 
				
			||||||
    restart: unless-stopped
 | 
					 | 
				
			||||||
    ports:
 | 
					 | 
				
			||||||
      - "5000:5000"
 | 
					 | 
				
			||||||
| 
						 | 
					@ -2,24 +2,19 @@ from flask import Flask, request, jsonify
 | 
				
			||||||
import torch
 | 
					import torch
 | 
				
			||||||
from transformers import MobileBertTokenizer, MobileBertForSequenceClassification
 | 
					from transformers import MobileBertTokenizer, MobileBertForSequenceClassification
 | 
				
			||||||
 | 
					
 | 
				
			||||||
print("Starting server...")
 | 
					# Initialize Flask app
 | 
				
			||||||
 | 
					 | 
				
			||||||
# initialize Flask app
 | 
					 | 
				
			||||||
app = Flask(__name__)
 | 
					app = Flask(__name__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# set device, use gpu if available
 | 
					# Set device (GPU if available, otherwise CPU)
 | 
				
			||||||
device = torch.device("cpu")
 | 
					device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
 | 
				
			||||||
# device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
# load tokenizer and model
 | 
					# Load tokenizer and model
 | 
				
			||||||
print("Loading model...")
 | 
					 | 
				
			||||||
tokenizer = MobileBertTokenizer.from_pretrained("google/mobilebert-uncased")
 | 
					tokenizer = MobileBertTokenizer.from_pretrained("google/mobilebert-uncased")
 | 
				
			||||||
model = MobileBertForSequenceClassification.from_pretrained("cssupport/mobilebert-sql-injection-detect")
 | 
					model = MobileBertForSequenceClassification.from_pretrained("cssupport/mobilebert-sql-injection-detect")
 | 
				
			||||||
model.to(device)
 | 
					model.to(device)
 | 
				
			||||||
model.eval()
 | 
					model.eval()
 | 
				
			||||||
print("Model loaded")
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
# function for model to predict sql injection
 | 
					# Function to predict SQL injection
 | 
				
			||||||
def predict(text):
 | 
					def predict(text):
 | 
				
			||||||
    inputs = tokenizer(text, padding=False, truncation=True, return_tensors="pt", max_length=512)
 | 
					    inputs = tokenizer(text, padding=False, truncation=True, return_tensors="pt", max_length=512)
 | 
				
			||||||
    input_ids = inputs["input_ids"].to(device)
 | 
					    input_ids = inputs["input_ids"].to(device)
 | 
				
			||||||
| 
						 | 
					@ -35,7 +30,7 @@ def predict(text):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return predicted_class, confidence
 | 
					    return predicted_class, confidence
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# the api endpoint
 | 
					# Define API endpoint
 | 
				
			||||||
@app.route("/predict", methods=["POST"])
 | 
					@app.route("/predict", methods=["POST"])
 | 
				
			||||||
def classify_query():
 | 
					def classify_query():
 | 
				
			||||||
    data = request.json
 | 
					    data = request.json
 | 
				
			||||||
| 
						 | 
					@ -45,16 +40,16 @@ def classify_query():
 | 
				
			||||||
    query = data["query"]
 | 
					    query = data["query"]
 | 
				
			||||||
    predicted_class, confidence = predict(query)
 | 
					    predicted_class, confidence = predict(query)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # if >0.7, then mark as bad
 | 
					    # Thresholding (if confidence > 0.7, mark as SQL Injection)
 | 
				
			||||||
    is_vulnerable = predicted_class == 1 and confidence > 0.7
 | 
					    is_vulnerable = predicted_class == 1 and confidence > 0.7
 | 
				
			||||||
    result = {
 | 
					    result = {
 | 
				
			||||||
        "query": query,
 | 
					        "query": query,
 | 
				
			||||||
        "result": "fail" if is_vulnerable else "pass",
 | 
					        "classification": "SQL Injection Detected" if is_vulnerable else "No SQL Injection Detected",
 | 
				
			||||||
        "confidence": round(confidence, 2)
 | 
					        "confidence": round(confidence, 2)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    return jsonify(result)
 | 
					    return jsonify(result)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# run the flask server
 | 
					# Run Flask server
 | 
				
			||||||
if __name__ == "__main__":
 | 
					if __name__ == "__main__":
 | 
				
			||||||
    app.run(host="0.0.0.0", port=5000, debug=False)
 | 
					    app.run(host="0.0.0.0", port=5000, debug=True)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,7 +3,7 @@ name = "server-ml"
 | 
				
			||||||
version = "0.1.0"
 | 
					version = "0.1.0"
 | 
				
			||||||
description = "Add your description here"
 | 
					description = "Add your description here"
 | 
				
			||||||
readme = "README.md"
 | 
					readme = "README.md"
 | 
				
			||||||
requires-python = ">=3.11"
 | 
					requires-python = ">=3.13"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
    "ctransformers>=0.2.27",
 | 
					    "ctransformers>=0.2.27",
 | 
				
			||||||
    "flask>=3.1.0",
 | 
					    "flask>=3.1.0",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,48 +1,3 @@
 | 
				
			||||||
accelerate==1.3.0
 | 
					flask
 | 
				
			||||||
blinker==1.9.0
 | 
					scikit-learn
 | 
				
			||||||
certifi==2025.1.31
 | 
					joblib
 | 
				
			||||||
charset-normalizer==3.4.1
 | 
					 | 
				
			||||||
click==8.1.8
 | 
					 | 
				
			||||||
ctransformers==0.2.27
 | 
					 | 
				
			||||||
filelock==3.17.0
 | 
					 | 
				
			||||||
flask==3.1.0
 | 
					 | 
				
			||||||
fsspec==2025.2.0
 | 
					 | 
				
			||||||
huggingface-hub==0.28.1
 | 
					 | 
				
			||||||
idna==3.10
 | 
					 | 
				
			||||||
itsdangerous==2.2.0
 | 
					 | 
				
			||||||
jinja2==3.1.5
 | 
					 | 
				
			||||||
markupsafe==3.0.2
 | 
					 | 
				
			||||||
mpmath==1.3.0
 | 
					 | 
				
			||||||
networkx==3.4.2
 | 
					 | 
				
			||||||
numpy==2.2.2
 | 
					 | 
				
			||||||
nvidia-cublas-cu12==12.4.5.8
 | 
					 | 
				
			||||||
nvidia-cuda-cupti-cu12==12.4.127
 | 
					 | 
				
			||||||
nvidia-cuda-nvrtc-cu12==12.4.127
 | 
					 | 
				
			||||||
nvidia-cuda-runtime-cu12==12.4.127
 | 
					 | 
				
			||||||
nvidia-cudnn-cu12==9.1.0.70
 | 
					 | 
				
			||||||
nvidia-cufft-cu12==11.2.1.3
 | 
					 | 
				
			||||||
nvidia-curand-cu12==10.3.5.147
 | 
					 | 
				
			||||||
nvidia-cusolver-cu12==11.6.1.9
 | 
					 | 
				
			||||||
nvidia-cusparse-cu12==12.3.1.170
 | 
					 | 
				
			||||||
nvidia-cusparselt-cu12==0.6.2
 | 
					 | 
				
			||||||
nvidia-nccl-cu12==2.21.5
 | 
					 | 
				
			||||||
nvidia-nvjitlink-cu12==12.4.127
 | 
					 | 
				
			||||||
nvidia-nvtx-cu12==12.4.127
 | 
					 | 
				
			||||||
packaging==24.2
 | 
					 | 
				
			||||||
peft==0.14.0
 | 
					 | 
				
			||||||
psutil==6.1.1
 | 
					 | 
				
			||||||
py-cpuinfo==9.0.0
 | 
					 | 
				
			||||||
pyyaml==6.0.2
 | 
					 | 
				
			||||||
regex==2024.11.6
 | 
					 | 
				
			||||||
requests==2.32.3
 | 
					 | 
				
			||||||
safetensors==0.5.2
 | 
					 | 
				
			||||||
setuptools==75.8.0
 | 
					 | 
				
			||||||
sympy==1.13.1
 | 
					 | 
				
			||||||
tokenizers==0.21.0
 | 
					 | 
				
			||||||
torch==2.6.0
 | 
					 | 
				
			||||||
tqdm==4.67.1
 | 
					 | 
				
			||||||
transformers==4.48.2
 | 
					 | 
				
			||||||
triton==3.2.0
 | 
					 | 
				
			||||||
typing-extensions==4.12.2
 | 
					 | 
				
			||||||
urllib3==2.3.0
 | 
					 | 
				
			||||||
werkzeug==3.1.3
 | 
					 | 
				
			||||||
							
								
								
									
										46
									
								
								server-ml/test-cases.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								server-ml/test-cases.md
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,46 @@
 | 
				
			||||||
 | 
					# Test Cases
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 1. Basic test cases
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[Good] `SELECT _ FROM users WHERE id = 1`  
 | 
				
			||||||
 | 
					[Bad] `SELECT _ FROM users WHERE id = 1 OR 1=1`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 2. Authentication bypass cases
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[Bad] `SELECT _ FROM users WHERE username = 'admin' --`  
 | 
				
			||||||
 | 
					[Bad] `SELECT _ FROM users WHERE username = 'admin' #`  
 | 
				
			||||||
 | 
					[Bad] `SELECT \* FROM users WHERE username = 'admin' OR '1'='1'`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 3. Union based injection cases
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[Bad] `SELECT id, username FROM users WHERE id = 1 UNION SELECT null, 'hacker'`  
 | 
				
			||||||
 | 
					[Bad] `SELECT id, username FROM users WHERE id = 1 UNION SELECT 1, 'hacked' FROM dual`  
 | 
				
			||||||
 | 
					[Bad] `SELECT database() UNION SELECT 1`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 4. Error based injection cases
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[Bad] `SELECT _ FROM users WHERE id = 1 AND (SELECT 1 FROM users WHERE id=2)=1`  
 | 
				
			||||||
 | 
					[Bad] `SELECT _ FROM users WHERE id = (SELECT COUNT(\*) FROM users)`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 5. Blind SQL injection cases
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[Bad] `SELECT _ FROM users WHERE id = 1; WAITFOR DELAY '00:00:10' --`  
 | 
				
			||||||
 | 
					[Bad] `SELECT _ FROM users WHERE username = 'admin' AND 1=1`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 6. Hex and Base64 encoded injection cases
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[Bad] `SELECT _ FROM users WHERE username = 0x61646D696E`  
 | 
				
			||||||
 | 
					[Bad] `SELECT _ FROM users WHERE username = 'YWRtaW4='`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 7. False positives cases
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[Good] `SELECT _ FROM users WHERE id = 5`  
 | 
				
			||||||
 | 
					[Good] `SELECT users.name, orders.amount FROM users JOIN orders ON users.id = orders.user_id`  
 | 
				
			||||||
 | 
					[Good] `SELECT _ FROM users WHERE username = ? AND password = ?`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 8. Edge cases
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[Good] `""`  
 | 
				
			||||||
 | 
					[Bad] `'; --`  
 | 
				
			||||||
 | 
					[Good] `12345`  
 | 
				
			||||||
 | 
					[Good] `asdkjhasdkjh`
 | 
				
			||||||
							
								
								
									
										35
									
								
								server-ml/training.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								server-ml/training.py
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,35 @@
 | 
				
			||||||
 | 
					import joblib
 | 
				
			||||||
 | 
					from sklearn.feature_extraction.text import CountVectorizer
 | 
				
			||||||
 | 
					from sklearn.linear_model import LogisticRegression
 | 
				
			||||||
 | 
					from sklearn.pipeline import make_pipeline
 | 
				
			||||||
 | 
					from sklearn.model_selection import train_test_split
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# random data
 | 
				
			||||||
 | 
					data = [
 | 
				
			||||||
 | 
					    ("' OR '1'='1", 1),
 | 
				
			||||||
 | 
					    ("SELECT * FROM users WHERE id=1", 1),
 | 
				
			||||||
 | 
					    ("DROP TABLE users;", 1),
 | 
				
			||||||
 | 
					    ("username=admin'--", 1),
 | 
				
			||||||
 | 
					    ("hello world", 0),
 | 
				
			||||||
 | 
					    ("this is a normal query", 0),
 | 
				
			||||||
 | 
					    ("select data from table", 0),
 | 
				
			||||||
 | 
					    ("just another harmless input", 0),
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					queries, labels = zip(*data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# split data into training and testing sets
 | 
				
			||||||
 | 
					X_train, X_test, y_train, y_test = train_test_split(
 | 
				
			||||||
 | 
					    queries, labels, test_size=0.2, random_state=42
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# build a pipeline with a vectorizer and a logistic regression model
 | 
				
			||||||
 | 
					pipeline = make_pipeline(CountVectorizer(), LogisticRegression())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# train the model
 | 
				
			||||||
 | 
					pipeline.fit(X_train, y_train)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# save the model to a file
 | 
				
			||||||
 | 
					joblib.dump(pipeline, "model.pkl")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					print("Model trained and saved to model.pkl")
 | 
				
			||||||
| 
						 | 
					@ -1,7 +0,0 @@
 | 
				
			||||||
FROM alpine:latest
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
WORKDIR /app
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
COPY server /usr/local/bin/server
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
RUN chmod +x /usr/local/bin/server
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,2 +0,0 @@
 | 
				
			||||||
#!/bin/bash
 | 
					 | 
				
			||||||
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o server main.go
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,11 +0,0 @@
 | 
				
			||||||
services:
 | 
					 | 
				
			||||||
  cspj-server:
 | 
					 | 
				
			||||||
    image: cspj-server
 | 
					 | 
				
			||||||
    container_name: cspj-server
 | 
					 | 
				
			||||||
    restart: unless-stopped
 | 
					 | 
				
			||||||
    network_mode: host
 | 
					 | 
				
			||||||
    depends_on:
 | 
					 | 
				
			||||||
      - postgres
 | 
					 | 
				
			||||||
    volumes:
 | 
					 | 
				
			||||||
      - "/home/vomitblood/build/cspj-application/docker/chungus/logs/:/tmp"
 | 
					 | 
				
			||||||
    command: ["server", "-l", "/tmp"]
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,24 +0,0 @@
 | 
				
			||||||
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
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,3 +0,0 @@
 | 
				
			||||||
package config
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var LogDirectory string
 | 
					 | 
				
			||||||
| 
						 | 
					@ -87,7 +87,6 @@ func SetupDemoDb(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
	// avoid duplicate entries and specify roles
 | 
						// avoid duplicate entries and specify roles
 | 
				
			||||||
	insertDataSQL := `
 | 
						insertDataSQL := `
 | 
				
			||||||
	INSERT INTO users (email, password, role) VALUES
 | 
						INSERT INTO users (email, password, role) VALUES
 | 
				
			||||||
	('asdf@gmail.com', 'asdf', 'user'),
 | 
					 | 
				
			||||||
	('alice@example.com', 'asdfalicepassword', 'user'),
 | 
						('alice@example.com', 'asdfalicepassword', 'user'),
 | 
				
			||||||
	('bob@example.com', 'asdfbobpassword', 'user'),
 | 
						('bob@example.com', 'asdfbobpassword', 'user'),
 | 
				
			||||||
	('charlie@example.com', 'asdfcharliepassword', 'admin')
 | 
						('charlie@example.com', 'asdfcharliepassword', 'admin')
 | 
				
			||||||
| 
						 | 
					@ -153,6 +152,7 @@ func FetchEmails() (map[string]bool, error) {
 | 
				
			||||||
		emails[email] = true
 | 
							emails[email] = true
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						log.Println("Fetched emails:", emails)
 | 
				
			||||||
	return emails, nil
 | 
						return emails, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,17 +3,16 @@ package log_backup
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"log"
 | 
						"log"
 | 
				
			||||||
	"path/filepath"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/Vomitblood/cspj-application/server/internal/config"
 | 
					 | 
				
			||||||
	"github.com/Vomitblood/cspj-application/server/internal/webdav"
 | 
						"github.com/Vomitblood/cspj-application/server/internal/webdav"
 | 
				
			||||||
	"github.com/studio-b12/gowebdav"
 | 
						"github.com/studio-b12/gowebdav"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TODO: use values from config file
 | 
				
			||||||
var localLogPaths = []string{
 | 
					var localLogPaths = []string{
 | 
				
			||||||
	filepath.Join(config.LogDirectory, "host-fs-accesslog.log"),
 | 
						"/home/vomitblood/build/cspj-application/docker/chungus/logs/host-fs-accesslog.log",
 | 
				
			||||||
	filepath.Join(config.LogDirectory, "host-fs-auditlog.log"),
 | 
						"/home/vomitblood/build/cspj-application/docker/chungus/logs/host-fs-auditlog.log",
 | 
				
			||||||
	filepath.Join(config.LogDirectory, "host-fs-errorlog.log"),
 | 
						"/home/vomitblood/build/cspj-application/docker/chungus/logs/host-fs-errorlog.log",
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var remoteFiles = []string{
 | 
					var remoteFiles = []string{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,14 +5,17 @@ import (
 | 
				
			||||||
	"encoding/json"
 | 
						"encoding/json"
 | 
				
			||||||
	"log"
 | 
						"log"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
	"path/filepath"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/Vomitblood/cspj-application/server/internal/config"
 | 
					 | 
				
			||||||
	"github.com/Vomitblood/cspj-application/server/internal/telegram"
 | 
						"github.com/Vomitblood/cspj-application/server/internal/telegram"
 | 
				
			||||||
	"github.com/fsnotify/fsnotify"
 | 
						"github.com/fsnotify/fsnotify"
 | 
				
			||||||
	tg "github.com/go-telegram-bot-api/telegram-bot-api/v5"
 | 
						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
 | 
					var lastReadPosition int64 = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type LogEntry struct {
 | 
					type LogEntry struct {
 | 
				
			||||||
| 
						 | 
					@ -22,8 +25,6 @@ type LogEntry struct {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func WatchFile(bot *tg.BotAPI) {
 | 
					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()
 | 
						watcher, err := fsnotify.NewWatcher()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		log.Fatal("Failed to initialize watcher:", err)
 | 
							log.Fatal("Failed to initialize watcher:", err)
 | 
				
			||||||
| 
						 | 
					@ -59,7 +60,6 @@ func WatchFile(bot *tg.BotAPI) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func readNewLines(bot *tg.BotAPI) {
 | 
					func readNewLines(bot *tg.BotAPI) {
 | 
				
			||||||
	modsecLogFile := filepath.Join(config.LogDirectory, "host-fs-auditlog.log")
 | 
					 | 
				
			||||||
	file, err := os.Open(modsecLogFile)
 | 
						file, err := os.Open(modsecLogFile)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		log.Println("Failed to reopen log file:", err)
 | 
							log.Println("Failed to reopen log file:", err)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,6 @@
 | 
				
			||||||
package sql_injection
 | 
					package sql_injection
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"bytes"
 | 
					 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"encoding/json"
 | 
						"encoding/json"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
| 
						 | 
					@ -135,7 +134,6 @@ func SecureRegisterSql(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func UnsecureLoginSql(w http.ResponseWriter, r *http.Request) {
 | 
					func UnsecureLoginSql(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
	log.Println("/unsecure-login-sql hit")
 | 
					 | 
				
			||||||
	// decode the json body
 | 
						// decode the json body
 | 
				
			||||||
	var requestData struct {
 | 
						var requestData struct {
 | 
				
			||||||
		Email    string `json:"email"`
 | 
							Email    string `json:"email"`
 | 
				
			||||||
| 
						 | 
					@ -177,18 +175,12 @@ func UnsecureLoginSql(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// very secure login endpoint
 | 
					// very secure login endpoint
 | 
				
			||||||
func SecureLoginSql(w http.ResponseWriter, r *http.Request) {
 | 
					func SecureLoginSql(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
	log.Println("/secure-login-sql hit")
 | 
						// decode the json body
 | 
				
			||||||
	var requestData struct {
 | 
						var requestData struct {
 | 
				
			||||||
		Email    string `json:"email"`
 | 
							Email    string `json:"email"`
 | 
				
			||||||
		Password string `json:"password"`
 | 
							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
 | 
						// declare new json decoder with custom property
 | 
				
			||||||
	jsonDecoder := json.NewDecoder(r.Body)
 | 
						jsonDecoder := json.NewDecoder(r.Body)
 | 
				
			||||||
	// rejects any unknown fields in the json, more strict
 | 
						// rejects any unknown fields in the json, more strict
 | 
				
			||||||
| 
						 | 
					@ -222,35 +214,6 @@ func SecureLoginSql(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
		return
 | 
							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
 | 
						// retrieve the email and password from the database
 | 
				
			||||||
	var id int
 | 
						var id int
 | 
				
			||||||
	var email string
 | 
						var email string
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,8 +3,6 @@ package main
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"log"
 | 
						"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/db"
 | 
				
			||||||
	"github.com/Vomitblood/cspj-application/server/internal/http_server"
 | 
						"github.com/Vomitblood/cspj-application/server/internal/http_server"
 | 
				
			||||||
	"github.com/Vomitblood/cspj-application/server/internal/log_watcher"
 | 
						"github.com/Vomitblood/cspj-application/server/internal/log_watcher"
 | 
				
			||||||
| 
						 | 
					@ -13,9 +11,6 @@ import (
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func main() {
 | 
					func main() {
 | 
				
			||||||
	cli.GetFlags()
 | 
					 | 
				
			||||||
	log.Printf("Log directory set to: %s", config.LogDirectory)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	var err error
 | 
						var err error
 | 
				
			||||||
	db.DbPool, err = db.ConnectToDb()
 | 
						db.DbPool, err = db.ConnectToDb()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
| 
						 | 
					@ -32,5 +27,7 @@ func main() {
 | 
				
			||||||
	// start log watcher
 | 
						// start log watcher
 | 
				
			||||||
	go log_watcher.WatchFile(tgBot)
 | 
						go log_watcher.WatchFile(tgBot)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	http_server.ServeApi()
 | 
						http_server.ServeApi()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue