Restrict access to private images - javascript

As a photographer, I have my own website with a portfolio and such. I also have a log-in system for users, where I give them access to their own private images (it displays all images placed inside a specific folder - I do this manually for each user).
When a user logs in and sees his private images, he'll notice the URL says the following (when he downloads it/clicks it/etc):
www.mywebsite.com/FOLDER_NAME/IMG_123.jpg
By simply doing a bit of guessing, he'll be able to find other users private images. Of course this is defeats the purpose of having private images on my website, so I have to find a way around that.
At the moment, the user can only see his private images if his user_email (unique) matches userRow:
if ($userRow['user_email'] == "email#hotmail.com")
I'm not so sure what to search for. Restrict access to images wasn't a successful search query for me.
What can I do? I guess an option would be to call the folders something random, such as:
"Charles661846Xkdfdsnf34590u". That will be hard to guess, but I'm not so sure about security (as in if there are other ways to get access to the root?).
I have taken a look at Deny direct access to all .php files except index.php but that is not what I want exactly.
What can I do in this case?
I've programmed my site in php,html and a bit javascript.

If you need to restrict access to files only to a logged-in user, you should move all files from the web-root and put them in a place where you cannot access them directly through the web-server.
Then you serve the files after the user is authenticated through php. See for example the first example on the readfile() page of the php manual.
So when a user logs in, you store for example the user ID in a session variable and on top of the file-serving script you check if the id is correct / allowed access to that specific file.

Further to what Jeroen has said, you're on the right track in identifying that the folder name could be the weak point, and that it should be difficult/impossible to guess. There is no need to name folders after users; you can create a random 8, 12 or 16-char alphanumerical string and store that in the userRow as, perhaps, $userRow['folder_name'].
You can also put all user folders under a structure like http://example.com/storage/A97LD34B2 and ensure that the storage folder has an .htaccess file with:
Options All -Indexes
That's all you need in that text-only file. This, of course, assumes you have an Apache web server (by far the most common, especially for shared hosting accounts.) This file would prevent Mr Snoopy from navigating to http://example.com/storage and seeing a list of files.
Here are two S.O. questions that outline how to construct a password-protected members-only system:
Login into a website and get html from a page
PHP - Secure member-only pages with a login system
Note that each folder would contain an index.php file that would serve up files as jeroen described.

Related

Saving filename in DB after uploading to GCP Storage or using bucket.getFiles()

I've been searching in StackOverflow, but it seems that this question has not been asked yet. It's an architecture question about files being uploaded to GCP Storage.
TL;DR : Is there any issue using bucket.getFiles() directly (from a server), rather than storing each filename in my db, and then asking for them one by one and returning the array to the client ?
The situation:
I’m working on a feature that will allow the user to upload image attachements linked to a delivery note. This delivery note can have multiple attachements.
I use a simple upload button on my client (mobile device), and upload the content in GCP in a path/to/id-deliveryNote folder such as: path/to/id-deliveryNote/filename.jpg path/to/id-deliveryNote/filename2.jpg etc…
Somewhere else in the app the user should be able to click and download on each of those attachements.
The solution
After the upload being done in GCP, I asked myself how to read those files and give the user a download link to the file. That’s when I found the: bucket.getFiles() function.
Since my path to files are all below the same id-deliveryNote/ prefix, I leverage the usage of bucket.getFiles(prefix) and after the promise resolve can safely return to my user the list of links available.
The issue
I do not store the filenames in my deliveryNote table in my DB. Which can sound a bit problematic, relying on GCP to know the attachements of one deliveryNote. The way I see it is that, in my way I do not need to replicate the information in our DB (and possibly handling failure at two spots), and if I need those files I will at the ask GCP to give me their links. The opposed way of thinking is that, storing the names you will be able to list the attachements for the clients, and then generating the download link, when the user click a specific attachement.
My question is: Is there any issue using bucket.getFiles() directly (from a server), rather than storing each filename in my db, and then asking for them one by one and returning the array to the client ?
Some point that could influence the chosen method:
GCP costs per call difference ?
Invalid application data structure ?
Other things ?
There is no issue with using this method to return the link for the files to download. In the API documentation for this method - accessible here - they even show an example of returning files using prefixes as well. You just need to look out that Cloud Storage actually doesn't use real folders and only names that look like they are in folders - more details in this case here - so you don't mix up concepts when working with names and prefixes.
For the pricing point, you can get the whole pricing for Google Cloud Storage in this documentation, including how much each operation will cost - for example, it will cost you $ 0.02 per 50000 operations for object gets, retrieving bucket and object metadata - storing data, etc. After you check that, you can compare with your database costs as well, to check it if this point will impact you.
To summarize, there is no problem for you to follow this. The advantage of storing the names on Database, it's actually that even though you could have failure in two spots, it's more probable for you to face issues in only one place and this way the replication would be a great thing to have. So, you just need to decide which one fits you best.

How do I correctly access my PHP files? Directly from JS or a thru a "master" PHP?

I'm not sure I fully understand this aspect of site security, but seems it is a bad idea to keep PHP files on root, so we move them into a PHP folder, and we call this folder phpIncludes. Some issues that are obscure are:
1) how do I access a file doStuff.php inside phpIncludes? From javascript? Seems to be a bad idea to have my javascript tell the name of the folder where sensitive stuff is, as in:
executeAjaxCall("phpFiles/doStuff.php",success,error);
2) Or from a "master" PHP that resides on root? Can't that be tampered with for being on root?
$secretVariableThatOnlyThisPHPWouldKnow="bla"; //then check it in the included file? Does that work?
//in JS
executeAjaxCall("masterFile.php?fileNeeded=doStuff");
//in PHP
$secretVar="bla";
include("myPathString/phpIncludes/".$_GET['fileNeeded'].".php");
//in all other INCLUDEable PHP files
if (!isset($secretVar))
{
die();
}
if (!isFromThisDomain)
{
die();
}
(How do I perform last test?)
What I have in mind is: "If someone wants to get the PHP files inside folder phpIncludes they can't, but they can access them thru HTML so requests need to be validated. Is it easily doable without sessions, like generating something in master.php that doStuff.php would recognize and hence do its job? Or is sessions the way to go?"
I am actually wondering about the "no session" scenario for this frees me from the task of attempting to implement anti-session hijacking code (if I ever learn it...). On the other hand, I am also thinking:"Isnt the variable secretVar accessable/tamperable since it will be on root?"
3) Do as (2), but have master.php inside yet ANOTHER folder (lets call it "master"), making it non-root? In this case, do I access my phpIncludes folder from the master folder using getcwd()+string manipulation? Or is there a "more elegant" (lazier...) method?
3 seems magical, where the only file I have on root would be index.php, that simply starts the HTML+JS and does nothing sensitive. Or am I missing something?
It is completely irrelevant how your PHP file and folder structure is. The only thing that matters is this:
What happens when you access a particular URL?
phpFiles/doStuff.php is a URL first and foremost. It doesn't matter how you access it ("directly" via the browser address bar, via AJAX, curl, whatever else); all that matters is what happens when you access that URL. And it's entirely up to you to ensure that nothing undesirable will happen with each URL access.
Don't publicly expose any URLs which aren't meant to exist in the first place. If you have a bunch of .php files which aren't mean to be accessed directly via a URL, then don't publicly expose them. That either means that you block access to them via your web server configuration (e.g. deny all in an .htaccess file), or that you take those files out of the public webroot to begin with.
Validate all input and necessary conditions in all publicly exposed URL endpoints as necessary. The user needs to be logged in to do something? Verify that. You require certain query parameters or POST body data? Verify that. Validate and verify every incoming request on its own merits before doing anything. Whether you repeat this validation code in each file individually or do it somewhere centrally is up to you.
Split your code across multiple files as appropriate to make it reusable. See points 1. and 2., you must simply take care which files are publicly exposed as URL entry points and at which point you need to do what sort of validation.

share a variable between computers using dropbox

I am making a website where users make posts all the posts are stored in a variable i save these variables in local storage and i host the site through dropbox public folder.
Sadly you can only see your posts because there in local storage.
Is there a way i could store that variable in a json file so other users can access it?
E.g.
var dump = "User post 1"
user 2 can see user 1's post and when they submit a post
var dump = "User post 1, User post 2"
I already have it working with multiple posts but i want to be able to share them on multiple computers
maybe the vars value could be stored in a .json or .txt and when a user posts it adds to that file in dropbox?
JavaScript in the browser does not have the ability to write files, making this idea unfortunately an impossible one. Further complicating things, Dropbox (last I checked) only "serves" static pages, meaning you can't use JavaScript to do an HTTP POST to a Dropbox-hosted file.
Alas, I think the answer is, "No, it can't be done like this".

Does everyone shares the same javascript file?

So I'm using Javascript and ajax to connect to a database through an php file, but something came in mind.
If a User log in, the user data will be stored in my Javascript file tittle UserProces.js as:
Var Username = "James"
Var Age ="25";
(Data obtain from a query through a php: RetrieveUserData.php)
If 1 minute after James loged in, another user name Amy log in will the values of name and age of amy will effect the values of James? Since there is only one UserProces.js.
Of course NO! Each user is getting his local copy of javascript file.
The server sends each client that requests the page a copy of the javascript file it has stored. That copy is then in their browser and running there. Any changes to variables are done in that copy in their browser. They have to way (well, unless you set up something special) to change the original file on the server. Think of it like this:
I'm a teacher with a test document on my computer (this is the javascript file on the server). For each student who comes into the class and asks to take the test (a client requesting the page) I'm going to print off a copy in my printer and give them. They will then write their name on the test and fill in answers (assign values to variables). A student doing this doesn't effect anyone else in the class because they aren't changing the original document, they are just editing their copy.
Not a perfect analogy, obviously, but pretty darn close.
Also, addressing a comment made earlier, you probably aren't accessing the service "through a php file". You are using a php file to generate a copy of the web page for the user to view. Again, printing off a copy for the user, but in this case the php file gives a special set of instructions for exactly what should be "printed off".
Each user will load the same script file but all variables, objects and everything else gets stored by each browser, and even your browser doesnt share that info, which prevents one website to have access to variables on another website.
So, final answer is no. They will not share any info. Just load the same "base".

Special URL for language selection?

Just a simple question, I was wondering why some websites have something like "?lang=EN" in their URL after selecting a language? Is it because their html file or folder containing it is named "?lang=EN", or some other code that does this? I'd like to set the URL like that for my website (has 2 languages). Currently I have folder structure like this:
Language selection: D:/media/index.html
EN site: D:/media/en/index.html
CN site: D:/media/cn/index.html
Files for the website: D:/media/site
Thanks.
First of all, anything after the file extension ( .html ) is a server side function.
The ? is a function for PHP and adds variables to the super global GET array ( in the form: ?variable=value&variable2=value2 ) that is directed to from another page and from that point many things can be done with the data.
Sites that use the ?lang=EN are probably programmed to print out the chunks of text needed on the single page in the places and languages required. Though it is possible using this method to redirect to a language specific directory.
Hope this helps :)
That's because they often have a content management system where the content isn't stored in files necessarily, but in a database. The lang=en is a GET variable from the URL that they retrieve in, for example, PHP, to display the correct content. In your case, however, you can just redirect the user if they click EN or CN to the appropriate locations, in your case, /en/index.html and /cn/index.html.
The url you see at the address bar, whatever comes after "?" is called "QueryString" and with libraries on the server side (based on the developing platform that website is made on) you can access the values. For instance the value of "lang" can be equal to "EN" or "CN" etc.
By the way you can have some http handlers to rewrite the requested url and get your parameters through the url that physically doesn't exists. Like the one you mentioned, "http://yoursite.com/en/default.whatever". I myself prefer this way but as you requested you should use some server side libraries to access the query string values and choose the language of the content you wanna send to client.
Also as one solution that once I used, you can also use some translation service (like translate.google.com) client libraries and call it at client side with jquery or even javascript and translate all the texts on page load. Although it's damn fast in action, it has some issues you will see.
Hope it helps.
PHP uses $_GET to get value from variables from the URL.It gets the value from that LANG variable and then it selects all from a file where are stored all the words in different languages or from the database
You don't need to copy every file and then translate it.
Search for php dynamic pages tutorial in your case. I found THIS.
P.S. PHP is one from many ways to do this.

Categories

Resources