From 8080c525fd453bfba9c35f01a08013e148bb2144 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Tue, 15 Sep 2020 16:12:53 +0300 Subject: [PATCH] - backend: require CSRF token to be passed via POST - do not leak CSRF token via GET request in feed debugger - rework Article/redirect to use POST --- backend.php | 2 +- classes/feeds.php | 4 ++-- classes/handler/public.php | 6 +++--- js/App.js | 35 ++++++++++++++++++++++++++++++++--- js/Article.js | 34 ++++------------------------------ js/FeedTree.js | 5 +++-- 6 files changed, 45 insertions(+), 41 deletions(-) diff --git a/backend.php b/backend.php index e65ce1b94..1bbeec2bd 100644 --- a/backend.php +++ b/backend.php @@ -20,7 +20,7 @@ return; } - @$csrf_token = $_REQUEST['csrf_token']; + @$csrf_token = $_POST['csrf_token']; require_once "autoload.php"; require_once "sessions.php"; diff --git a/classes/feeds.php b/classes/feeds.php index 58ba1b6f8..71890f6ab 100755 --- a/classes/feeds.php +++ b/classes/feeds.php @@ -751,7 +751,7 @@ class Feeds extends Handler_Protected { $feed_id = (int)$_REQUEST["feed_id"]; @$do_update = $_REQUEST["action"] == "do_update"; - $csrf_token = $_REQUEST["csrf_token"]; + $csrf_token = $_POST["csrf_token"]; $sth = $this->pdo->prepare("SELECT id FROM ttrss_feeds WHERE id = ? AND owner_uid = ?"); $sth->execute([$feed_id, $_SESSION['uid']]); @@ -799,7 +799,7 @@ class Feeds extends Handler_Protected {

Feed Debugger: getFeedTitle($feed_id) ?>

-
+ diff --git a/classes/handler/public.php b/classes/handler/public.php index 7f8d01ad0..e4199a95e 100755 --- a/classes/handler/public.php +++ b/classes/handler/public.php @@ -291,7 +291,7 @@ class Handler_Public extends Handler { $uuid = clean($_REQUEST["key"]); if ($uuid) { - $sth = $this->pdo->prepare("SELECT ref_id, owner_uid + $sth = $this->pdo->prepare("SELECT ref_id, owner_uid FROM ttrss_user_entries WHERE uuid = ?"); $sth->execute([$uuid]); @@ -366,7 +366,7 @@ class Handler_Public extends Handler { } body.css_loading * { display : none; - } + } "; @@ -728,7 +728,7 @@ class Handler_Public extends Handler { if ($_SESSION["uid"]) { $feed_url = trim(clean($_REQUEST["feed_url"])); - $csrf_token = clean($_REQUEST["csrf_token"]); + $csrf_token = clean($_POST["csrf_token"]); header('Content-Type: text/html; charset=utf-8'); ?> diff --git a/js/App.js b/js/App.js index 2bc2020bb..1bf4ed881 100644 --- a/js/App.js +++ b/js/App.js @@ -126,7 +126,33 @@ const App = { return callOriginal(options); } ); - }, + }, + postOpenWindow: function(target, params) { + const w = window.open(""); + + if (w) { + w.opener = null; + + const form = document.createElement("form"); + + form.setAttribute("method", "post"); + form.setAttribute("action", App.getInitParam("self_url_prefix") + "/" + target); + + for (const [k,v] of Object.entries(params)) { + const field = document.createElement("input"); + + field.setAttribute("name", k); + field.setAttribute("value", v); + field.setAttribute("type", "hidden"); + + form.appendChild(field); + } + + w.document.body.appendChild(form); + form.submit(); + } + + }, urlParam: function(param) { return String(window.location.href).parseQuery()[param]; }, @@ -986,8 +1012,11 @@ const App = { }; this.hotkey_actions["feed_debug_update"] = () => { if (!Feeds.activeIsCat() && parseInt(Feeds.getActive()) > 0) { - window.open("backend.php?op=feeds&method=update_debugger&feed_id=" + Feeds.getActive() + - "&csrf_token=" + this.getInitParam("csrf_token")); + //window.open("backend.php?op=feeds&method=update_debugger&feed_id=" + Feeds.getActive()); + + /* global __csrf_token */ + App.postOpenWindow("backend.php", {op: "feeds", method: "update_debugger", feed_id: Feeds.getActive(), csrf_token: __csrf_token}); + } else { alert("You can't debug this kind of feed."); } diff --git a/js/Article.js b/js/Article.js index e2284b190..174015a61 100644 --- a/js/Article.js +++ b/js/Article.js @@ -131,37 +131,11 @@ const Article = { }); }, openInNewWindow: function (id) { + /* global __csrf_token */ + App.postOpenWindow("backend.php", + { "op": "article", "method": "redirect", "id": id, "csrf_token": __csrf_token }); - const w = window.open(""); - - if (w) { - w.opener = null; - - const form = document.createElement("form"); - - form.setAttribute("method", "post"); - form.setAttribute("action", App.getInitParam("self_url_prefix") + "/backend.php"); - - /* global __csrf_token */ - - const params = { "op": "article", "method": "redirect", "id": id, "csrf_token": __csrf_token }; - - for (const [k,v] of Object.entries(params)) { - const field = document.createElement("input"); - - field.setAttribute("name", k); - field.setAttribute("value", v); - field.setAttribute("type", "hidden"); - - form.appendChild(field); - } - - w.document.body.appendChild(form); - form.submit(); - - Headlines.toggleUnread(id, 0); - } - + Headlines.toggleUnread(id, 0); }, render: function (article) { App.cleanupMemory("content-insert"); diff --git a/js/FeedTree.js b/js/FeedTree.js index 74c29d2f7..c61d8a50f 100755 --- a/js/FeedTree.js +++ b/js/FeedTree.js @@ -101,8 +101,9 @@ define(["dojo/_base/declare", "dojo/dom-construct", "dojo/_base/array", "dojo/co menu.addChild(new dijit.MenuItem({ label: __("Debug feed"), onClick: function() { - window.open("backend.php?op=feeds&method=update_debugger&feed_id=" + this.getParent().row_id + - "&csrf_token=" + App.getInitParam("csrf_token")); + /* global __csrf_token */ + App.postOpenWindow("backend.php", {op: "feeds", method: "update_debugger", + feed_id: this.getParent().row_id, csrf_token: __csrf_token}); }})); }