1<?php
2	/* Copyright (c) by Hugo Leisink <hugo@leisink.net>
3	 * This file is part of the Banshee PHP framework
4	 * https://www.banshee-php.org/
5	 *
6	 * Licensed under The MIT License
7	 */
8
9	class prevent_CSRF {
10		const TOKEN_KEY = "banshee_csrf";
11
12		private $page = null;
13		private $user = null;
14		private $output = null;
15
16		/* Constructor
17		 *
18		 * INPUT:  object page, object user, object output
19		 * OUTPUT: -
20		 * ERROR:  -
21		 */
22		public function __construct($page, $user, $output) {
23			$this->page = $page;
24			$this->user = $user;
25			$this->output = $output;
26		}
27
28		/* Prevent CSRF attack
29		 *
30		 * INPUT:  -
31		 * OUTPUT: -
32		 * ERROR:  -
33		 */
34		public function execute() {
35			if ($this->page->module == "setup") {
36				return false;
37			}
38
39			if (isset($_SESSION[self::TOKEN_KEY]) == false) {
40				$_SESSION[self::TOKEN_KEY] = random_string(32);
41			}
42
43			$token = hash("sha256", $_SESSION[self::TOKEN_KEY].$this->user->username);
44
45			$this->output->add_javascript("banshee/prevent_csrf.js");
46			$this->output->run_javascript("prevent_csrf('".self::TOKEN_KEY."', '".$token."')");
47
48			if (($_SERVER["REQUEST_METHOD"] != "POST") || $this->page->ajax_request) {
49				return;
50			}
51
52			if ($_POST[self::TOKEN_KEY] == $token) {
53				return;
54			}
55
56			/* CSRF attack detected
57			 */
58			if (isset($_SERVER["HTTP_ORIGIN"])) {
59				$referer = $_SERVER["HTTP_ORIGIN"];
60			} else if (isset($_SERVER["HTTP_REFERER"])) {
61				$referer = $_SERVER["HTTP_REFERER"];
62			} else {
63				$referer = "previous visited website";
64			}
65
66			$message = "CSRF attempt via %s blocked";
67			$this->output->add_system_warning($message, $referer);
68			$this->user->log_action($message, $referer);
69			$this->user->logout();
70
71			$_SERVER["REQUEST_METHOD"] = "GET";
72			$_GET = array();
73			$_POST = array();
74		}
75	}
76?>
77