Jump to content

Massive security issues!


hoponhiggo

Recommended Posts

Hi Guys

 

Ok, so, i started to try and teach myself how to build a website early this year. I started with a small project, following a load of online tutorials, picking up bits of HTML, PHP and MYSQL on the way. The problem is, the small project has developed into a massive one, and one that i want to continue with and push forward.

 

However alot of the early tutorials i followed seriously lack security.

 

Since using this forums (which has been a saviour) i have become aware of the  massive security risks my site and users data could be open too.

 

If i post the code of my log in and sign up page (both on same page) would  somebody be kind enough to point out its major flaws and suggest some fixes?

 

Note: alot of the code at the top has been generated by dreamweaver...

 

<?php require_once('Connections/example.php'); ?>
<?php
if (!function_exists("GetSQLValueString")) {
function GetSQLValueString($theValue, $theType, $theDefinedValue = "", $theNotDefinedValue = "") 
{
  if (PHP_VERSION < 6) {
    $theValue = get_magic_quotes_gpc() ? stripslashes($theValue) : $theValue;
  }

  $theValue = function_exists("mysql_real_escape_string") ? mysql_real_escape_string($theValue) : mysql_escape_string($theValue);

  switch ($theType) {
    case "text":
      $theValue = ($theValue != "") ? "'" . $theValue . "'" : "NULL";
      break;    
    case "long":
    case "int":
      $theValue = ($theValue != "") ? intval($theValue) : "NULL";
      break;
    case "double":
      $theValue = ($theValue != "") ? doubleval($theValue) : "NULL";
      break;
    case "date":
      $theValue = ($theValue != "") ? "'" . $theValue . "'" : "NULL";
      break;
    case "defined":
      $theValue = ($theValue != "") ? $theDefinedValue : $theNotDefinedValue;
      break;
  }
  return $theValue;
}
}
?>
<?php
// *** Validate request to login to this site.
if (!isset($_SESSION)) {
  session_start();
}

$loginFormAction = $_SERVER['PHP_SELF'];
if (isset($_GET['accesscheck'])) {
  $_SESSION['PrevUrl'] = $_GET['accesscheck'];
}

if (isset($_POST['Username'])) {
  $loginUsername=$_POST['Username'];
  $password=$_POST['Password'];
  $MM_fldUserAuthorization = "";
  $MM_redirectLoginSuccess = "index.php";
  $MM_redirectLoginFailed = "loginsignup.php";
  $MM_redirecttoReferrer = false;
  mysql_select_db($database_example, $example);
  
   $LoginRS__query=sprintf("SELECT username, password, uid FROM users WHERE username=%s AND password=%s",
    GetSQLValueString($loginUsername, "text"), GetSQLValueString($password, "text")); 
   
  $LoginRS = mysql_query($LoginRS__query, $example) or die(mysql_error());
  $loginFoundUser = mysql_num_rows($LoginRS);
  if ($loginFoundUser) {
  if(isset($_POST['checkcookie'])){
	  setcookie("cookname",
	  $loginUsername, time()+60*60*24*100, "/");
	  setcookie("cookpass", $password,
	  time()+60*60*24*100, "/");
  }
     $loginStrGroup = "";
     $pullID = mysql_fetch_assoc($LoginRS);
     $usrID = $pullID['uid'];
    
if (PHP_VERSION >= 5.1) {session_regenerate_id(true);} else {session_regenerate_id();}
    //declare two session variables and assign them
    $_SESSION['MM_Username'] = $loginUsername;
    $_SESSION['MM_UserGroup'] = $loginStrGroup;
    $_SESSION['MM_userid'] = $usrID;	      

    if (isset($_SESSION['PrevUrl']) && false) {
      $MM_redirectLoginSuccess = $_SESSION['PrevUrl'];	
    }
    header("Location: " . $MM_redirectLoginSuccess );
  }
  else {
    header("Location: ". $MM_redirectLoginFailed );
  }
}
?>
<?php
if (!function_exists("GetSQLValueString")) {
function GetSQLValueString($theValue, $theType, $theDefinedValue = "", $theNotDefinedValue = "") 
{
  if (PHP_VERSION < 6) {
    $theValue = get_magic_quotes_gpc() ? stripslashes($theValue) : $theValue;
  }

  $theValue = function_exists("mysql_real_escape_string") ? mysql_real_escape_string($theValue) : mysql_escape_string($theValue);

  switch ($theType) {
    case "text":
      $theValue = ($theValue != "") ? "'" . $theValue . "'" : "NULL";
      break;    
    case "long":
    case "int":
      $theValue = ($theValue != "") ? intval($theValue) : "NULL";
      break;
    case "double":
      $theValue = ($theValue != "") ? doubleval($theValue) : "NULL";
      break;
    case "date":
      $theValue = ($theValue != "") ? "'" . $theValue . "'" : "NULL";
      break;
    case "defined":
      $theValue = ($theValue != "") ? $theDefinedValue : $theNotDefinedValue;
      break;
  }
  return $theValue;
}
}
?>
<?php
if (!function_exists("GetSQLValueString")) {
function GetSQLValueString($theValue, $theType, $theDefinedValue = "", $theNotDefinedValue = "") 
{
  if (PHP_VERSION < 6) {
    $theValue = get_magic_quotes_gpc() ? stripslashes($theValue) : $theValue;
  }

  $theValue = function_exists("mysql_real_escape_string") ? mysql_real_escape_string($theValue) : mysql_escape_string($theValue);

  switch ($theType) {
    case "text":
      $theValue = ($theValue != "") ? "'" . $theValue . "'" : "NULL";
      break;    
    case "long":
    case "int":
      $theValue = ($theValue != "") ? intval($theValue) : "NULL";
      break;
    case "double":
      $theValue = ($theValue != "") ? doubleval($theValue) : "NULL";
      break;
    case "date":
      $theValue = ($theValue != "") ? "'" . $theValue . "'" : "NULL";
      break;
    case "defined":
      $theValue = ($theValue != "") ? $theDefinedValue : $theNotDefinedValue;
      break;
  }
  return $theValue;
}
}

