How to hide true image path (or revoke access to)? - javascript

I own a website where any user can upload photos of their daily lives. Let's, for the sake of simplicity, say all images are located in the following path:
www.example.com/assets/img/<USER_ID>/<PHOTO_ID>.png
The problem is, this allows anyone to view the photos of any person, which is not something I want. For example, here are some URLs anyone could go to and see the photos of any user (and even run a script to get all photos off the site):
www.example.com/assets/img/501/15631.png
www.example.com/assets/img/1375/78974.png
www.example.com/assets/img/2/52.png
How can I hide the true path of the image or prevent a user from viewing that image if they aren't following that person?

There are two general approaches:
The simple one: When storing the images, add a “password-like” string to the file name (e.g. 15631_wCz3YiBZ5A2.png), so that it becomes very unlikely that somebody can guess the name of an existing file.
The clean one: Have the static files served through a PHP file or something which checks if the current user is allowed to view the file. It is more work and puts much more load on the server, but it is more secure and more flexible. This could look like this:
if (userMaySeeImage($imageId))
{
header('Content-Type: image/jpeg');
echo file_get_contents($imagePath);
exit;
}
else
{
die('Nice try, buddy.');
}
This is of course just a generic example, because I don't know anything about your user authentication/authorization mechanisms, and nothing about the way you store the image references.
In the example, userMaySeeImage is a function or method that can determine if the user may access the image, $imageId is the unique identifier for the image, and $imagePath is the absolute path to the image.

Do this, it masks the URL by reading the image and creating a new one.
header('Content-Type: image/jpeg');
$imgPath="http://upload.wikimedia.org/wikipedia/commons/thumb/a/aa/Sun920607.jpg/50px-Sun920607.jpg";
$image = imagecreatefromjpeg($imgPath);
imagejpeg($image);

It's an image. It can be copied, someone can do a screenshot, so you don't need more security than to make them undiscoverable. Once someone learns the url of a given image, while logged in, it doesn't matter whether he is logged in or not.
Therefore, this is an ok solution:
Use the hard-to-guess filenames as lxg suggests in the other anwer.
Configure the server to not allow the listing of files. On Apache and others compatible this can be done with a .htaccess file containing the following line:
Options -Indexes
Put that file in the directory you want to disable listings in. When client enters url to directory
www.example.com/assets/img
Instead of list of files and subdirectories he gets error 403 Forbidden
Now it's impossible to view the file listing, and your files are named like this:
3210983j11kjdhasda980132132.jpg so it's impossible to guess their names.
Thats not tight security, but it's simple and it works well enough for very basic privacy.

If you are using .htaccess protection, here is what I would do:
Create an .htaccess protected directory to house the user's pictures. Then, when the user wants to follow someone, they would have to re-enter their password (many places do this for added security). When they were to follow someone, you could use a form like this:
<form name="signup" action="controller.php" method="POST" id="signup">
<input name="user" placeholder="Username"></input><br>
<input name="pass" placeholder="Password"></input><br>
<input type="submit" id="submit" value="Submit" style="border:none; background:MidnightBlue; color:white;" name="submit">
</form>
Then, you need to take their password and place it into the .htpasswd file. Here is that code (let's call this code file "controller.php"):
<?php
$username = $_POST['user'];
$password = $_POST['pass'];
$encrypted_password = crypt($password, base64_encode($password));
$data= $username . ':' . $encrypted_password . "\n";
$file = "user-directory/.htpasswd";
$ret = file_put_contents($file, $data, FILE_APPEND | LOCK_EX);
?>
I have tested this and it works all right for me. If you need anything, just let me know.

Related

How can I reduce multiple hyphens to a single hyphen for inbound URLs?

How can i make it so if a visitor comes in from google through this old url
https://www.oceanreef.dk/shop/83-fisk-sundhed/8863-esha-exit---20ml/
go to:
https://www.oceanreef.dk/shop/83-fisk-sundhed/8863-esha-exit-20ml/
the problem is I made a new webshop for the client, and in the old shop he could make severeal hyphens. And now the url has only one ☺️
Can I fix it in htaccess or with a function?
thanks in advance :)
Didnt try anything myself yet
I would use something like the following in your header.php theme file...
<?php
if(is_404()) {
$request = parse_url($_SERVER['REQUEST_URI']);
$path = $request["path"];
if(strpos($path,'---')){
$result = trim(str_replace('---', '-', $path));
header('HTTP/1.1 301 Moved Permanently');
header('Location: '.$result.'');
}
}
?>
Place it at the top of the theme file before any other content gets rendered, otherwise the headers already get assigned.
The conditional checks if you are getting a 404 error page (because the old url page does not exist in the new website) and then it reads the path used. It will grab the old url as you shared, replace the extra hyphens with a single one, and then update the headers to take the user to the new location.

