VYPR
Moderate severityNVD Advisory· Published Nov 13, 2021· Updated Aug 3, 2024

Cross-Site Request Forgery (CSRF) in firefly-iii/firefly-iii

CVE-2021-3921

Description

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

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
grumpydictator/firefly-iiiPackagist
< 5.6.35.6.3

Affected products

1

Patches

1
47fa9e39561a

Fix huntr.dev logout issue.

https://github.com/firefly-iii/firefly-iiiJames ColeNov 9, 2021via ghsa
9 files changed · +27 14
  • resources/views/v1/auth/login.twig+3 3 modified
    @@ -61,7 +61,7 @@
         <div class="login-box-body">
             <p class="login-box-msg">{{ 'sign_in_to_start'|_ }}</p>
     
    -        <form action="{{ URL.to('/login') }}" method="post">
    +        <form action="{{ route('login') }}" method="post">
                 <input type="hidden" name="_token" value="{{ csrf_token() }}"/>
     
                 <div class="form-group has-feedback">
    @@ -88,10 +88,10 @@
                 </div>
             </form>
             {% if allowRegistration %}
    -            <a href="{{ URL.to('/register') }}" class="text-center">{{ 'register_new_account'|_ }}</a><br>
    +            <a href="{{ route('register') }}" class="text-center">{{ 'register_new_account'|_ }}</a><br>
             {% endif %}
             {% if allowReset %}
    -            <a href="{{ URL.to('/password/reset') }}">{{ 'forgot_my_password'|_ }}</a>
    +            <a href="{{ route('password.reset.request') }}">{{ 'forgot_my_password'|_ }}</a>
             {% endif %}
         </div>
     {% endblock %}
    
  • resources/views/v1/auth/passwords/email.twig+2 2 modified
    @@ -27,7 +27,7 @@
             {% else %}
                 <p class="login-box-msg">{{ 'reset_password'|_ }}</p>
     
    -            <form role="form" method="POST" action="{{ URL.to('/password/email') }}">
    +            <form role="form" method="POST" action="{{ route('password.email') }}">
                     <input type="hidden" name="_token" value="{{ csrf_token() }}"/>
     
                     <div class="form-group has-feedback">
    @@ -43,7 +43,7 @@
                 </form>
     
             {% endif %}
    -        <a href="{{ URL.to('/login') }}">{{ 'want_to_login'|_ }}</a><br>
    +        <a href="{{ route('login') }}">{{ 'want_to_login'|_ }}</a><br>
             {% if allowRegistration %}
                 <a href="{{ route('register') }}" class="text-center">{{ 'register_new_account'|_ }}</a><br>
             {% endif %}
    
  • resources/views/v1/auth/passwords/reset.twig+1 1 modified
    @@ -40,7 +40,7 @@
     
             </form>
     
    -        <a href="{{ URL.to('/login') }}">{{ 'want_to_login'|_ }}</a><br>
    +        <a href="{{ route('login') }}">{{ 'want_to_login'|_ }}</a><br>
             {% if allowRegistration %}
                 <a href="{{ route('register') }}" class="text-center">{{ 'register_new_account'|_ }}</a><br>
             {% endif %}
    
  • resources/views/v1/auth/register.twig+3 3 modified
    @@ -15,7 +15,7 @@
         <div class="register-box-body">
             <p class="login-box-msg">{{ 'register_new_account'|_ }}</p>
     
    -        <form id="register" method="POST" action="{{ URL.to('/register') }}">
    +        <form id="register" method="POST" action="{{ route('register') }}">
                 <input type="hidden" name="_token" value="{{ csrf_token() }}">
     
                 <div class="form-group has-feedback">
    @@ -41,8 +41,8 @@
                 </div>
             </form>
     
    -        <a href="{{ URL.to('/login') }}">{{ 'want_to_login'|_ }}</a><br>
    -        <a href="{{ URL.to('/password/reset') }}">{{ 'forgot_my_password'|_ }}</a>
    +        <a href="{{ route('login') }}">{{ 'want_to_login'|_ }}</a><br>
    +        <a href="{{ route('password.reset.request') }}">{{ 'forgot_my_password'|_ }}</a>
         </div>
     
         {% include 'v1.partials.password-modal' %}
    
  • resources/views/v1/partials/menu-sidebar.twig+6 1 modified
    @@ -221,9 +221,14 @@
                 {% endif %}
             </ul>
         </li>
    +
    +
         {% if 'remote_user_guard' != authGuard or '' != logoutUri %}
    +        <form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: none;">
    +            <input type="hidden" name="_token" value="{{ csrf_token() }}" />
    +        </form>
             <li>
    -            <a href="{{ route('logout') }}">
    +            <a href="{{ route('logout') }}" onclick="event.preventDefault();document.getElementById('logout-form').submit();">
                     <span class="fa fa-sign-out fa-fw"></span>
                     <span>{{ 'logout'|_ }}</span>
                 </a>
    
  • resources/views/v1/profile/index.twig+6 1 modified
    @@ -52,7 +52,12 @@
                                                 <a href="{{ route('profile.change-password') }}">{{ 'change_your_password'|_ }}</a>
                                             </li>
                                             {% endif %}
    -                                        <li><a href="{{ route('logout') }}">{{ 'logout'|_ }}</a></li>
    +
    +                                        <form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: none;">
    +                                            <input type="hidden" name="_token" value="{{ csrf_token() }}" />
    +                                        </form>
    +
    +                                        <li><a href="{{ route('logout') }}" onclick="event.preventDefault();document.getElementById('logout-form').submit();">{{ 'logout'|_ }}</a></li>
     
                                             {% if true == isInternalAuth and true == isInternalIdentity %}
                                             <li>
    
  • resources/views/v2/auth/register.twig+1 1 modified
    @@ -86,7 +86,7 @@
                                         </a>
                                     </li>
                                     <li>
    -                                    <a href="{{ URL.to('/login') }}">{{ 'want_to_login'|_ }}</a>
    +                                    <a href="{{ route('login') }}">{{ 'want_to_login'|_ }}</a>
                                     </li>
                                     <li>
                                         <a href="{{ route('password.reset.request') }}">{{ 'forgot_my_password'|_ }}</a>
    
  • resources/views/v2/partials/layout/navbar.twig+4 1 modified
    @@ -50,6 +50,9 @@
             </li>
             <!-- Notifications Dropdown Menu -->
             <li class="nav-item dropdown">
    +            <form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: none;">
    +                <input type="hidden" name="_token" value="{{ csrf_token() }}" />
    +            </form>
                 <a class="nav-link" data-toggle="dropdown" href="#">
                     <span class="far fa-user"></span>
                 </a>
    @@ -62,7 +65,7 @@
                         <span class="fas fa-fw fa-cogs mr-2"></span> {{ 'preferences'|_ }}
                     </a>
                     <div class="dropdown-divider"></div>
    -                <a href="{{ route('logout') }}" class="dropdown-item">
    +                <a href="{{ route('logout') }}" class="dropdown-item" onclick="event.preventDefault();document.getElementById('logout-form').submit();">
                         <span class="fas fa-sign-out-alt mr-2"></span> {{ 'logout'|_ }}
                     </a>
                 </div>
    
  • routes/web.php+1 1 modified
    @@ -81,7 +81,7 @@ static function () {
         ['middleware' => 'user-simple-auth', 'namespace' => 'FireflyIII\Http\Controllers'],
         static function () {
             Route::get('error', ['uses' => 'DebugController@displayError', 'as' => 'error']);
    -        Route::any('logout', ['uses' => 'Auth\LoginController@logout', 'as' => 'logout']);
    +        Route::post('logout', ['uses' => 'Auth\LoginController@logout', 'as' => 'logout']);
             Route::get('flush', ['uses' => 'DebugController@flush', 'as' => 'flush']);
             //Route::get('routes', ['uses' => 'DebugController@routes', 'as' => 'routes']);
             Route::get('debug', 'DebugController@index')->name('debug');
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

4

News mentions

0

No linked articles in our index yet.