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
Use `' OR 1=1; --`
- `/unsecure-register-sql`
- `/secure-register-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.
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"
"github.com/Vomitblood/cspj-application/server/internal/db"
"golang.org/x/crypto/bcrypt"
)
// secure register endpoint
@ -57,17 +56,9 @@ func UnsecureRegisterSql(w http.ResponseWriter, r *http.Request) {
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
// 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)
if err != nil {
http.Error(w, "Error inserting user into the database", http.StatusInternalServerError)
@ -126,17 +117,10 @@ func SecureRegisterSql(w http.ResponseWriter, r *http.Request) {
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
// use parameterization
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 {
http.Error(w, "Error inserting user into the database", http.StatusInternalServerError)
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)
}
// very secure login endpoint
func UnsecureLoginSql(w http.ResponseWriter, r *http.Request) {
// decode the json body
var requestData struct {
@ -157,43 +140,29 @@ func UnsecureLoginSql(w http.ResponseWriter, r *http.Request) {
Password string `json:"password"`
}
// declare new json decoder with custom property
jsonDecoder := json.NewDecoder(r.Body)
// rejects any unknown fields in the json, more strict
jsonDecoder.DisallowUnknownFields()
// decode the request body
if err := json.NewDecoder(r.Body).Decode(&requestData); err != nil {
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
}
// validate that user is provided
if requestData.Email == "" || requestData.Password == "" {
http.Error(w, "Invalid request format", http.StatusBadRequest)
return
}
// make insecure sql command
query := fmt.Sprintf("SELECT id, email, password FROM users WHERE email = '%s' AND password = '%s'", requestData.Email, requestData.Password)
// 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 email string
var hashedPassword 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
}
var password string
// compare the provided password with the stored hashed password
err = bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(requestData.Password))
// execute the query to retrieve the data
err := db.DbPool.QueryRow(context.Background(), query).Scan(&id, &email, &password)
if err != nil {
http.Error(w, "Invalid email or password", http.StatusUnauthorized)
log.Println("Error during query execution:", err)
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{}{
"id": id,
"email": email,
@ -248,17 +217,16 @@ func SecureLoginSql(w http.ResponseWriter, r *http.Request) {
// retrieve the email and password from the database
var id int
var email string
var hashedPassword string
var storedPassword string
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 {
http.Error(w, "Invalid email or password", http.StatusNotFound)
return
}
// compare the provided password and the stored password hashes
err = bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(requestData.Password))
if err != nil {
// compare the provided password with the stored plain-text password
if storedPassword != requestData.Password {
http.Error(w, "Invalid email or password", http.StatusUnauthorized)
return
}