Can we detect if a root CA certificate is installed? - php

Is this possible with JavaScript or PHP? I want to be able to detect if my private CA is installed on the user's iOS or Android device. From there I can decide whether to provide instructions for installation or not. I've been "googlin" and haven't found anything useful. Has anyone tried this before? I want to find out what I should spend my time learning. If it's not possible, could you suggest an in browser alternative?
EDIT : I don't have a choice here and it's not my decision. A private CA certificate is going to be used for other security reasons.

I doubt there will be any sort of device query to test this.
I haven't actually done this, but you could probably come up with a test where the JavaScript makes an AJAX request to an https server that uses the certificate you want to test for. If the request succeeds, then the certificate is working. (This question seems to imply that AJAX requests will (correctly) fail if the SSL certificate doens't validate)
Note that, because the scheme (http or https) of the URL will be different (and maybe the domain depending on how you set this up), your test site will have to use the CORS Access-Control-Allow-Origin header to allow the browser to make the request. See: AJAX calls to untrusted (self-signed) HTTPS fail silently
EDIT:
I had some time and put together a very simple example. Goto http://ssl_test.gjp.cc . That page will attempt to make an AJAX request to https://ssl_test2.gjp.cc, which uses a self-signed certificate. Before you trusted ssl_test2, you will see "Failed" on the ssl_test page, however once you trust the certificate for ssl_test2, you should always see "Success" on ssl_test.
Note that this doesn't prove that your user has the CA cert installed - all it proves is that they have configured their browser to trust the test site (ssl_test2). If you never directly point the user to the test site, then they will never have the chance to trust only that site, so this should work reasonably well.

Maybe this will help :
<img src="https://the_site/the_image" onerror="redirectToCertPage()" />

Related

php login with SSL

