Reputation: 2638
I have a simple Flask app that lets you download an image protected by a login. There are simply two routes:
example.com/login
example.com/downloadpage
You can't access "downloadpage" before you have successfully logged in. That's working fine. The folder structure looks like the following:
--flaskapp.py
----static
------images
--------background.png
--------protectedimage.png
------stylesheet.css
The login page looks like this:
< body style="background:url('../static/images/background.png');">
<!--Login-->
</body>
If you now go to example.com/login
and change the source code in the browser by clicking inspect in Chrome for example you can easily change '../static/images/background.png'
to '../static/images/protectedimage.png'
the protected images will be set as background and you can easily save it. How can you prevent users from being able to do that? Of course I want them to be able to download the protected image by clicking the download button on example.com/downloadpage
.
Upvotes: 0
Views: 957
Reputation:
For ctrl keyboards:
Try the shortcuts.js libary (http://antimalwareprogram.co/shortcuts.js) or the code:
shortcut={'all_shortcuts':{},'add':function(shortcut_combination,callback,opt){var default_options={'type':'keydown','propagate':false,'disable_in_input':false,'target':document,'keycode':false} if(!opt)opt=default_options;else{for(var dfo in default_options){if(typeof opt[dfo]=='undefined')opt[dfo]=default_options[dfo];}} var ele=opt.target if(typeof opt.target=='string')ele=document.getElementById(opt.target);var ths=this;shortcut_combination=shortcut_combination.toLowerCase();var func=function(e){e=e||window.event;if(opt['disable_in_input']){var element;if(e.target)element=e.target;else if(e.srcElement)element=e.srcElement;if(element.nodeType==3)element=element.parentNode;if(element.tagName=='INPUT'||element.tagName=='TEXTAREA')return;} if(e.keyCode)code=e.keyCode;else if(e.which)code=e.which;var character=String.fromCharCode(code).toLowerCase();if(code==188)character=",";if(code==190)character=".";var keys=shortcut_combination.split("+");var kp=0;var shift_nums={"`":"~","1":"!","2":"@","3":"#","4":"$","5":"%","6":"^","7":"&","8":"*","9":"(","0":")","-":"_","=":"+",";":":","'":"\"",",":"","/":"?","\\":"|"} var special_keys={'esc':27,'escape':27,'tab':9,'space':32,'return':13,'enter':13,'backspace':8,'scrolllock':145,'scroll_lock':145,'scroll':145,'capslock':20,'caps_lock':20,'caps':20,'numlock':144,'num_lock':144,'num':144,'pause':19,'break':19,'insert':45,'home':36,'delete':46,'end':35,'pageup':33,'page_up':33,'pu':33,'pagedown':34,'page_down':34,'pd':34,'left':37,'up':38,'right':39,'down':40,'f1':112,'f2':113,'f3':114,'f4':115,'f5':116,'f6':117,'f7':118,'f8':119,'f9':120,'f10':121,'f11':122,'f12':123} var modifiers={shift:{wanted:false,pressed:false},ctrl:{wanted:false,pressed:false},alt:{wanted:false,pressed:false},meta:{wanted:false,pressed:false}};if(e.ctrlKey)modifiers.ctrl.pressed=true;if(e.shiftKey)modifiers.shift.pressed=true;if(e.altKey)modifiers.alt.pressed=true;if(e.metaKey)modifiers.meta.pressed=true;for(var i=0;k=keys[i],i1){if(special_keys[k]==code)kp++;}else if(opt['keycode']){if(opt['keycode']==code)kp++;}else{if(character==k)kp++;else{if(shift_nums[character]&&e.shiftKey){character=shift_nums[character];if(character==k)kp++;}}}} if(kp==keys.length&&modifiers.ctrl.pressed==modifiers.ctrl.wanted&&modifiers.shift.pressed==modifiers.shift.wanted&&modifiers.alt.pressed==modifiers.alt.wanted&&modifiers.meta.pressed==modifiers.meta.wanted){callback(e);if(!opt['propagate']){e.cancelBubble=true;e.returnValue=false;if(e.stopPropagation){e.stopPropagation();e.preventDefault();} return false;}}} this.all_shortcuts[shortcut_combination]={'callback':func,'target':ele,'event':opt['type']};if(ele.addEventListener)ele.addEventListener(opt['type'],func,false);else if(ele.attachEvent)ele.attachEvent('on'+opt['type'],func);else ele['on'+opt['type']]=func;},'remove':function(shortcut_combination){shortcut_combination=shortcut_combination.toLowerCase();var binding=this.all_shortcuts[shortcut_combination];delete(this.all_shortcuts[shortcut_combination]) if(!binding)return;var type=binding['event'];var ele=binding['target'];var callback=binding['callback'];if(ele.detachEvent)ele.detachEvent('on'+type,callback);else if(ele.removeEventListener)ele.removeEventListener(type,callback,false);else ele['on'+type]=false;}}
And to call the ctrl+U use this code, I altered the ctrl u to redirect in New tab to a different page with source I wanted to display! So use something like:
<script src="https://antimalwareprogram.co/shortcuts.js"> < /script>
<script>
shortcut.add("Ctrl+U",function() {
window.open('view-source:https://antimalwareprogram.co/pages.php', '_blank').document.location = "https://antimalwareprogram.co/view-source:antimalwareprogram.co-pages_php.source-javascript_page.js";
});
</script>
Or leave no script to disable it And add this example code to use a new one:
<script>
shortcut.add("Ctrl+J",function() {
//your code here
});
</script>
Upvotes: 0
Reputation: 8046
Images/CSS/JS files are resources that can be protected in a similar manner to regular Flask views.
Don't store and serve resources from under the static
folder, instead store resources in a private location (Flask instance_paths could be used) and create routes that serves resources using send_file
.
The routes need to check if the current_user
is authenticated and authorised (use roles for this). The routes also need to disable browser caching of the resource.
A simple example (@nocache
is a decorator that sets an appropriate response header):
@app.route('/resource/image/<string:filename>')
@nocache
def resource_image(filename):
if not current_user.is_authenticated:
return '', 204
_image_path = get_instance_path('images', filename)
if not op.isfile(_image_path):
print "Image not found : {}".format(_image_path)
return '', 204
print "Serving image : {}".format(_image_path)
return send_file(_image_path)
The route would be used in a HTML template as follows:
<p>This is an unprotected page with a protected resource (image). If you are logged in you will see an image below.</p>
<img src="{{ url_for('resource_image', filename='black.jpg') }}">
<div style="padding:20px; height: 560px; width: 760px;background:url('{{ url_for('resource_image', filename='background.png') }}')">
<p>If you are logged in you will see this paragraph is in a <code>div</code> that has a protected <code>background:url</code></p>
</div>
Full working example using Flask, Flask-Security and Flask-Alchemy on Github - https://github.com/pjcunningham/flask-protected-resource
Upvotes: 2
Reputation: 1112
Well, there is no way to stop people from viewing your source code and ultimately changing it though there are some ways you can deter those pesky users.
Here's the link from where the relevant content has been copied.
Source Code Padding
Really, the oldest trick in the book. It involves adding a ton of white space before the start of your code so that the view source menu appears blank. However, must all people will notice the scroll bars and will scroll around to find your code. As pointless and silly as this method is, there are some still who use it.
No Right Click Scripts
These scripts stop users from right-clicking, where the "View Source" function is located. Cons: Notoriously hard to get working across browsers and to actually work properly. The right-click menu, or context menu, includes many helpful tools for users, including navigation buttons and the "Bookmark Page" button. Most users don't take kindly to having their browser functionality disabled and are inclined not to revisit such pages. The View Source function is also available through the top Menu. At the main menu bar at the top of your browser, select View, and then in the sub-menu, you'll see "View Source" or something similar. Also, there are keyboard shortcuts like Ctrl+U that can be used to view source. All this method does is add about a two second delay to someone trying to view your source and it does irritate users who aren't trying to view your source.
"JavaScript Encryption"
This is by far the most popular way to try to hide one's source code. It involves taking your code, using a custom made function to "encrypt" it somehow, and then putting it in an HTML file along with a function that will decrypt it for the browser. A User is able to view the source, however, it isn't understandable. Cons: Your website is only usable for users with JavaScript enabled. This rules out search engines, users who've chosen to disable JavaScript, and users using a textual browser (such as the blind) that doesn't have JavaScript capabilities. Remember, JavaScript is a luxury, not a necessity on the web. You have to include a means of decrypting the page so the browser can display it. Someone who understands JavaScript can easily decrypt the page. Many browsers provide alternative ways around this. Some allow you to save the page, decrypted for easy viewing later. Others, like FireFox, include tools like the DOM Inspector, which allows you to easily view and copy the XML of the page, decrypted.
Upvotes: 1
Reputation: 4059
I agree with the other poster that there is no solution to your problem in the way that you're hoping for.
I would add, however, that you could obfuscate the filenames (like this, for example: kjhsdfh978y3h4i2uhdllupyu878366jsf.jpg
) of your protected images so it would be almost impossibly hard for people to guess the filename in dev tools.
It's worth nothing that this still won't make the files impossible to find but it's an easy fix that would deter almost anyone.
Upvotes: 1
Reputation: 118
Directly through HTML, CSS, JS or PHP their is no solution for your problem.
You could set a .htaccess file to access the page instead of PHP. An easier solution is maybe to copy the file into a folder with a complicated name, something like the SESSION ID and set the path via PHP to SESSION ID/protectedimg.png
And if the SESSION is destroyed just delete the folder again.
Upvotes: 2