Home Upgrade Search Memberlist Extras Hacker Tools Award Goals Help Wiki Contact

C# 

How to secure a login request from program?

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:
Code
http://mydomain.com/login.php?u=username&p=MD5(password)&h=hwid&c=computername
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:
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]
this belong to the php section anyway its look k the only thing u should change is using pdo
Nicely written, i will rewrite my authentification system just because of that. Thanks for wasting your time for us.
(Feb 25, 2015 10:27 AM)Only3 Wrote:  this belong to the php section anyway its look k the only thing u should change is using pdo

He's using mysqli which is fine.

PDO is in my opinion easier to understand and use prepared statements with...

Share the generateSalt method I think it's a bad salting we got here.
As for hashing use bcrypt.
The generate salt is just a random 10 chars.

PHP Code

<?php 
function generateSalt()
{
    
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    
$charactersLength = strlen($characters);
    
$randomString = '';
    for (
$i = 0; $i < 10; $i++) {
      
$randomString .= $characters[rand(0, $charactersLength - 1)];
    }
    return 
$randomString;
} 
[Image: khyz4yZ.png]
(Feb 25, 2015 10:20 AM)Natsumi Wrote:  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)
POST requests are just as easily sent as a GET request is easy.
Skype: happy.cbb
0x38E6A0912657E
This is still not secure. One can easily emulate the request and see what is sent and retrieved with a tool like wireshark. And because you've hardcoded that URL string into the program, it would be even easier to modify that with a hex editor. It's not like the expected value for when the user is authenticated is hidden either as you'll have to compare the received value with something defined by the program too lol... So unless you've got strong obfuscation on this, the user would probably even more easily be able to open that up in a .NET decompiler program to see what is going on. For those who know how to use a program like WinDbg, and the SOS extension, this process is even easier.

It's funny what people think is "secure" on this forum lol.
Getting Started: C/C++
[C/C++/.NET/x86 ASM - Automation Programmer]
(Feb 25, 2015 04:33 PM)Natsumi Wrote:  The generate salt is just a random 10 chars.

PHP Code

<?php 
function generateSalt()
{
    
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    
$charactersLength = strlen($characters);
    
$randomString = '';
    for (
$i = 0; $i < 10; $i++) {
      
$randomString .= $characters[rand(0, $charactersLength - 1)];
    }
    return 
$randomString;
} 

try to use this instead for salting:
mcrypt_create_iv() PHP Documentation

Would save you time and you're sure that it's randomized :-)
as for your hashing.
Use bcrypt. would help a lot more then using sha512 :-)

Watch this: Password Storage (and hacking) in PHP [Anthony Ferrara]
- the salting used here is currently changed with /dev/urandom aka mcrypt_urandom

And this: Password Hashing in PHP [Anthony Ferrara]

enjoy the videos
You could always create a session ID type authentication. If the login credentials are correct, hash them in some format and return that value as a session ID. Have your application verify the session ID to make sure that the hash is the same with the values the application provides, and keep doing this in the background every so often.
шкідливе ПО для ентузіастів

Jabber: [email protected]
[email protected]



Possibly Related Threads...
Thread / Author Replies Views Last Post
[.NET] by CacheIsAFagOct 17, 2017 05:15 AM 20 1,193 Oct 17, 2017 05:15 AM
Last Post: CacheIsAFag
[.NET] by MonetizationAug 26, 2013 03:03 AM 16 480 Aug 26, 2013 03:03 AM
Last Post: System[X]
[Python] by ノクス。Feb 12, 2013 01:44 PM 23 690 Feb 12, 2013 01:44 PM
Last Post: PigBacon