NotionCommotion Posted January 15, 2015 Share Posted January 15, 2015 I have two servers: WebServer and FaxServer. WebServer needs to send a fax. Is my approach shown below fairly secure?Before sending a fax, ServerWeb needs to store a record in a table representing the message, and I am using a pseudo random value for the PK which is generated as 2147483648+mt_rand(-2147483647,2147483647).WebServer then generates a hash equal to hash('sha256',$pk.'secretCodeWhichOnlyWebServerAndFaxServerKnow').WebServer then sends curl request to FaxServer using POST which includes $pk, the hash, the fax number, some text to include in the fax, and an optional array of document to include (array(array('id'=>321,'name')=>'fileName.pdf')).FaxServer verifies that the hash is correct given $pk, that the minimum information has been received, and that the fax number is a valid phone number, and quickly responds to WebServer by echoing 0 or 1 so the code in the WebServer could continue and inform the user. If all looks okay, a new instance of PHP is started. if(missingInformation) {echo(0);} else { session_start(); $_SESSION['_xfr']=$_POST; exec('/usr/bin/php -q /path/to/send_fax.php '.session_id().' >/dev/null &'); echo(1); } New instance of PHP send_fax.php then does the following: session_id($argv[1]);//Set by parent session_start(); $data=$_SESSION['_xfr']; $doc_list=null; foreach ($data['documents'] AS $doc) { if(ctype_alnum($doc['id'])) { $file='/some/tmp/directory/'.$doc['id']; if(!file_exists($file)) { $url='http://machine.WebServer.com/index.php?task=displayDocument&id='.$doc['id'].'&x='.hash('sha256','displayDocument'.$doc['id'].'secretCodeWhichOnlyWebServerAndFaxServerKnow'); $cmd='wget -O '.$file.' '.escapeshellarg($url); exec($cmd); } $doc_list.=' '.$file; } exit('invalid document'); } //Send the fax... //Send another CURL request to the WebServer similar to the wget giving the fax status. exit; When WebServer receives the wget request for a document, it confirms the hash and sends the document to the FaxServer using X-Sendfile.When WebServer receives the CURL request regarding status, it updates the database for the applicable message. Seem reasonably secure? Quote Link to comment https://forums.phpfreaks.com/topic/293958-relatively-secure-server-to-server-communication/ Share on other sites More sharing options...
Jacques1 Posted January 15, 2015 Share Posted January 15, 2015 (edited) First of all: Inventing your own security protocol makes no sense, even if it only needs to be “fairly secure” (whatever that means). Coming up with your own stuff usually takes more effort than simply setting up a proper HTTPS connection, custom protocols are almost always fundamentally flawed (yours is), and it's not even possible to reliably estimate their strengths and weaknesses. I mean, even if I told you that your approach is “fairly secure” (which I don't), that wouldn't mean anything. Protocols are evaluated by teams of experts, not a bunch of random guys in a PHP forum. Just use HTTPS with self-issued certificates. It's easy to set up, it doesn't cost anything, and it provides solid security. Knowing how to do this is also a very important ability which will probably help you in the future. As to your protocol: The first fundamental issue is that you haven't defined the goal (or at least you haven't told us). What does “fairly secure” mean? Which threats are you trying to protect against, and which threats are you willing to accept? We can't evaluate a protocol if we don't even know what it's supposed to do. Generally speaking, there are several issues (or properties, if you will): The protocol (obviously) provides no confidentiality, so an eavesdropper can read all data going back and forth. An eavesdropper can also record valid requests an replay them. The hash stuff is dubious at best and uses common anti-patterns. While you've been lucky(?) enough to avoid the even worse construction SHA256(key + message), your variation is highly vulnerable to hash collisions. Granted, there are currently no known SHA-2 collisions. But that's still not an excuse for using a broken scheme instead of a standardized construction like HMAC. If you do the hash validation in a naïve way like $provided_hash == $expected_hash, you'll reveal the key through time differences. The whole idea really only makes sense if you assume that passive eavesdropping is no problem at all (is this reasonable?). But then why do you think that active attacks are a problem? Active attacks are generally more difficult than passive attacks, so it's odd to assume that an attacker can do the former but not the latter. Or maybe you just want to authenticate the client so that a random visitor cannot simply download a document? Then you might as well use a plain password. Again, without a concrete definition, the whole exercise is pointless from the beginning. Edited January 15, 2015 by Jacques1 Quote Link to comment https://forums.phpfreaks.com/topic/293958-relatively-secure-server-to-server-communication/#findComment-1503097 Share on other sites More sharing options...
NotionCommotion Posted January 16, 2015 Author Share Posted January 16, 2015 (edited) My goals are: Prevent any access to the fax server except from the webserver application. A user will interact with the webserver, and the webserver application will assure the user is authorized. Prevent the ability to download files from the webserver except by the faxserver (or by other parts of the webserver application, but let's ignore this as it is not relevant). I planned on using HTTPS after I get some basic concept working. I never used HTTPS with CURL, and didn't know if I would have challenges. Also, while I've implemented HTTPS with self signed certificates between a browser client and a webserver, I've never done so between two servers and didn't know the challenges. Yes, HTTPS would prevent eavesdropping, but how would it protect against some just sending a HTTPS request to the faxserver and sending an unauthorized fax, or sending a HTTPS request to the webserver and downloading a file? Unless, should I just include a plan text password in the POST, and use HTTPS so that it can't be viewed? And if I use HTTPS, is even HMAC required? Also, not necessarily security related, but any advice or constructive criticism about the other parts of my implementation would be appreciated. Edited January 16, 2015 by NotionCommotion Quote Link to comment https://forums.phpfreaks.com/topic/293958-relatively-secure-server-to-server-communication/#findComment-1503141 Share on other sites More sharing options...
Jacques1 Posted January 16, 2015 Share Posted January 16, 2015 Once you've established an HTTPS connection, you can safely use classical password authentication. So you generate a random password on the web server, store its hash on the fax server (plain SHA-256 is enough), and now the web server has to include the password in every request. You do the same thing in the other direction. HTTPS also supports mutual public key authentication: We all know server certificates, but there are also client certificates which can be used to authenticate the client. This is more secure than passwords, but it's a bit more effort to set up if you've never done it before. HTTPS doesn't require any additional HMAC stuff. It automatically protects against eavesdropping, data tampering and even replay attacks (it's not possible to record a valid request and then send the same data again). Also, not necessarily security related, but any advice or constructive criticism about the other parts of my implementation would be appreciated. Personally, I'm a fan of cleanly designed APIs and standardized protocols like JSON-RPC, so the whole approach looks a bit hacky to me. Sure, wget and echo are theoretically enough to make two parties communicate over HTTP(S). But once things get more complex, you may regret that choice and wish for an actual API with proper error handling etc. It really depends on the job. Do you just need a quick hack so that you can move on? Or is this a serious task which is worth some extra effort? Quote Link to comment https://forums.phpfreaks.com/topic/293958-relatively-secure-server-to-server-communication/#findComment-1503184 Share on other sites More sharing options...
NotionCommotion Posted January 16, 2015 Author Share Posted January 16, 2015 In regards to storing the hash of of the password on the other server, I suppose it could be hardcoded into some configuration file, right? And, not the same password (and associated hash) for both directions? Just read up on HMAC and was excited to use it. Oh well, will do so next time. Just curious, would one ever include the IP of the server in the message so that the password would only work from a given IP? Proxies and the like will probably be an issue, so likely not a good idea. Yea, it is a bit hackish, but I just need to get it down quick, and could later improve. I've decided on going away with my ugly passing data from one PHP instance to another via a session, and will either pass it as an argument (assuming it is not too much data), or maybe better yet have the script respond but continue to execute by sending the appropriate headers. Quote Link to comment https://forums.phpfreaks.com/topic/293958-relatively-secure-server-to-server-communication/#findComment-1503201 Share on other sites More sharing options...
QuickOldCar Posted January 16, 2015 Share Posted January 16, 2015 I would build an api using https, json responses, checking $_SERVER['REMOTE_ADDR'] and hard coding a relatively secure password. If multiple users can make a public and also private api key system. Make yourself a script acting as the front door. Include anything considered not for public view from outside the servers root folder if passes. Quote Link to comment https://forums.phpfreaks.com/topic/293958-relatively-secure-server-to-server-communication/#findComment-1503202 Share on other sites More sharing options...
Jacques1 Posted January 16, 2015 Share Posted January 16, 2015 (edited) I'm not sure if IP checks are a good idea. They provide very little protection, and the IP must be kept up-to-date for the lifetime of the application. The check may also break entirely if the server architecture changes (e. g. Apache running behind a front end server and receiving the server IP rather than the client IP). If you are and will be in full control of the server, sure, you can use this as additional protection. But otherwise it probably causes more harm than good. In regards to storing the hash of of the password on the other server, I suppose it could be hardcoded into some configuration file, right? Yes. And, not the same password (and associated hash) for both directions? Two separate passwords. If one password gets compromised, then at least the other password is still intact. If you used the same password, then the hash would actually be rather useless, because the plaintext would be sitting right next to it. Edited January 16, 2015 by Jacques1 Quote Link to comment https://forums.phpfreaks.com/topic/293958-relatively-secure-server-to-server-communication/#findComment-1503212 Share on other sites More sharing options...
NotionCommotion Posted January 16, 2015 Author Share Posted January 16, 2015 Thanks Jacques. I feel that if HTTPS is not used, then the IP addition to the message adds protection, but why not just use HTTPS and not deal with the problems. Quote Link to comment https://forums.phpfreaks.com/topic/293958-relatively-secure-server-to-server-communication/#findComment-1503223 Share on other sites More sharing options...
kicken Posted January 17, 2015 Share Posted January 17, 2015 Yes, make sure you setup HTTPS between the servers. That is your main protection. If you want to just use a self-generated certificate that is fine, you'll just need to tell curl to accept certificates from your custom CA. You can do this with the CURLOPT_CAINFO option. You also want to ensure that CURLOPT_SSL_VERIFYPEER is enabled. $ch = curl_init($url); curl_setopt($ch, CURLOPT_CAINFO, '/path/to/caroot.pem'); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); //... Once HTTPS is up and running, you could just use something as simple as HTTP Basic Auth rather than have to code specific verification procedures into your application. 1 Quote Link to comment https://forums.phpfreaks.com/topic/293958-relatively-secure-server-to-server-communication/#findComment-1503232 Share on other sites More sharing options...
boompa Posted January 17, 2015 Share Posted January 17, 2015 Prevent any access to the fax server except from the webserver application. This should be enforced at the hardware level, i.e. via firewall. Quote Link to comment https://forums.phpfreaks.com/topic/293958-relatively-secure-server-to-server-communication/#findComment-1503267 Share on other sites More sharing options...
NotionCommotion Posted January 18, 2015 Author Share Posted January 18, 2015 This should be enforced at the hardware level, i.e. via firewall. Not critical enough for me to want to buy one And if I did use a firewall, why not software such as iptables?. Quote Link to comment https://forums.phpfreaks.com/topic/293958-relatively-secure-server-to-server-communication/#findComment-1503283 Share on other sites More sharing options...
boompa Posted January 18, 2015 Share Posted January 18, 2015 True, iptables would be fine. As someone who works with virtualization, I tend to think of even iptables as "hardware" Quote Link to comment https://forums.phpfreaks.com/topic/293958-relatively-secure-server-to-server-communication/#findComment-1503311 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.