$editFormAction = $_SERVER['PHP_SELF'];
if (isset($_SERVER['QUERY_STRING'])) {
  $editFormAction .= "?" . htmlentities($_SERVER['QUERY_STRING']);
}

if(isset($_POST['username'])){
if($_POST['username'] == ""){
//username empty
die("You must enter a username");
}
} else {
//username not set
} 

if(isset($_POST['password'])){
if($_POST['password'] == ""){
//username empty
die("You must enter a password");
}
} else {
//password not set
} 
if ((isset($_POST["MM_insert"])) && ($_POST["MM_insert"] == "form1")) {
  $insertSQL = sprintf("INSERT INTO users (username, password, email, fname, sname) VALUES (%s, %s, %s, %s, %s)",
                       GetSQLValueString($_POST['username'], "text"),
                       GetSQLValueString($_POST['password'], "text"),
                       GetSQLValueString($_POST['email'], "text"),
                       GetSQLValueString($_POST['fname'], "text"),
                       GetSQLValueString($_POST['sname'], "text"));

  mysql_select_db($database_example, $example);
  $Result1 = mysql_query($insertSQL, $example) or die(mysql_error());

  $insertGoTo = "loginsignup.php";
  if (isset($_SERVER['QUERY_STRING'])) {
    $insertGoTo .= (strpos($insertGoTo, '?')) ? "&" : "?";
    $insertGoTo .= $_SERVER['QUERY_STRING'];
  }
  header(sprintf("Location: %s", $insertGoTo));
}

//send mail
$to = $_POST['email'];
$subject = "Welcome to ...";
$message = "
<html>
<head>
  <title>Welcome to ...</title>
</head>
<body>
<p>Thank you for registering</p>
<p>Hoponhiggo (admin)</p>
</body>
</html>
";


// To send HTML mail, the Content-type header must be set
$headers  = 'MIME-Version: 1.0' . "\r\n";
$headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
$headers .= 'From: example@hoponhiggo.co.uk' . "\r\n";

preg_match('/^([0-9a-zA-Z]([-\.\w]*[0-9a-zA-Z])*@([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9})$/i');


mail($to,$subject,$message,$headers);
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>login and signup</title>
<script type="text/javascript" src="http://ajax.googleapis.com/
ajax/libs/jquery/1.5/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function()
{

$(".tab").click(function()
{
var X=$(this).attr('id');

if(X=='signup')
{
$("#login").removeClass('select');
$("#signup").addClass('select');
$("#loginbox").slideUp();
$("#signupbox").slideDown();
}
else
{
$("#signup").removeClass('select');
$("#login").addClass('select');
$("#signupbox").slideUp();
$("#loginbox").slideDown();
}

});

});
</script>
<script lanuage="javascript" script type="text/javascript">
// Example:

// alert( readCookie("myCookie") );

function readCookie(name)

{

  var cookieValue = "";

  var search = name + "=";

  if(document.cookie.length > 0)

  { 

    offset = document.cookie.indexOf(search);

    if (offset != -1)

    { 

      offset += search.length;

      end = document.cookie.indexOf(";", offset);

      if (end == -1) end = document.cookie.length;

      cookieValue = unescape(document.cookie.substring(offset, end))

    }

  }

  return cookieValue;

}

function remember()
{
if(readcookie("cookname")){
	document.getElementById("username").value=readcookie
	("cookname");
	document.getElementById("password").value=readcookie
	("cookpass");
}
}

</script>


<link href="css/pwnedbookv4.css" rel="stylesheet" type="text/css" />
</head>

<body>
<div id="header">

  <div align="center"><img src="Images/Banner1.gif" width="252" height="140" alt="pwnedbokv4!" />
  
  </div>
</div>
<div style="margin:40px">
<div id="container">
<div id="tabbox">
<a href="#" id="signup" class="tab signup">Signup</a>
<a href="#" id="login" class="tab select">Login</a>
</div>
<div id="panel">
<div id="loginbox"><h1>Login</h1>
<form action="<?php echo $loginFormAction; ?>" method="POST" name="login">
  <p align="center">
    <label for="Username">Username</label>
    <input type="text" name="Username" id="Username" />
    </p>
  <p align="center">
    <label for="Password">Password</label>
    <input type="password" name="Password" id="Password" />
  </p>
  <p align="center">
  <label for="RememberMe">Remember Me</label>
  <input name="RememberMe" type="checkbox" onclick="if (this.checked) (remember())" value="Remember Me" />
  </p>
  <p align="center">
    <input type="submit" name="Submit" id="Submit" value="Submit" />
  </p>
</form>
</div>
<div id="signupbox"><h1>Signup</h1>
<form action="<?php echo $editFormAction; ?>" method="post" enctype="multipart/form-data" name="form1" id="form1">
  <table align="center">
    <tr valign="baseline">
      <td nowrap="nowrap" align="right">Username:</td>
      <td><input type="text" name="username" value="" size="32" /></td>
    </tr>
    <tr valign="baseline">
      <td nowrap="nowrap" align="right">Password:</td>
      <td><input type="password" name="password" value="" size="32" /></td>
    </tr>
    <tr valign="baseline">
      <td nowrap="nowrap" align="right">First Name:</td>
      <td><input type="text" name="fname" value="" size="32" /></td>
    </tr>
    <tr valign="baseline">
      <td nowrap="nowrap" align="right">Surname:</td>
      <td><input type="text" name="sname" value="" size="32" /></td>
    </tr>
    <tr valign="baseline">
      <td nowrap="nowrap" align="right">Email:</td>
      <td><input type="text" name="email" value="" size="32" /></td>
    </tr>
    <tr valign="baseline">
    <?php
//define a maxim size for the uploaded images in Kb
define ("MAX_SIZE","100"); 

//This function reads the extension of the file. It is used to determine if the file  is an image by checking the extension.
function getExtension($str) {
         $i = strrpos($str,".");
         if (!$i) { return ""; }
         $l = strlen($str) - $i;
         $ext = substr($str,$i+1,$l);
         return $ext;
}

