Secure Encrypted FormMail, PHP and GPG based.
We are all familiar with the original FormMail script created back in 1995, but are you familiar with a secure formmail script?
And by secure I mean one that encrypts the data.
I sure wasn’t so one night while I was up late, waiting for my scheduled maintenance window to come around, I typed one up.
On common misconception that I see a lot of people do is put an https URL for their formmail action tag, and then think the form is secure.
Well, that doesn’t help a whole lot, it would secure the data back to the server, but then emailing it to you would not necessarily be secure, especially if your mail server is different than your web server, plus there will be a period of time where the form results are in plain text on the server.
What you need is not only a formmail that will use https, but that will also encrypt the data with GPG.
That said I bring you Secure Formmail:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 | <?php //Doug Walker's Secure Formmail Copyright 2009 FreeGPG.org //This script is provided with absolutely no guarantee or warrrenty //This script is not assumed to be bug free or error free //Secure Formmail may not be 100% secure, and may not be secure enough or appropriate for your specific use //We are not responsible for misencrypted or unencryptable messages or damages caused by use of this script //You agree to limit any loss from the use of this script to $5, which you agree is a fair amount since the script is free //This script was developed using GnuPG v1.4.5 //This script is meant to be used in conjunction with SSL (https://) //***** YOU MUST SET $referrers $recipients AND ENTER YOUR PUBLIC KEY***** //Set valid referring URLs, seperate multiple approved referrers with a , no spaces $referrers="domain.com,www.domain.com"; //Set valid recipient domains $recipients=$referrers."emaildomain.com,us.emaildomain.com"; //include your publickey, by default it is in publickey.txt in the same directory as this script //include the Begin and End lines and no extra spaces //You can get a public key from freegpg.org but are not required to use that public key //***Paste the your key starting with the BEGIN line right below <<<EOI //***and with your END line right above EOI; $publickey=<<<EOI -----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v1.4.5 (GNU/Linux) qwerwqerwer YOUR PUBLIC KEY HERE qwerqwerwq -----END PGP PUBLIC KEY BLOCK----- EOI; // Escape the key and message for added security $publickey=escapeshellarg(trim($publickey)); //Declare variables $secure=1; //Set secure mode 0 = off 1 = on define('GPG', '/usr/bin/gpg'); // The gpg binary define('HOME', '/tmp'); // .gnupg will be created here putenv('HOME=' . HOME); //Set the home environment $to_max_len=200; $ref = getenv("HTTP_REFERER"); $timestamp = date("m/d/y H:i:s", time()); $ip = $REMOTE_ADDR; $msg=""; //set referrer if($_SERVER['HTTP_HOST']!="") $referrer=$_SERVER['HTTP_HOST']; else $referrer=$_SERVER['HTTPS_HOST']; //end set referrer $recipient=$_POST['recipient']; //Begin the message with the referring URL, date/time stamp, and remote IP $msg.="$ref\n$timestamp\n$ip\n\n"; //$msg.="$ref<br>$timestamp<br>$ip<br><br>"; //validate referring URL //initialize switch $sw=0; $ref_array = explode(",", $referrers); foreach ($ref_array as $ref_ele){ if($ref_ele==$referrer) $sw=1; } if(!$sw) die("Error: Invalid referring domain"); //check reciepient is set if($recipient=="") die("Error: No recipient set"); //check recipient length if(strlen($recipient)>200) die("Error: Recipient length too long"); //validate recipient //get domain portion of recipient $recip_email_arr=explode('@',$recipient); $recip_dom=$recip_email_arr[1]; //set from email $from_email="webmaster@".$recip_dom; //initialize switch $sw=0; $rec_array = explode(",", $recipients); foreach ($rec_array as $rec_ele){ if($rec_ele==$recip_dom) $sw=1; } if(!$sw) die("Error: Invalid recipient domain"); //The Guts //required field error switch $err_sw=0; $err_msg="The following field(s) were left blank, please hit back and fill in:<br>"; foreach ($_POST as $field => $formvar){ //switch to add to the message or not $sw=1; //Check if required field if($required!=""){ //build required field array $req_arr=explode(",",$required); foreach ($req_arr as $req_ele){ if($req_ele==$field) if($formvar==""){ $err_sw=1; $err_msg.="* $field<br>"; } } } //Check for recipient if($field=="recipient") $sw=0; //Check for subject if($field=="subject") $sw=0; //Check for requied post var if($field=="required") $sw=0; //Check for redirect URL if($field=="redirect") $sw=0; //for testing only #echo "$field: $formvar<br>"; //Build the message if($sw) $msg.="$field: $formvar\n"; } //display error message if required fields were left blank if($err_sw) die($err_msg); //Encrypt the message if($secure){ // Import the key into the keyring $result=shell_exec("/bin/echo $publickey | " . GPG . " --dearmor | " . GPG . " --import - 2>&1"); // Find the key ID so that we can remove it later preg_match('/key ([A-Z0-9]+):/', $result, $matches); if (empty($matches[1])) { die('Problem importing key!'); } $key_id=$matches[1]; // Escape the key and message for added security $message=escapeshellarg(trim($msg)); // Fire up GPG and encrypt the message $result=shell_exec("/bin/echo $message | " . GPG . " --batch --recipient '$key_id' --trust-model always --armor --encrypt 2>&1"); $msg=$result; // Remove the key from the keyring $result=shell_exec(GPG . " --batch --yes --delete-key $key_id' 2>&1"); if (!empty($result)) { die('Error: 29391'); } } //Send the email mail($recipient,$subject,$msg,"From: $from_email"); //Redirect the user if redirect set if($redirect!="") header( "Location: $redirect" ); else header( "Location: http://$referrer" ); ?> |
The nice thing about this script is, its easy to use. Simply paste in your public key, and if you don’t have one, get one at freegpg.org, and then set the referrers URL, and if necessary change the path to gpg. This script has been tested and works well with the shared web hosting servers of Penguin Web Hosting
After the form is submitted, it sends you an email with the GPG encrypted message, and then you can decrypt it with your gpg compatible email client, or paste it in, along with your private key, at FreeGPG.org.
Secure FormMail can accept the 4 common hidden fields:
1 2 3 4 | <input type=hidden name=recipient value=""> <input type=hidden name=required value=""> <input type=hidden name=redirect value=""> <input type=hidden name=subject value=""> |
Hope you find this useful!
TTYL,
Doug Walker