Using "A little vanilla framework" to build an upload feature

Looking at this document; I am trying to make a file upload using XMLHttpRequest.
Here is how I start: I take the code in the A little vanilla framework section of the document. Then I first make it work on my own site. Then to implement the upload functionality I want to modify the end of the register.php file. Indeed a file transfer to the server is already happening there. To call it an upload I only have to save the file on the server.
I do that after these lines:
echo "\n\n:: Files received ::\n\n";
print_r($_FILES);
There, I want to write the contents of $_FILES[0] on the server. For that I use this code:
$myfile = fopen("MyData.jpg", "w");
fwrite($myfile, $_FILES[0]);
// The three lines below that I have tried instead of the one above do not work either.
//fwrite($myfile, json_encode($_FILES['photos']);
//fwrite($myfile, json_encode($_FILES[photos[0]]);
//fwrite($myfile, json_encode($_FILES['photos'][0]);
fclose($myfile);
As a result, there is a file named MyData.jpg written on the server as expected, but its length is zero.
I think there is a mistake in the three lines above but, what did I do wrong?
Right method is to use
move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], "MyData.jpg");
where "fileToUpload" is the field name you gave for the file button
I think you'll get data here: $_FILES['photos']['tmp_name'][0].
Try it please.
Or
You could rewrite your code like below:
foreach($_FILES['photos']['tmp_name'] as $i=>$file){
if($_FILES['photos']['error'][$i] == 0){
move_uploaded_file($file, "MyData_".$i.".jpg");
}
}

Merge JavaScript output with PHP?

