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:                 die('Parameter check failed! (' . $this->_failure . '=' . $_GET[$this->_failure] . $_POST[$this->_failure] . ')');
215:             }
216:         }
217: 
218:         return true;
219:     }
220: 
221:     222: 223: 224: 225: 226: 
227:     public function checkGetParams() {
228:         return $this->checkArray($_GET, 'GET');
229:     }
230: 
231:     232: 233: 234: 235: 236: 
237:     public function checkPostParams() {
238:         return $this->checkArray($_POST, 'POST');
239:     }
240: 
241:     242: 243: 244: 245: 246: 247: 248: 249: 250: 
251:     public function checkParameter($type, $key, $value) {
252:         $result = false;
253: 
254:         if (in_array(strtolower($key), $this->_blacklist)) {
255:             return false;
256:         }
257: 
258:         if (in_array(strtoupper($type), array(
259:             'GET',
260:             'POST'
261:         ))) {
262:             if (!isset($this->_check[$type][$key]) && (is_null($value) || empty($value))) {
263:                 
264:                 $result = true;
265:             } elseif (isset($this->_check[$type][$key])) {
266:                 
267:                 $result = preg_match($this->_check[$type][$key], $value);
268:             } else {
269:                 
270:                 $result = true;
271:             }
272:         }
273: 
274:         return $result;
275:     }
276: 
277:     278: 279: 280: 281: 
282:     public function getBadParameter() {
283:         return $this->_failure;
284:     }
285: 
286:     287: 288: 289: 
290:     protected function logHackTrial() {
291:         if ($this->_log === true && !empty($this->_logPath)) {
292:             $content = date('Y-m-d H:i:s') . '    ';
293:             $content .= $_SERVER['REMOTE_ADDR'] . str_repeat(' ', 17 - strlen($_SERVER['REMOTE_ADDR'])) . "\n";
294:             $content .= '    Query String: ' . $_SERVER['QUERY_STRING'] . "\n";
295:             $content .= '    Bad parameter: ' . $this->getBadParameter() . "\n";
296:             $content .= '    POST array: ' . print_r($_POST, true) . "\n";
297:             cFileHandler::write($this->_logPath, $content, true);
298:         } elseif ($this->_mode == 'continue') {
299:             echo "\n<br>VIOLATION: URL contains invalid or undefined paramaters! URL: '" . conHtmlentities($_SERVER['QUERY_STRING']) . "' <br>\n";
300:         }
301:     }
302: 
303:     304: 305: 306: 307: 308: 309: 310: 
311:     protected function checkArray($arr, $type) {
312:         $result = true;
313: 
314:         foreach ($arr as $key => $value) {
315:             if (!$this->checkParameter(strtoupper($type), $key, $value)) {
316:                 $this->_failure = $key;
317:                 $result = false;
318:                 break;
319:             }
320:         }
321: 
322:         return $result;
323:     }
324: 
325: }
326: