Are there any vulnerabillities here? (PHP) - php

So, my script allows people to write content into a .txt file and save it on the server. They can currently write anything they want to. This is the method I'm using to save the file.
<?php
$victim = $_POST['victim'];
$user = $_POST['user'];
$comment = $_POST['comment'];
$IP = $_POST['IP'];
$data = "$victim | $user | $comment | $IP\n";
//open the file and choose the mode
$fh = fopen($victim.".txt", "a");
fwrite($fh, $data); //close the file fclose($fh);
print "User Submitted";
echo "URL is mysite.com/".$victim.".txt"
?>
My question is - is there anything they could write that would damage the way my server works?

Sure. I can send this string as your victim POST argument:
/var/www/your_website/index.php\0
And you'll modify index.php. The \0 makes PHP ignore the .txt extension. In user, I could send some PHP code and append it into your index page, which is pretty bad.

This is an impossible question to answer because there are so many possibilities. One thing that I see is that someone could upload executable code or script. If the attacker can then cause the server to process the script in some way it could lead to compromise of the server. If the text file is ever served out to another user, you have a XSS vulnerability.

Yes. Depending on your server configuration, for example people could provide an URL (for example http://someotherpage/somepage?) as the victim argument and thereby make PHP open a HTTP (or some other kind of possibly malicious) connection. You propably don't want this to happen.

Related

Sending data from PHP

I need to 'export' certain information with PHP. However, sending an email won't solve my issue. I also don't want to use PECL functions since the package is not installed by default and I can't know whether it is on the server I'll need to send the information from.
Considering I'm dragging the information from a certain file with a regular expression or whatever and sending it out to an external source. The best scenario would be to write the information to a remote file so that it is publicly easily accessible. I thought of forging a raw socket and appending the data to an additional header but I don't know how that could work. Again, as I said, mail() isn't an alternative in this case.
Any ideas are highly appreciated.
If you only have little data, you could use file_get_contents() method and append your data URL encoded as parameter to a web resource. The receiver could be a simple PHP script as well.
sender.php
$data_plain = "to be sent";
$data_enc = urlencode($data);
file_get_contents("https://www.your-receiver.com/receiver.php?data=" . $data_enc);
receiver.php
$data_enc = $_GET["data"];
$data_plain = urldecode($data_enc);
If you want to store it in a variable (and have server side processing done at the same time)
$file = 'some_file.php';
ob_start();
include_once($file);
$contents = ob_get_contents();
ob_end_clean();
echo $contents;

Am I vulnerable to sql injection and cross site scripting (and others...)? What to do?

To start, please pardon my ignorance, I'm not a programmer but rather a student research assistant who happens to need to write some programs.
Right now I'm working on a page that will take user input (eventually will be guesses in a guessing game) and store it in a csv file. The tech guy here warned me about the danger of sql injection and cross site scripting, so I googled them as well as strategies for protection. But it looks like there are MANY strategies, and I'm having a hard time understanding which ones I need to use. For instance, do I even need to be worried about sql injection if I'm not using sql? Am I using sql and I just don't know it? Would it be sufficient to strip all non-alphabet characters from the input using javascript (I really don't need them)?
Can someone please tell me: Which protection strategies do I need to use, given what I'm trying to do?
If it helps, here is my code so far. I'm trying to use Ajax, so I have the following components:
A. HTML: presents text box and buttons to write the input into the csv file (one to write to the same line, one to write to a new line).
<input id="input" type="text"><br>
<input type="button" onClick="javascript:writeToFile(0, document.getElementById('input').value)" value="write on same line"><br>
<input type="button" onClick="javascript:writeToFile(1,document.getElementById('input').value)" value="write on new line"><br>
B. Javascript: Creates an XMLHttpRequest object, opens it with post and specifies the php script, and sends it along with a the user inputted string (I didn't include a callback function here because I'm not changing the html page in response, but if I need one let me know).
function createRequestObject()
{
var ro;
var browser = navigator.appName;
if(browser == "Microsoft Internet Explorer")
{
ro = new ActiveXObject("Microsoft.XMLHTTP");
}
else
{
ro = new XMLHttpRequest();
}
return ro;
}
function writeToFile(newline, content)
{
var ajaxRO = createRequestObject();
content+=", "
var params="newline=" + newline + "&content=" + content
ajaxRO.open("POST", "writer2.php", true);
ajaxRO.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
ajaxRO.send(params);
}
C. PHP: Retrieves the variables from Post (the first tells it if a new line is needed, the second tells it what to write)
<?php
$myFile = "results.csv";
$fh = fopen($myFile, 'a') or die("can't open file");
$toWrite = $_POST['content'];
$newLine = $_POST['newline'];
if($newLine==1)
{
fwrite($fh, "\n");
fwrite($fh, $toWrite);
fclose($fh);
}
else
{
fwrite($fh, $toWrite);
fclose($fh);
}
?>
Thanks so much for any information you can provide!
I'm not sure why you posted HTML/JavaScript thats not really where the problems are. XSS and SQL Injection are a server side problem and you should post PHP code if you need help.(Putting DOM Based XSS aside because its so uncommon).
For SQL Injection you should always use parametrized quires. PDO and ADOB are both good libraries for this.
Cross-Site Scripting defense is a lot more complex. You can't just throw htmlspeicalchars($var,ENT_QUOTES) at every variable you print out and expect to be safe. This is a good practice but should also make sure to TEST EVERYTHING. I suggest using a free service like Sitewatch which will test for xss, sql injection and a lot more. Or you could use Acunetix's free xss scanner.
In terms of the CSV file, thats just slow and cumbersome. You should be using a database for this. If you need to serve the csv file you can select out what you need and print it with PHP.
Validating your input in the server is what you should be doing. Since you're writing to a CSV file, your PHP code should look for commas and new-lines and maybe replace them with spaces or issue an error message back to the user. Also, think about the maximum length that you can accept as input.
After collecting the input, if you display the collected data as output in a page, you should HTML encode it.
This is just the tip of the iceberg, though. Security is never a solved problem, you're just raising the bar for potential attackers.
Your code isn't vulnerable to Cross Site Scripting, and you aren't using SQL, only plain text.
But, watch out for another vulnerability called Cross Site Request Forgery. You must add a token value in the form:
$_SESSION['token'] = md5(rand());
if($_SESSION['token'] != $_POST['token']){
echo 'Invalid Request!';
}
else{
//valid request!
}

How do I use php so that when a user presses a specific button, they can write to a specific .txt file?

Basically, as in other questions I've asked related to my php chat application, I am trying to get it so that there is a text field where $msg is displayed via msg.txt. Two users can communicate to another in this way. This would be easy if I wanted to use a simple include function. But I don't want to take all the trouble to make and upload all those pages to my server. So how can I have it where when the user, say named Aaron, clicks on a button titled Benjamin, and types to a file called aaronbenjamin.txt, and if Aaron wants to talk to another user, he can press on a button titled Chris, and type to a file called aaronchris.txt? And all from the same box and text field? Thanks, I appreciate it.
EDIT: This is my code-
http://key-mail.zxq.net/msg.txt
Well, you should learn about using forms with PHP, with regards to your comment. If you read that tutorial fully, it should answer all of your questions about forms and php.
As far as getting it to write to a different text file, since you seem worried about "uploading all those pages", you'll be happy to know there's an easy solution!
There's a function called file_put_contents, which will create or write into a file.
Since you're new(ish) to PHP, here's an example:
<?php
$file = 'hello.txt';
$text = 'Hello World!';
file_put_contents($file, $text);
?>
This puts the contents of the $text variable into the file with the name stored in $file.
Reading from a file is similarly easy, with file_get_contents.
Assuming the file hello.txt exists from before and has the same contents, you can use the following code to read from the file and output its contents:
<?php
$file = 'hello.txt';
echo(file_get_contents($file));
?>
That will show the contents of $file.
Now, moving into the specifics of your question, if your form sets a "to" and a "from" GET variable where "to" is your username already, then the following code would write the value in a "message" GET variable into the file based on the pattern you gave:
<?php
$to = addslashes($_GET['to']);
$from = addslashes($_GET['from']);
$msg = addslashes($_GET['message']);
//addslashes is used as a small security measure
$file = $to . $from . '.txt';
file_put_contents($file, $msg);
?>
This fetches our variables from the GET array, sanitizes them to some extent, sets the file name, and writes the message to the file.
If you have any questions about specific parts of this or you'd like me to go into more detail, please feel free to ask!
This is how to write to a file:
http://php.net/manual/en/function.fopen.php
You're better off to use a database tho for sure.
To make different links do different things, you can use AJAX as you suggested or you can use GET variables to route functions on the PHP side. The latter is easier but means you will need to reload the page after the user presses the button.
here's a little demo:
click here
then at the top of the page in php:
if($_GET['clicked']==1){--write to file1---}
else if($_GET['clicked']==2){--write to file2---}
Hope it helps

save php variables permanently without database

In the admin area of my site there is a form which is for the hostname, username and password for the mysql database that the site uses. Currently these values are hardcoded into a php class. But who can I link it so the form can edit the variables in the php class (and keep the results on the server, in other words the variables are hardcoded). I'd normally keep things like this in a database but obviously this can't be done.
Create a configuration file, and grant your web server write access to it. Then it's just a simple matter of writing a script which saves the DB config to this file. E.g.
$fh = fopen('config.php', 'w');
fwrite($fh, chr(60) . "?php\n");
fwrite($fh, sprintf("define('DB_HOST', '%s');\n", addslashes($_POST['DB_HOST'])));
fwrite($fh, sprintf("define('DB_USER', '%s');\n", addslashes($_POST['DB_USER'])));
fwrite($fh, sprintf("define('DB_PASS', '%s');\n", addslashes($_POST['DB_PASS'])));
fclose($fh);
Keep the values in a config file. And make sure it is not accessible from the web.
The easiest solution is to keep the values in a configuration array - the user enters the values, you generate an array from it, then file_put_contents("config.php", "<?php $config = " . var_export($config)). With this method whenever you need the config array, all you need to do is include config.php and it's there.
This is untested code, for example purposes only. Depending on your situation, you may need to solve race conditions, file_put_contents is not enought for that. The main point of the above code is: var_export returns valid php code, that you can eval (if you're evil enough) or echo to a file and include that later.

PHP Username Password Solution

I am working on my first PHP based website, and I was wondering what solutions were out there for a username/password system? I have tried using a .htaccess file for basic security, and while it works, I want something a little easier for a layman to administer. Are there any other solutions out there that I could try? I don't have a database server available, so it would have to support flat file databases...thanks!
Edit I have determined that I do have SQLite support, so I do have a database option available. Also, I feel I should mention a little further some requirements that I have. I originally looked to using .htaccess to protect my website, since I need security over the entire directory. Most of the files I am trying to protect are .pdf and .doc...any solution would have to allow me to secure those files as well as any web pages in the directory.
If I could find a good solution to more or less "skin" the .htaccess method of locking a directory, so that I could do things like have an actual login/register page, etc. then I would just stick to the .htaccess method. I would however like something that is more manageable, I just need the directory security.
I wrote up this code quickly, it is syntacticly correct but I have not tested it.
There are 2 things that I did not do here, first, I did not provide a function to remove a user and second I did not provide a function to change a users password, these you'll have to write yourself.
However this should provide for a good place to start.
These functions will store your usernames/passwords in a file called passwords in the following format
username0:password0
username1:password1
username2:password2
...
.
function authenticate($username, $password)
{
//ALWAYS use a salt to secure the encryption of your passwords, this can be any value of any
//length, the longer and the more characters the better
//I like to use a "perfect password" from Steve Gibbson's https://www.grc.com/passwords.htm
//This must the exactly the same as the salt in theaddUser() function
$salt = 'voDeaFWckErOPPGwiapYBwEoc4O2d1M60m2QsYc7A15PUshrLamoVioG1wUmEgF';
//First we need to get the contents of the file that has the usernames/passwords in it.
//we don't want to use fopen() or we may end up with a locked file error if another access is
//attempted before we've closed it.
//this line will get the contents of the file named passwords and store it in the $fh variable
$fh = file_get_contents('passwords');
//Now lets take the file and split it into an array where each line is a new element in the array.
$fh = split("\n", $fh);
//Now lets loop over the entire array spliting each row into it's username/password pair
foreach($fh as $r)
{
//Every time this loop runs $r will be populated with a new row
//Lets split the line into it's username/password pairs.
$p = split(':', $p);
//Since we don't need all the usernames/password to be in memory lets stop when we find the one we need
if($p[0] == $username && $p[1] == sha1($salt . $password))
{
//We've found the correct use so lets stop looping and return true
return true;
}
}
//If we've reached this point in the code then we did not find the user with the correct password in the 'database'
//so we'll just return false
return false;
}
function addUser($username, $password)
{
//ALWAYS use a salt to secure the encryption of your passwords, this can be any value of any
//length, the longer and the more characters the better
//I like to use a "perfect password" from Steve Gibbson's https://www.grc.com/passwords.htm
//This must the exactly the same as the salt in the authenticate() function
$salt = 'voDeaFWckErOPPGwiapYBwEoc4O2d1M60m2QsYc7A15PUshrLamoVioG1wUmEgF';
//We need to parse out some preticularly bad characters from the user name such as : which is used to seperate the username and password
//and \r and \n which is the new line character which seperates our lines
$username = preg_replace('/\r|\n|\:/', '', $username);
//Now lets encrypt our password with the salt added
$password = sha1($salt . $password);
//Lets build the new line that is going to be added
$line = $username . ':' . $password . "\n";
//Lets open the file in append mode so that the pointer will be placed at the end of the file
$fh = fopen('passwords', 'a');
//Write the new entry to the file
fwrite($fh, $line);
//Close the file
fclose($fh);
//Typicaly one would write a bunch of error handling code on the above statments and if something
//goes wrong then return false but if you make it this far in the code then return true
return true;
}
Have a look at Zend_Auth. It's open source, so you can sniff around to get a feel for how an authentication module should (or could) be implemented. From the doc:
Zend_Auth is concerned only with
authentication and not with
authorization. Authentication is
loosely defined as determining whether
an entity actually is what it purports
to be (i.e., identification), based on
some set of credentials.
Sure, there are plenty of flat file database PHP security systems available. Doing a quick Google search will pull up many results. Here is a tutorial:
http://www.devshed.com/c/a/PHP/Private-Pages-with-PHP-and-Text-Files/
Check if you have support for sqlite, it doesn't require a server so it might work for you.
And don't forget to hash your passwords. ;)
To check create a file (ex. php_info.php) add:
<?php
phpinfo();
Then upload the file to your host, load it in your browser (example.com/php_info.php) and do a search for sqlite.
You should see several references to sqlite in the page that shows if you have support. The line with "SQLite Library" will tell you the version of sqlite you have (if you have it).
Also once you are done you should delete the php_info.php file from your site, since it does give some information on your setup which can be helpful to crackers.
have you seen if you have SQLite available? It is PHP's built in database. If not you could just use read/write to a file hope this helps a bit
According to this page from the Apache website:
In general, you should never use .htaccess files unless you don't have access to the main server configuration file. There is, for example, a prevailing misconception that user authentication should always be done in .htaccess files. This is simply not the case. You can put user authentication configurations in the main server configuration, and this is, in fact, the preferred way to do things.
Its easy to see why this is so, too. Its far preferable to have centralized control, rather than digging through EVERY SINGLE DIRECTORY when debugging a faulty configuration.
I urge you to transfer your .htaccess file config to your main configuration file ASAP, for your own good!

Categories