Security - Things to look out for

 

#1 Rule: Never trust input from the user, or any data submitted from a form submission, even hidden input fields.

eg: 

  1. if expecting an integer from a form submission, don't assume the value is an integer when processing the form in PHP, even if it's a hidden field
  2. if a form calculates the total price for an order using javascript, recalculate the price on the server using PHP. i.e. don't accept the total price from a form submission

    eg, THIS IS BAD:

    <form method="post" action="process.php">
      <input type="hidden" name="totalPrice" value="10.00"/>
    </form>

    process.php:

    <?php
      $totalPrice = $GLOBALS["WT"]->getRequestValue("totalPrice");
    ?>

    INSTEAD:

    process.php

    <?php
      $totalPrice = calculateOrderTotalPrice();
    ?>


     
  3. it's better to save a value in a session variable rather than output it to a hidden field and then set a variable from the hidden field.

    eg, THIS IS BAD:

    <!-- pass the current user id through a form submission - bad -->
    <form method="post" action="process.php">
      <input type="hidden" name="userID" value="[wt:wt.currentuser.guid]"/>
    </form> 

    process.php:

    <?php
      // get the current user id from the form submission -- bad
      $userID = $GLOBALS["WT"]->getRequestValue("userID");
    ?>

    INSTEAD:

    process.php:

    <?php
      $currentUser = $GLOBALS["WT"]->getCurrentUser();
      $userID = $currentUser->m_guid;
    ?>

Summary of things to look out for:

1    Escape variables used in criteria/queries/sql statements    
2    Validate input from the user    
3    Check for the correct user before deleting/changing data    
4    Avoid absolute links using the webtemplate.com.au domain name    
5    Dont create JSON strings manually    
6    Use WebTemplate functions instead of $_POST and $_REQUEST    
7    If displaying inputted data back to the user, escape it first    

 

1    Escape variables used in criteria/queries/sql statements

1.1    Reason

If variables in queries aren’t escaped, it opens the site up to SQL injection attacks.
http://en.wikipedia.org/wiki/Sql_injection

1.2    In templates

Use |dbEscapeString  when using [wt:wt.request] in criteria

Example:

<wt:list type="Screen Sponsor" source="/Data/Screen Sponsors" criteria="`Screen Sponsor`.`__guid`='[wt:wt.request.guid|dbEscapeString]'">
</wt:list>

1.3    In PHP

Use $GLOBALS[“WT”]->dbEscape()

Example:

$q = Array();
$q["Node Type"] = "Screen Sponsor";
$q["Path"] = "/Data/Screen Sponsors/*"
$q["Criteria"] = "`Screen Sponsor`.__guid = '" . $GLOBALS["WT"]->dbEscape($guid) . "'";

2    Validate input from the user

If a script is expecting a numerical value from a user, check that it is a number

2.1    Reason

Validating input helps protect against SQL injection attacks

2.2    In templates

Use |verifyNumeric to check if a value is a number

Example:

<wt:if test="![wt:wt.request.guid|verifyNumeric]">
  Error: Number expected
  <?php exit() ?>
</wt:if>

2.3    In PHP

$guid = $GLOBALS["WT"]->getRequestValue("guid");
if(!is_numeric($guid)) {
  echo "Number expected";
  exit();
}

3    Check for the correct user before deleting/changing data

If a front end script accepts a guid and then deletes a node or sets its attributes without checking if the correct user is logged in, potentially anyone on the internet could try sending guids to the script to delete nodes in the database.

3.1    Reason

The public shouldn’t be able to delete/edit nodes by guessing URLs
http://en.wikipedia.org/wiki/Semantic_URL_attack

3.2    Example

THIS IS BAD

<?php
  // this script will potentially allow anyone on the internet to guess the url and delete values from the database
  $guid = $GLOBALS["WT"]->getRequestValue("guid");
  $node = $GLOBALS["WT"]->getNode($guid);
  $node->deleteNode():
?>

INSTEAD

<?php
  $guid = $GLOBALS["WT"]->getRequestValue("guid");

  // make sure the guid is a number
  if(!is_numeric($guid) || !$guid) {
    print "Invalid guid";
    exit();
  }
  $node = $GLOBALS[“WT”]->getNode($guid);

  // make sure a valid node was found
  //  replace {THE EXPECTED NODE TYPE} with the node type that is expected
  if(!$node || $node->getType() != "{THE EXPECTED NODE TYPE}") {
    print "invalid guid";
    exit();
  }
  // get the current user
  $currentUser = $GLOBALS[“WT”]->getCurrentUser();
  // make sure the user has permission to delete the node...in this case, only the creator can delete
  if($node->m_createdByGuid != $currentUser->m_guid) {
    print "you do not have permission";
    exit();
  }
  // correct user has permission to delete correct node
  $node->deleteNode();
?>

4    Avoid absolute links using the webtemplate.com.au domain name

Don’t use http://s2.webtemplate.com.au/bridgehead/{siteid} to link to files.
Instead use relative paths
or use [wt:wt.settings.Site Details.Site URL]

4.1    Reason

The site directory may change and also there should not be links to s2.webtemplate.com.au in the live site

4.2    In Templates

Example where an absolute URL is needed:

<input type="hidden" name="return" value="[wt:wt.settings.Site Details.Site URL]sponsor-purchase-thanks" />

5    Dont create JSON strings manually

Use the PHP function json_encode() instead.

5.1    Reason

Creating JSON strings manually may cause errors in a browser if the string hasn’t been created taking special characters into account.
For example, if $name has double quotes in it, echo ‘{ “name”: “‘ . $name . ‘“}’ will cause an error.

5.2    Example

Don’t do this

echo '{"name": "' . $name . '"}'

Instead:

Create an associative array and use json_encode():

$data = Array("name" => $name);
echo json_encode($data);

6    Use WebTemplate functions instead of $_POST and $_REQUEST

Use $GLOBALS["WT"]->getPostValue() and $GLOBALS["WT"]->getRequestValue() instead of $_POST and $_REQUEST

6.1    Reason

$GLOBALS["WT"]->getPostValue() and $GLOBALS["WT"]->getRequestValue() take into account magic quotes.

If you want or need to use $_POST or $_REQUEST, the code should test for magic quotes and strip slashes if magic quotes is enabled:

$value = $_POST["guid"];
if(get_magic_gpc()) {
  $value = stripslashes($value);
}

7    If displaying inputted data back to the user, escape it first

7.1    Reason

Users may enter values with HTML characters which may break the HTML in the page.
Or a malicious user may perform a Cross site scripting hack.
http://en.wikipedia.org/wiki/Cross-site_scripting

7.2    In templates

Use |htmlEntities to escape request data when displaying it back to a user.

Example:

You entered: [wt:wt.request.firstName|htmlEntities]

or in a form

<input name="firstName" value="[wt:wt.request.firstName|htmlEntities"/>