Database.php 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. <?php
  2. /**
  3. * PHPIDS
  4. *
  5. * Requirements: PHP5, SimpleXML
  6. *
  7. * Copyright (c) 2008 PHPIDS group (https://phpids.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. `ip2` varchar(15) NOT null,
  47. `impact` int(11) unsigned NOT null,
  48. `origin` varchar(15) NOT null,
  49. `created` datetime NOT null,
  50. PRIMARY KEY (`id`)
  51. ) ENGINE=MyISAM ;
  52. *
  53. *
  54. *
  55. */
  56. /**
  57. * Database logging wrapper
  58. *
  59. * The database wrapper is designed to store reports into an sql database. It
  60. * implements the singleton pattern and is based in PDO, supporting
  61. * different database types.
  62. *
  63. * @category Security
  64. * @package PHPIDS
  65. * @author Christian Matthies <ch0012@gmail.com>
  66. * @author Mario Heiderich <mario.heiderich@gmail.com>
  67. * @author Lars Strojny <lars@strojny.net>
  68. * @copyright 2007-2009 The PHPIDS Group
  69. * @license http://www.gnu.org/licenses/lgpl.html LGPL
  70. * @version Release: $Id:Database.php 517 2007-09-15 15:04:13Z mario $
  71. * @link http://php-ids.org/
  72. */
  73. class IDS_Log_Database implements IDS_Log_Interface
  74. {
  75. /**
  76. * Database wrapper
  77. *
  78. * @var string
  79. */
  80. private $wrapper = null;
  81. /**
  82. * Database user
  83. *
  84. * @var string
  85. */
  86. private $user = null;
  87. /**
  88. * Database password
  89. *
  90. * @var string
  91. */
  92. private $password = null;
  93. /**
  94. * Database table
  95. *
  96. * @var string
  97. */
  98. private $table = null;
  99. /**
  100. * Database handle
  101. *
  102. * @var object PDO instance
  103. */
  104. private $handle = null;
  105. /**
  106. * Prepared SQL statement
  107. *
  108. * @var string
  109. */
  110. private $statement = null;
  111. /**
  112. * Holds current remote address
  113. *
  114. * @var string
  115. */
  116. private $ip = 'local/unknown';
  117. /**
  118. * Instance container
  119. *
  120. * Due to the singleton pattern this class allows to initiate only one instance
  121. * for each database wrapper.
  122. *
  123. * @var array
  124. */
  125. private static $instances = array();
  126. /**
  127. * Constructor
  128. *
  129. * Prepares the SQL statement
  130. *
  131. * @param mixed $config IDS_Init instance | array
  132. *
  133. * @return void
  134. * @throws PDOException if a db error occurred
  135. */
  136. protected function __construct($config)
  137. {
  138. if ($config instanceof IDS_Init) {
  139. $this->wrapper = $config->config['Logging']['wrapper'];
  140. $this->user = $config->config['Logging']['user'];
  141. $this->password = $config->config['Logging']['password'];
  142. $this->table = $config->config['Logging']['table'];
  143. } elseif (is_array($config)) {
  144. $this->wrapper = $config['wrapper'];
  145. $this->user = $config['user'];
  146. $this->password = $config['password'];
  147. $this->table = $config['table'];
  148. }
  149. // determine correct IP address and concat them if necessary
  150. $this->ip = $_SERVER['REMOTE_ADDR'];
  151. $this->ip2 = isset($_SERVER['HTTP_X_FORWARDED_FOR'])
  152. ? $_SERVER['HTTP_X_FORWARDED_FOR']
  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. ip2,
  168. impact,
  169. origin,
  170. created
  171. )
  172. VALUES (
  173. :name,
  174. :value,
  175. :page,
  176. :tags,
  177. :ip,
  178. :ip2,
  179. :impact,
  180. :origin,
  181. now()
  182. )
  183. ');
  184. } catch (PDOException $e) {
  185. throw new PDOException('PDOException: ' . $e->getMessage());
  186. }
  187. }
  188. /**
  189. * Returns an instance of this class
  190. *
  191. * This method allows the passed argument to be either an instance of IDS_Init or
  192. * an array.
  193. *
  194. * @param mixed $config IDS_Init | array
  195. * @param string $classname the class name to use
  196. *
  197. * @return object $this
  198. */
  199. public static function getInstance($config, $classname = 'IDS_Log_Database')
  200. {
  201. if ($config instanceof IDS_Init) {
  202. $wrapper = $config->config['Logging']['wrapper'];
  203. } elseif (is_array($config)) {
  204. $wrapper = $config['wrapper'];
  205. }
  206. if (!isset(self::$instances[$wrapper])) {
  207. self::$instances[$wrapper] = new $classname($config);
  208. }
  209. return self::$instances[$wrapper];
  210. }
  211. /**
  212. * Permitting to clone this object
  213. *
  214. * For the sake of correctness of a singleton pattern, this is necessary
  215. *
  216. * @return void
  217. */
  218. private function __clone()
  219. {
  220. }
  221. /**
  222. * Stores given data into the database
  223. *
  224. * @param object $data IDS_Report instance
  225. *
  226. * @throws Exception if db error occurred
  227. * @return boolean
  228. */
  229. public function execute(IDS_Report $data)
  230. {
  231. if (!isset($_SERVER['REQUEST_URI'])) {
  232. $_SERVER['REQUEST_URI'] = substr($_SERVER['PHP_SELF'], 1);
  233. if (isset($_SERVER['QUERY_STRING']) && $_SERVER['QUERY_STRING']) {
  234. $_SERVER['REQUEST_URI'] .= '?' . $_SERVER['QUERY_STRING'];
  235. }
  236. }
  237. foreach ($data as $event) {
  238. $page = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
  239. $ip = $this->ip;
  240. $ip2 = $this->ip2;
  241. $name = $event->getName();
  242. $value = $event->getValue();
  243. $impact = $event->getImpact();
  244. $tags = implode(', ', $event->getTags());
  245. $this->statement->bindParam('name', $name);
  246. $this->statement->bindParam('value', $value);
  247. $this->statement->bindParam('page', $page);
  248. $this->statement->bindParam('tags', $tags);
  249. $this->statement->bindParam('ip', $ip);
  250. $this->statement->bindParam('ip2', $ip2);
  251. $this->statement->bindParam('impact', $impact);
  252. $this->statement->bindParam('origin', $_SERVER['SERVER_ADDR']);
  253. if (!$this->statement->execute()) {
  254. $info = $this->statement->errorInfo();
  255. throw new Exception(
  256. $this->statement->errorCode() . ', ' . $info[1] . ', ' . $info[2]
  257. );
  258. }
  259. }
  260. return true;
  261. }
  262. }
  263. /**
  264. * Local variables:
  265. * tab-width: 4
  266. * c-basic-offset: 4
  267. * End:
  268. * vim600: sw=4 ts=4 expandtab
  269. */