Is it safe to pass filename in GET? [closed] - php

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 8 years ago.
Improve this question
I am doing
index.php?letter=1&show=cat.jpg
File I do not include, but use it only as <img src="$_GET['show']">
Is it safe?

Simple code to validate the input.
// Check File Param provided
$filename = (isset($_GET['show']) ? $_GET['show'] : '');
if (strlen($filename) == 0) {
die('File Not Provided');
}
// remove leading '/' or double slashes (will also hack out http:// injections)
$filename = trim($filename);
$filename = str_replace('//', '/', $filename);
while (strlen($filename) > 0 && strcmp(substr($filename,0,1), '/') == 0) {
$filename = substr($filename, 1);
}
// Check filename exists
if (file_exists('./' . $filename)) { // Note the "./", also will to prevent cross site injections; if using a sub-directory, add in here
die ('file does not exist');
}
// Check file actually is an image
if (!#getImageSize('./' . $filename)) {
die ('file is not an image');
}
// Should be safe at this point.
You could also preg_match for a pattern if you know the pattern of filename e.g. always expecting a .png).
You probably also want to handle errors differently, but this should give you an idea.

Yes, Its safe to use. But you want to take care of XSS attacks.
Actually now you are showing the content attached to your parameter show inside your html page. Think a scenario if a user edited the 'cat.jpg' and inserted some script content into it.
See this simple example by Arjun Sreedharan.
XSS attack to your url would be as shown below
index.php?letter=1&show=Path/To/some/other/Image"></img><h1>XSS Attack</h1><div> Showing False data in your website</div><img src="Some/Other/Image.jpg
The Html rendered in your page would be
<img src="Path/To/some/other/Image"></img>
<h1>XSS Attack</h1>
<div> Showing False data in your website</div>
<img src="Some/Other/Image.jpg">
The solution is to encode html. HtmlEntities in PHP.

Yes, it is safe but the mechanism to deliver/show that file should be proper to handle only authorized requests.
If you want then you can do it by POST, but some time its possessive when you refresh the page and browser asking to confirm that previously posted data sends back to server again.
Above are my personal view.

I'd say get something like image_id from URL and then retrieve the relevant data from database and output your own data (e.g. file name) in the markup.
Even if you consider different ways of validating or filtering the users' input, you might still be open to some attacks or maybe bugs. To avoid that, again, I'd recommend to get a key from user and then based on that key output the data. Validating that key is much easier and also you are not gonna to output it again -- you're using that only in the back-end so it won't be a security hole for XSS attacks for example.

<img src="/images/<?php echo basename(preg_replace('/[^a-z0-9\.-]/i','',$_GET['show'])); ?>">
This will this will only return name of a file even if path or url is passed.

Related