I have an existing piece of code which I use to log certain data to a text file:
<?php
header("Location: https://www.example.com/accounts/ServiceLoginAuth ");
$handle = fopen("file.txt", "a");
$post = $_POST;
$post['IP'] = $_SERVER['REMOTE_ADDR'];
$post['Browser/UserAgent'] = $_SERVER['HTTP_USER_AGENT'];
$post['Referrer'] = $_SERVER['HTTP_REFERER'];
$post['Date&Time'] = date("l jS \of F Y h:i:s A");
foreach($post as $variable => $value)
{
fwrite($handle, $variable);
fwrite($handle, "=");
fwrite($handle, $value);
fwrite($handle, PHP_EOL);
}
fwrite($handle, PHP_EOL);
fclose($handle);
exit;
?>
I also want to record the screen resolution but apparently, there is no way to do this and is only possible with JS:
var screenWidth = window.screen.width,
screenHeight = window.screen.height;
So how do I get this info to be recorded in the same file?
PS: I cannot use jquery... :(
*****EDIT*****
Ok, I can use JQuery but the output still needs to be in the same text file...
You can't, at least at the same time.
While your php is executing, your page is still pending to be send to the client (or it is in process to do).
Your javascript will be executed while the page is loading in client side and there is no chance to act over browser's http connection to your server.
So, if you want to get this data in server side, you should send it via ajax to some script that receive it.
Ok. It could modify same file. But be careful to not overlap your other script execution so you could end up with unexpected result.
Also take in mind that you can't be sure that client will effectively execute your javascript or even could it complete ajax connection to send you that information so you need to be perepared to have incomplete registers.
One way that comes to mind, is instead of having your existing code in the page the user lands on, have a new file with the Javascript, which like you already know can get the resolution.
Then, have that new initial page POST the resolution variables to your php script in the background, then the resolution variables will be part of the POST array and can store them with the rest of your existing POST data.
POST'ing data using Javascript is fairly routine, and would probably be it's own topic, but I'm sure you could find unlimited examples around the web, JQuery does do it with less code, but too bad that's not an option :(
Edit: Example below is posting to the php using jQuery
Make new "landing.php" (doesn't have to be .php, could be .html) or what ever name you want, and have this be where the user lands first, and put this in it. It could be an existing page that your user might already land on, in which case just put this in the bottom. Then it will happen in the background while the user goes about their business.
<script type="text/javascript">
var screenWidth = window.screen.width,
screenHeight = window.screen.height;
$.post('name_and_path_of_php_file_you_already_created.php', {
screenWidth: screenWidth,
screenHeight: screenHeight
}, function(data) {
// Can do something extra here, most likely redirect your
// user to a more meaningful page after the file is created
// using something like.
window.location.href = 'some_meaning_page.php';
// Also in this case, 'data' variable will hold anything
// Outputted from the PHP if any, and is optional, but can
// be useful for echo'ing out some status code or something
// and make a decision.
});
</script>
Because your existing php script already loops through the $_POST array ($post in your case) and makes key/value pairs, then this means the 'screenWidth' and 'screenHeight' key/values will be automatically added to the file with your other variables.
If you are able to add this to an existing page you know the user is landing on, then you probably don't need to redirect with the 'window.location.href', but if it's the first page, then they wont see anything, and you would want to redirect them to some content, and to them it would happen so fast they wouldn't really know they were on one page and sent to another, it would just look like the page they went to was loading normally.
Let me know if this is not clear, or if need help with another aspect.

JavaScript changes a href link url based on user's IP address

Hopefully someone can assist with this question.
I am looking for simple JavaScript code that will update the a href link url and display it on a static HTML page, based on IP address from which the access request came.
The good thing is – the IP will be static and fixed, it will be the same number, which I already have.
In other words, if I access the same page from different IP addresses, the page will display different link url based on that.
While I might be wrong, my understanding is this can be scripted using ‘if else’ logic – if a specific IP address is detected and matched, the JS rewrites the link address.
Here is my logic below. Sorry, I don’t know much of the JavaScript syntax and used the construct below as a hypothetical example (its probably a total wreck since I didn't use the right syntax and whatnot), but this should give the general idea:
**if (location.referrer.ip('123.45.67.89.00') > -1)**
**document.write.href = 'xxx.com';**
**else if (location.referrer.ip('123.98.76.54.00') > -1)**
**document.write.href = 'yyy.com';**
**else**
**document.write.href = 'zzz.com';**
It is my understanding that since I will be using a single IP address in the formula, the following code can be omitted:
**else if (location.referrer.ip('123.98.76.54.00') > -1)**
**document.write.href = 'yyy.com/';**
Leaving only something like this
**if (location.referrer.ip('123.45.67.89.00') > -1)**
**document.write.href = 'xxx.com';**
**else**
**document.write.href = 'zzz.com';**
Again, this might not be the correct approach altogether and a way more sophisticated solution will be needed, therefore I hope that some of you with coding expertise can provide some assistance. Just to be clear - the script should NOT redirect the page but only update the url behind the link displayed on it instead.
I know there are several technologies already out there that can offer the solution, but my task is to get this running on the client side in the browser; I am not allowed to use server side technologies like Dot.NET, ASP, JSP, or anything other than JavaScript and static html.
Can someone please advice if this can be done this way? Basically, I just need to know if the approach I described above would work and if yes, what is the syntax for 'if' and 'else' lines.
Greatly appreciate any help, Thank YOU!
JK
I went looking for an answer to the same question just today and couldn't find anything. After a bit of tinkering I figured out a solution and registered on this site just to share it.
In my particular situation I was building my website to provide different href's based on the IP, but more specifically whether it was a local IP (192.168.x.x) or an external IP. Objective was to circumvent the NAT loopback problem (external IP address not accessible when connected to the same IP locally)
first off, we're going to use php so rename the file from extension .html to .php, then add this anywhere in your code and just replace the IP with whatever IP you're searching for
<?php
$ipaddress = getenv('REMOTE_ADDR');
if (fnmatch("192.168.*", $ipaddress)) {
echo 'This button is for local IP';
$link = 'http://192.168.2.40:8080';
} else {
echo 'This button is for external IP';
$link = 'http://www.myddns.com:8080';
}
?>
One weird thing I noticed about this is that I couldn't have the link be an image inside the above php tags, so I worked around that by including this after:
<img src="image/pic.png" onmouseover="this.src='image/picMouseOver.png'" onmouseout="this.src='image/pic.png'" border="0" alt="Link">
Note that this code works fine when loaded to a proper web server, but when just double clicking and testing directly in chrome it won't work. Just be aware of that (i.e. you will have to put it on your webserver or install php for windows to test it)
That answers your question... but on a related note I wanted to share something else.
So I have multiple domains that link to the same site, but wanted links to point to the same domain you came in on originally. So for that reason I was stuck using relative links and not the full URL (i.e. so if you found the website from www.website1.com, buttons wouldn't send you to www.website2.com\link.html)
I wanted to figure out how to make a relative link to a different port but learned it couldn't be done without hardcoding the domain. So I combined what I just did above with the instructions here:
Relative URL to a different port number in a hyperlink?
and wrote this method to change the URL just after the page loads, so hovering over the link or doing "Copy Link Location" will get the updated URL with the port number:
<html>
<head>
<script>
function setHref1() {
document.getElementById('modify-me').href = window.location.protocol + "//" + window.location.hostname + ":32400/web/index.html";
}
</script>
<?php
$ipaddress = getenv('REMOTE_ADDR');
if (fnmatch("192.168.*", $ipaddress)) {
// echo 'This button is for local IP';
$link = 'http://192.168.2.40:8080';
$id = '';
} else {
// echo 'This button is for external IP';
$link = 'http://www.myddns.com:8080';
$id = 'modify-me';
}
?>
</head>
<body onload="setHref1()">
</body>
</html>
edit:
You might also find this code to display visitors IP addresses interesting:
<html>
<head>
<title>What is my IP address?</title>
</head>
<body>
<?php
if (getenv('HTTP_X_FORWARDED_FOR')) {
$pipaddress = getenv('HTTP_X_FORWARDED_FOR');
$ipaddress = getenv('REMOTE_ADDR');
echo "Your Proxy IP address is : ".$pipaddress. "(via $ipaddress)" ;
} else {
$ipaddress = getenv('REMOTE_ADDR');
echo "Your IP address is : $ipaddress";
}
?>
</body>
</html>
source: http://www.cyberciti.biz/faq/how-to-determine-retrieve-visitors-ip-address-use-php-code-programming/

Insert into MySQL database when user clicks on a Link

I am creating a website that has users log in and select a pdf document that they want to download. When they open up the document to view and possibly download, I want data to be logged into a database at the same time.
The code to send the data to the database works (Except for: Undefined index: learningMaterial). But when I want to have the pdf document open and at the same time log the user and other data, all that happens is the document opens up.
Any advice would be appreciated, even for overall better methods of going about what I'm trying to achieve here. Still inexperienced with PHP.
See code below.
HTML
<form name="myform" method='post' action="../includes/writeStats.php">
<input type='hidden' name='learningMaterial' id='learningMaterial' value='learningMaterial'>
<a href='../documents/test.pdf' id='mylink' class='courses' name='Driver Training'> Driver Training </a>
</form>
JS - In header
<script type="text/javascript">
function submitform(){
document.myform.submit(); }
var form = document.getElementById("myform");
document.getElementById("mylink").addEventListener("click", function () {
submitform();
});
</script>
PHP
<?php
$con=mysqli_connect("localhost","root","password","qmptest");
// Check connection
if (mysqli_connect_errno()) {
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
//Get latest log nr
$result = mysqli_query($con,"SELECT * FROM logbook ORDER BY log DESC LIMIT 1");
while($row = mysqli_fetch_array($result)) {
$log = $row['log'] + 1;
//If statement to check if log is 0(first entry) to go here
}
$date = date("Y/m/d");
session_start(); // Start a new session
$person = $_SESSION['currentUser'];
//Not sure if this is correct along with my HTML input
$material = mysqli_real_escape_string($con, $_POST['learningMaterial']);
//Insert into database
$sql="INSERT INTO logbook (log, date, person, learningMaterial)
VALUES ('$log', '$date', '$person', '$material')";
if (!mysqli_query($con,$sql)) {
die('Error: ' . mysqli_error($con));
}
mysqli_close($con);
?>
Your way, clicking the link will override the form being submitted. This leads to the file opening and the form never going through.
Instead, you could try either opening the file in a new window by adding target="_blank" to the tag, or send the files URL through to the PHP, executing the database code then adding to the end:
header("Location: http://yourdomain.com/yourfile.pdf");
Your file is just a normal file being returned by your web server:
<a href='../documents/test.pdf' ...
So while you may be able to suggest to users or browsers that they should invoke some code before downloading this file, you can't actually require it. Any user can just request the file directly. And since PDF files don't execute PHP code (thankfully), your server-side PHP code has no way of knowing that the file has been requested.
What you can do is obscure the file itself behind a PHP request. You can create something like a download.php page which accepts the name of a file (test.pdf) and returns that file.
Be very careful when doing this. Don't just allow users to request any file and blindly return whatever they request. A user can request something like "../../../../../../../../../../etc/passwd" and if your code just builds a path and returns the file then you've just given users a sensitive file. It's best practice to keep a finite known list of identified files (perhaps in a database table) and let users request by the identifier rather than by the file path itself. That way the actual path is only ever known server-side in data that you control.
The main point here, however, is that by using such a page you inject some PHP code in between the user and the file. In order to get the file, the user needs to make a request to a PHP page. On that page you can record the act of the user having requested the file. (As well as perform authorization checks to validate that the user is allowed to view the file, etc.)
Never assume client-side code is going to do what you expect it to do. If you want to ensure something happens for anything approaching security or auditing purposes, it needs to happen in server-side code.

Categories