Authentication without database ( PHP ) - php

How to securely authenticate a user without using any type of database.
authenticate.php?username={$_GET['username']}&password={$_GET['password']}
if ($_GET['username'] == "secret_username" && password == "secret_password")
{
$_SESSION['user'] = $username;
header("Location: password_protected_page.php");
exit;
}
This method seems to be an option. Is it secure?

Use a file to hold your data.
have a users.txt below your public html like so:
username:hashedpassword
then you use fopen
<?php
$filename = "/home/users.txt";
$file = fopen( $filename, "r" );
$display = fread( $file, filesize( $filename ) );
fclose($file);
?>
Then explode it by newline and then |, then check if the first is equal to username and the second is equal to md5(password).
Seems like the easiest way to me...

I would at least post for authentication but otherwise it should work fine.

Definitely, you can do that. But, just use POST.
There is nothing wrong with the process. Even when we use database, we actually do the same thing but just using some select command.
You might be thinking about password hash, but they are used so that, even if the 3rd party gets a hold of database dump(somehow), they can never actually decrypt the password, as hash are one way function. Now in you case you are not using database, so that's not a problem.
However the problem lies in scalability. Are you sure that there will always be just one user of the system. If yes, then its okay, else go for DB.

I learned PHP on my own. I never took a course nor had a mentor. I had issues "getting" datasbase calls, as they seemed so convoluted compared to other PHP which seemed natural. I started using this a long time ago.
You can create a text file (username.php) in a directory OFF the web server accesible folders.
(consider permissions!)
So you have /root/users and in that folder you have (by username)
/root/users.Joe.php
/root/users/Juan.php
/root/users/Tim.php
Tim.php contents
<?php
$userpath='/var/www/html/users/Tim';
$password='Timspassword';
?>
Now when Tim logs on wee have code that does this:
<?php
include '/root/users/'.$_POST[username].'.php';
if ($password == $_POST['password'])
{
$_SESSION['loggedin']='yes';
$_SESSION['expire']='<how much time you need?>';
}
?>
This way you can more easily create new users . BTW I use an index.php in each users folder that will do very little if not logged in as that particular user that matches the name of the folder. You should also use https. You could also use password encryption/decryption in these user passwords.
Truth be told, Database injection is a real vulberability. Daily I get hackers looking for databases on my sites. THERE ARE NONE, so they go away.
no databese required.

Related

Can a default user's password be set in SQL using PHP's password_hash?

