| 1: | <?php | 
| 2: |  | 
| 3: | use Xmf\IPAddress; | 
| 4: |  | 
| 5: |  | 
| 6: |  | 
| 7: |  | 
| 8: |  | 
| 9: |  | 
| 10: |  | 
| 11: |  | 
| 12: |  | 
| 13: |  | 
| 14: |  | 
| 15: |  | 
| 16: |  | 
| 17: |  | 
| 18: |  | 
| 19: |  | 
| 20: |  | 
| 21: |  | 
| 22: |  | 
| 23: |  | 
| 24: | defined('XOOPS_ROOT_PATH') || exit('Restricted access'); | 
| 25: |  | 
| 26: |  | 
| 27: |  | 
| 28: |  | 
| 29: | class XoopsSecurity | 
| 30: | { | 
| 31: | public $errors = array(); | 
| 32: |  | 
| 33: |  | 
| 34: |  | 
| 35: |  | 
| 36: |  | 
| 37: |  | 
| 38: |  | 
| 39: |  | 
| 40: |  | 
| 41: |  | 
| 42: | public function check($clearIfValid = true, $token = false, $name = 'XOOPS_TOKEN') | 
| 43: | { | 
| 44: | return $this->validateToken($token, $clearIfValid, $name); | 
| 45: | } | 
| 46: |  | 
| 47: |  | 
| 48: |  | 
| 49: |  | 
| 50: |  | 
| 51: |  | 
| 52: |  | 
| 53: |  | 
| 54: |  | 
| 55: | public function createToken($timeout = 0, $name = 'XOOPS_TOKEN') | 
| 56: | { | 
| 57: | $this->garbageCollection($name); | 
| 58: | if ($timeout == 0) { | 
| 59: | $expire  = @ini_get('session.gc_maxlifetime'); | 
| 60: | $timeout = ($expire > 0) ? $expire : 900; | 
| 61: | } | 
| 62: | $token_id = md5(uniqid(mt_rand(), true)); | 
| 63: |  | 
| 64: | if (!isset($_SESSION[$name . '_SESSION'])) { | 
| 65: | $_SESSION[$name . '_SESSION'] = array(); | 
| 66: | } | 
| 67: | $token_data = array( | 
| 68: | 'id'     => $token_id, | 
| 69: | 'expire' => time() + (int)$timeout); | 
| 70: | $_SESSION[$name . '_SESSION'][] = $token_data; | 
| 71: |  | 
| 72: | return md5($token_id . $_SERVER['HTTP_USER_AGENT'] . XOOPS_DB_PREFIX); | 
| 73: | } | 
| 74: |  | 
| 75: |  | 
| 76: |  | 
| 77: |  | 
| 78: |  | 
| 79: |  | 
| 80: |  | 
| 81: |  | 
| 82: |  | 
| 83: |  | 
| 84: | public function validateToken($token = false, $clearIfValid = true, $name = 'XOOPS_TOKEN') | 
| 85: | { | 
| 86: | global $xoopsLogger; | 
| 87: | $token = ($token !== false) ? $token : (isset($_REQUEST[$name . '_REQUEST']) ? $_REQUEST[$name . '_REQUEST'] : ''); | 
| 88: | if (empty($token) || empty($_SESSION[$name . '_SESSION'])) { | 
| 89: | $xoopsLogger->addExtra('Token Validation', 'No valid token found in request/session'); | 
| 90: |  | 
| 91: | return false; | 
| 92: | } | 
| 93: | $validFound = false; | 
| 94: | $token_data = &$_SESSION[$name . '_SESSION']; | 
| 95: | foreach (array_keys($token_data) as $i) { | 
| 96: | if ($token === md5($token_data[$i]['id'] . $_SERVER['HTTP_USER_AGENT'] . XOOPS_DB_PREFIX)) { | 
| 97: | if ($this->filterToken($token_data[$i])) { | 
| 98: | if ($clearIfValid) { | 
| 99: |  | 
| 100: | unset($token_data[$i]); | 
| 101: | } | 
| 102: | $xoopsLogger->addExtra('Token Validation', 'Valid token found'); | 
| 103: | $validFound = true; | 
| 104: | } else { | 
| 105: | $str = 'Valid token expired'; | 
| 106: | $this->setErrors($str); | 
| 107: | $xoopsLogger->addExtra('Token Validation', $str); | 
| 108: | } | 
| 109: | } | 
| 110: | } | 
| 111: | if (!$validFound && !isset($str)) { | 
| 112: | $str = 'No valid token found'; | 
| 113: | $this->setErrors($str); | 
| 114: | $xoopsLogger->addExtra('Token Validation', $str); | 
| 115: | } | 
| 116: | $this->garbageCollection($name); | 
| 117: |  | 
| 118: | return $validFound; | 
| 119: | } | 
| 120: |  | 
| 121: |  | 
| 122: |  | 
| 123: |  | 
| 124: |  | 
| 125: |  | 
| 126: |  | 
| 127: |  | 
| 128: | public function clearTokens($name = 'XOOPS_TOKEN') | 
| 129: | { | 
| 130: | $_SESSION[$name . '_SESSION'] = array(); | 
| 131: | } | 
| 132: |  | 
| 133: |  | 
| 134: |  | 
| 135: |  | 
| 136: |  | 
| 137: |  | 
| 138: |  | 
| 139: |  | 
| 140: | public function filterToken($token) | 
| 141: | { | 
| 142: | return (!empty($token['expire']) && $token['expire'] >= time()); | 
| 143: | } | 
| 144: |  | 
| 145: |  | 
| 146: |  | 
| 147: |  | 
| 148: |  | 
| 149: |  | 
| 150: |  | 
| 151: |  | 
| 152: | public function garbageCollection($name = 'XOOPS_TOKEN') | 
| 153: | { | 
| 154: | $sessionName = $name . '_SESSION'; | 
| 155: | if (!empty($_SESSION[$sessionName]) && \is_array($_SESSION[$sessionName])) { | 
| 156: | $_SESSION[$sessionName] = array_filter($_SESSION[$sessionName], array($this, 'filterToken')); | 
| 157: | } | 
| 158: | } | 
| 159: |  | 
| 160: |  | 
| 161: |  | 
| 162: |  | 
| 163: |  | 
| 164: |  | 
| 165: |  | 
| 166: |  | 
| 167: | public function checkReferer($docheck = 1) | 
| 168: | { | 
| 169: | $ref = xoops_getenv('HTTP_REFERER'); | 
| 170: | if ($docheck == 0) { | 
| 171: | return true; | 
| 172: | } | 
| 173: | if ($ref == '') { | 
| 174: | return false; | 
| 175: | } | 
| 176: | return !(strpos($ref, XOOPS_URL) !== 0); | 
| 177: | } | 
| 178: |  | 
| 179: |  | 
| 180: |  | 
| 181: |  | 
| 182: |  | 
| 183: |  | 
| 184: | public function checkSuperglobals() | 
| 185: | { | 
| 186: | foreach (array( | 
| 187: | 'GLOBALS', | 
| 188: | '_SESSION', | 
| 189: | 'HTTP_SESSION_VARS', | 
| 190: | '_GET', | 
| 191: | 'HTTP_GET_VARS', | 
| 192: | '_POST', | 
| 193: | 'HTTP_POST_VARS', | 
| 194: | '_COOKIE', | 
| 195: | 'HTTP_COOKIE_VARS', | 
| 196: | '_REQUEST', | 
| 197: | '_SERVER', | 
| 198: | 'HTTP_SERVER_VARS', | 
| 199: | '_ENV', | 
| 200: | 'HTTP_ENV_VARS', | 
| 201: | '_FILES', | 
| 202: | 'HTTP_POST_FILES', | 
| 203: | 'xoopsDB', | 
| 204: | 'xoopsUser', | 
| 205: | 'xoopsUserId', | 
| 206: | 'xoopsUserGroups', | 
| 207: | 'xoopsUserIsAdmin', | 
| 208: | 'xoopsConfig', | 
| 209: | 'xoopsOption', | 
| 210: | 'xoopsModule', | 
| 211: | 'xoopsModuleConfig', | 
| 212: | 'xoopsRequestUri') as $bad_global) { | 
| 213: | if (isset($_REQUEST[$bad_global])) { | 
| 214: | header('Location: ' . XOOPS_URL . '/'); | 
| 215: | exit(); | 
| 216: | } | 
| 217: | } | 
| 218: | } | 
| 219: |  | 
| 220: |  | 
| 221: |  | 
| 222: |  | 
| 223: |  | 
| 224: |  | 
| 225: |  | 
| 226: | public function checkBadips() | 
| 227: | { | 
| 228: | global $xoopsConfig; | 
| 229: |  | 
| 230: | $addr = IPAddress::fromRequest(); | 
| 231: | $ip = $addr->asReadable(); | 
| 232: | if ($xoopsConfig['enable_badips'] == 1 && $ip != '0.0.0.0') { | 
| 233: | foreach ($xoopsConfig['bad_ips'] as $bi) { | 
| 234: | if (!empty($bi) && preg_match('/' . $bi . '/', $ip)) { | 
| 235: | exit(); | 
| 236: | } | 
| 237: | } | 
| 238: | } | 
| 239: | } | 
| 240: |  | 
| 241: |  | 
| 242: |  | 
| 243: |  | 
| 244: |  | 
| 245: |  | 
| 246: |  | 
| 247: |  | 
| 248: | public function getTokenHTML($name = 'XOOPS_TOKEN') | 
| 249: | { | 
| 250: | require_once XOOPS_ROOT_PATH . '/class/xoopsformloader.php'; | 
| 251: | $token = new XoopsFormHiddenToken($name); | 
| 252: |  | 
| 253: | return $token->render(); | 
| 254: | } | 
| 255: |  | 
| 256: |  | 
| 257: |  | 
| 258: |  | 
| 259: |  | 
| 260: |  | 
| 261: |  | 
| 262: |  | 
| 263: | public function setErrors($error) | 
| 264: | { | 
| 265: | $this->errors[] = trim($error); | 
| 266: | } | 
| 267: |  | 
| 268: |  | 
| 269: |  | 
| 270: |  | 
| 271: |  | 
| 272: |  | 
| 273: |  | 
| 274: |  | 
| 275: | public function &getErrors($ashtml = false) | 
| 276: | { | 
| 277: | if (!$ashtml) { | 
| 278: | return $this->errors; | 
| 279: | } else { | 
| 280: | $ret = ''; | 
| 281: | if (count($this->errors) > 0) { | 
| 282: | foreach ($this->errors as $error) { | 
| 283: | $ret .= $error . '<br>'; | 
| 284: | } | 
| 285: | } | 
| 286: |  | 
| 287: | return $ret; | 
| 288: | } | 
| 289: | } | 
| 290: | } | 
| 291: |  |