diff --git a/application/components/search/engines/ElasticConnection.php b/application/components/search/engines/ElasticConnection.php index 8f77977..0cca6d6 100644 --- a/application/components/search/engines/ElasticConnection.php +++ b/application/components/search/engines/ElasticConnection.php @@ -36,13 +36,13 @@ private function getHeaders() 'Authorization: Basic ' . base64_encode($this->username.':'.$this->password), ); - $clientIp = $this->getClientIp(); + $clientIp = $this->sanitizeHeaderValue($this->getClientIp()); if (!empty($clientIp)) { $headers[] = 'X-Forwarded-For: ' . $clientIp; $headers[] = 'X-Real-IP: ' . $clientIp; } - $userAgent = Yii::$app->getRequest()->getUserAgent(); + $userAgent = $this->sanitizeHeaderValue(Yii::$app->getRequest()->getUserAgent()); if (!empty($userAgent)) { $headers[] = 'User-Agent: ' . $userAgent; } @@ -50,6 +50,21 @@ private function getHeaders() return $headers; } + /** + * Strip CR/LF and other control characters from a value before placing it + * in an outbound HTTP header. Prevents header / request smuggling via + * client-controlled headers like User-Agent and X-Forwarded-For. + */ + private function sanitizeHeaderValue($value) + { + if ($value === null) { + return ''; + } + // Drop anything that could terminate a header line or inject control chars. + $clean = preg_replace('/[\x00-\x1F\x7F]/', '', (string)$value); + return trim($clean); + } + private function getClientIp() { $request = Yii::$app->getRequest(); diff --git a/application/modules/front/controllers/IndexController.php b/application/modules/front/controllers/IndexController.php index 5d22d6c..4b7f2cc 100644 --- a/application/modules/front/controllers/IndexController.php +++ b/application/modules/front/controllers/IndexController.php @@ -146,12 +146,21 @@ public function actionContact() { } public function actionFlushCache($key = NULL) { + // Restrict cache management to loopback callers (server-local maintenance scripts). + // Without this guard any anonymous visitor could repeatedly flush the cache + // and cause a stampede on the origin database. + $remoteIp = Yii::$app->getRequest()->getUserIP(); + $allowedIps = ['127.0.0.1', '::1']; + if (!in_array($remoteIp, $allowedIps, true)) { + throw new \yii\web\ForbiddenHttpException('Forbidden.'); + } + if (!Yii::$app->getRequest()->getIsPost()) { + throw new \yii\web\MethodNotAllowedHttpException('POST required.'); + } if (is_null($key)) $success = Yii::$app->cache->flush(); else { $key = rawurldecode($key); $success = Yii::$app->cache->delete($key); - //Yii::log("Attempting to delete key $key", 'info', 'system.web.CController'); - //$success = $key; } $this->view->params['success'] = $success; echo $this->renderPartial('flushcache'); diff --git a/public/processer.php b/public/processer.php index 70e0b7f..5e2ef8d 100644 --- a/public/processer.php +++ b/public/processer.php @@ -24,8 +24,14 @@ function getIP() { $errortype = $_POST['type']." ".$_POST['othererror']; $errortext = $_POST['re_additional']; - $email = $_POST['email']; - if (strlen($email) <= 3) $email = $parameters['adminEmail']; + $email = isset($_POST['email']) ? trim((string)$_POST['email']) : ''; + // Reject anything that doesn't look like a valid email address or that + // contains CR/LF (mail header injection). Fall back to adminEmail. + if (strlen($email) <= 3 + || !filter_var($email, FILTER_VALIDATE_EMAIL) + || preg_match('/[\r\n]/', $email)) { + $email = $parameters['adminEmail']; + } $resp = recaptcha_check_answer( $privatekey, diff --git a/public/share.php b/public/share.php index 3cf2d34..da0080b 100644 --- a/public/share.php +++ b/public/share.php @@ -1,6 +1,17 @@