'. $msg.''); } else { die(); } } /** * Enter description here... * */ function wpids_admin_header() { (get_option("wpld-framebrk") == 1) ? wpld_framebreaker() : ''; wpld_window_name_protection(); wpids_css(); wpld_admin_ip_check(); } /** * Enter description here... * * @return unknown */ function wpld_admin_ip_check() { $ips = split(",", get_option("wpld-admin-ip")); if (count($ips) == 0) { return true; } if (strlen($ips[0]) == 0) { return true; } if (!eregi("\/wp\-admin\/", $_SERVER['PHP_SELF'])) { return true; } if (in_array($_SERVER['REMOTE_ADDR'], $ips, true)) { return true; } else { //TODO: activate it again but more user friendly //wpids_error('You are not allowed to use wp-admin from this computer.', 1); } } /** * When the Plugin is activated this function is called to create all needed Tablestructures and WP Values * */ function wpids_ctable() {//creates the Table Structure for the Storage of Bad Requests $wpdb =& $GLOBALS['wpdb']; $prefix = ereg_replace("[^-_[:alnum:]]", "", $GLOBALS['table_prefix']); $wpdb->query("CREATE TABLE IF NOT EXISTS `".$prefix."sec_intrusions` ( `id` int(11) unsigned NOT NULL auto_increment, `impact` int(11) unsigned NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 COMMENT='Stores PHPIDS logged Bad Requests'"); $wpdb->query("CREATE TABLE IF NOT EXISTS `".$prefix."sec_log` ( `id` INT (11) unsigned NOT NULL auto_increment, `ref_id` INT (11) unsigned NULL , `ip` VARCHAR( 40 ) NOT NULL , `page` TEXT NOT NULL, `tag` VARCHAR (40) NULL, `value` TEXT NOT NULL, `app` TINYINT( 4 ) unsigned NOT NULL , `type` VARCHAR( 40 ) NOT NULL , `date` DATETIME NOT NULL , `status` TINYINT( 4 ) unsigned NOT NULL, PRIMARY KEY (`id`) ) ENGINE = MYISAM DEFAULT CHARSET=utf8 COMMENT='Stores the LD Log'"); add_option("wpids-emailwhen", "50");//email is send on impact... add_option("wpids-emailto", "");//email is send to add_option("wpids-blockat", "60");//block request when it reached add_option("wpids-showlate", "25");//show the latest ... entries on mainpage add_option("wpids-keeptable", "1");//keep logtables after deactivation add_option("wpids-dolog", "1");//do logging add_option("wpids-filter", "xml");//filter format add_option("wpids-ignore", "25");//value to what nothing is done add_option("wpids-sanitize","25");//value up to what the impact is only sanitzed add_option("wpld-lockpage", "1");//lock some breakable pages add_option("wpld-framebrk", "1");//framebreaker add_option("wpld-blocktor", "1");//block Tor IPs add_option("wpld-admin-ip", "100");//admin IP, which isn't blocked add_option("wpld-xmlrpc", 1);//per default xmlrpc will be blocked/disabled } /** * Includes the CSS Code for the HTML of the Backend * */ function wpids_css() { include_once $pathto.'wpids-css.php';//adds the CSS code } /** * Is called when the Plugin gets deactivated, it will drop all previously created DB data * */ function wpids_dtable() { $wpdb =& $GLOBALS['wpdb']; $prefix = ereg_replace("[^-_[:alnum:]]", "", $GLOBALS['table_prefix']); if (get_option("wpids-keeptable") != 1) { $wpdb->query("DROP TABLE ".$prefix."sec_intrusions"); $wpdb->query("DROP TABLE ".$prefix."sec_log"); } delete_option("wpids-emailwhen"); delete_option("wpids-emailto"); delete_option("wpids-blockat"); delete_option("wpids-banfor"); delete_option("wpids-showlate"); delete_option("wpids-keeptable"); delete_option("wpids-dolog"); delete_option("wpids-filter"); delete_option("wpids-ignore"); delete_option("wpld-lockpage"); delete_option("wpld-framebrk"); delete_option("wpld-blocktor"); delete_option("wpld-xmlrpc"); } /** * Creates within the Admin Backend an Optiontab for the Plugin * */ function wpids_cpage() { add_submenu_page("plugins.php", "WPIDS", "WPIDS", 10, __FILE__, "wpids_page"); } /** * The main function of this Plugin, is called on Everypage view done to WP * */ function wpids_init() { $wpdb =& $GLOBALS['wpdb']; $pathto = ABSPATH. 'wp-content/plugins/wp-ids/'; /*include_once ($pathto."IDS/lockdown_filter.php"); if (isset($_SESSION['ban']) && $_SESSION['ban'] === 1) { sleep(rand(0, 5)); wpids_error(''); } if (in_array($_SERVER['REMOTE_ADDR'], $wpld_banned, true)) { $_SESSION['ban'] = 1; wpids_error(''); } if (get_option("wpld-blocktor") === 1 && in_array($_SERVER['REMOTE_ADDR'], $wp_lockdown_tor, true)) {//block tor user if you want it $_SESSION['ban'] = 1; wpids_error('Please disable TOR. You can not use it here.', 2); }*///reactivate Banning later again, but more userfriendly //let's check some Vars that they contain no bad values $_SERVER['PHP_SELF'] = wpld_filter('input', $_SERVER['PHP_SELF'], 'PHP_SELF'); $_SERVER['PHP_SELF'] = wpld_filter('get', $_SERVER['PHP_SELF'], 'PHP_SELF'); //properly testing of path that only these are excluded $sitepath = preg_replace("/http:\/\/(" . str_replace(".", "\.", $_SERVER['SERVER_NAME'])."|".str_replace(".", "\.", $_SERVER['SERVER_ADDR']).")/", "", get_option("siteurl")); if (!eregi("(^/wp\-admin/|^/wp\-includes/js/tinymce/)", str_replace($_SERVER['DOCUMENT_ROOT'].$sitepath, "", $_SERVER['SCRIPT_FILENAME']))) { //ony run these parts if we're not in the backend, tinymce is as well allowed to be used. $_SERVER['DOCUMENT_ROOT'] = wpld_filter('path', $_SERVER['DOCUMENT_ROOT'], 'DOCUMENT_ROOT'); $_SERVER['PATH_TRANSLATED'] = wpld_filter('path', $_SERVER['PATH_TRANSLATED'], 'PATH_TRANSLATED'); $_SERVER['HTTP_HOST'] = wpld_filter('input', $_SERVER['HTTP_HOST'], 'HTTP_HOST'); $_SERVER['REMOTE_ADDR'] = wpld_filter('ip', $_SERVER['REMOTE_ADDR'], 'REMOTE_ADDR'); $_SERVER['HTTP_X_FORWARDED_FOR'] = wpld_filter('ip', $_SERVER['HTTP_X_FORWARDED_FOR'], 'HTTP_X_FORWARDED_FOR'); $_SERVER['SERVER_ADDR'] = wpld_filter('ip', $_SERVER['SERVER_ADDR'], 'SERVER_ADDR'); $_SERVER['HTTP_REFERER'] = wpld_filter('input', $_SERVER['HTTP_REFERER'], 'HTTP_REFERER'); $_SERVER['HTTP_COOKIE'] = wpld_filter('input', $_SERVER['HTTP_COOKIE'], 'HTTP_COOKIE'); $_SERVER['SCRIPT_FILENAME'] = wpld_filter('input', $_SERVER['SCRIPT_FILENAME'], 'SCRIPT_FILENAME'); $_SERVER['QUERY_STRING'] = wpld_filter('input', $_SERVER['QUERY_STRING'], 'QUERY_STRING'); $_SERVER['QUERY_STRING'] = wpld_filter('get', $_SERVER['QUERY_STRING'], 'QUERY_STRING'); $_SERVER['QUERY_STRING'] = wpld_filter('sql', $_SERVER['QUERY_STRING'], 'QUERY_STRING'); $_SERVER['REQUEST_URI'] = wpld_filter('input', $_SERVER['REQUEST_URI'], 'REQUEST_URI'); $_SERVER['REQUEST_URI'] = wpld_filter('get', $_SERVER['REQUEST_URI'], 'REQUEST_URI'); $_SERVER['SCRIPT_NAME'] = wpld_filter('input', $_SERVER['SCRIPT_NAME'], 'SCRIPT_NAME'); $_SERVER['SCRIPT_NAME'] = wpld_filter('get', $_SERVER['SCRIPT_NAME'], 'SCRIPT_NAME'); //checking every User given Input /*foreach ($_GET as $name => $value) { $_GET[$name] = wpld_filter('get', $_GET[$name], $name); $_GET[$name] = wpld_filter('sql', $_GET[$name], $name); $_GET[$name] = wpld_filter('codecomment', $_GET[$name], $name); }*/ // WORDPRESS STUFF if (ereg_replace("[^a-zA-Z.]", "", basename($_SERVER['PHP_SELF'])) == 'xmlrpc.php' && get_option("wpld-xmlrpc") == 1) { wpids_error('You tried to attack the xmlrpc.php file!');//Disable the Access to XML-RPC, to minimize threat to it. } if (isset($_POST['page_options'])) { $_POST['page_options'] = wpld_filter('sql', $_POST['page_options'], 'page_options'); $_POST['page_options'] = wpld_filter('input', $_POST['page_options'], 'page_options'); $_POST['page_options'] = wpld_filter('get', $_POST['page_options'], 'page_options'); } if (isset($_GET['apage'])) { $_GET['apage'] = (int) $_GET['apage']; if ($_GET['apage'] < 0) { $_GET['apage'] = 0; } } if (isset($_POST['cat_id'])) { $_POST['cat_id'] = (int) $_POST['cat_id']; if ($_POST['cat_id'] < 0) { $_POST['cat_id'] = 0; } } if (isset($_GET['style'])) { $_GET['style'] = wpld_filter('input', $_GET['style'], 'style'); $_GET['style'] = wpld_filter('get', $_GET['style'], 'style'); } if (isset($_POST['style'])) { $_POST['style'] = wpld_filter('input', $_POST['style'], 'style'); $_POST['style'] = wpld_filter('get', $_POST['style'], 'style'); } if (isset($_REQUEST['style'])) { $_REQUEST['style'] = wpld_filter('input', $_REQUEST['style'], 'style'); $_REQUEST['style'] = wpld_filter('get', $_REQUEST['style'], 'style'); } if (isset($_REQUEST['action'])) { $_REQUEST['action'] = wpld_filter('get', $_REQUEST['action'], 'action'); } if (isset($_REQUEST['redirect_to'])) { if (!eregi("^(http://|/).*", $_REQUEST['redirect_to'])) { $wpld_found = 0; $whitelists = array('^wp-admin/.*', '^wp-login.*', '^categories.php.*', '^post.php.*', '^edit.php.*'); foreach ($whitelists as $whitelist) { if (!eregi($whitelist, $_REQUEST['redirect_to'])) { $wpld_found = 1; } } if (!$wpld_found) { $_REQUEST['redirect_to'] = get_option('siteurl'); } } if (eregi("^http://.*", $_REQUEST['redirect_to'])) { if (eregi("^http://".WPLD_DOMAIN.".*", $_REQUEST['redirect_to'])) { $_REQUEST['redirect_to'] = get_option('siteurl'); } } } if (isset($_REQUEST['njfontcolor'])) { $_REQUEST['njfontcolor'] = wpld_filter('get', $_REQUEST['njfontcolor'], 'njfontcolor'); } if (isset($_REQUEST['njuppercolor'])) { $_REQUEST['njuppercolor'] = wpld_filter('get', $_REQUEST['njuppercolor'] , 'njuppercolor'); } if (isset($_REQUEST['njlowercolor'])) { $_REQUEST['njlowercolor'] = wpld_filter('get', $_REQUEST['njlowercolor'] , 'njlowercolor'); } if (isset($_REQUEST['toggledisplay'])) { $_REQUEST['toggledisplay'] = wpld_filter('get', $_REQUEST['toggledisplay'] , 'toggledisplay'); } if (isset($_REQUEST['headerimage'])) { $_REQUEST['headerimage'] = wpld_filter('get', $_REQUEST['headerimage'], 'headerimage'); } if (isset($_REQUEST['fontcolor'])) { $_REQUEST['fontcolor'] = wpld_filter('get', $_REQUEST['fontcolor'], 'fontcolor'); } if (isset($_REQUEST['fontdisplay'])) { $_REQUEST['fontdisplay'] = wpld_filter('get', $_REQUEST['fontdisplay'], 'fontdisplay'); } if (isset($_REQUEST['saved'])) { $_REQUEST['saved'] = wpld_filter('get', $_REQUEST['saved'], 'saved'); } if (isset($_REQUEST['_wp_original_http_referer'])) { $_REQUEST['_wp_original_http_referer'] = wpld_filter('input', $_REQUEST['_wp_original_http_referer'], '_wp_original_http_referer'); } //end of WP stuff //$_SERVER['HTTP_USER_AGENT'] = wpld_filter('user-agent', $_SERVER['HTTP_USER_AGENT'], 'HTTP_USER_AGENT', $agents);currently disabled //end of lockdown checks if (function_exists('phpversion') && phpversion() >= '5.1.6') {//only run with PHPIDS if it's possible to use it $pre_include_path = set_include_path( get_include_path() . PATH_SEPARATOR . $pathto . PATH_SEPARATOR . $pathto . "htmlpurifier/"); //HTML Purifier added include_once("htmlpurifier/HTMLPurifier.php"); $purify = new HTMLPurifier(); $_GET['content'] = $purify->purify($_GET['content']);//validate Posts $_POST['content'] = $purify->purify($_POST['content']); $_GET['comment'] = $purify->purify($_GET['comment']);//validate Comments $_POST['comment'] = $purify->purify($_POST['comment']); $_POST['title'] = $purify->purify($_POST['title']);//Trackback validating $_POST['excerpt'] = $purify->purify($_POST['excerpt']); $_POST['blog_name'] = $purify->purify($_POST['blog_name']); //loading all needed files to proceed checks require_once $pathto.'IDS/Init.php'; $request = array($_GET, $_POST, $_REQUEST, $_SERVER['REQUEST_URI'], $_SERVER['HTTP_REFERER'], $_COOKIE);//adds all user given Params for checking $init = IDS_Init::init(dirname(__FILE__). '/IDS/Config/Config.ini'); $init->config['General']['tmp_path'] = dirname(__FILE__) . '/IDS/tmp'; $init->config['Caching']['caching'] = 'none'; $init->config['Caching']['path'] = dirname(__FILE__) . '/IDS/tmp'; $init->config['General']['filter_type'] = (get_option('wpids-filter') == 'xml')? 'xml': 'json'; $init->config['General']['filter_path'] = (get_option('wpids-filter') == 'xml')? dirname(__FILE__) . '/IDS/default_filter.xml': dirname(__FILE__). '/IDS/default_filter.json'; //starting phpids and fetch results $ids = new IDS_Monitor($request, $init); $result = $ids->run(); if (!$result->isEmpty()) { foreach ($result as $event) {//loggin every bad Request to the database and sanitize as well the Bad Request Input //$value, $type, $tag, $status=0, $app=0, &$IDS = 0 $IDS['impact'] = $event->getImpact(); if ($result->getImpact() > get_option("wpids-ignore")) { if (get_option("wpids-sanitize") <= $result->getImpact() && get_option("wpids-ignore") > $result->getImpact()) { //sanitize bad Usergiven Inputs $attackedparam = substr($event->getName(), 2); wpids_log ($event->getValue(), substr($event->getName(), 0, 1),substr($event->getName(), 2), 1, 1, $IDS); switch (substr($event->getName(), 1, 0)) { case 0: $_GET[$attackedparam] = wpld_filter('get', $_SERVER[$attackedparam], $attackedparam); break; case 1: $_POST[$attackedparam] = wpld_filter('post', $_POST[$attackedparam], $attackedparam); break; case 2: $_REQUEST[$attackedparam] = wpld_filter('post', $_REQUEST[$attackedparam], $attackedparam); break; case 3: $_SERVER['REQUEST_URI'] = wpld_filter('input', $_SERVER['REQUEST_URI'], 'REQUEST_URI'); $_SERVER['REQUEST_URI'] = wpld_filter('get', $_SERVER['REQUEST_URI'], 'REQUEST_URI'); break; case 4: $_SERVER['HTTP_REFERER'] = wpld_filter('input', $_SERVER['HTTP_REFERER'], 'HTTP_REFERER'); break; case 5: $_COOKIE[$attackedparam] = wpld_filter('post', $_COOKIE[$attackedparam], $attackedparam); break; } } else {//remove bad Usergiven Inputs $attackedparam = substr($event->getName(), 2); wpids_log ($event->getValue(), substr($event->getName(), 0, 1),substr($event->getName(), 2), 0, 1, $IDS); switch (substr($event->getName(), 1, 0)) { case 0: unset ($_GET[$attackedparam]); break; case 1: unset ($_POST[$attackedparam]); break; case 2: unset ($_REQUEST[$attackedparam]); break; case 3: $_SERVER['REQUEST_URI'] = ''; break; case 4: $_SERVER['HTTP_REFERER'] = 'Bad Referer Removed'; break; case 5: unset ($_COOKIE[$attackedparam]); break; } } } else {//we only noticed something which maybe an intrusion try wpids_log ($event->getValue(), substr($event->getName(), 0, 1),substr($event->getName(), 2), 2, 1, $IDS); } if ($result->getImpact() >= get_option("wpids-emailwhen") && get_option("wpids-emailto") <> '') {//email the User when the Impact is equal or bigger than his value include_once $pathto.'IDS/Log/Email.php'; include_once $pathto.'IDS/Log/Composite.php'; $compositeLog = new IDS_Log_Composite(); $compositeLog->addLogger(IDS_Log_Email::getInstance(get_option("wpids-emailto"), 'WP PHPIDS - attack detected')); $compositeLog->execute($result); } if ($result->getImpact() >= get_option("wpids-blockat")) { var_dump($_REQUEST); wpids_error('You tried to run some Request/Code, which seems to aim to damage this Website, therefore the Request was blocked!
If you didn\'t run any Attack please notice the Webmaster about your Blocking.'); } } }//endif impact detected }//end if phpversion }//backend only checking } /** * Includes the Admin page, as the Code is moved outside * */ function wpids_page() { include_once 'ids-admin.php';//loading the ids-admin page, everything is put external to make the core file smaller, and give it a better overview } /** * Is called when some Page was requested, which is blocked by Lockdown * */ function wpld_disabled() { wpids_error('This option has been disabled by the security filter.'); } /** * Enter description here... * */ function wpld_head() { wpld_window_name_protection(); } /** * Sanitizes * * @param string $content HTML code which needs to be sanitized * @return string Sanitized HTML code */ function wpld_filter_html($content) { $content = str_replace("<", "<", $content); $content = str_replace(">", ">", $content); return $content; } /** * Prevents that any Frame is displayed, through redirecting Code in JS * */ function wpld_framebreaker() { ?> window.name=false;',"\n"; } /** * Checks a given Value if it contains bad Code, if so it will sanitize it; If $type is SQL and some changes where made * the script dies * * @param string $type contains any of the Switch available Values, if wrong Value inputed You'll get an Notice about it * @param string $item Contains the Value which is checked for bad Input * @param string $name the Name of the Variable which is checked * @param string_array $badAgents Optional; only needed if $type is user-agent; REGEX expression of Bad User-Agents * @return string Sanitized $item */ function wpld_filter($type, $item, $name, $badAgents ='') { $original = $item; switch($type) { default: echo 'WP Lockdown filter failed. Please check the code.'; exit(); break; case "sql": $item = eregi_replace("(;|'|\"|%22|%27).*(union|select|insert|drop|update|md5|benchmark|or|and|if).*", "", $item); $item = eregi_replace("UNION.ALL.SELECT", "", $item); $item = eregi_replace("FROM.wp_users.WHERE", "", $item); break; case "codecomment": $item = str_replace("/*","", $item); $item = str_replace("*/","", $item); $item = str_replace("%2F*","", $item); $item = str_replace("*%2F","", $item); $item = str_replace("%2f*","", $item); $item = str_replace("*%2f","", $item); break; case "user-agent": foreach($badAgents as $badAgent) { if(eregi($badAgent, $item)) { $_SESSION['ban'] = 1; wp_lockdown_log($item, $type); die(); } } break; case "path": $whitelist = ".[:alnum:][:space:]/_-"; $item = ereg_replace("[^$whitelist]", "", $item); $item = ereg_replace("(\.\.+)", "", $item); $item = ereg_replace("(\\\\+)", "", $item); break; case "ip": $whitelist = "[:digit:]."; $item = ereg_replace("[^$whitelist]", "", $item); break; case "url": $whitelist = "+%&[:alnum:][:space:]/_?:=.-"; $item = ereg_replace("[^".$whitelist."]", "", $item); if(substr($item, 0, 7) != 'http://') { $item = ''; } $item = ereg_replace("(&|%26|&?)(#|%23)", "", $item); break; case "input": $item = ereg_replace("[<>']", "", $item); $item = eregi_replace("(%3C|%3E|%22)", "", $item); $item = ereg_replace("(&|%26|&?)(#|%23)", "", $item); break; case "get": $whitelist = "\+#.%[:alnum:][:space:]/_?&=-"; $item = ereg_replace("[^".$whitelist."]", "", $item); $item = ereg_replace("(&|%26|&?)(#|%23)", "", $item); break; case "encoded": $item = ereg_replace("(&|%26|&?)(#|%23)", "", $item); break; } if($original != $item && strlen($original) > 0) { if($type == "sql") { wpids_log($item, $type, $name); wpids_error(''); } wpids_log($item, $type, $name, 1); } return $item; } /** * Loggin function, can be called without the need off any block, e.g. for Verbose Loggin * * * @param string $value Value which caused the loggin(bad input) * @param unknown_type $type * @param string $tag * @param int $status Accepted Values 0/1/2/3; these stand for Blocked, Sanitized, Noticed, Verbose * @param int $app Accepted Values 0/1; stand for Lockdown, PHPIDS which app caused the loggin * @param array_structure $IDS holds some needed Informations if $app = 1, as we need additional Informations */ function wpids_log($value, $type, $tag, $status = 0, $app = 0, &$IDS = 0) { if (get_option("wpids-dolog") == 1) { $wpdb =& $GLOBALS['wpdb']; $remote_addr = ($_SERVER['HTTP_X_FORWARDED_FOR'])? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR']; $prefix = ereg_replace("[^-_[:alnum:]]", "", $GLOBALS['table_prefix']); $page = ereg_replace("[^+%&[:alnum:][:space:]/_?:=.-]", "", $_SERVER['PHP_SELF']); $value = str_replace('\'', ''', htmlentities(stripslashes($value),ENT_QUOTES)); if ($app === 0) { $wpdb->query ("INSERT INTO `".$prefix."sec_log` (`id`, `ref_id`, `ip`, `page`, `tag`, `value`, `app`,`type`,`date`,`status`) VALUES (0, 0, '".$remote_addr."', '".$page."', '".$tag."', '".$value."', ".$app.", '".$type."', '".date('c')."', ".$status.")"); } else { $wpdb->query ("INSERT INTO `".$prefix."sec_intrusions` (`id`, `impact`) VALUES (0,".$IDS['impact'].")"); $intr_cnt = $wpdb->get_var ("SELECT `id` FROM `".$prefix."sec_intrusions` ORDER BY `id` DESC LIMIT 1"); $wpdb->query ("INSERT INTO `".$prefix."sec_log` (`id`, `ref_id`, `ip`, `page`, `tag`, `value`, `app`,`type`,`date`,`status`) VALUES (0, ".$intr_cnt.", '".$remote_addr."', '".$page."', '".$tag."', '".$value."', ".$app.", '".$type."', '".date('c')."', ".$status.")"); } } }