removed bcrypt; too secure haha

This commit is contained in:
Vomitblood 2025-01-14 04:12:55 +08:00
parent ffbdd9d427
commit ec31b5318a
2 changed files with 17 additions and 57 deletions

View file

@ -41,6 +41,8 @@ PGPASSWORD=asdfpassword
### SQL Injection ### SQL Injection
Use `' OR 1=1; --`
- `/unsecure-register-sql` - `/unsecure-register-sql`
- `/secure-register-sql` - `/secure-register-sql`
- `/unsecure-login-sql` - `/unsecure-login-sql`
@ -50,13 +52,3 @@ PGPASSWORD=asdfpassword
Used `pool.Query()` with a parameterized query, instead of dynamically constructing the SQL query by directly inserting the user input. Used `pool.Query()` with a parameterized query, instead of dynamically constructing the SQL query by directly inserting the user input.
Parameterized queries separate the SQL code from the data, so user input is never directly put into the query's structure. Placeholders are used instead, and the data is passed as parameters. The DB will treat them as data, not executable code. Parameterized queries separate the SQL code from the data, so user input is never directly put into the query's structure. Placeholders are used instead, and the data is passed as parameters. The DB will treat them as data, not executable code.
#### 2. Input Validation and Query Type Restriction
Only allow `SELECT` statement by verifying that the input query starts with it.
Sanitized the input to ensure that no other types of statements could be executed.
The input is checked against a list of allowed query terms, and if it doesn't match, the query is rejected.
#### 3. Controlled JSON Input for Parameters
Instead of using raw SQL strings, we restructured the input to ONLY expect JSON data with `query` and `params` fields.

View file

