CVE-2015-8032: Improper Privilege Management (CWE-269)
value: In Textpattern 4.5.7, an unprivileged author can change an article's markup setting.
CWE description: The product does not properly assign, modify, track, or check privileges for an actor, creating an unintended sphere of control for that actor.
CVSS v3 base score: 5.3
Published: 2020-08-14T19:15Z
Repository: https://github.com/textpattern/textpattern
Language: PHP
Files changed: textpattern/include/txp_article.php
Commit date: 2015-10-16 16:46:58 +0200
Commit message: Do not allow unprivileged authors to modify an existing article's markup setting.

Refs #558.

Diff: diff --git a/textpattern/include/txp_article.php b/textpattern/include/txp_article.php
index ff88604e..a1de6a6d 100644
--- a/textpattern/include/txp_article.php
+++ b/textpattern/include/txp_article.php
@@ -325,11 +325,11 @@ function article_save()
 
     extract($prefs);
 
     $incoming = array_map('assert_string', psa($vars));
 
-    $oldArticle = safe_row('Status, url_title, Title, '.
+    $oldArticle = safe_row('Status, url_title, Title, textile_body, textile_excerpt, '.
         'unix_timestamp(LastMod) as sLastMod, LastModID, '.
         'unix_timestamp(Posted) as sPosted, '.
         'unix_timestamp(Expires) as sExpires',
         'textpattern', 'ID = '.(int) $incoming['ID']);
 
@@ -349,11 +349,12 @@ function article_save()
 
         return;
     }
 
     if (!has_privs('article.set_markup')) {
-        $incoming['textile_body'] = $incoming['textile_excerpt'] = $use_textile;
+        $incoming['textile_body'] = $oldArticle['textile_body'];
+        $incoming['textile_excerpt'] = $oldArticle['textile_excerpt'];
     }
 
     $incoming = textile_main_fields($incoming);
 
     extract(doSlash($incoming));
@@ -747,10 +748,16 @@ function article_edit($message = '', $concurrent = false, $refresh_partials = fa
             $store_out = gpsa($vars);
 
             if ($concurrent) {
                 $store_out['sLastMod'] = safe_field('unix_timestamp(LastMod) as sLastMod', 'textpattern', 'ID='.$ID);
             }
+
+            if (!has_privs('article.set_markup')) {
+                $oldArticle = safe_row('textile_body, textile_excerpt', 'textpattern', 'ID = '.$ID);
+                $store_out['textile_body'] = $oldArticle['textile_body'];
+                $store_out['textile_excerpt'] = $oldArticle['textile_excerpt'];
+            }
         }
 
         // Use preferred Textfilter as default and fallback.
         $hasfilter = new Textpattern_Textfilter_Constraint(null);
         $validator = new Validator();

Vulnerable code:     $oldArticle = safe_row('Status, url_title, Title, '.
        $incoming['textile_body'] = $incoming['textile_excerpt'] = $use_textile;
Fixed code:     $oldArticle = safe_row('Status, url_title, Title, textile_body, textile_excerpt, '.
        $incoming['textile_body'] = $oldArticle['textile_body'];
        $incoming['textile_excerpt'] = $oldArticle['textile_excerpt'];

            if (!has_privs('article.set_markup')) {
                $oldArticle = safe_row('textile_body, textile_excerpt', 'textpattern', 'ID = '.$ID);
                $store_out['textile_body'] = $oldArticle['textile_body'];
                $store_out['textile_excerpt'] = $oldArticle['textile_excerpt'];
            }