INSERTions into ses table for unknown users [message #168060] |
Tue, 08 January 2013 17:00 |
|
San ???????
Messages: 4 Registered: January 2013
Karma: 0
|
Junior Member |
|
|
Some time ago I discovered high load on my site server system caused by MySQL instance (about 50% of CPU time). I checked httpd load and found nothing serious (about 0.2 req/sec). Then I enabled query logging in MySQL and got lot of following lines:
...
1 Query INSERT INTO 2frmdb_ses (ses_id, time_sec, sys_id, user_id) VALUES ('da44744b0744e7182e2d8e21bb2b4063', 1357649603, '', 2001593538)
1 Query INSERT INTO 2frmdb_ses (ses_id, time_sec, sys_id, user_id) VALUES ('517bf2b9b646c2e48dbc28f996941b15', 1357649603, '', 2053834729)
1 Query INSERT INTO 2frmdb_ses (ses_id, time_sec, sys_id, user_id) VALUES ('ecb78d35baa48deec43abf7d649ea7eb', 1357649603, '', 2055756004)
...
I checked users table against that IDs (user_id above) and found nothing - users table has no such IDs at all.
Is it normal? If no then how is that possible and what should I do to stop that?
Forum version 3.0.1, php version 5.3.17, MySQL version 5.0.84, server OS - Slackware Linux 13.0.
|
|
|
|
|
Re: INSERTions into ses table for unknown users [message #168063 is a reply to message #168062] |
Wed, 09 January 2013 01:33 |
|
San ???????
Messages: 4 Registered: January 2013
Karma: 0
|
Junior Member |
|
|
It seems like I found a cause of the problem. There is session checking in index.php on every request and if client has no session cookie it created (for anonymous users too, in ses_anon_make()). The last could be used for DoS attack if client ignores forum cookie - that is why I'm having a lot of new lines in ses table for non-existing accounts. The code (from ses_anon_make()) gives me no chance in this case:
do {
$uid = 2000000000 + mt_rand(1, 147483647);
$ses_id = md5($uid . __request_timestamp__ . getmypid());
} while (!($id = db_li("INSERT INTO 2frmdb_ses (ses_id, time_sec, sys_id, user_id) VALUES ('".$ses_id."', ".__request_timestamp__.", '".ses_make_sysid(). "', ".$uid.')', $ef, 1)));
Cyclic INSERTions to DB to get ID just brilliant. For crackers, of course... For example, my forum has about 6000 registered accounts and only few of them are really active, but my sesssion table file (MyISAM) takes about 2 GBytes on disk now and grows quickly.
|
|
|
Re: INSERTions into ses table for unknown users [message #168064 is a reply to message #168063] |
Wed, 09 January 2013 02:14 |
|
San ???????
Messages: 4 Registered: January 2013
Karma: 0
|
Junior Member |
|
|
I applied following quick&dirty hack to prevent my site from that kind of attacks:
306c306
< do {
---
> /* do { */
307a308
> $id = $uid;
309c310
< } while (!($id = db_li("INSERT INTO 2frmdb_ses (ses_id, time_sec, sys_id, user_id) VALUES ('".$ses_id."', ".__request_timestamp__.", '".ses_make_sysid()."', ".$uid.')', $ef, 1)));
---
> /* } while (!($id = db_li("INSERT INTO 2frmdb_ses (ses_id, time_sec, sys_id, user_id) VALUES ('".$ses_id."', ".__request_timestamp__.", '".ses_make_sysid()."', ".$uid.')', $ef, 1))); */
The problem is that ses_anon_make() declared in more than one place. Strange code organization, yes...
|
|
|
Re: INSERTions into ses table for unknown users [message #168074 is a reply to message #168064] |
Tue, 15 January 2013 15:00 |
NeXuS
Messages: 121 Registered: July 2010 Location: South Korea
Karma: 5
|
Senior Member Contributing Core Developer |
|
|
The code is in desperate need of a good refactoring and that is why FUDf 4 will not be released in the near future.
Regarding the the sess_anon_make() function, it is declared in only one template file (cookies.inc.t). Which are the multiple declarations you found?
I'll have a look at the code and see if there is a way to make the function behave better, other than just commenting the offending part.
|
|
|
Re: INSERTions into ses table for unknown users [message #168075 is a reply to message #168074] |
Tue, 15 January 2013 15:26 |
NeXuS
Messages: 121 Registered: July 2010 Location: South Korea
Karma: 5
|
Senior Member Contributing Core Developer |
|
|
Ok, two things:
1. The version you are running is outdated. The latest released version has a different session table, so the sessions also track the user's IP and user agent.
2. I am starting to think that the best way to prevent this kind of attack would be to configure your firewall correctly and limit the maximum rate of connections allowed from a single IP address (or even do temporary or permanent IP bans). I am saying this because the sysid is the same for all your logs. You should update FUDf, track down the IP and block it.
On a sidenote, the function definitely needs reworking to avoid doing an INSERT even if the key parameters are the same (e.g. IP, useragent and sysid). I will work on a patch.
[Updated on: Tue, 15 January 2013 15:27] Report message to a moderator
|
|
|
Re: INSERTions into ses table for unknown users [message #168076 is a reply to message #168075] |
Tue, 15 January 2013 17:19 |
NeXuS
Messages: 121 Registered: July 2010 Location: South Korea
Karma: 5
|
Senior Member Contributing Core Developer |
|
|
The problem you reported actually stems from an early return in a different function, i.e. ses_get() in the same cookies.inc.t template file.
I have patched the function and committed the change to the code repository. Given that it may represent a significant performance issue and possibly lead to a DoS attack, I suppose it will be released in a later minor update.
For the time being I am leaving the unified diff with respect to FUDf 3.0.4.1 here below.
--- cookies.inc.t-rev5581.svn000.tmp.t 수 4 18 22:31:18 2012
+++ cookies.inc.t 수 1 16 02:06:23 2013
@@ -2,7 +2,7 @@
/**
* copyright : (C) 2001-2012 Advanced Internet Designs Inc.
* email : forum(at)prohost(dot)org
-* $Id: cookies.inc.t 5450 2012-04-18 13:31:18Z naudefj $
+* $Id: cookies.inc.t 5582 2013-01-15 17:06:15Z theonlynexus $
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -34,13 +34,16 @@
if (!$id) {
/* Cookie or URL session? If not, check for known bots. */
if (!empty($_COOKIE[$GLOBALS['COOKIE_NAME']])) {
+ /* Have cookie */
$q_opt = 's.ses_id='. _esc($_COOKIE[$GLOBALS['COOKIE_NAME']]);
} else if ((isset($_GET['S']) || isset($_POST['S'])) && $GLOBALS['FUD_OPT_1'] & 128) {
+ /* Have session string */
$url_session = 1;
$q_opt = 's.ses_id='. _esc((isset($_GET['S']) ? (string) $_GET['S'] : (string) $_POST['S']));
/* Do not validate against expired URL sessions. */
$q_opt .= ' AND s.time_sec > '. (__request_timestamp__ - $GLOBALS['SESSION_TIMEOUT']);
} else {
+ /* Unknown user, maybe bot? */
// Auto login authorized bots.
// To test: wget --user-agent="Googlebot 1.2" http://127.0.0.1:8080/forum
$spider_session = 0;
@@ -76,7 +79,14 @@
}
$GLOBALS['FUD_OPT_1'] ^= 128; // Disable URL sessions for user.
} else {
- return;
+ /* NeXuS: What is this? Return if user unknown? Function should
+ return only after the query is run. */
+ //return;
+
+ // Check sys_id, ip_addr and useragent for a possible match
+ $q_opt = 's.sys_id= '._esc(ses_make_sysid()).
+ ' AND s.ip_addr='._esc(get_ip()).
+ ' AND s.useragent='._esc(substr($_SERVER['HTTP_USER_AGENT'], 0, 32));
}
}
|
|
|