//This variable is used as a flag. The value is initialized with 0 (meaning no error  found)  
//and it will be changed to 1 if an errro occures.  
//If the error occures the file will not be uploaded.
$errors=0;
//checks if the form has been submitted
if(isset($_POST['Submit'])) {
 if($_POST['Submit'] == ""){
	 // submit empty
	 die ("you must include a picture");
 }
	//reads the name of the file the user submitted for uploading
	$image=$_FILES['image']['name'];
	//if it is not empty
	if ($image) 
	{
	//get the original name of the file from the clients machine
		$filename = stripslashes($_FILES['image']['name']);
	//get the extension of the file in a lower case format
  		$extension = getExtension($filename);
		$extension = strtolower($extension);
	//if it is not a known extension, we will suppose it is an error and will not  upload the file,  
//otherwise we will do more tests
if (($extension != "jpg") && ($extension != "jpeg") && ($extension != "png") && ($extension != "gif")) 
		{
	//print error message
			echo '<h1>Unknown extension!</h1>';
			$errors=1;
		}
		else
		{
//get the size of the image in bytes
//$_FILES['image']['tmp_name'] is the temporary filename of the file
//in which the uploaded file was stored on the server
$size=filesize($_FILES['image']['tmp_name']);

//compare the size with the maxim size we defined and print error if bigger
if ($size > MAX_SIZE*1024)
{
echo '<h1>You have exceeded the size limit!</h1>';
$errors=1;
}

//we will give an unique name, for example the time in unix time format
$image_name=time().'.'.$extension;
//the new name will be containing the full path where will be stored (images folder)
$newname="prof_pics/".$image_name;

//Writes the information to the database
mysql_query("UPDATE users SET prof_pic = '$image_name' WHERE username = '$username'");

//we verify if the image has been uploaded, and print error instead
$copied = copy($_FILES['image']['tmp_name'], $newname);
if (!$copied) 
{
echo '<h1>Copy unsuccessfull!</h1>';
$errors=1;
}}}}

?>
      <td nowrap="nowrap" align="right">Picture:</td>
      <td>
            <input type="file" name="image"></td>
    </tr>
    <tr valign="baseline">
      <td nowrap="nowrap" align="right"> </td>
      <td><input name="Submit" type="submit" id="Submit" value="Submit" /></td>
    </tr>
  </table>
  <input type="hidden" name="MM_insert" value="form1" />
</form>
</div>
</div>

</div>
<div id="textcontainer">
<div class="h1">Welcome to ...!</div>
<div class="h2"></div>
  </div>
</div>
</div>
</body>
</html>

 

None of the tutorials i followed mentioned SALT or MD5 or Validation or anything.

 

I know this is a big subject and a big ask, so thank you in advance!

Link to comment
Share on other sites

Security goes over and above form validation, although that it a major part of it.  SALT is more or less the defacto for encrypting input.  You really should use this.

Other suggestions that can/should be done are:

1)  Being clever with your queries - only select the information that you need, you should never ever need to actualy pull a password back out of your database.

2)  Being clever with your connections - if security is more important than performance you can have your database connections opend only when they are needed and closed when they are done.  You can also maintain a read only connection for the most part and have it switch to a read/write connection only for specific queries.

3)  Use an approprite database user regardless - Never open a page to the public that is running a connection with credentials for the root account or any other account that has full controll of the database.  Make a limited user for only the tables and permissions that your page needs to run.

4)  last on my list - though most deffinately not least do not send any form data to the database without proper 'sanitisation'.  learn mysql_real_escape_string() and search the forum here for other examples of how to properly check the input of any type of form field.

 

There's probably a lot more, but that's all I can think of off the top of my head.

Link to comment
Share on other sites

I've also got this little gem in my function library which I apply to ALL user inputs before they can interact with any part of my DB or scripts

 

function cleanInput($input){
	$input=htmlentities($input);
	$input=stripslashes($input);
	$input=strip_tags($input);
	$input=mysql_real_escape_string($input);
	return $input;
}

 

This is good to use unless you want your users to be able to apply html formatting to any input

Link to comment
Share on other sites

@Nodral, your cleanInput() function only protects against sql injected in string data (i.e. a value put into a query in between single-quotes.) As has been written many times before, mysql_real_escape_string does nothing to prevent sql injection in a numerical value because it is possible to use a hex value to inject sql, which mysql automatically converts to a string, that contains no quotes in it so there is nothing for mysql_real_escape_string to escape.

 