My old PHP app has a default admin user and md5 encrypted password created by the SQL that creates the database: insert into users values ( 1, 'admin', MD5('changeMe'), 2 );
Is there a simple way to include a default user and encrypted password using PHP's passowrd_hash function on creating the tables? I ask because I understand that password_hash is a native PHP function and I assume it won't be understood in SQL.
The solution to my problem came in three parts. My OP sought a simple way to create a hashed password for the admin user for insertion in the MySQL database on the installation of the application, using the native PHP password_hash() function.
(1) Based on a suggestion by #Nick and #Tadman, I decided to incorporate setting the hash in an installer script that would set not only the hash but other defined site/application variables.
Rather than inserting user values when the database table is created, it was deferred until immediately after, with the admin user entering their credentials in the form that inserts the hash and writes other definitions to a file:
$userpass = $_POST['userpass'];
echo password_hash($userpass, PASSWORD_BCRYPT);
(2) The second part of my problem was replacing all instances of md5()`` withpassword_hash()` and I achieved that by using a neat PHP script I found online to recursively search and replace the occurrences on the server.
Having replaced the md5() occurrences, I needed to change the hash comparison method and again by searching the relevant files I was able to replace instances of:
if ($p != $theUser->pwd ) {
return( false ); }
with:
if(password_verify($p, $theUser->pwd)) {
// Success!
}
else {
// Invalid credentials
echo "Uh oh!";
}
(3) The third step in resolving the problem was discovering that adding $1$ to the opening of the md5 hash could make it readable by password_hash(); so I just needed to make a couple of adjustments in the installed database to the admin user's old password.
Thanks to those who helped shine the light so I could find my way. I'm off now to invent the wheel and sliced bread.
you can do something like this in php:
$hash = password_hash('changeMe');
//echo $hash;
then use this hash in the Database.

PHP Login System without MySQL

So, I'm trying to set up a login script without the usage of MySQL because I don't have any experience with it at all I need to wait one year until I can sign up for a course at our school.
My thoughts of approaching this:
The user needs to login with a username and a invitation key. I'd like to have a .txt (I know that's insecure as hell but whatever) where both the username and invitation key of an accepted person are stored. The PHP scripts compares the sent credentials with the ones stored in the .txt. If it matches, you're logged in, if not, then it gets aborted.
So, how can I read data from a .txt and how could I format the .txt so my script can differ between username and invitation key?
Here's what I've got so far:
if(isset($_POST['auth']) && $_SERVER['REQUEST_METHOD'] == 'POST'){
session_start();
$usr=$_POST['user'];
$invkey=$_POST['key'];
function authenticate($usr, $invkey){
}
}
Thanks in advance!
PS: I know this would be very insecure, so if you're bored you could give me tips how I could secure it. :)
You can keep usernames and keys in one string, one user per line in a txt file.
user1|user1_inv_key
user2|user2_inv_key
...
So you can use fgets() and explode()
Your code should look like this :
if(isset($_POST['auth']) && $_SERVER['REQUEST_METHOD'] == 'POST'){
session_start();
$usr=$_POST['user'];
$invkey=$_POST['key'];
function authenticate($usr, $invkey){
$fh = fopen('auth.txt', 'r');
if ($handle) {
while (($line = fgets($handle)) !== false) {
// Exploding the line, using | as separator.
$info = explode($line, '|');
$username = $info[0];
$key = $info[1];
if($usr == $username && $key == $invkey) return true;
}
} else {
// error opening the file.
}
// Return false because something went wrong or data wasn't correct.
return false;
}
}
You could use a normal csv file like
user1,key1
user2,key2
and then use the str_getcsv function to parse it.
See http://php.net/manual/de/function.str-getcsv.php for more documentation.
You would have to do something like
$txt_file = file_get_contents('path/to/file.txt');
Then you could explode $txt_file based on a delimiter for each user, or a new line or something. Then, you could add a new user to your file with something like
file_put_contents("path/to/file.txt", $user_string, FILE_APPEND);
To secure it, you could save the password for the user as the product of a one way hash, like md5.
$salt = 'whatever you want';
$securish_pw = md5($password.$salt);
Then store that. Then, someone logs in, you find their line in the txt file, put their compared password through the same md5 function and if they are the same, then you log them in. This way, you don't store a plain text password.
All said, you should just learn a bit about how to use a database. It's pretty simple if you use PHP's PDO library and there's a million and one tutorials out there explaining how to do exactly what you're trying to accomplish.

How to make a zipped download with files that exist in a database?

I want to make some kind of user panel for my users - after they will update the info on the panel it will make a new row for them in the database with an original source code which i build but with the edited fields they made.
Example:
UserName: [_______]
PageID: [_______]
They fill it in and the when they press update it will automatically insert the data to a pre-made code to a new field in the table.
<?php
$username = ? (whats the best way to insert UserName textarea value in here?)
$pageid = ? (whats the best way to insert UserName textarea value in here?)
?>
Now that was the first question: whats the best way to insert UserName textarea value in here?
The Second question is how to Auto Encrypt this on insert (I don't care about the way it will be encrypted, even if it will not be IonCube encrypted it will be fine)
And the last and the most important question is how to make an automatic function that when they will press "Update" will automatically make files from the SQL field and prompt them to download the zipped files with their files (I don't want to store any of those files on my server because they may interrupt one with the other cause there may be 100 users doing this action at the same time)
Guys trust me i has been looking for this answers all over the net and didn't found a thing.. (I found EVERYTHING i need except this stuff).
Thanks for future assistance guys!
Best Regards, Rico S.
1) The best way to do it is by using some sort of formatting like
Put you template like this
$template = "whats the best way to insert %%UserName%% %%textarea%% value in here.";
And then create an array with like
$trans = array ("%%UserName%%" => $username, "%%textarea%% => $textarea);
Then use php's strtr function to convert it
$data_to_store = strtr($template, $trans);
2) You can find a lot of encryption and decryption algorithms and php classes for doing that check out PHP Classes.
3) You could try this. But i am not 100% sure if its works properly.
Use PHP's ZipArchive Directory
And then load the content's into a string
then
<?php
header('Content-Disposition: attachment; filename="downloaded.pdf"');
$zip = new ZipArchive;
$res = $zip->open('php://stdout', ZipArchive::CREATE);
if ($res === TRUE) {
$zip->addFromString('file.txt', $content_populated_from_db);
$zip->close();
echo 'ok';
} else {
echo 'failed';
}
exit;
?>
I hope this works, If it didn't try changing the flags of ZipArchive::open. And if it didn't work then also. In that case let me know, with you code and i might be able to help you. As of this point, i havn't tried it.

How to 'encrypt' information passed along in URL when redirecting in PHP?

Sorry if the title's unclear, couldn't think of anything better since I'm still new to this area. :)
Anyway, my question is this: I want to send some information from one page (let's call it 1.php) to another page (let's call it 2.php) using this (don't know the formal name, sorry):
http://localhost/X/2.php?user_id=5&user_type=2&ssn=1234567890&first_name=John&last_name=Doe
As you can see, the information is in plain text, which I dislike. Is there an easy way to encrypt the string after the question mark above in 1.php, and then let the 2.php (that gets the passed-along info) decrypt it? I'd like for it to be something along:
http://localhost/X/2.php?user_id=rj3i15k&user_type=8109fk1JIf&ssn=6893kfj399JFk...
Sorry if this is a stupid question. Many thanks in advance!
If you don't want information to be modified, use a hash string to verify them.
For instance :
$hash = sha1($user_id."haha".$user_type.$ssn.$first_name.$last_name);
The "haha" here, is a salt. Use a random string, it will be use so someone can't reuse your algorithm to inject fake data.
Then put this hash at the end of your url, eg
http://localhost/X/2.php?user_id=5&user_type=2&ssn=1234567890&first_name=John&last_name=Doe&hash=$hash`
When you'll get this information, make the hash again, and compare it to the hash sent : If the information was modified, the hash won't match.
Maybe you're going about it the wrong way.
Thought about storing the data in a serverside session variable?
Or even in a database (if you're passing to another machine), then you just need to send the unique identifier of the database entry.
page2 will then read the session variable, or retrieve it out of the database again.
Basically, keep the data serverside and then you wont need to encrypt/decrypt.
Session Example:
page1
<?
session_start();
$_SESSION['pagedata'] = array(
'user_id'=>5,
'user_type'=>2,
'ssn'=>1234567890,
'first_name'=>'John',
'last_name'=>'Doe'
);
header('Location: page2.php');
?>
page2
<?
session_start();
$user_id = $_SESSION['pagedata']['user_id'];
$user_type = $_SESSION['pagedata']['user_type'];
$user_ssn = $_SESSION['pagedata']['user_ssn'];
$user_first_name = $_SESSION['pagedata']['first_name'];
$user_last_name = $_SESSION['pagedata']['last_name'];
// use variables to do stuff
?>
Its called GET, never relate 100% on 2 Way Decryption but this may help you Best way to use PHP to encrypt and decrypt passwords?
you could use base64_encode on the one side and bas64_decode on the other - just as one possibility - but note that this is only for "better looking" url als you want it (for me, this is ugly). this isn't encrypting your data for being more safe or something like that - to achive this, use https and don't confuse your users by doing such crazy stuff.
You should use $_SESSION.

Examples of vulnerable PHP code? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
Ok so me and a friend are doing a mini presentation on PHP security (I'm not really into PHP though) and he asked me to find some examples of vulnerable PHP code (one that is prone to SQL injections and all other types of attacks). I was wondering are there any websites with both good and bad pieces of code showing how you should and shouldn't code?
Basically I will put them into our website and he will try to hack it, then we will show the "proper" website and he will try to hack it again.
SQL injection is easy:
$var = $_POST['var'];
mysql_query("SELECT * FROM sometable WHERE id = $var");
This is easily solved by:
$var = mysql_real_escape_string($_POST['var']);
The other common one is XSS (cross site scripting):
$var = $_POST['var'];
echo "<div>$var</div>\n";
allows you to inject Javascript that is run from your site. There are several ways of dealing with this, for example:
$var = strip_tags($_POST['var']);
and
$var = filter_var($_POST['var'], FILTER_SANITIZE_STRING);
A really common beginner's mistake is forget to terminate script execution after a redirect.
<?php
if ($_SESSION['user_logged_in'] !== true) {
header('Location: /login.php');
}
omg_important_private_functionality_here();
The solution:
if ($_SESSION['user_logged_in'] !== true) {
header('Location: /login.php');
exit();
}
This can be missed when testing in a normal browser, because browsers usually follow the Location header without rendering any of the output of the script.
Oh boy, you won't be short of examples. Just Google PHP tutorial and every single one of them has enough holes to fill the Albert Hall.
Result 1, w3schools. What's their first example to include user input?
Welcome <?php echo $_POST["fname"]; ?>!<br />
Bzzt. HTML injection, repeated throughout every piece of example code. What's their first database query?
$sql="INSERT INTO Persons (FirstName, LastName, Age) VALUES ('$_POST[firstname]','$_POST[lastname]','$_POST[age]')";
Bzzt. SQL injection, you lose. Next.
Result 2, official PHP tutorial. What's the first example of outputting a variable?
echo $_SERVER['HTTP_USER_AGENT'];
Bzzt. HTML injection. Not an easily-exploitable one, but still, bad practice of the sort that is repeated throughout php.net's learning materials.
Result 3, tizag.com. What's the first example of echoing user input?
echo "You ordered ". $quantity . " " . $item . ".<br />";
Bzzt.
Result 4, freewebmasterhelp.com. Too basic to include much, but still manages:
print "Hello $name"; // Welcome to the user
Bzzt.
Result 5, learnphp-tutorial.com.
<title><?= $greeting ?> World!</title>
Bz...
I could go on.
Is it any wonder the general quality of PHP code in the wild is so disastrous, when this woeful rubbish is what coders are learning?
Bobby Tables
Bobby Tables is a page devoted to detailing the ways that a script can be vulnerable via SQL injection. This is not unique to PHP, however, SQL injection is the cause of many web page vulnerabilities.
It might be someting you want to include in your presentation.
I've seen code like this written in the past:
foreach ($_REQUEST as $var => $val) {
$$var = $val;
}
It's a way to simulate the maligned register_globals option. It means you can access your variables like this:
$myPostedVar
rather than the terribly more complicated:
$_POST['myPostedVar']
The security risk pops up in situations like this:
$hasAdminAccess = get_user_access();
foreach ($_REQUEST as $var => $val) {
$$var = $val;
}
if ($hasAdminAccess) { ... }
Since all you'd have to do is add ?hasAdminAccess=1 to the url, and you're in.
Another example of a sql-injection-vulnerable login script. This is unfortunately very common among new programmers.
$username = $_POST["username"];
$password = $_POST["password"];
$query = "SELECT username, password
FROM users
WHERE (username = '{$username}')
AND (password = '{$password}')";
Today's DailyWTF:
if(strstr($username, '**')) {
$admin = 1;
$username = str_replace('**', '', $username);
$_SESSION['admin'] = 1;
} else {
$admin = 0;
}
CSRF for the win.
<?php
$newEmail = filter_input(INPUT_POST, 'email', FILTER_SANITIZE_EMAIL);
$pdoStatement = $pdoDb->prepare('UPDATE user SET email=:email WHERE ID=:id');
$pdoStatement->execute(array(':email'=>$newEmail, ':id'=>$_SESSION['userId']));
You feel safe with this kind of code. All is good your users can change their emails without injecting SQL because of your code.
But, imagine you have this on your site http://siteA/, one of your users is connected.
With the same browser, he goes on http://siteB/ where some AJAX does the equivalent of this code :
<form method="post" action="http://site/updateMyAccount.php">
<p>
<input name="email" value="badguy#siteB"/>
<input type="submit"/>
</p>
</form>
Your user just got his email changed without him knowing it. If you don't think this kind of attack is dangerous, ask google about it
To help against this kind of attacks, you can either :
Check your user REFERER (far from perfect)
Implement some tokens you had to your forms and check their presence when getting your data back.
Another one is session hijacking. One of the methods to do it is piggybacking.
If your server accepts non cookie sessions, you can have URLs like http://siteA/?PHPSESSID=blabla which means your session ID is blabla.
An attacker can start a session and note his session ID, then give the link http://siteA/?PHPSESSID=attackerSessionId to other users of your website. When these users follow this link, they share the same session as your attacker : a not logged session. So they login.
If the website does not do anything, your attacker and your user are still sharing the same session with the same rights. Bad thing if the user is an admin.
To mitigate this, you have to use session_regenerate_id when your users credentials change (log in and out, goes in administration section etc.).
HTTP Response Splitting attack
If web application is storing the input from an HTTP request in cookie let's say
<?php setcookie("author",$_GET["authorName"]); ?>
It is very prone to HTTP response splitting attack if input is not validated properly for "\r\n" characters.
If an attacker submits a malicious string,such as "AuthorName\r\nHTTP/1.1 200 OK\r\n..",then the HTTP response would be split into two responses of the following form:
HTTP/1.1 200 OK
...
Set-cookie: author=AuthorName
HTTP/1.1 200 OK
...
Clearly,the second response is completely controlled by the attacker and can be constructed with any header and body content instead
Check out the Open Web Application Security Project. They have explanations and examples of lots of different kinds of attacks.
http://www.owasp.org/index.php/Category:Attack
Email header injection attacks are a much bigger pain in the neck then you might suspect (unless you've had to deal with them).
This is very bad:
$to = 'contact#domain.com';
$subject = $_POST["subject"];
$message = $_POST["message"];
$headers = "From: ".$_POST["from"];
mail($to,$subject,$message,$headers);
(code copied from the second reference above.)
The WRONG way to do templates.
<?php
include("header.php");
include($_GET["source"]); //http://www.mysite.com/page.php?source=index.php
include("footer.php");
?>
XSS vulnerabilities are easy to show. Just create a page that puts the value of the GET variable "q" somewhere on the page and then hit the following URL:
http://mysite.com/vulnerable_page.php?q%3D%3Cscript%20type%3D%22javascript%22%3Ealert(document.cookie)%3B%3C%2Fscript%3E
This will cause the user's cookies to be displayed in an alert box.
Allowing upload and not checking extension. Observe:
Site A allows image uploading and displays them.
Cracker guy uploads a file and tricks you to believe its an image file (via HTTP mimetypes). This file has PHP extension and contains malicious code. Then he tries to see his image file and because every PHP extesioned file is executed by PHP, the code is run. He can do anything that apache user can do.
Basic (often security sensitive) operations not working as expected, instead requiring the programmer to use a second "real" version to get non-broken functionality.
The most serious one of these would be where an actual operator is affected: The "==" operator does not work as one would expect, instead the "===" operator is needed to get true equality comparison.
One of the big 3 PHP forum packages was affected by a vulnerability in it's "stay logged in" code. The cookie would contain the user's ID and their password hash. The PHP script would read and cleanse the ID, use it to query the user's correct hash in the database, and then compare it with the one in the cookie to see if they should be automatically logged in.
However the comparison was with ==, so by modifying the cookie, an attacker use a hash "value" of boolean:true, making the hash comparison statement useless. The attacker could thus substitute any user ID to log in without a password.
Allowing people to upload files, whether that API is supposed to be used by users or not. For example, if a program uploads some files to a server, and that program will never upload a bad file, that's fine.
But a hacker could trace what is being sent, and where to. He could find out that it is allowing files to be uploaded.
From there, he could easily upload a php file. Once that's done, it's game over. He now has access to all your data and can destroy or change anything he wants.
Another common mistake is allowing flooding. You should put some sane limits on your data. Don't allow users to input nonsensical data. Why is a user's name 2MB in length? Things like that make it so easy for someone flood your database or filesystem and crash the system due to out of space errors.

Categories