Database.php 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. <?php
  2. /**
  3. * PHPIDS
  4. *
  5. * Requirements: PHP5, SimpleXML
  6. *
  7. * Copyright (c) 2008 PHPIDS group (http://php-ids.org)
  8. *
  9. * PHPIDS is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU Lesser General Public License as published by
  11. * the Free Software Foundation, version 3 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * PHPIDS is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public License
  20. * along with PHPIDS. If not, see <http://www.gnu.org/licenses/>.
  21. *
  22. * PHP version 5.1.6+
  23. *
  24. * @category Security
  25. * @package PHPIDS
  26. * @author Mario Heiderich <mario.heiderich@gmail.com>
  27. * @author Christian Matthies <ch0012@gmail.com>
  28. * @author Lars Strojny <lars@strojny.net>
  29. * @license http://www.gnu.org/licenses/lgpl.html LGPL
  30. * @link http://php-ids.org/
  31. */
  32. require_once 'IDS/Log/Interface.php';
  33. /*
  34. * Needed SQL:
  35. *
  36. CREATE DATABASE IF NOT EXISTS `phpids` DEFAULT CHARACTER
  37. SET utf8 COLLATE utf8_general_ci;
  38. DROP TABLE IF EXISTS `intrusions`;
  39. CREATE TABLE IF NOT EXISTS `intrusions` (
  40. `id` int(11) unsigned NOT null auto_increment,
  41. `name` varchar(128) NOT null,
  42. `value` text NOT null,
  43. `page` varchar(255) NOT null,
  44. `tags` varchar(128) NOT null,
  45. `ip` varchar(15) NOT null,
  46. `impact` int(11) unsigned NOT null,
  47. `origin` varchar(15) NOT null,
  48. `created` datetime NOT null,
  49. PRIMARY KEY (`id`)
  50. ) ENGINE=MyISAM ;
  51. *
  52. *
  53. *
  54. */
  55. /**
  56. * Database logging wrapper
  57. *
  58. * The database wrapper is designed to store reports into an sql database. It
  59. * implements the singleton pattern and is based in PDO, supporting
  60. * different database types.
  61. *
  62. * @category Security
  63. * @package PHPIDS
  64. * @author Christian Matthies <ch0012@gmail.com>
  65. * @author Mario Heiderich <mario.heiderich@gmail.com>
  66. * @author Lars Strojny <lars@strojny.net>
  67. * @copyright 2007-2009 The PHPIDS Group
  68. * @license http://www.gnu.org/licenses/lgpl.html LGPL
  69. * @version Release: $Id:Database.php 517 2007-09-15 15:04:13Z mario $
  70. * @link http://php-ids.org/
  71. */
  72. class IDS_Log_Database implements IDS_Log_Interface
  73. {
  74. /**
  75. * Database wrapper
  76. *
  77. * @var string
  78. */
  79. private $wrapper = null;
  80. /**
  81. * Database user
  82. *
  83. * @var string
  84. */
  85. private $user = null;
  86. /**
  87. * Database password
  88. *
  89. * @var string
  90. */
  91. private $password = null;
  92. /**
  93. * Database table
  94. *
  95. * @var string
  96. */
  97. private $table = null;
  98. /**
  99. * Database handle
  100. *
  101. * @var object PDO instance
  102. */
  103. private $handle = null;
  104. /**
  105. * Prepared SQL statement
  106. *
  107. * @var string
  108. */
  109. private $statement = null;
  110. /**
  111. * Holds current remote address
  112. *
  113. * @var string
  114. */
  115. private $ip = 'local/unknown';
  116. /**
  117. * Instance container
  118. *
  119. * Due to the singleton pattern this class allows to initiate only one instance
  120. * for each database wrapper.
  121. *
  122. * @var array
  123. */
  124. private static $instances = array();
  125. /**
  126. * Constructor
  127. *
  128. * Prepares the SQL statement
  129. *
  130. * @param mixed $config IDS_Init instance | array
  131. *
  132. * @return void
  133. * @throws PDOException if a db error occurred
  134. */
  135. protected function __construct($config)
  136. {
  137. if ($config instanceof IDS_Init) {
  138. $this->wrapper = $config->config['Logging']['wrapper'];
  139. $this->user = $config->config['Logging']['user'];
  140. $this->password = $config->config['Logging']['password'];
  141. $this->table = $config->config['Logging']['table'];
  142. } elseif (is_array($config)) {
  143. $this->wrapper = $config['wrapper'];
  144. $this->user = $config['user'];
  145. $this->password = $config['password'];
  146. $this->table = $config['table'];
  147. }
  148. // determine correct IP address
  149. if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
  150. $this->ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
  151. } else {
  152. $this->ip = $_SERVER['REMOTE_ADDR'];
  153. }
  154. try {
  155. $this->handle = new PDO(
  156. $this->wrapper,
  157. $this->user,
  158. $this->password
  159. );
  160. $this->statement = $this->handle->prepare('
  161. INSERT INTO ' . $this->table . ' (
  162. name,
  163. value,
  164. page,
  165. tags,
  166. ip,
  167. impact,
  168. origin,
  169. created
  170. )
  171. VALUES (
  172. :name,
  173. :value,
  174. :page,
  175. :tags,
  176. :ip,
  177. :impact,
  178. :origin,
  179. now()
  180. )
  181. ');
  182. } catch (PDOException $e) {
  183. throw new PDOException('PDOException: ' . $e->getMessage());
  184. }
  185. }
  186. /**
  187. * Returns an instance of this class
  188. *
  189. * This method allows the passed argument to be either an instance of IDS_Init or
  190. * an array.
  191. *
  192. * @param mixed $config IDS_Init | array
  193. * @param string $classname the class name to use
  194. *
  195. * @return object $this
  196. */
  197. public static function getInstance($config, $classname = 'IDS_Log_Database')
  198. {
  199. if ($config instanceof IDS_Init) {
  200. $wrapper = $config->config['Logging']['wrapper'];
  201. } elseif (is_array($config)) {
  202. $wrapper = $config['wrapper'];
  203. }
  204. if (!isset(self::$instances[$wrapper])) {
  205. self::$instances[$wrapper] = new $classname($config);
  206. }
  207. return self::$instances[$wrapper];
  208. }
  209. /**
  210. * Permitting to clone this object
  211. *
  212. * For the sake of correctness of a singleton pattern, this is necessary
  213. *
  214. * @return void
  215. */
  216. private function __clone()
  217. {
  218. }
  219. /**
  220. * Stores given data into the database
  221. *
  222. * @param object $data IDS_Report instance
  223. *
  224. * @throws Exception if db error occurred
  225. * @return boolean
  226. */
  227. public function execute(IDS_Report $data)
  228. {
  229. if (!isset($_SERVER['REQUEST_URI'])) {
  230. $_SERVER['REQUEST_URI'] = substr($_SERVER['PHP_SELF'], 1);
  231. if (isset($_SERVER['QUERY_STRING']) && $_SERVER['QUERY_STRING']) {
  232. $_SERVER['REQUEST_URI'] .= '?' . $_SERVER['QUERY_STRING'];
  233. }
  234. }
  235. foreach ($data as $event) {
  236. $page = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
  237. $ip = $this->ip;
  238. $name = $event->getName();
  239. $value = $event->getValue();
  240. $impact = $event->getImpact();
  241. $tags = implode(', ', $event->getTags());
  242. $this->statement->bindParam('name', $name);
  243. $this->statement->bindParam('value', $value);
  244. $this->statement->bindParam('page', $page);
  245. $this->statement->bindParam('tags', $tags);
  246. $this->statement->bindParam('ip', $ip);
  247. $this->statement->bindParam('impact', $impact);
  248. $this->statement->bindParam('origin', $_SERVER['SERVER_ADDR']);
  249. if (!$this->statement->execute()) {
  250. $info = $this->statement->errorInfo();
  251. throw new Exception(
  252. $this->statement->errorCode() . ', ' . $info[1] . ', ' . $info[2]
  253. );
  254. }
  255. }
  256. return true;
  257. }
  258. }
  259. /**
  260. * Local variables:
  261. * tab-width: 4
  262. * c-basic-offset: 4
  263. * End:
  264. * vim600: sw=4 ts=4 expandtab
  265. */