10 ways to get Hacked!

Cash Williams

Technical Consultant


Dallas Drupal Days 2012


This is a presentation of security mistakes.


I enjoy learning this way, and its fun to see what other people do wrong!

#1 Development User Accounts

Deploying development data to production during the initial deploy.

#2 Input Filters

Site allows untrusted users to create content with insecure html (or PHP!!) content.

We're allowing everyone to use <iframe> because it is now an expected feature.

#3 Login & Sessions

Not using https!

That was easy!

#4 View Access

Exposing sensitive data with Views.

#5 Displaying User Supplied Data

Where did the data come from?
print $user->bio;
$form['bio'] = array(
  '#type' => 'item',
  '#title' => t('Bio'),
  '#markup' => $user->bio,

#6 Hook_Menu Access Argument

Built to be a general AJAX autopopulate callback.

Developer set 'access arguments' = TRUE to ensure it would always be accessabile.

$items['gethacked/cache/get/%'] = array(
	'page callback' => 'gethacked_get_cache',
	'page arguments' => array(3),
	'access callback' => TRUE,
	'type' => MENU_CALLBACK,

#7 Exposing Sensitive Data

This function simply returns
the value of any cache ID.

function gethacked_get_cache($cache_id) {
  $cache_table = isset($_POST['cache_table']) ? $_POST['cache_table'] : 'cache';
  print cache_get($cache_id, $cache_table);

#8 Setting Data

Allowing data to be set via a request.

function gethacked_set_cache($cache_id) {
  $cache_table = isset($_POST['cache_table']) ? $_POST['cache_table'] : 'cache';
  $expire_type = isset($_POST['expiry']) ? $_POST['expiry'] : 'CACHE_PERMANENT';

  cache_set($cache_id, $_POST['cache_data'], $cache_table, $expire_type);
  print $_POST['cache_data'];

#9 Drupal Database API (& #6)

function gethacked_autocomplete($args, $string) {
    $matches = array();
    $sql = t("SELECT tid, name FROM {term_data} td WHERE td.name LIKE '$string%'");
    $res = db_query($sql);

    if ($res->num_rows > 0) {
        while ($row = db_fetch_array($res)) {
            $matches[$row['name']] = $row['name'];
        print drupal_json($matches);

#10 Custom Authentication

Insecurly communicating with external authorization system.

Relying on an insecure cookie.

## Q & A