So currently on my website I log users OS when they register an account. And then they can view it (their OS that was logged upon registration) on their "account page".
But my question is, is getting users OS from parsing useragent in PHP reliable? For example I get users useragent via this $_SERVER['HTTP_USER_AGENT'] in php, then parse it to extract their OS from the useragent. Can I rely on this being accurate for legitimate users?
I don't really care if hackers can spoof the useragent, all I really am wondering is if this ($_SERVER['HTTP_USER_AGENT']) will give me the users accurate OS from legitimate (non hacker) site visitors?
You appear to be asking whether you can trust this field to be reliable when it's reliable? Well, yes, you can; when it's reliable, it's reliable.
But these times are rare. You don't need to be a "hacker" to spoof a User Agent. A simple browser extension will do it, or one extra argument in your wget or curl command if the request is scripted.
User agent is 100% fallible and you should not rely on it for anything useful.
Yes its reliable for non hacker user.
More Explaination
The user agent string is a text that the browsers themselves send to the webserver to identify themselves, so that websites can send different content based on the browser or based on browser compatibility.
Mozilla is a browser rendering engine (the one at the core of Firefox) and the fact that Chrome and IE contain the string Mozilla/4 or /5 identifies them as being compatible with that rendering engine.
You can also use get_browser() function of php.
Most of the time it is pretty reliable, in that most people can't be bothered to change this information. So using it for purely secondary, and ease-of-use, functionality is OK.
Especially in cases like these, where you use it to fill out the "default" values. Which the user have an option to change if wrong.
However, as it can be changed/spoofed by anyone who knows a little bit about HTTP and/or web browsers, you must not rely upon it for anything security related. There are quite a few browsers even, which will let the user change their user-agent string at will.
That includes using the user-agent string in an attempt to identify a user. As it is trivially easy to copy the headers, and spoof your own.
Use of SSL would increase the difficulty slightly. Still, in order to get all of the headers from your users (or admins), all an attacker would need is to post a link on your site to a server of his own. After which he could do whatever he wanted with his own.
If you want to make your UI more friendly. Lets say: "Is user on Chromer?" then show him some usefull info. Then its 100% reliable and very usefull. I don't care how friendly my UI is for hackers.
In some cases, for example ... lets say that for some reason you would like to block every one but Chrome owner,.. you can't rely on it.
Related
I'm using a simple service called I'm PDF to create PDF versions on online invoices. Right now, the client has to login to see the online version, but as a result, the api service doesn't have access to it either. How would I detect that the pdf service is accessing the site and allow it accordingly without a password?
I thought $_Server['http_referrer'] would do it, but I didn't have any luck. I wasn't sure even what the variables would be, so I had a var_dump($_Server)it emailed to me, whenever the page was visited. It sent it beautifully when I went to the page, but when the pdf was generated, no luck.
Any ideas?
Thanks for your help!
You need to identify the user. The only way with this service seems to be to append something to the pdf URL (GET parameter).
So create some secret on the server side, sign user id with it, append it to impdf URL and parse it with your secret on request. You will end up with user id that you can use for authorization.
Have you tried looking at the IP address?
The service probably accesses the site from the same IP address (or range of addresses). If that's the case, then all you have to do is check the remote IP address of the request, which I believe is in $_SERVER['REMOTE_ADDR'] for PHP.
I should also mention that IP address ACLs are not quite perfect, though, because IP addresses can be spoofed. They probably should not be too heavily relied upon for security unless there is absolute control over (or guarantee of safety) of packets leaving and entering the network. That said, they are most likely sufficient for your "simple" security requirements.
The HTTP referer is pretty much trivial to circumvent. As such, it is not reliable enough for security and should be taken with a grain of salt.
I wouldn't go for any of the above mentioned advices. Basically they all bring down your security measures.
I'd use an API such as PDFmyURL's API, which allows you to login directly via a host of standard ways. This makes sure you don't have to build anything new.
Direct link to section on accessing secure area: PDFmyURL API documentation
Disclosure: I work for Kaiomi, which owns this service.
I'm developing a website where people will be able to register and access different data via Ajax (powered by jQuery). This is all simple and i shall have no problems doing. the issue is that the data showed by Ajax needs to be secure and not available to be parsed through remote scripts. I can encrypted the data through a AES (in PHP) and decrypt successfully in javascript, but the javascript code will always be visible to everyone (after login). I can use an obfuscator and javascript encryption, but both ways, even mixed, are not secure enough and decryptable. I would prefer avoiding SSL connections, since I am trying to prevent registered users from accessing the information and the SSL connection would only prevent unregistered users from accessing the data.
Registered users will be able to earn money therefore very interested in cheating the code, this is why it has to be bulletproof.
Unfortunately the system needs definitely Ajax (the whole working principle needs to be based on Ajax). The ideal solution would be a way to save the encryption key on a place that can be saved by php and accessed by javascript, but not by users, remote script parsers etc.
Does anyone know a way to create a secure Ajax connection for this purpose?
I really appreciate all your help.
You want something that browsers do not do.
You've asked for: "The ideal solution would be a way to save the encryption key on a place that can be saved by php and accessed by javascript, but not by users, remote script parsers etc."
The design of the web browser and javascript engine in the browser is such that any Javascript that the web browser can execute can be seen by a human who wants to look at it, steal it, borrow it, whatever. Period. There is NO such place that can be accessed by Javascript, but not by users or remote script parsers. You will have to rethink how your app works if this is a problem. Most likely, you need to keep the secret stuff on the server and do more work on the server and less work on the client in order to protect what you want to protect. If you think about it, a browser is just a remote script parser so if you prevent remote script parsing, you prevent a browser. If you allow a browser, you allow a remote script parser.
You can obfuscate your Javascript to your heart's content if you want. That will make it a little more work for a human to understand and do something useful with it, but it will only be an additional obstacle that any determined and competent person can defeat if they really want to. If this secrecy is really important to you, then you need to rethink the design of the app so that secret information is not required in the browser and the browser just works as a display and interaction engine.
Just so I'm clear here. Any code that can be executed by a browser must, by definition, be something that any user or any tool can download and inspect. You can use SSL to protect data from snoopers in transport, but it ultimately has to be readable as Javascript for the browser to be able to execute it.
You can't do exactly what you want. It's like a cheat-proof game design. You CAN make it HARDER, even MORE hard, but NOT 100% secure. You've got to solve the problem froma different approach, like, whatever that is, examine the actions at server-side (e.g. in a stateful manner) and try to detect any non-human behavior. But it's only a matter of someone creating a realistic bot that mimicks the behavior of humans. Encryption is used for preventing 3rd parties -- other than the server and the client -- from eavesdropping/capturing data, NOT for the client. I'm not saying give up on the whole thing, but try a different approach to secure the system. I want to help more, but don't know what exactly you are trying to achieve.
authentication is the only ways to do it.
Just get your users to authenticate (login) and send them the random seed and salt you've used to encrypt their data.
Without the seed/salt, even though a malicious user can decrypt your data it will still be garbage.
If you want javascript to use a piece of data then clients use that data.
If you don't want data to be re-used set up a server-side system where each chunk of data is only valid once.
Proper authentication should solve all these problems.
I want the users to be able to see the data only when Ajax displays them
Then load the data when ajax get's it and not before. Or only partially load data and off-load any sensitive work to the server.
i think the best practice is to make your code (production code) too mush complex to read and edit
you should rename all your variable with letters [a-z] you should not declare ny function always use function(){} inside of another to make it more logical complex this way
the client can still see the code but has nothing to do with it
EDIT: I realize now it's a terrible advice
My requirement is i have a portion of the site that should allow user to access from only one system. He may used different IP's and different by if the system is same he should be able to get the access. My site is in PHP. Doing some R&D i found so JS which helps to get the MAC address if the visitor is using IE. My case is i cannot restrict user to use IE. He may use any browser. Is there any way to get the MAC address. If not possible how should i restrict the same user from accessing content from different computers.
No. MAC addresses are not useful beyond the local network, so they're not available in the upper layers (eg. Application layer). Using Javascript to get the the address isn't exactly foolproof either, since it's incredibly easy for someone to manipulate.
If you want to restrict the hosts that a user can access your site on, you'll need to use a method of storage persistence within the browser to store a key - something that uniquely identifies them. Some forums use this method to catch people attempting to bypass their bans.
You should generate some kind of random key (or encrypt a string), store it on the server-side along with the user you want to identify, then give the user the key to be stored in a cookie/localStorage.
Though, there is the obvious problem of a user clearing their cookies...
Hopefully that gives you a bit of head-start.
Daniel is correct, it's not practical to attempt to use MAC addresses.
For your purpose, you'll probably want to use a few layers. Cookies are a good place to start. As stated though, they can be cleared. The user also may have cookies turned off. Cookies are also stored in plain text on their computer, and they're really easy for the user to modify.
You could also implement sessions with PHP. Each session is unique for each system, and browser. If the user switches browsers or restarts their current browser, the session is re-created.
You could also check their user-agent string. It will be different for each browser, and "most likely" each system, but it can easily be spoofed.
You could also use a public/private key exchange, but that can be a pain to implement and manage.
There really is no one fool proof solution. The best bet is probably to use a combination of techniques to get it as "close to foolproof" as you can. Just try not to make it too inconvenient for the user.
I have been working on a secure login/portal type set of tools, the general code is free from SQL injections, XSS etc, I have mulitple things in place to stop session hijacking.
regenerate session's ID for EVERY page
Compare the user's IP with the IP at login
compare the user's user_agent with the agent at login
have short session time outs
etc
I have done all I can think of to stop hijacking, however I have still located a situation where it might be possible and would like to know if anyone has any ideas.
Imagine a situation where you have 2 users behind a firewall which does SNAT/DNAT, so both apart to come from the same IP. They are both identical machines supplied by the same place. One connects to the site and logs in, the other copies the PHPSESSID cookie and can simply steal the session.
This might sound like an extreme example, however this is very similar to my place of work, everyone is behind a firewall so looks to be the same IP, and all machines are managed/supplied by the IT team, so all have the same version of browser, OS etc etc.
I am trying to think of another way (server side) to stop the hijacking or minimize it further, I was thinking of a token which gets embedded into every URL (changed for each page), and checked.
I am looking for ideas or suggestions, if you want to offer code or examples you're welcome, but I am more interested in out of the box ideas or comments on my token idea.
Force everything to use HTTPS.
I think you are referring to a passive attack where a user in the network sniffs the cookie. For that, you don't need HTTPS. There are several options that are sufficient when the parties are sure to whom they're talking (e.g. you could do a DH exchange first and the server would encrypt a token the client would use in the next request...), but it's not worth the trouble going down that route.
If the user initially types in a non-https address, an active attack is still possible, but there's nothing you can do in that case. In the future, you might prevent future attacks of this kind once the user establishes one unadulterated connection to your site through HTTP strict transport security..
I wrote the main login portal for a major branch of the U.S. military.
I did all you mentioned above, plus at least one more step:
Have you stored a cookie on first login w/ the SESSION salt? Then encrypt everything serverside using that salt. The crooks would have to know about THAT cookie and STEAL IT, and it dramatically reduces exposure to session hijacking, as they just aren't lokoing for it.
Also, use JS and AJAX to detect if they have flash installed and if they do, store a flash cookie, too, with another salt. At that point you can more or less assume you have some pretty dedicated attackers out there and there's not much more you can do (like sending your users GPG keys to use via javascript and make them sign every single bit of data they send to you).
Do not reinvent the wheal, the built in session handler for your platform is very secure.
There are a number of configuration for PHP's session handler. Use HTTPS, at no point can a session ID be transmitted over http "cookie_secure" does this, its a great feature but a terrible name. httponly cookies makes xss harder because javascript cannot access document.cookie. Use_only_cookies stops session fixation, because an attacker cannot influence this value on another domain (unless he has xss, but thats a moot point).
PHP configuration:
session.cookie_httponly=on
session.cookie_secure=on
session.use_only_cookies=on
I am trying to think of another way (server side) to stop the hijacking or minimize it further, I was thinking of a token which gets embedded into every URL (changed for each page), and checked.
You should look at:
Understanding the Rails Authenticity Token
Tokens are a good idea.
I'm working on what aims to be a secure method of user registration and authentication using php and javascript but not ssl/tls.
I realise this may well be considered an impossible task that's been tried 1000 times before but I'm going to give it a go anyway. Every example I see online that claims to do it seems to have some huge fatal flaw!
Anyway, my current problem is verifying javascript at the client. The problem being that if my sha1 implementation in javascript is modified by some man-in-the-middle it's not secure at all. If I could just verify that the received javascript has not been tampered with then I think I can pull this off.
The real problem though, is that the only way to do things on the client side is javascript. Simple: write a javascript to verify the integrity of the other javascript files. Nope! Man-in-the-middle can just modify this file too.
Is there a way around this?
To secure your JavaScript, you must examine it in an guaranteed untampered environment. Since you can't create such an environment in the browser this is not possible. Your best option is to download the JavaScript via HTTPS. That isn't safe but better. Possible attack vectors left:
A virus can modify the browser to load some malicious JavaScript for every page
A keylogger can monitor what the user is typing
A proxy can act as a man-in-the-middle for an HTTPS connection. The proxy will actually decode what you send via HTTPS and encode it again (with a different certificate) for the browser.
A proxy can add iframes to the pages you send
Matt
I believe (despite the naysayers) that what you're asking is not impossible, merely extremely difficult. What you're asking is that code that is completely accessible to abuse nevertheless permits the user to identify herself to the server, and vice versa. One possible way is to use a zero-knowledge proof, which will leak no information to the eavesdropper (Eve). For example, the server might provide javascript that draws a representation of a graph that combines user provided information of no value to Eve on its own with server-provided information also of no value. The javascript may have been modified, but will either fail to provide the correct graph (at which point the user WALKS AWAY) or succeed. In the latter case, the user similarly provides 'zero-knowledge' evidence that they have an isomporphic representation of the graph; again, this either succeeds or fails. Also look at the SRP protocol, but the problem with this is that it's a patent minefield. See Practical Cryptography by Ferguson and Schneier. Jo
There's no way around it. As you said: if you cannot verify the source a man-in-the-middle attacker can replace anything the client receives, i.e. anything the client interprets and executes.
You say your only issue is a man in the middle modifying the javascript you use to perform a SHA1. I therefore guess you are using username + SHA1 of password for login....
That is completely insecure even with no Javascript tampering. Even though a man in the middle may not know the plain password if the javascript is not modified, he will know the hash, and he can perfectly use that hash to perform a login on his own by just replaying it.
Even if you include a salt / nonce, the man in the middle could still be able to use those tokens at the moment, and even steal the account by performing a password / email change.
Even ignoring this, and assuming you could actualy get around all that + actually get a javascript to test the integrity of a second javascript, how would you prevent that "verification script" from being tampered too? You keep depending on a script sent over an unsecure channel to assure security on such data (and could recursively go on for ever having a script that checks the integrity of a script that checks the integrity of a script...) all being perfectly tampered since they are sent over an unsecure channel.
The only way to do this would be to be able to build yourself a secure channel on top of http, which would need some client-side extras (a Firefox plugin / an ActiveX extension), but having native support for https that's just absurd.
as they are in the client you cannot access them.
This is the nature of the web pages...
try using important things in server side...
If your security architecture somehow requires functions to run in Javascript, then your security is flawed.
with JavaScript one can protect from passive network attacks (such as eavesdropping WiFi traffic), but you cannot protect yourself from active network attacks where the intruder is capable of controlling your HTTP response header and body data.
If you don't want to pay for the SSL certificate, you can create a self-signed certificate instead. However, this will only prevent passive network attacks, but is a lot easier than some hacky JavaScript implementations you ever create.
Essentially you need a CA signed SSL certificate to prevent active network attacks (a man in the middle).
You can only verify the integrity of Javascript files at the client if, and only if, server and client previously share a secret. That is most often not the case on the Internet. If such a secret is not available, then any attempt to verify transferred Javascript can be broken. It is a catch 22 situation.
Most often, people want to ensure JS integrity because it makes them feel like they can delegate security checks on the client side. In cryptography, there is a fundamental rule that should not be broken: never trust remote user input. Always double-check.
SSL/TLS can make middle-man attacks harder to achieve, but it is not watertight.