Hi all! This question somewhat ties in with PHP, but I still will need to know what I can do in the C# side of things. If anyone could provide suggestions as to what I can implement to increase the security of my program (or at least, the login / register side of it), that would be really kind of you! Thank you, all!
I help build a program. This program requires a user to register and be approved by an administrator to be able to use it.
The program shows a screen where a user has to enter a username and password. This is the Login / Register screen, as a user can either login or register from here.
This is where my problem stems.
When the "Submit" button is clicked, the username and password, as well as the user's computer name and HWID are sent to a PHP file, then it would return a string saying whether the user was approved or not. If the string said "APPROVED" the program would allow the user in. Otherwise, anything else would result in an error and would either prompt the user to try logging in again (incorrect password) or close the program (network errors, etc).
Before, this was highly insecure because the PHP file I was using was designed to receive a GET request.
Someone sniffed the packets being sent, and was able to see that the the URL was simply:
Someone then created a program to spam new users into my database, using generic values.
Image here, column names from left to right are: uid, username, password, computername, HWID, isAllowed.
Obviously, I have revamped the security so it is not as easily compromised.
My new system uses POST requests instead of GET (which makes it unable to send a request using a url and the ?value= appended), as well as a few other improvements:
Once a user fills out a field and clicks Submit, a NameValueCollection is created and keys and values are assigned. The keys are named in a way so that it is not easy to identify what they represent (example: instead of having a key for the username being "u", it is "gun" which stands for "given user name"). The values assigned are all encrypted using Rijndael each with a different key and IV every time (which are also sent with the request, encoded in Base 64, so that the PHP file can decrypt all the other values).
Besides the encrypted username, password, HWID, computer name, IV and key being sent, it sends another value in the request: the encrypted SHA512 hash of the current date and hour (formatted with symbols like { } and ||; example: { 2 | 25 | 15 } || { 12 }) of my server's timezone. The PHP file will generate this string and hash it as well, and check it against the sent value (when it has been decrypted). If the PHP file finds that they are not the same, it will immediately echo an error stating something along the lines of "INVALID REQUEST RECEIVED" and exit, ceasing any further execution of the script.
If the date and time hashes match, the PHP file will decrypt the four values (username, password, computer name, and HWID) using the key and IV sent along with it, and do some basic login / register checks:
I think this is sufficient protection, but do you guys think I am missing anything or I should implement something else?
Thank you all for reading! I appreciate it! c:
I help build a program. This program requires a user to register and be approved by an administrator to be able to use it.
The program shows a screen where a user has to enter a username and password. This is the Login / Register screen, as a user can either login or register from here.
This is where my problem stems.
When the "Submit" button is clicked, the username and password, as well as the user's computer name and HWID are sent to a PHP file, then it would return a string saying whether the user was approved or not. If the string said "APPROVED" the program would allow the user in. Otherwise, anything else would result in an error and would either prompt the user to try logging in again (incorrect password) or close the program (network errors, etc).
Before, this was highly insecure because the PHP file I was using was designed to receive a GET request.
Someone sniffed the packets being sent, and was able to see that the the URL was simply:
Code
http://mydomain.com/login.php?u=username&p=MD5(password)&h=hwid&c=computernameImage here, column names from left to right are: uid, username, password, computername, HWID, isAllowed.
Obviously, I have revamped the security so it is not as easily compromised.
My new system uses POST requests instead of GET (which makes it unable to send a request using a url and the ?value= appended), as well as a few other improvements:
Once a user fills out a field and clicks Submit, a NameValueCollection is created and keys and values are assigned. The keys are named in a way so that it is not easy to identify what they represent (example: instead of having a key for the username being "u", it is "gun" which stands for "given user name"). The values assigned are all encrypted using Rijndael each with a different key and IV every time (which are also sent with the request, encoded in Base 64, so that the PHP file can decrypt all the other values).
Besides the encrypted username, password, HWID, computer name, IV and key being sent, it sends another value in the request: the encrypted SHA512 hash of the current date and hour (formatted with symbols like { } and ||; example: { 2 | 25 | 15 } || { 12 }) of my server's timezone. The PHP file will generate this string and hash it as well, and check it against the sent value (when it has been decrypted). If the PHP file finds that they are not the same, it will immediately echo an error stating something along the lines of "INVALID REQUEST RECEIVED" and exit, ceasing any further execution of the script.
If the date and time hashes match, the PHP file will decrypt the four values (username, password, computer name, and HWID) using the key and IV sent along with it, and do some basic login / register checks:
PHP Code
<?php
// This is really bad psuedocode
// Retrieve all of the values via $_POST["key"];
$gun = $_POST["gun"]; // given username
$gup = $_POST["gup"]; // given password
$gnc = $_POST["gnc"]; // given name of computer
$shu = $_POST["shu"]; // secret HWID of user
$hdt = $_POST["hdt"]; // hash of server date and time
$eky = $_POST["eky"]; // encrypted key
$eiv = $_POST["eiv"]; // encrypted IV
// Decrypt and escape all values after decrypting key and IV
$key = base64_decode($eky);
$iv = base64_decode($eiv);
// Check to see if date / time sent is correct
$inputHash = mysqli_real_escape_string($link, decrypt($hdt, $key, $iv));
$hashDateTime = getHashOfDateTime();
if ($inputHash != $hashDateTime) {
echo "NOT ALLOWED: CONNECTION REJECTED";
exit();
}
$inputUser = mysqli_real_escape_string($link, decrypt($gun, $key, $iv));
// This password, after decrypting and escaping, is the plaintext.
$inputPass = mysqli_real_escape_string($link, decrypt($gup, $key, $iv));
$inputComp = mysqli_real_escape_string($link, decrypt($gnc, $key, $iv));
$inputHWID = mysqli_real_escape_string($link, decrypt($shu, $key, $iv));
if (!userExistsInDB($inputUser)) {
// User does not exist in database, check to see if HWID exists
if (HWIDExistsInDB($inputHWID)) {
// HWID exists in database
echo "NOT ALLOWED: HWID DUPLICATE";
exit();
}
else {
// HWID does not exist in database
// We can create the user and insert into database
$salt = generateSalt();
$passEntry = hash("sha512", combineSaltPassword($salt, $inputPass));
$result = mysqli_query($link, "INSERT INTO `db`(`username`, `password`, `salt`, `cName`, `HWID`, `allowed`) VALUES ('$inputUser', '$passEntry', '$salt', '$inputComp', '$inputHWID', 0)");
if ($result) {
// User inserted successfully
echo "NOT ALLOWED: NEW USER";
exit();
}
else {
// User not inserted
echo "NOT ALLOWED: INSERTION ERROR";
exit();
}
}
}
else {
// Username sent in exists; check the credentials
$credCheck = mysqli_fetch_array(mysqli_query($link, "SELECT * FROM `db` WHERE `username`='$inputUser'"), MYSQLI_ASSOC);
$salt = $credCheck['salt'];
// Check if password is correct
if (hash("sha512", combineSaltPassword($salt, $inputPass)) != $credCheck['password']) {
// Password is not correct
echo "NOT ALLOWED: PASSWORD MISMATCH";
exit();
}
// Check if HWID matches one HWID sent in
if ($inputHWID != $credCheck['HWID']) {
// HWID is not the same
echo "NOT ALLOWED: HWID MISMATCH";
exit();
}
// Check if user is allowed
if ($credCheck['allowed'] != 1) {
// User is not allowed, value is 0
echo "NOT ALLWED: NOT APPROVED";
exit();
}
// User is allowed
echo "ALLOWED: WELCOME";
exit();
}
I think this is sufficient protection, but do you guys think I am missing anything or I should implement something else?
Thank you all for reading! I appreciate it! c:
![[Image: khyz4yZ.png]](https://i.imgur.com/khyz4yZ.png)