@ -9,7 +9,6 @@ import (
"regexp" "regexp"
"github.com/Vomitblood/cspj-application/server/internal/db" "github.com/Vomitblood/cspj-application/server/internal/db"
"golang.org/x/crypto/bcrypt"
) )
// secure register endpoint // secure register endpoint
@ -57,17 +56,9 @@ func UnsecureRegisterSql(w http.ResponseWriter, r *http.Request) {
return return
} }
// hash the password
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(credentials.Password), bcrypt.DefaultCost)
fmt.Println(hashedPassword)
if err != nil {
http.Error(w, "Error hashing password", http.StatusInternalServerError)
return
}
// over here the validations has passed, so insert into the db // over here the validations has passed, so insert into the db
// also use concatenation here // also use concatenation here
insertSQL := fmt.Sprintf("INSERT INTO users (email, password, role) VALUES ('%s', '%s', 'user')", credentials.Email, string(hashedPassword)) insertSQL := fmt.Sprintf("INSERT INTO users (email, password, role) VALUES ('%s', '%s', 'user')", credentials.Email, credentials.Password)
_, err = db.DbPool.Exec(context.Background(), insertSQL) _, err = db.DbPool.Exec(context.Background(), insertSQL)
if err != nil { if err != nil {
http.Error(w, "Error inserting user into the database", http.StatusInternalServerError) http.Error(w, "Error inserting user into the database", http.StatusInternalServerError)
@ -126,17 +117,10 @@ func SecureRegisterSql(w http.ResponseWriter, r *http.Request) {
return return
} }
// hash the password
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(credentials.Password), bcrypt.DefaultCost)
if err != nil {
http.Error(w, "Error hashing password", http.StatusInternalServerError)
return
}
// over here the validations has passed, so insert into the db // over here the validations has passed, so insert into the db
// use parameterization // use parameterization
insertSQL := `INSERT INTO users (email, password, role) VALUES ($1, $2, $3)` insertSQL := `INSERT INTO users (email, password, role) VALUES ($1, $2, $3)`
_, err = db.DbPool.Exec(context.Background(), insertSQL, credentials.Email, hashedPassword, "user") _, err = db.DbPool.Exec(context.Background(), insertSQL, credentials.Email, credentials.Password, "user")
if err != nil { if err != nil {
http.Error(w, "Error inserting user into the database", http.StatusInternalServerError) http.Error(w, "Error inserting user into the database", http.StatusInternalServerError)
log.Printf("Error inserting user: %v", err) log.Printf("Error inserting user: %v", err)
@ -149,7 +133,6 @@ func SecureRegisterSql(w http.ResponseWriter, r *http.Request) {
log.Println("User registered successfully:", credentials.Email) log.Println("User registered successfully:", credentials.Email)
} }
// very secure login endpoint
func UnsecureLoginSql(w http.ResponseWriter, r *http.Request) { func UnsecureLoginSql(w http.ResponseWriter, r *http.Request) {
// decode the json body // decode the json body
var requestData struct { var requestData struct {
@ -157,43 +140,29 @@ func UnsecureLoginSql(w http.ResponseWriter, r *http.Request) {
Password string `json:"password"` Password string `json:"password"`
} }
// declare new json decoder with custom property // decode the request body
jsonDecoder := json.NewDecoder(r.Body)
// rejects any unknown fields in the json, more strict
jsonDecoder.DisallowUnknownFields()
if err := json.NewDecoder(r.Body).Decode(&requestData); err != nil { if err := json.NewDecoder(r.Body).Decode(&requestData); err != nil {
http.Error(w, "Invalid request format", http.StatusBadRequest) http.Error(w, "Invalid request format", http.StatusBadRequest)
log.Println("Failed to decode JSON body or extra fields present:", err) log.Println("Failed to decode JSON body:", err)
return return
} }
// validate that user is provided // make insecure sql command
if requestData.Email == "" || requestData.Password == "" { query := fmt.Sprintf("SELECT id, email, password FROM users WHERE email = '%s' AND password = '%s'", requestData.Email, requestData.Password)
http.Error(w, "Invalid request format", http.StatusBadRequest)
return
}
// retrieve the user data
// construct sql command using concatenation
query := fmt.Sprintf("SELECT id, email, password FROM users WHERE email = '%s'", requestData.Email)
var id int var id int
var email string var email string
var hashedPassword string var password string
err := db.DbPool.QueryRow(context.Background(), query).Scan(&id, &email, &hashedPassword)
if err != nil {
http.Error(w, "Invalid email or password", http.StatusNotFound)
return
}
// compare the provided password with the stored hashed password // execute the query to retrieve the data
err = bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(requestData.Password)) err := db.DbPool.QueryRow(context.Background(), query).Scan(&id, &email, &password)
if err != nil { if err != nil {
http.Error(w, "Invalid email or password", http.StatusUnauthorized) http.Error(w, "Invalid email or password", http.StatusUnauthorized)
log.Println("Error during query execution:", err)
return return
} }
// send back the user data as a JSON response // if the email and password match then send back the user data
response := map[string]interface{}{ response := map[string]interface{}{
"id": id, "id": id,
"email": email, "email": email,
@ -248,17 +217,16 @@ func SecureLoginSql(w http.ResponseWriter, r *http.Request) {
// 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
var hashedPassword string var storedPassword string
query := "SELECT id, email, password FROM users WHERE email = $1" query := "SELECT id, email, password FROM users WHERE email = $1"
err = db.DbPool.QueryRow(context.Background(), query, requestData.Email).Scan(&id, &email, &hashedPassword) err = db.DbPool.QueryRow(context.Background(), query, requestData.Email).Scan(&id, &email, &storedPassword)
if err != nil { if err != nil {
http.Error(w, "Invalid email or password", http.StatusNotFound) http.Error(w, "Invalid email or password", http.StatusNotFound)
return return
} }
// compare the provided password and the stored password hashes // compare the provided password with the stored plain-text password
err = bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(requestData.Password)) if storedPassword != requestData.Password {
if err != nil {
http.Error(w, "Invalid email or password", http.StatusUnauthorized) http.Error(w, "Invalid email or password", http.StatusUnauthorized)
return return
} }