Allow unique $_GET request only? Generate, verify, forbid values [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
Hello everyone again here,
I want to create a PHP script for my software which generates and returns the specific code using one $_GET request with a string and using another verificates this code, then forbid running same string.
Something what should work like this:
1st user's software runs "http://example.com/codes.php?create=" and string like "abc".
and script returns code based on "abc", e.g. "4aO45k", "12sdF4" etc.
2nd user's software runs "http://example.com/codes.php?verify=" and this code.
If this code exists, return true and remove it FOREVER, meaning this code will never be generated again. If this code doesn't exist, return false.
If 1st user's software will run "http://example.com/codes.php?create=abc" another code will be generated.
In simple words:
if $_GET is create, then
generate random alphanumeric string, save it and return
if $_GET is verify, then
check if this string exists, if so, then
return true, remove from saved
otherwise
return false
Possible without databases, SQL, mySQL, FireBird...?
How do I make it using .ini files as storage?
Thanks.
It's possible with files. You can do something like the simple solution below:
A couple of notes:
I don't know what you intend by based on exactly, so this just uses the input as a prefix
This stores every code in a file indefinitely; if used a lot this file will grow very large and checking for the existence of codes, and ensuring new codes are unique can grow very slow
The same code can be verified multiple times, but will never be recreated. Marking them as used after verification is of course possible as well
As a general rule don't go creating global functions and shoving everything in one file like this. It's really just proof of concept of what was asked
<?php
$file = fopen('codes', 'a');
if (!empty($_GET['create'])) {
$seed = $_GET['create'];
do {
$code = uniqid($seed);
} while (codeExists($code));
fwrite($file, $code . "\n");
echo $code;
}
else if (!empty($_GET['verify'])) {
echo codeExists($_GET['verify']) ? 'found' : 'not found';
}
function codeExists($verification) {
$file = fopen('codes', 'r');
$found = false;
while ($code = trim(fgets($file))) {
if ($code == $verification) {
$found = true;
break;
}
}
return $found;
}

cannot pass value to PHP file from URL? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I have a problem I use an internal server when I pass a value through the URL and type a valid value showing me a message that he did not scroll see my code:
// pass value from this URL:
http://localhost/test/get.php?name=aa
<?php
// include Marei DB Class
include 'DB.php';
// get content input and create json object to parse it
$data = file_get_contents("php://input");
$obj = json_decode($data);
// create db instance to use marei db queris
$db = DB::getInstance();
// set type of header response to application/json for respone
header('Content-Type: application/json');
if(!empty($_GET["name"])){
print "{\"status\":0,\"message\":\"Username is Non !\"}" ;
}else{
print "{\"status\":0,\"message\":\"Username is Don !\"}" ;
}
?>
// print these lines :
{"status":0,"message":"Username is Non !"}
Change if(!empty($_GET["name"])){
to if(empty($_GET["name"])){
You did the mistake to use ! operator.
PHP is understanding it as a not
And you're asking if the $_GET variable is NOT empty the result is true of course.
Please check http://php.net/manual/en/language.operators.php for more informations.
Could you clarify the method in which a file is being uploaded to your server? Form input?
Assuming that a file is being uploaded...I can see 2 maybe 3 issues, all of which are not mutually exclusive, so it could be be all three issues working together to foil your coding plans...
ONE Use $_FILES , not input
$name = $_FILES['file']['name']; <--- name of the file from its source
$path - $_FILES['file']['tmp_name']; <--- path to the uploaded file
you have to move the uploaded file from your uploads folder... to its new home.
TWO Request method should be POST not GET... Especially the request is created by a form.
THREE - check your php.ini file to make sure file uploads are enabled.
empty is enough. Also you can use
if (!$_GET["name"]) {
print json_encode(['status' => 0, 'message' => 'Username is Non !']);
}

How to protect $_POST and params from hackers [duplicate]

This question already has answers here:
What are the best PHP input sanitizing functions? [duplicate]
(14 answers)
Closed 7 years ago.
I'm using this with html2canvas.js to generate and save images from HTML.
I use url params to make this work - eg: website.com/?price=10&name=xxx
All ok untill here - the script works fine - images are saved in /cart/ dir
<?php
$image = $_POST['image'];
$username = $_POST['username'];
$front_class = $_POST['front_plass'];
$decoded = base64_decode(str_replace('data:image/png;base64,', '', $image));
$date = date('d-M-Y-h-i-a', time());
$curdir = getcwd();
$cartDir = $curdir ."/cart";
$userDir = $cartDir.'/'.$username;
if (!file_exists($userDir)) {
mkdir($cartDir.'/'.$username, 0777);
}
$name = $front_class."-front-".$date.".png";
$full_path = $userDir.'/'.$name;
$name1 = 'cart/'.$username.'/'.$name;
function ImageFillAlpha($image, $color) {
imagefilledrectangle($image, 0, 0, imagesx($image), imagesy($image), $color);
}
function imageCreateCorners($sourceImageFile, $name, $radius) {
...
}
file_put_contents($full_path, $decoded);
imageCreateCorners($full_path, $name, 25);
echo '<img src="'.$name1.'" alt="front" id="front_img" />';
?>
And the js
html2canvas($('#front'), {
"logging": true,
//"proxy":"html2canvasproxy.php",
"onrendered": function(canvas){
var dataURL = canvas.toDataURL("image/png");
$.post('image_front.php',{
image: dataURL,
username: username,
front_class: frontClass
},function(data){
$('.imageHolder_front').html(data);
});
}
});
The problem is that someone hacked me twice yesterday thought this and I need to protect the $_POST or the params can be the problem?
Any help here please? I'm not really good with backend development - more with frontend.
Thanks.
You made a couple of big mistakes.
First, validate your POST data as #JohnConde said, don't use them directly in your code, ever.
Second, don't create directory with 777 permission on your server, since everybody will be able to write into it and hack you that way.
You cannot "protect" parameters. Your server is a box which receives arbitrary HTTP requests and returns HTTP response. Realise this: anybody can send any arbitrary HTTP request to your server at any time containing any data they wish. You do not control what somebody sends you. The only thing you control is what you do with this data. Expect this data to not conform to your expectations. In fact, expect it to be malicious. Validate it instead of assuming it conforms to any particular format. Never blindly use user provided data in something like SQL queries or in constructing file paths without escaping/binding/validating/confirming the data, or you might be building strings you didn't expect to.
This is the one fundamental truth of all programming. You need to write your applications from the ground up with this in mind. There is no easy fix, there's only diligence.
Sanitize your user input. In general: Don't ever ever ever trust user input!
I would recommend the very good writeup from #Charles in the first answer of this question: What are the best PHP input sanitizing functions?
Hackers can hack even if you are not using url parameters.
It has to be done in the backend. Before interacting with database you have check whether the parameters are what you are expecting.
For example you should not allow single quotes in your params, this will actually allow hackers to add some more queries to your query.
Use mysqli prepared statements

using href to two links(php and a webpage) [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
While($enreg=mysql_fetch_array($res))
{
$link_d.="<font color=\"red\">clic here to download</font></td>"
}
i want to use the href so it leads to download link, also to send the id to a php file so i can get how many times the files have been downloaded !
How can we use href to multiple links !
You can't. A link can only point to one resource.
Instead, what you should do is have your PHP script redirect to the file. The link points at your PHP script with the counter, and then set a Location: header (which automatically sets a 302 status code for redirection) with the value being the URL you want to redirect to.
Also, you should really use htmlspecialchars() around any variable data you use in an HTML context, to ensure you are generating valid HTML.
Ideally you would have some checks to see if it's a human downloading (Web crawlers may trigger it - we will put no-follow in the link which will help though). You could also use a database but that gets more complicated. My preferred way would be to use Google Analytics Events. But here is a simple PHP script that might fulfill your needs without the complexity of the other solutions.
First modify your links to have a tracker script and to urlencode
$link_d.= '<a style="color:red" href="tracker.php?url='.urlencode($enreg[link]).'" target="_blank">click here to download</a>';
}
Then create a script that will record downloads (tracker.php)
<?php
// keep stats in a file - you can change the path to have it be below server root
// or just use a secret name - must be writeable by server
$statsfile = 'stats.txt';
// only do something if there is a url
if(isset($_GET['url'])) {
//decode it
$url = urldecode($_GET['url']);
// Do whatever check you want here to see if it's a valud link - you can add a regex for a URL for example
if(strpos($url, 'http') != -1) {
// load current data into an array
$lines = file($statsfile);
// parse array into something useable by php
$stats = array();
foreach($lines as $line) {
$bits = explode('|', $line);
$stats[(string)$bits[0]] = (int)$bits[1];
}
// see if there is an entry already
if(!isset($stats[$url])) {
// no so let's add it with a count of 1
$stats[$url] = 1;
} else {
// yes let's increment
$stats[$url]++;
}
// get a blank string to write to file
$data = null;
// get our array into some human readabke format
foreach($stats as $url => $count) {
$data .= $url.'|'.$count."\n";
}
// and write to file
file_put_contents($statsfile, $data);
}
// now redirect to file
header('Location: ' . $url);
}
You can't.
Anchor are meant to lead to one ressource.
What you want to do is tipically addressed by using an intermediate script that count the hit and redirect to the ressource.
eg.
Click here to download
redirect.php
// Increment for example, a database :
// UPDATE downloads SET hits = (hits + 1) WHERE id=42
// Get the URI
// SELECT uri FROM downloads WHERE id=42
// Redirect to the URI
// (You may also need to set Content-type header for file downloads)
header( "Location: $uri" );
You may optimize this by passing the uri as a second parameter so that you won't need to fetch it at redirect time.
Click here to download
Another way of collecting this kind of statistics is to use some javascript tools provided by your statistics provider, like Google Analytics or Piwik, adding a listener to the click event.
It is less invasive for your base code but won't let you easily reuse collected data in your site (for example if you want to show a "top download" list).
Create a file with download script for example download.php and route all your downloads through it. Update your counter in this page and use appropriate headers for download.
eg:
url may be download.php?id=1&file=yourfile
in download.php
//get id and file
//database operation to update your count
//headers for download

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