CVE-2021-3728 (published 2021-08-23T13:15Z)

firefly-iii is vulnerable to Cross-Site Request Forgery (CSRF)

Severity: MEDIUM
CVSS v2 base score: 4.3 (AV:N/AC:M/Au:N/C:N/I:P/A:N)
CVSS v3 base score: 6.5, MEDIUM (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N)

Weakness information:
cwe_id: CWE-352
cwe_name: Cross-Site Request Forgery (CSRF)
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.
extended_description: When a web server is designed to receive a request from a client without any mechanism for verifying that it was intentionally sent, then it might be possible for an attacker to trick a client into making an unintentional request to the web server which will be treated as an authentic request. This can be done via a URL, image load, XMLHttpRequest, etc. and can result in exposure of data or unintended code execution.
         

Fix information:
repo_url: https://github.com/firefly-iii/firefly-iii
commit_details: repo_url: https://github.com/firefly-iii/firefly-iii
author: James Cole
author_date: 2021-08-20 09:38:52+02:00
msg: Fix vulnerability https://huntr.dev/bounties/dd54c5a1-0d4a-4f02-a111-7ce4ddc67a4d/
repository: repo_url: https://github.com/firefly-iii/firefly-iii
repo_name: firefly-iii/firefly-iii
description: Firefly III: a personal finances manager
repo_language: PHP
owner: firefly-iii
file_changes: filename: index.js
change_type: ModificationType.MODIFY
diff: @@ -133,7 +133,7 @@ function updateTotalBudgetedAmount(currencyId) {
         });
 
     // get new amount:
-    $.get(totalBudgetedUri.replace('REPLACEME',currencyId)).done(function (data) {
+    $.get(totalBudgetedUri.replace('REPLACEME', currencyId)).done(function (data) {
         // set thing:
         $('span.budgeted_amount[data-currency="' + currencyId + '"]')
             .html(data.budgeted_formatted)
@@ -207,9 +207,14 @@ function createBudgetLimit(e) {
 }
 
 function deleteBudgetLimit(e) {
+    e.preventDefault();
     var button = $(e.currentTarget);
     var budgetLimitId = button.data('budget-limit-id');
-    var url = deleteBudgetLimitUrl.replace('REPLACEME', budgetId.toString();
+    var url = deleteBudgetLimitUrl.replace('REPLACEME', budgetLimitId.toString());
+    $.post(url, {_token: token}).then(function () {
+        $('.bl_entry[data-budget-limit-id="' + budgetLimitId + '"]').remove();
+        
+    });
     return false;
 }
 

programming_language: JavaScript
filename: index.twig
change_type: ModificationType.MODIFY
diff: @@ -285,7 +285,7 @@
                                                         {{ trans('firefly.budget_limit_not_in_range', {start: budgetLimit.start_date, end: budgetLimit.end_date}) }}
                                                     </small><br>
                                                 {% endif %}
-                                                <div class="input-group">
+                                                <div class="input-group bl_entry" data-budget-limit-id="{{ budgetLimit.id }}">
                                                     <div class="input-group-addon">{{ budgetLimit.currency_symbol }}</div>
                                                     <input class="form-control budget_amount" data-original="{{ budgetLimit.amount }}"
                                                         data-id="{{ budget.id }}" data-limit="{{ budgetLimit.id }}" value="{{ budgetLimit.amount }}"
@@ -295,7 +295,9 @@
                                                         <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true"
                                                                 aria-expanded="false"><span class="caret"></span></button>
                                                         <ul class="dropdown-menu">
-                                                            <li><a href="{{ route('budget-limits.delete', [budgetLimit.id]) }}">{{ trans('firefly.remove_budgeted_amount', {currency: budgetLimit.currency_name }) }}</a></li>
+                                                            <li>
+                                                                <a class="delete_bl" href="#" data-budget-limit-id="{{ budgetLimit.id }}">{{ trans('firefly.remove_budgeted_amount', {currency: budgetLimit.currency_name }) }}</a>
+                                                            </li>
                                                         </ul>
                                                     </div>
                                                 </div>
@@ -468,6 +470,7 @@
         var createBudgetLimitUri = "{{ route('budget-limits.create', ['REPLACEME', start.format('Y-m-d'), end.format('Y-m-d')]) }}";
         var storeBudgetLimitUri = "{{ route('budget-limits.store') }}";
         var updateBudgetLimitUri = "{{ route('budget-limits.update', ['REPLACEME']) }}";
+        var deleteBudgetLimitUrl = "{{ route('budget-limits.delete', ['REPLACEME']) }}";
         var totalBudgetedUri = "{{ route('json.budget.total-budgeted', ['REPLACEME', start.format('Y-m-d'), end.format('Y-m-d')]) }}";
 
         // period thing:

programming_language: HTML
filename: web.php
change_type: ModificationType.MODIFY
diff: @@ -282,7 +282,7 @@ static function () {
         Route::get('create/{budget}/{start_date}/{end_date}', ['uses' => 'Budget\BudgetLimitController@create', 'as' => 'create']);
         Route::post('store', ['uses' => 'Budget\BudgetLimitController@store', 'as' => 'store']);
 
-        Route::get('delete/{budgetLimit}', ['uses' => 'Budget\BudgetLimitController@delete', 'as' => 'delete']);
+        Route::post('delete/{budgetLimit}', ['uses' => 'Budget\BudgetLimitController@delete', 'as' => 'delete']);
 
         Route::post('update/{budgetLimit}', ['uses' => 'Budget\BudgetLimitController@update', 'as' => 'update']);
     }

programming_language: PHP