The GetSQLValueString() function that hoponhiggo does have in his code, provided it is being used correctly, does protect against sql injection in numerical data, because it casts numerical data as the correct numeric data type and strips out everything but the numerical value.

Link to comment
Share on other sites

Thanks for your responses. I have read through the suggested tutorial, and while it provides some great advice on security, it doesnt really help me implement any of them.

 

My main concern at the minute is for my users password and SQL injections.

 

Can anybody advise on how to apply a hash and SALT to my code, or point me in the direction of a good tutorial ( i did read a tutorial before, but there where a load of comments at the bottom saying it was flawed)

Link to comment
Share on other sites

To hash and salt,  take your password inputs, and prior to saving in the DB simply set it as

$salt="Any random gobbldy-gook";
$password=md5($salt(md5($password)));

 

This should stop anyone getting to your passwords.  Then when you call back from your DB table, don't SELECT * FROM Table

Just call it back by

 

$salt="same random gobbldy-gook as above";
$password=md5($salt(md5($password)));
$sql="SELECT id FROM table where username='$username' AND password='$password'";

 

Then refer to everything by user id.  This way you never actually pull your usernames and passwords out of  the DB, you are just referring to them for a comparrison to get records.

Link to comment
Share on other sites

based on the code in the original post, where you would you put the first:

 

$salt="Any random gobbldy-gook";
$password=md5($salt(md5($password)));

 

Wherever i try it, i get a fatal error: Fatal error: Call to undefined function Any random gobbldy-gook()

 

(ps. i do realise that i need to change "Any random gobbldy-gook"() to my own gobbldy-gook!)

Link to comment
Share on other sites

Sounds like you've missed your quotes off it.

 

$salt is a  string which you set which will add to your users password prior to hashing.

 

Post your code where you've added this.  Obviously you can change your salt once we've fixed it.

Link to comment
Share on other sites

i have edited my code (see below), but while i get no errors, the passwords are not being hashed. They are still being stored into my db as plain text. any ideas?

 

$editFormAction = $_SERVER['PHP_SELF'];
if (isset($_SERVER['QUERY_STRING'])) {
  $editFormAction .= "?" . htmlentities($_SERVER['QUERY_STRING']);
}


if(isset($_POST['username'])){
if($_POST['username'] == ""){
//username empty
die("You must enter a username");
}
} else {
//username not set
} 



if(isset($_POST['password'])){
if($_POST['password'] == ""){
//username empty
die("You must enter a password");
}
} else {
//password not set
} 


if ((isset($_POST["MM_insert"])) && ($_POST["MM_insert"] == "form1")) {
  $insertSQL = sprintf("INSERT INTO users (username, password, email, fname, sname) VALUES (%s, %s, %s, %s, %s)",
                       GetSQLValueString($_POST['username'], "text"),
                       GetSQLValueString($_POST['password'], "text"),
                       GetSQLValueString($_POST['email'], "text"),
                       GetSQLValueString($_POST['fname'], "text"),
                       GetSQLValueString($_POST['sname'], "text"));
				   
				   $salt="Any random gobbldy-gook";
					$password=md5( md5($password), $salt);

  mysql_select_db($database_pwnedbookv4, $pwnedbookv4);
  $Result1 = mysql_query($insertSQL, $pwnedbookv4) or die(mysql_error());

  $insertGoTo = "loginsignup.php";
  if (isset($_SERVER['QUERY_STRING'])) {
    $insertGoTo .= (strpos($insertGoTo, '?')) ? "&" : "?";
    $insertGoTo .= $_SERVER['QUERY_STRING'];
  }
  header(sprintf("Location: %s", $insertGoTo));
}

Link to comment
Share on other sites

That's becasue you're hasing it after you insert it.

 

Try

$editFormAction = $_SERVER['PHP_SELF'];
if (isset($_SERVER['QUERY_STRING'])) {
  $editFormAction .= "?" . htmlentities($_SERVER['QUERY_STRING']);
}


if(isset($_POST['username'])){
if($_POST['username'] == ""){
//username empty
die("You must enter a username");
}
} else {
//username not set
} 



if(isset($_POST['password'])){
if($_POST['password'] == ""){
//username empty
die("You must enter a password");
}
} else {
//password not set
} 

$salt="Any random gobbldy-gook";
$password=md5( md5($password), $salt);



if ((isset($_POST["MM_insert"])) && ($_POST["MM_insert"] == "form1")) {
  $insertSQL = sprintf("INSERT INTO users (username, password, email, fname, sname) VALUES (%s, %s, %s, %s, %s)",
                       GetSQLValueString($_POST['username'], "text"),
                       GetSQLValueString($password, "text"),
                       GetSQLValueString($_POST['email'], "text"),
                       GetSQLValueString($_POST['fname'], "text"),
                       GetSQLValueString($_POST['sname'], "text"));
				   
				     mysql_select_db($database_pwnedbookv4, $pwnedbookv4);
  $Result1 = mysql_query($insertSQL, $pwnedbookv4) or die(mysql_error());

  $insertGoTo = "loginsignup.php";
  if (isset($_SERVER['QUERY_STRING'])) {
    $insertGoTo .= (strpos($insertGoTo, '?')) ? "&" : "?";
    $insertGoTo .= $_SERVER['QUERY_STRING'];
  }
  header(sprintf("Location: %s", $insertGoTo));
}

Link to comment
Share on other sites

The code you have, isn't doing what you expect. The second parameter of the md5 function isn't a salt string. It is a bool flag that determines what format the value is returned as.

 

A 'salt' is a random string that you prepend and/or append to the actual password before you apply a hash function to it. Therefore, in php you would need to concatenate the salt string to the $_POST['password'] value.

Link to comment
Share on other sites

Set them to VARCHAR(255)

 

Done!

 

The code you have, isn't doing what you expect. The second parameter of the md5() function isn't a salt string. It is a bool flag that determines what format the value is returned as.

 

A 'salt' is a random string that you prepend and/or append to the actual password before you apply a hash function to it. Therefore, in php you would need to concatenate the salt string to the $_POST['password'] value.

 

I have no idea what this means!

 

Still cant get this to work

Link to comment
Share on other sites

change

 

$password=md5( md5($password), $salt);

 

to

$password=md5( md5($salt.$password));

 

This way you are appending the salt onto the password before double hashing it, rather than trying to use $salt as some sort of flag

Link to comment
Share on other sites

Tried the changes. still not working.

 

My current code is:

 

$editFormAction = $_SERVER['PHP_SELF'];
if (isset($_SERVER['QUERY_STRING'])) {
  $editFormAction .= "?" . htmlentities($_SERVER['QUERY_STRING']);
}


if(isset($_POST['username'])){
if($_POST['username'] == ""){
//username empty
die("You must enter a username");
}
} else {
//username not set
} 



if(isset($_POST['password'])){
if($_POST['password'] == ""){
//username empty
die("You must enter a password");
}
} else {
//password not set
} 

$salt="Any random gobbldy-gook";
$password=md5( md5($salt.$password));

if ((isset($_POST["MM_insert"])) && ($_POST["MM_insert"] == "form1")) {
  $insertSQL = sprintf("INSERT INTO users (username, password, email, fname, sname) VALUES (%s, %s, %s, %s, %s)",
                       GetSQLValueString($_POST['username'], "text"),
                       GetSQLValueString($_POST['password'], "text"),
                       GetSQLValueString($_POST['email'], "text"),
                       GetSQLValueString($_POST['fname'], "text"),
                       GetSQLValueString($_POST['sname'], "text"));
				   


  mysql_select_db($database_pwnedbookv4, $pwnedbookv4);
  $Result1 = mysql_query($insertSQL, $pwnedbookv4) or die(mysql_error());

  $insertGoTo = "loginsignup.php";
  if (isset($_SERVER['QUERY_STRING'])) {
    $insertGoTo .= (strpos($insertGoTo, '?')) ? "&" : "?";
    $insertGoTo .= $_SERVER['QUERY_STRING'];
  }
  header(sprintf("Location: %s", $insertGoTo));
}

Link to comment
Share on other sites

Refer to my previous post, you are still trying to insert $_POST['password'] into the database, rather than the hashed and salted variable, $password

 

Damn...Cant beleive i missed this...Rookie mistake

 

Thank you very much for your help. You have been very patient with me haha

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.