CVE-2017-1000008: Cross-Site Request Forgery (CSRF) (CWE-352)
value: Chyrp Lite version 2016.04 is vulnerable to a CSRF in the user settings function allowing attackers to hijack the authentication of logged in users to modify account information, including their password.
CWE description: The web application does not, or can not, sufficiently verify whether a well-formed, valid, consistent request was intentionally provided by the user who submitted the request.
CVSS v3 base score: 8.8
Published: 2017-07-17T13:18Z
Repository: https://github.com/xenocrat/chyrp-lite
Language: Other
Files changed: includes/controller/Main.php, themes/blossom/forms/user/controls.twig, themes/sparrow/forms/user/controls.twig, themes/topaz/forms/user/controls.twig, themes/umbra/forms/user/controls.twig
Commit date: 2017-01-06 22:32:03 +0000
Commit message: MainController, Blog Themes: protect against CSRF

My thanks to @fleetcaptain for the report.

Diff: diff --git a/includes/controller/Main.php b/includes/controller/Main.php
index fbc8994e..8dc7f8c4 100755
--- a/includes/controller/Main.php
+++ b/includes/controller/Main.php
@@ -618,10 +618,13 @@
                 Flash::notice(__("You must be logged in to access user controls."), "login");
 
             if (!empty($_POST)) {
                 $visitor = Visitor::current();
 
+                if (!isset($_POST['hash']) or $_POST['hash'] != token($_SERVER["REMOTE_ADDR"]))
+                    Flash::warning(__("Invalid security key."));
+
                 if (!empty($_POST['new_password1']))
                     if (empty($_POST['new_password2']) or $_POST['new_password1'] != $_POST['new_password2'])
                         Flash::warning(__("Passwords do not match."));
                     elseif (password_strength($_POST['new_password1']) < 100)
                         Flash::message(__("Please consider setting a stronger password for your account."));
diff --git a/themes/blossom/forms/user/controls.twig b/themes/blossom/forms/user/controls.twig
index 10070fed..50425549 100644
--- a/themes/blossom/forms/user/controls.twig
+++ b/themes/blossom/forms/user/controls.twig
@@ -16,8 +16,9 @@
 <input type="password" name="new_password2" value="" id="new_password2" maxlength="128">
 {{ trigger.call("user_controls") }}
 <div class="doaction">
 <button name="submit" type="submit" id="submit" tabindex="4">{{ "Update" | translate }}</button>
 </div>
+<input type="hidden" name="hash" value="{{ ip | token }}" id="hash">
 </form>
 </div>
 {% endblock %}
diff --git a/themes/sparrow/forms/user/controls.twig b/themes/sparrow/forms/user/controls.twig
index 10070fed..50425549 100644
--- a/themes/sparrow/forms/user/controls.twig
+++ b/themes/sparrow/forms/user/controls.twig
@@ -16,8 +16,9 @@
 <input type="password" name="new_password2" value="" id="new_password2" maxlength="128">
 {{ trigger.call("user_controls") }}
 <div class="doaction">
 <button name="submit" type="submit" id="submit" tabindex="4">{{ "Update" | translate }}</button>
 </div>
+<input type="hidden" name="hash" value="{{ ip | token }}" id="hash">
 </form>
 </div>
 {% endblock %}
diff --git a/themes/topaz/forms/user/controls.twig b/themes/topaz/forms/user/controls.twig
index 10070fed..50425549 100644
--- a/themes/topaz/forms/user/controls.twig
+++ b/themes/topaz/forms/user/controls.twig
@@ -16,8 +16,9 @@
 <input type="password" name="new_password2" value="" id="new_password2" maxlength="128">
 {{ trigger.call("user_controls") }}
 <div class="doaction">
 <button name="submit" type="submit" id="submit" tabindex="4">{{ "Update" | translate }}</button>
 </div>
+<input type="hidden" name="hash" value="{{ ip | token }}" id="hash">
 </form>
 </div>
 {% endblock %}
diff --git a/themes/umbra/forms/user/controls.twig b/themes/umbra/forms/user/controls.twig
index 10070fed..50425549 100644
--- a/themes/umbra/forms/user/controls.twig
+++ b/themes/umbra/forms/user/controls.twig
@@ -16,8 +16,9 @@
 <input type="password" name="new_password2" value="" id="new_password2" maxlength="128">
 {{ trigger.call("user_controls") }}
 <div class="doaction">
 <button name="submit" type="submit" id="submit" tabindex="4">{{ "Update" | translate }}</button>
 </div>
+<input type="hidden" name="hash" value="{{ ip | token }}" id="hash">
 </form>
 </div>
 {% endblock %}

Fixed code:                 if (!isset($_POST['hash']) or $_POST['hash'] != token($_SERVER["REMOTE_ADDR"]))
                    Flash::warning(__("Invalid security key."));

<input type="hidden" name="hash" value="{{ ip | token }}" id="hash">
<input type="hidden" name="hash" value="{{ ip | token }}" id="hash">
<input type="hidden" name="hash" value="{{ ip | token }}" id="hash">
<input type="hidden" name="hash" value="{{ ip | token }}" id="hash">