[support] Spammers filling sessions table

Jeremy Andrews lists at kerneltrap.org
Wed Mar 29 16:18:16 UTC 2006


On Wed, 29 Mar 2006 21:36:22 +0800
"Grant Malcolm" <grant.malcolm at gmail.com> wrote:

> Hi folks
> 
> Anyone have a solution for this one? Drupal 4.6.5
> 
> My site is getting hammered by spammers and I'm struggling
> to keep it going - particularly on a shared server.
> 
> As near as I can tell a regular anonymous visitor generates
> a single row in the sessions table.

I was suffering from massive spam comment attacks on
KernelTrap.org which were choking the database.  I finally
solved this by introducing form tokens on comments.  I've
created a patch for Drupal 4.6.6, attached (untested).

Cheers,
 -Jeremy



> 
> I've been regularly deleting sessions where uid=0 but
> referrer and comment spammers are choking my sessions table
> with anonymous sessions. In an eight hour period I suddenly
> gained 14,700 rows in sessions table. In a half hour period
> towards the end of this before the db choked with too many
> connections, I had 500+ attempts to post comment spam.
> 
> Bad behaviour and spam are blocking almost all of the
> comment spam from publication, but the site is choking in
> the meantime.
> 
> I've tried session_limit module, but the spammers are
> spoofing random ips and ignoring the sessions, so it
> doesn't seem to have any effect.
> 
> Any suggestions welcomed.
> 
> Cheers
> Grant
> 
> --
> *
> http://www.theatre.asn.au/
> Connect with your local theatre online
-------------- next part --------------
--- includes/common.inc.orig	2006-03-13 17:14:49.000000000 -0500
+++ includes/common.inc	2006-03-17 14:55:38.000000000 -0500
@@ -943,6 +943,53 @@
 }
 
 /**
+ * Set a hidden 'form_token' field to be included in a form, used to validate
+ * that the resulting submission was actually generated by a local form. 
+ *
+ * @param $key
+ *   A unique key to identify the form that is currently being displayed.
+ *   This identical key is later used to validate that the resulting submission
+ *   actually originated with this form.
+ * @result
+ *   A themed HTML string representing the hidden token field.
+ */
+function form_token($key) {
+  // this private key should always be kept secret
+  if (!variable_get('drupal_private_key', '')) {
+    variable_set('drupal_private_key', mt_rand());
+  }
+
+  // the verification token is an md5 hash of the form key and our private key
+  return form_hidden('form_token', md5(session_id() . $key . variable_get('drupal_private_key', '')));
+}
+
+/**
+ * Verify that the hidden 'form_token' field was actually generated with our
+ * private key.
+ *
+ * @param $edit
+ *  An array containing the form that needs to be validated.
+ * @param $key
+ *  The same key that was used to generate the 'form_token'.
+ * @param $error_message
+ *  An optional error message to display if the form does not validate.
+ * @result
+ *  There is nothing returned from this function, but if the 'form_token' does
+ *  not validate an error is generated, preventing the submission.
+ */
+function form_validate($edit, $key, $error_message = NULL) {
+  if ($error_message == NULL) {
+    // set a generic default error message
+    $error = t('Validation error, please try again.  If this error persists, please contact the site administrator.');
+  }
+
+  if ($edit['form_token'] != md5(session_id() . $key . variable_get('drupal_private_key', ''))) {
+    // setting this error will cause the form to fail validation
+    form_set_error('form_token', $error);
+  }
+}
+
+/**
  * File an error against the form element with the specified name.
  */
 function form_set_error($name, $message) {
--- modules/comment.module.orig	2006-03-13 17:14:49.000000000 -0500
+++ modules/comment.module	2006-03-17 14:52:45.000000000 -0500
@@ -481,6 +481,8 @@
       }
     }
   }
+  // verify that this submission was actually generated using a local form
+  form_validate($edit, 'comment'. $edit['nid'] . $edit['pid']);
 
   return $edit;
 }
@@ -1415,6 +1417,8 @@
   $form .= form_hidden('cid', $edit['cid']);
   $form .= form_hidden('pid', $edit['pid']);
   $form .= form_hidden('nid', $edit['nid']);
+  // generate a token used to validate that submissions came from this form 
+  $form .= form_token('comment'. $edit['nid'] . $edit['pid']);
 
   $form .= form_submit(t('Preview comment'));
 


More information about the support mailing list