login and registration unsecured
This commit is contained in:
parent
53c0ada12e
commit
ffbdd9d427
|
@ -41,7 +41,9 @@ PGPASSWORD=asdfpassword
|
||||||
|
|
||||||
### SQL Injection
|
### SQL Injection
|
||||||
|
|
||||||
|
- `/unsecure-register-sql`
|
||||||
- `/secure-register-sql`
|
- `/secure-register-sql`
|
||||||
|
- `/unsecure-login-sql`
|
||||||
- `/secure-login-sql`
|
- `/secure-login-sql`
|
||||||
|
|
||||||
#### 1. Parameterization of Queries
|
#### 1. Parameterization of Queries
|
||||||
|
|
BIN
client/public/images/logo.webp
Normal file
BIN
client/public/images/logo.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
|
@ -17,7 +17,7 @@ export const HeaderLogo: FC<HeaderLogoProps> = ({ sx }) => {
|
||||||
alt="Logo"
|
alt="Logo"
|
||||||
height={40}
|
height={40}
|
||||||
priority
|
priority
|
||||||
src="images/logo.gif"
|
src="images/logo.webp"
|
||||||
width={40}
|
width={40}
|
||||||
/>
|
/>
|
||||||
<Typography
|
<Typography
|
||||||
|
|
|
@ -9,9 +9,9 @@ export const ServerUrlInput = () => {
|
||||||
return (
|
return (
|
||||||
<TextField
|
<TextField
|
||||||
fullWidth
|
fullWidth
|
||||||
label='Backend server URL'
|
label="Backend server URL"
|
||||||
onChange={(event) => setServerUrl(event.target.value)}
|
// onChange={(event) => setServerUrl(event.target.value)}
|
||||||
size='small'
|
size="small"
|
||||||
value={serverUrl}
|
value={serverUrl}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
|
@ -30,12 +30,12 @@ export const Home = () => {
|
||||||
CSPJ Application Attack Simulator
|
CSPJ Application Attack Simulator
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
<Button
|
{/* <Button
|
||||||
href="https://github.com/cspj-nyp/cspj-application"
|
href="https://github.com/cspj-nyp/cspj-application"
|
||||||
sx={{ mb: 2 }}
|
sx={{ mb: 2 }}
|
||||||
>
|
>
|
||||||
Need help getting started?
|
Need help getting started?
|
||||||
</Button>
|
</Button> */}
|
||||||
</Box>
|
</Box>
|
||||||
<Grid2
|
<Grid2
|
||||||
container
|
container
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
import { Box, TextField, Typography } from "@mui/material";
|
import { LoadingButton } from "@mui/lab";
|
||||||
|
import { Box, FormControlLabel, Switch, TextField, Typography } from "@mui/material";
|
||||||
|
import { fetch } from "@tauri-apps/plugin-http";
|
||||||
import { useAtom } from "jotai";
|
import { useAtom } from "jotai";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useNotification } from "../../../contexts/NotificationContext";
|
import { useNotification } from "../../../contexts/NotificationContext";
|
||||||
import { serverUrlAtom } from "../../../lib/jotai";
|
import { serverUrlAtom } from "../../../lib/jotai";
|
||||||
import { HeaderLogo } from "../../Generic/HeaderLogo";
|
import { HeaderLogo } from "../../Generic/HeaderLogo";
|
||||||
import { LoadingButton } from "@mui/lab";
|
|
||||||
|
|
||||||
export const SqlInjectionLogin = () => {
|
export const SqlInjectionLogin = () => {
|
||||||
// contexts
|
// contexts
|
||||||
|
@ -18,6 +19,7 @@ export const SqlInjectionLogin = () => {
|
||||||
const [passwordValueRaw, setPasswordValueRaw] = useState<string>("");
|
const [passwordValueRaw, setPasswordValueRaw] = useState<string>("");
|
||||||
const [errorMsg, setErrorMsg] = useState<string>("");
|
const [errorMsg, setErrorMsg] = useState<string>("");
|
||||||
const [loginLoading, setLoginLoading] = useState<boolean>(false);
|
const [loginLoading, setLoginLoading] = useState<boolean>(false);
|
||||||
|
const [secured, setSecured] = useState<boolean>(false);
|
||||||
|
|
||||||
const nextClickEvent = async () => {
|
const nextClickEvent = async () => {
|
||||||
// reset the error messages
|
// reset the error messages
|
||||||
|
@ -35,9 +37,11 @@ export const SqlInjectionLogin = () => {
|
||||||
// start loading indicator
|
// start loading indicator
|
||||||
setLoginLoading(true);
|
setLoginLoading(true);
|
||||||
|
|
||||||
|
const endpointUrl = serverUrl + (secured ? "/secure-login-sql" : "/unsecure-login-sql");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// make request good
|
// make request good
|
||||||
const response = await fetch(serverUrl + "/register-sql", {
|
const response = await fetch(endpointUrl, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
@ -100,7 +104,7 @@ export const SqlInjectionLogin = () => {
|
||||||
label="Email"
|
label="Email"
|
||||||
onChange={(e: { target: { value: string } }) => setEmailValueRaw(e.target.value)}
|
onChange={(e: { target: { value: string } }) => setEmailValueRaw(e.target.value)}
|
||||||
size="small"
|
size="small"
|
||||||
type="email"
|
type="text"
|
||||||
value={emailValueRaw}
|
value={emailValueRaw}
|
||||||
sx={{ mb: 2 }}
|
sx={{ mb: 2 }}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
|
@ -122,9 +126,20 @@ export const SqlInjectionLogin = () => {
|
||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
justifyContent: "end",
|
justifyContent: "space-between",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
<FormControlLabel
|
||||||
|
control={
|
||||||
|
<Switch
|
||||||
|
checked={secured}
|
||||||
|
onChange={(e) => {
|
||||||
|
setSecured(e.target.checked);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label="Use secure endpoint"
|
||||||
|
/>
|
||||||
<LoadingButton
|
<LoadingButton
|
||||||
loading={loginLoading}
|
loading={loginLoading}
|
||||||
type="submit"
|
type="submit"
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { LoadingButton } from "@mui/lab";
|
import { LoadingButton } from "@mui/lab";
|
||||||
import { Box, LinearProgress, TextField, Typography } from "@mui/material";
|
import { Box, FormControlLabel, LinearProgress, Switch, TextField, Typography } 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 { useState } from "react";
|
import { useState } from "react";
|
||||||
|
import { useNotification } from "../../../contexts/NotificationContext";
|
||||||
import { serverUrlAtom } from "../../../lib/jotai";
|
import { serverUrlAtom } from "../../../lib/jotai";
|
||||||
import { HeaderLogo } from "../../Generic/HeaderLogo";
|
import { HeaderLogo } from "../../Generic/HeaderLogo";
|
||||||
import { useNotification } from "../../../contexts/NotificationContext";
|
|
||||||
|
|
||||||
export const SqlInjectionRegister = () => {
|
export const SqlInjectionRegister = () => {
|
||||||
// contexts
|
// contexts
|
||||||
|
@ -25,6 +25,7 @@ export const SqlInjectionRegister = () => {
|
||||||
);
|
);
|
||||||
const [passwordStrengthInfo, setPasswordStrengthInfo] = useState("Enter a password");
|
const [passwordStrengthInfo, setPasswordStrengthInfo] = useState("Enter a password");
|
||||||
const [registerLoading, setRegisterLoading] = useState<boolean>(false);
|
const [registerLoading, setRegisterLoading] = useState<boolean>(false);
|
||||||
|
const [secured, setSecured] = useState<boolean>(false);
|
||||||
|
|
||||||
let newPasswordStrengthInfo = "Enter a password";
|
let newPasswordStrengthInfo = "Enter a password";
|
||||||
|
|
||||||
|
@ -105,9 +106,12 @@ export const SqlInjectionRegister = () => {
|
||||||
// start loading indicator
|
// start loading indicator
|
||||||
setRegisterLoading(true);
|
setRegisterLoading(true);
|
||||||
|
|
||||||
|
// construct endpoint url
|
||||||
|
const endpointUrl = serverUrl + (secured ? "/secure-register-sql" : "/unsecure-register-sql");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// make request good
|
// make request good
|
||||||
const response = await fetch(serverUrl + "/secure-register-sql", {
|
const response = await fetch(endpointUrl, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
@ -171,7 +175,7 @@ export const SqlInjectionRegister = () => {
|
||||||
label="Email"
|
label="Email"
|
||||||
onChange={(e: { target: { value: string } }) => setEmailValueRaw(e.target.value)}
|
onChange={(e: { target: { value: string } }) => setEmailValueRaw(e.target.value)}
|
||||||
size="small"
|
size="small"
|
||||||
type="email"
|
type="text"
|
||||||
value={emailValueRaw}
|
value={emailValueRaw}
|
||||||
sx={{ mb: 2 }}
|
sx={{ mb: 2 }}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
|
@ -237,9 +241,20 @@ export const SqlInjectionRegister = () => {
|
||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
justifyContent: "end",
|
justifyContent: "space-between",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
<FormControlLabel
|
||||||
|
control={
|
||||||
|
<Switch
|
||||||
|
checked={secured}
|
||||||
|
onChange={(e) => {
|
||||||
|
setSecured(e.target.checked);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label="Use secure endpoint"
|
||||||
|
/>
|
||||||
<LoadingButton
|
<LoadingButton
|
||||||
loading={registerLoading}
|
loading={registerLoading}
|
||||||
type="submit"
|
type="submit"
|
||||||
|
|
|
@ -13,4 +13,5 @@ type ServerConnection = "connected" | "connecting" | "disconnected";
|
||||||
export const serverConnectionAtom = atom<ServerConnection>("disconnected");
|
export const serverConnectionAtom = atom<ServerConnection>("disconnected");
|
||||||
|
|
||||||
// store the url of the backend server
|
// store the url of the backend server
|
||||||
export const serverUrlAtom = atom("");
|
// TODO: let user enter their own backend server url
|
||||||
|
export const serverUrlAtom = atom("http://localhost:5000");
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5/pgxpool"
|
"github.com/jackc/pgx/v5/pgxpool"
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
)
|
)
|
||||||
|
|
||||||
// db connection info
|
// db connection info
|
||||||
|
@ -75,6 +76,17 @@ func DbHealthCheck(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
// setup demo db
|
// setup demo db
|
||||||
func SetupDemoDb(w http.ResponseWriter, r *http.Request) {
|
func SetupDemoDb(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// default password for demo users
|
||||||
|
defaultPassword := "Password!23"
|
||||||
|
|
||||||
|
// Hash the default password
|
||||||
|
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(defaultPassword), bcrypt.DefaultCost)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, "Error hashing password", http.StatusInternalServerError)
|
||||||
|
log.Printf("Error hashing password: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// create table and insert demo data
|
// create table and insert demo data
|
||||||
createTableSQL := `
|
createTableSQL := `
|
||||||
CREATE TABLE IF NOT EXISTS users (
|
CREATE TABLE IF NOT EXISTS users (
|
||||||
|
@ -87,13 +99,13 @@ 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
|
||||||
('alice@example.com', 'asdfalicepassword', 'user'),
|
('alice@example.com', $1, 'user'),
|
||||||
('bob@example.com', 'asdfbobpassword', 'user'),
|
('bob@example.com', $2, 'user'),
|
||||||
('charlie@example.com', 'asdfcharliepassword', 'admin')
|
('charlie@example.com', $3, 'admin')
|
||||||
`
|
`
|
||||||
|
|
||||||
// execute create table
|
// execute create table
|
||||||
_, err := DbPool.Exec(context.Background(), createTableSQL)
|
_, err = DbPool.Exec(context.Background(), createTableSQL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Failed to create table", http.StatusInternalServerError)
|
http.Error(w, "Failed to create table", http.StatusInternalServerError)
|
||||||
log.Printf("Error creating table: %v", err)
|
log.Printf("Error creating table: %v", err)
|
||||||
|
@ -101,7 +113,7 @@ func SetupDemoDb(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// execute insert demo data
|
// execute insert demo data
|
||||||
_, err = DbPool.Exec(context.Background(), insertDataSQL)
|
_, err = DbPool.Exec(context.Background(), insertDataSQL, hashedPassword, hashedPassword, hashedPassword)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Failed to insert demo data", http.StatusInternalServerError)
|
http.Error(w, "Failed to insert demo data", http.StatusInternalServerError)
|
||||||
log.Printf("Error inserting demo data: %v", err)
|
log.Printf("Error inserting demo data: %v", err)
|
||||||
|
|
|
@ -21,8 +21,11 @@ func ServeApi() {
|
||||||
http.HandleFunc("/setup-demo-db", db.SetupDemoDb)
|
http.HandleFunc("/setup-demo-db", db.SetupDemoDb)
|
||||||
http.HandleFunc("/nuke-db", db.NukeDb)
|
http.HandleFunc("/nuke-db", db.NukeDb)
|
||||||
http.HandleFunc("/fetch-all-users", db.FetchAllUsers)
|
http.HandleFunc("/fetch-all-users", db.FetchAllUsers)
|
||||||
|
http.HandleFunc("/unsecure-register-sql", sql_injection.UnsecureRegisterSql)
|
||||||
http.HandleFunc("/secure-register-sql", sql_injection.SecureRegisterSql)
|
http.HandleFunc("/secure-register-sql", sql_injection.SecureRegisterSql)
|
||||||
|
http.HandleFunc("/unsecure-login-sql", sql_injection.UnsecureLoginSql)
|
||||||
http.HandleFunc("/secure-login-sql", sql_injection.SecureLoginSql)
|
http.HandleFunc("/secure-login-sql", sql_injection.SecureLoginSql)
|
||||||
|
|
||||||
log.Println("Server is running on http://localhost:5000")
|
log.Println("Server is running on http://localhost:5000")
|
||||||
if err := http.ListenAndServe(":5000", nil); err != nil {
|
if err := http.ListenAndServe(":5000", nil); err != nil {
|
||||||
log.Fatalf("Failed to start server: %v", err)
|
log.Fatalf("Failed to start server: %v", err)
|
||||||
|
|
|
@ -59,6 +59,7 @@ func UnsecureRegisterSql(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
// hash the password
|
// hash the password
|
||||||
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(credentials.Password), bcrypt.DefaultCost)
|
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(credentials.Password), bcrypt.DefaultCost)
|
||||||
|
fmt.Println(hashedPassword)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Error hashing password", http.StatusInternalServerError)
|
http.Error(w, "Error hashing password", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
|
|
Loading…
Reference in a new issue