I've read a lot of questions here about how login can be connected to SSL and so on, but still the idea is not that clear. Based on what I read that I need to have an SSL setup and installed on my web server so that I can use the https secure connection on the page where a login is going to be used. Ok, I have done that part,but still wondering what to include in the login code in order to have the entire session must be over https. in some sites they mention that I have to add this code tep_href_link(FILENAME_ACCOUNT, '', 'SSL') so that the php login page or code be secure.
any comments will be appreciated.
Thanks a lot.
Update: I believe that this code is very important to add so that the login page goes on the https. if(!isset($_SERVER['HTTPS']))
{
header("location: https://" . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI']);
}
HTTPS represents using an algorithm to secure transport layer communications that encrypts what the browser and server are sending each other. The encrypted form that is sent over the network is expensive computationally to turn back into it's original content, unless whoever is decrypting the ciphertext has the paired private key (or... a "computationally weak" algorithm was used).
This is point to point (client sends request to server, server accepts, determines response, sends response), so the browser and server first exchange public keys that represent what the data you are sending or receiving is going to be "scrambled" against. A private key is held by the public key issuer that allows that computer to "descramble" and obtain the original content that was sent to the receiver.
So when you create a private/public key pair, the private key is kept (in confidence and secret) on the server, and the related public key is sent to the browser. The browser, likewise, does the same thing and transmits a public key to the server.
"Protecting" sensitive information is not all that's going on; you may also use SSL/TLS to prevent tampering with data, for example, or even as an additional verification step.
To get HTTPS setup and available for you to use, you need to:
Procure a public/private key (signing by a certificate authority, or CA, is potentially optional depending on your end users).
Install it into the key store on the server that is available to your web server. OpenSSL is used for both of these steps in many cases.
Setup your system to use HTTPS URLs (for all resources, not just a <form action="https://...">s).
Couple of notes:
Browsers have their own certificates, so don't worry about that.
Many CMS' and frameworks allow you to specify HTTPS at the application layer
You can use WireShark to inspect what your computer is actually sending and receiving. This can be very illuminating, especially in combination with viewing the request/response in Firebug or Chrome Net consoles.
PHP online manual has the OpenSSL "book". Here is an example of how CodeIgniter handles configuring HTTPS at the application level.
There's various tutorials on how to setup SSL on a LAMP stack. Here is a tutorial on WAMP2 HTTPS and SSL Setup if you just need a development environment.
If you have a shared hosting environment, you may not be able to do the SSL setup on the server yourself; that may be handled by the server administrator. Check with your host. DreamHost, for example, has extensive docs.
Um, on a quick google, this function (tep_href_link) appears to be part of osCommerce. If your site has an SSL certificate setup properly, forcing users to an https url should be fine. If you don't know how to do that look into Location headers or mod_rewrite.
Also, as an aside, one thing you will need to do, is to ensure all links on the page are going over https. That will increase the likelihood of getting the green lock or w/e when a user comes to the page, assuming the cert isn't self-signed.

Providing Access-Control-Allow-Origin with a Wildcard

I am making a page that responds to an AJAX request with a certain string when another certain string is provided as a GET variable. In order to avoid problems with the "same origin" policy, I have found that I can include this line of PHP at the top of the page:
header('Access-Control-Allow-Origin: *');
There's no sensitive data being passed whatsoever, it's actually keywords passed back and forth from several different domains, (its an SEO related application). Due to this, hundreds of different domains will be using it, so if possible I would like to avoid specifying each one. Are there any risks to using this line? If so, what are they?
Also, if this page was located under an HTTPS URL is it still accessible?
Any advice, suggestions or concerns are most welcome. Thank you!
If the access truly is public, I'd say this is a good solution. However, if you want to limit the access to your site, you'll probably want to list explicitly each domain origin allowed.
Since you say your response doesn't include any sensitive information, you probably don't need to worry about hosting your service over HTTPS. The one reason you might is if a client HTTPS page tries to access your non-HTTPS service. In that case, I would guess they'd get a warning about unsecure information being sent/received when your AJAX service is called, and maybe even just a silent fail. If this is a common enough case, then I'd say looking into the HTTPS service. Make sure your HTTPS certificate is certified properly, because if the client's browser cannot verify the certificate the AJAX request will silently fail (as opposed to prompting when you navigate directly to an HTTPS page)! Also, I don't know how it will go in your case, but whenever I've worked with HTTPS, I've usually had to tweak things to get them to function properly.
Long story short, I'd start with HTTP and then evaluate the need of HTTPS. Good luck!

PHP OpenID doesn't work with Google/Yahoo and 'hacks' fix it... are they safe?

I've been experimenting with OpenID, and have set up a sample web page to access using my OpenID account. I'm using the Php OpenID Library by Janrain and it wasn't working with my Google Account. A little research led me to this question, which suggests the problem is that Google uses https and...
... it's likely the setup for making HTTPS requests is borked on your PHP server. Check to make sure you have the ca-certificates package installed.
In the same thread, someone links to their hacked version of the library which I deployed and have used with my Google Account successfully. Other questions have other customizations to get around similar problems (Janrain’s PHP-OpenID and Google/Yahoo, php-openID doesn’t work with Yahoo!, Example usage of AX in PHP OpenID...)
I'm not too hot on security, so I ask; does anyone know of a reason to not use these hacked versions?
Does the original library have whatever shortcoming these hacks fix by design, and therefore the hack is a potential security vulnerability?
Is there a qualified crypto-ifier out there who has looked at any of these solutions and gone "By David Chaum's beard! NO!!"
If so - and I therefore shouldn't use any of these hacks - how would I check that I "have the ca-certificates package installed"?
Here's what the author of one of those "hacked" versions wrote:
In particular CURLOPT_SSL_VERIFYPEER
and CURLOPT_SSL_VERIFYHOST are true by
default: I set them to false and it
worked for the test page!
The effect that has is to pretty much negate any security advantage offered by using HTTPS. The primary reason HTTPS is useful in OpenID is that it guards against a man-in-the-middle attack, i.e. some bad guy poisons your DNS cache to send all google.com requests to bad-guys.example. With properly configured HTTPS, you'd verify the certificate on the connection, find out it wasn't from Google, and say "I'm not going to believe anything you say, bad-guys!"
Unless, of course, you don't verify any certificates (you set all the SSL_VERIFY options to false), in which case your server will believe everything bad-guys says as if it were the real Google provider. You can imagine how that might be bad.
Now, frankly, this isn't the worst choice you could make, because it's no worse than just using HTTP, which a lot of people do anyway. You're just lying to your users if you imply that you're providing HTTPS-level security when you're not.
And there's a lot of information out there about how easy it is or isn't to do a dns-based attack, or how easy it is to forge SSL certificates. Either way, it does require someone to attack the connection between your server and Google, which is generally harder than attacking the connection between the user's laptop in the coffee shop and your server.
But still, much better to actually fix your PHP or CURL SSL configuration. Or if you don't, warn your users of that when they sign up with HTTPS identifiers, so they can choose if they really want to use that OpenID with your site.
Which leads to your second question. I think, not knowing anything about which server platform you're using, the best thing I can do is to link you to the Curl docs on SSL certificates; see the section that says "Get a better/different/newer CA cert bundle!"
From the Wikipedia article on Certificate Authority:
A CA issues digital certificates that contain a public key and the identity of the owner. When an end-user tries to access an unknown URL, the web browser (e.g. Mozilla Firefox and Microsoft Internet Explorer) will contact the CA to confirm the public key of the URL.
... so the CA Certificate is a Public Key Certificate used to communicate over https://. Your server should have CA Certificates on the file system somewhere. If not, you'll have to download the CA Certificate yourself and set the CURLOPT_CAINFO constant to point to its location. See this article.
http://unitstep.net/blog/2009/05/05/using-curl-in-php-to-access-https-ssltls-protected-sites/
[...] does anyone know of a reason to not
use these hacked versions?
Besides the fact that they're hacked versions, which are most likely undocumented and have no guarantee as to their behavior?
I can't answer specifically, but it there should be some warning lights flashing when you work with modules that have had quick fixes and workarounds applied, especially when you're dealing with authorization and security.. I think the best advice would be "Use at own risk!"
I'm sure someone with more knowledge on the topic will arrive soon enough with a more informed answer.

What is https and SSL? How do they work? How can they be used in PHP?

I know the general definition but I need more details on how to implement them in general and PHP in specific, and what exactly are the features I gain from them?
SSL stands for "Secure Socket Layer", and it's a method of encrypted HTTP communication (among other things). It encrypts the traffic between a web browser and a server, making it possible to send secure data without fear of eavesdropping.
SSL is a web-server level technology, and has nothing to do with PHP. You can enable any web server with SSL, whether it has PHP on it or not, and you don't have to write any special PHP code in order to make your PHP pages show up over SSL.
There are many, many guides to be found on the internet about how to set up SSL for whatever webserver you might be using. It's a broad subject. You could start here for Apache.
some webservers are configured to mirror the whole site, so you can get every page over http or https, depending on what you prefer, or how the webbrowser sends them around. https is secure, but a bit slower and it puts more strain on your hardware.
so you might implement your site and shop as usual, but decide to put everything from the cart to the checkout, payment and so on under https. to accomplish this, all links to the shopping cart are absolute and prefixed with https:// instead of http://. now, if people click on the shopping cart icon, they're transfered to the secure version, and because all links from there on are relative again, they stay there.
but! they might replace the https with http manually, or go on the unencrypted version using a malicious link, etc.
in this case, you probably might want to check if your script was called over https (_SERVER["SERVER_PROTOCOL"], afaik), and deny the execution if not (good practice). or issue a redirect to the secure site.
on a side note: https is not using ssl exclusivley anymore, tls (the successor to ssl, see rfc2818) is more modern
rule of thumb: users should have the choice if they want http or https in noncritical environments, but forced to use https on the critical parts of your site (login/cart/payment/...) to prevent malicious attacks.

What does a PHP developer need to know about https / secure socket layer connections?

I know next to nothing when it comes to the how and why of https connections. Obviously, when I'm transmitting secure data like passwords or especially credit card information, https is a critical tool. What do I need to know about it, though? What are the most common mistakes you see developers making when they implement it in their projects? Are there times when https is just a bad idea? Thanks!
An HTTPS, or Secure Sockets Layer (SSL) certificate is served for a site, and is typically signed by a Certificate Authority (CA), which is effectively a trusted 3rd party that verifies some basic details about your site, and certifies it for use in browsers. If your browser trusts the CA, then it trusts any certificates signed by that CA (this is known as the trust chain).
Each HTTP (or HTTPS) request consists of two parts: a request, and a response. When you request something through HTTPS, there are actually a few things happening in the background:
The client (browser) does a "handshake", where it requests the server's public key and identification.
At this point, the browser can check for validity (does the site name match? is the date range current? is it signed by a CA it trusts?). It can even contact the CA and make sure the certificate is valid.
The client creates a new pre-master secret, which is encrypted using the servers's public key (so only the server can decrypt it) and sent to the server
The server and client both use this pre-master secret to generate the master secret, which is then used to create a symmetric session key for the actual data exchange
Both sides send a message saying they're done the handshake
The server then processes the request normally, and then encrypts the response using the session key
If the connection is kept open, the same symmetric key will be used for each.
If a new connection is established, and both sides still have the master secret, new session keys can be generated in an 'abbreviated handshake'. Typically a browser will store a master secret until it's closed, while a server will store it for a few minutes or several hours (depending on configuration).
For more on the length of sessions see How long does an HTTPS symmetric key last?
Certificates and Hostnames
Certificates are assigned a Common Name (CN), which for HTTPS is the domain name. The CN has to match exactly, eg, a certificate with a CN of "example.com" will NOT match the domain "www.example.com", and users will get a warning in their browser.
Before SNI, it was not possible to host multiple domain names on one IP. Because the certificate is fetched before the client even sends the actual HTTP request, and the HTTP request contains the Host: header line that tells the server what URL to use, there is no way for the server to know what certificate to serve for a given request. SNI adds the hostname to part of the TLS handshake, and so as long as it's supported on both client and server (and in 2015, it is widely supported) then the server can choose the correct certificate.
Even without SNI, one way to serve multiple hostnames is with certificates that include Subject Alternative Names (SANs), which are essentially additional domains the certificate is valid for. Google uses a single certificate to secure many of it's sites, for example.
Another way is to use wildcard certificates. It is possible to get a certificate like ".example.com" in which case "www.example.com" and "foo.example.com" will both be valid for that certificate. However, note that "example.com" does not match ".example.com", and neither does "foo.bar.example.com". If you use "www.example.com" for your certificate, you should redirect anyone at "example.com" to the "www." site. If they request https://example.com, unless you host it on a separate IP and have two certificates, the will get a certificate error.
Of course, you can mix both wildcard and SANs (as long as your CA lets you do this) and get a certificate for both "example.com" and with SANs ".example.com", "example.net", and ".example.net", for example.
Forms
Strictly speaking, if you are submitting a form, it doesn't matter if the form page itself is not encrypted, as long as the submit URL goes to an https:// URL. In reality, users have been trained (at least in theory) not to submit pages unless they see the little "lock icon", so even the form itself should be served via HTTPS to get this.
Traffic and Server Load
HTTPS traffic is much bigger than its equivalent HTTP traffic (due to encryption and certificate overhead), and it also puts a bigger strain on the server (encrypting and decrypting). If you have a heavily-loaded server, it may be desirable to be very selective about what content is served using HTTPS.
Best Practices
If you're not just using HTTPS for the entire site, it should automatically redirect to HTTPS as required. Whenever a user is logged in, they should be using HTTPS, and if you're using session cookies, the cookie should have the secure flag set. This prevents interception of the session cookie, which is especially important given the popularity of open (unencrypted) wifi networks.
Any resources on the page should come from the same scheme being used for the page. If you try to fetch images from http:// when the page is loaded with HTTPS, the user will get security warnings. You should either use fully-qualified URLs, or another easy way is to use absolute URLs that do not include the hostname (eg, src="/images/foo.png") because they work for both.
This includes external resources (eg, Google Analytics)
Don't do POSTs (form submits) when changing from HTTPS to HTTP. Most browsers will flag this as a security warning.
I'm not going to go in depth on SSL in general, gregmac did a great job on that, see below ;-).
However, some of the most common (and critical) mistakes made (not specifically PHP) with regards to use of SSL/TLS:
Allowing HTTP when you should be enforcing HTTPS
Retrieving some resources over HTTP from an HTTPS page (e.g. images, IFRAMEs, etc)
Directing to HTTP page from HTTPS page unintentionally - note that this includes "fake" pages, such as "about:blank" (I've seen this used as IFRAME placeholders), this will needlessly and unpleasantly popup a warning.
Web server configured to support old, unsecure versions of SSL (e.g. SSL v2 is common, yet horribly broken)
(okay, this isn't exactly the programmer's issue, but sometimes noone else will handle it...)
Web server configured to support unsecure cipher suites (I've seen NULL ciphers only in use, which basically provides absolutely NO encryption)
(ditto)
Self-signed certificates - prevents users from verifying the site's identity.
Requesting the user's credentials from an HTTP page, even if submitting to an HTTPS page. Again, this prevents a user from validating the server's identity BEFORE giving it his password... Even if the password is transmitted encrypted, the user has no way of knowing if he's on a bogus site - or even if it WILL be encrypted.
Non-secure cookie - security-related cookies (such as sessionId, authentication token, access token, etc.) MUST be set with the "secure" attribute set. This is important! If it's not set to secure, the security cookie, e.g. SessionId, can be transmitted over HTTP (!) - and attackers can ensure this will happen - and thus allowing session hijacking etc. While you're at it (tho this is not directly related), set the HttpOnly attribute on your cookies, too (helps mitigate some XSS).
Overly permissive certificates - say you have several subdomains, but not all of them are at the same trust level. For instance, you have www.yourdomain.com, dowload.yourdomain.com, and publicaccess.yourdomain.com. So you might think about going with a wildcard certificate.... BUT you also have secure.yourdomain.com, or finance.yourdomain.com - even on a different server. publicaccess.yourdomain.com will then be able to impersonate secure.yourdomain.com....
While there may be instances where this is okay, usually you'd want some separation of privileges...
That's all I can remember right now, might re-edit it later...
As far as when is it a BAD idea to use SSL/TLS - if you have public information which is NOT intended for a specific audience (either a single user or registered members), AND you're not particular about them retrieving it specifically from the proper source (e.g. stock ticker values MUST come from an authenticated source...) - then there is no real reason to incur the overhead (and not just performance... dev/test/cert/etc).
However, if you have shared resources (e.g. same server) between your site and another MORE SENSITIVE site, then the more sensitive site should be setting the rules here.
Also, passwords (and other credentials), credit card info, etc should ALWAYS be over SSL/TLS.
Be sure that, when on an HTTPS page, all elements on the page come from an HTTPS address. This means that elements should have relative paths (e.g. "/images/banner.jpg") so that the protocol is inherited, or that you need to do a check on every page to find the protocol, and use that for all elements.
NB: This includes all outside resources (like Google Analytics javascript files)!
The only down-side I can think of is that it adds (nearly negligible) processing time for the browser and your server. I would suggest encrypting only the transfers that need to be.
I would say the most common mistakes when working with an SSL-enabled site are
The site erroneously redirects users to http from a page as https
The site doesn't automatically switch to https when it's necessary
Images and other assets on an https page are being loading via http, which will trigger a security alert from the browser. Make sure all assets are using fully-qualified URIs that specify https.
The security certificate only works for one subdomain (such as www) but your site actually uses multiple subdomains. Make sure to get a wildcard certificate if you will need it.
I would suggest any time any user data is stored in a database and communicated, use https. Consider this requirement even if the user data is mundane, because even many of these mundane details are used by that user to identify themselves on other websites. Consider all the random security questions your bank asks you (like what street do you live on?). This can be taken from address fields really easily. In this case, the data is not what you consider a password, but it might as well be. Furthermore, you can never anticipate what user data will be used for a security question elsewhere. You can also expect that with the intelligence of the average web user (think your grandmother) that that tidbit of information might make up part of that user's password somewhere else.
One pointer if you use https
make it so that if the user types
http://www.website-that-needs-https.com/etc/yadda.php
they will automatically get redirected to
https://www.website-that-needs-https.com/etc/yadda.php
(personal pet peeve)
However, if you're just doing a plain html webpage, that will be essentially a one-way transmission of information from the server to the user, don't worry about it.
All very good tip here... but I just want to add something..
Ive seen some sites that gives you a http login page and only redirect you to https after you post your username/pass.. This means the username is transmitted in the clear before the https connection is established..
In short make the page where you login from ssl, instead of posting to an ssl page.
I found that trying to <link> to a non-existent style sheet also caused security warnings. When I used the correct path, the lock icon appeared.

Categories