1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
15:
16: defined('CON_FRAMEWORK') || die('Illegal call: Missing framework initialization - request aborted.');
17:
18: 19: 20: 21: 22: 23:
24: class cRequestValidator {
25:
26: 27: 28: 29: 30:
31: private static $_instance = NULL;
32:
33: 34: 35: 36: 37:
38: protected $_logPath;
39:
40: 41: 42: 43: 44:
45: protected $_log = true;
46:
47: 48: 49: 50: 51:
52: protected $_configPath;
53:
54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66:
67: protected $_check = array();
68:
69: 70: 71: 72: 73: 74:
75: protected $_blacklist = array();
76:
77: 78: 79: 80: 81:
82: protected $_failure = '';
83:
84: 85: 86: 87: 88:
89: protected $_mode = '';
90:
91: 92: 93: 94: 95:
96: const CHECK_INTEGER = '/^[0-9]*$/';
97:
98: 99: 100: 101: 102:
103: const CHECK_PRIMITIVESTRING = '/^[a-zA-Z0-9 -_]*$/';
104:
105: 106: 107: 108: 109:
110: const CHECK_STRING = '/^[\w0-9 -_]*$/';
111:
112: 113: 114: 115: 116:
117: const CHECK_HASH32 = '/^[a-zA-Z0-9]{32}$/';
118:
119: 120: 121: 122: 123:
124: const CHECK_BELANG = '/^[a-z]{2}_[A-Z]{2}$/';
125:
126: 127: 128: 129: 130:
131: const CHECK_AREASTRING = '/^[a-zA-Z_]*$/';
132:
133: 134: 135: 136: 137:
138: const CHECK_PATHSTRING = '!([*]*\/)|(dbfs:\/[*]*)|(dbfs:)|(^)$!';
139:
140: 141: 142: 143: 144: 145: 146: 147:
148: private function __construct() {
149:
150: global $bLog, $sMode, $aCheck, $aBlacklist;
151:
152:
153: $installationPath = str_replace('\\', '/', realpath(dirname(__FILE__) . '/../..'));
154: $configPath = $installationPath . '/data/config/' . CON_ENVIRONMENT;
155:
156: $this->_logPath = $installationPath . '/data/logs/security.txt';
157:
158:
159: if (cFileHandler::exists($configPath . '/config.http_check.php')) {
160: $this->_configPath = $configPath;
161: } else {
162: throw new cFileNotFoundException('Could not load cRequestValidator configuration! (invalid path) ' . $configPath . '/config.http_check.php');
163: }
164:
165:
166: require($this->_configPath . '/config.http_check.php');
167:
168:
169: if (cFileHandler::exists($this->_configPath . '/config.http_check.local.php')) {
170: require($this->_configPath . '/config.http_check.local.php');
171: }
172:
173: $this->_log = $bLog;
174: $this->_mode = $sMode;
175:
176: if ($this->_log === true) {
177: if (empty($this->_logPath) || !is_writeable(dirname($this->_logPath))) {
178: $this->_log = false;
179: }
180: }
181:
182: $this->_check = $aCheck;
183: foreach ($aBlacklist as $elem) {
184: $this->_blacklist[] = strtolower($elem);
185: }
186: }
187:
188: 189: 190: 191: 192:
193: public static function getInstance() {
194: if (self::$_instance === NULL) {
195: self::$_instance = new self();
196: }
197:
198: return self::$_instance;
199: }
200:
201: 202: 203: 204: 205: 206: 207:
208: public function checkParams() {
209: if ((!$this->checkGetParams()) || (!$this->checkPostParams())) {
210: $this->logHackTrial();
211:
212: if ($this->_mode == 'stop') {
213: ob_end_clean();
214: $msg = 'Parameter check failed! (%s = %s %s)';
215:
216: $msg = sprintf($msg, htmlentities($this->_failure), htmlentities($_GET[$this->_failure]), htmlentities($_POST[$this->_failure]));
217: die($msg);
218: }
219: }
220:
221: return true;
222: }
223:
224: 225: 226: 227: 228: 229:
230: public function checkGetParams() {
231: return $this->checkArray($_GET, 'GET');
232: }
233:
234: 235: 236: 237: 238: 239:
240: public function checkPostParams() {
241: return $this->checkArray($_POST, 'POST');
242: }
243:
244: 245: 246: 247: 248: 249: 250: 251: 252: 253:
254: public function checkParameter($type, $key, $value) {
255: $result = false;
256:
257: if (in_array(strtolower($key), $this->_blacklist)) {
258: return false;
259: }
260:
261: if (in_array(strtoupper($type), array(
262: 'GET',
263: 'POST'
264: ))) {
265: if (!isset($this->_check[$type][$key]) && (is_null($value) || empty($value))) {
266:
267: $result = true;
268: } elseif (isset($this->_check[$type][$key])) {
269:
270: $result = preg_match($this->_check[$type][$key], $value);
271: } else {
272:
273: $result = true;
274: }
275: }
276:
277: return $result;
278: }
279:
280: 281: 282: 283: 284:
285: public function getBadParameter() {
286: return $this->_failure;
287: }
288:
289: 290: 291: 292:
293: protected function logHackTrial() {
294: if ($this->_log === true && !empty($this->_logPath)) {
295: $content = date('Y-m-d H:i:s') . ' ';
296: $content .= $_SERVER['REMOTE_ADDR'] . str_repeat(' ', 17 - strlen($_SERVER['REMOTE_ADDR'])) . "\n";
297: $content .= ' Query String: ' . $_SERVER['QUERY_STRING'] . "\n";
298: $content .= ' Bad parameter: ' . $this->getBadParameter() . "\n";
299: $content .= ' POST array: ' . print_r($_POST, true) . "\n";
300: cFileHandler::write($this->_logPath, $content, true);
301: } elseif ($this->_mode == 'continue') {
302: echo "\n<br>VIOLATION: URL contains invalid or undefined paramaters! URL: '" . conHtmlentities($_SERVER['QUERY_STRING']) . "' <br>\n";
303: }
304: }
305:
306: 307: 308: 309: 310: 311: 312: 313:
314: protected function checkArray($arr, $type) {
315: $result = true;
316:
317: foreach ($arr as $key => $value) {
318: if (!$this->checkParameter(strtoupper($type), $key, $value)) {
319: $this->_failure = $key;
320: $result = false;
321: break;
322: }
323: }
324:
325: return $result;
326: }
327:
328: }
329: