yii2 CSRF not working properly - csrf

I copied create form code from view source when user use to logged in and then I created html file from copied code then I logged out and then logged in again. when i submited html file then system accept it witout any csrf checking. not sure where issue is. csrf is enabled also _csrf code also avaiable in view source too
<input type="hidden" name="_csrf" value="ttPy-NP-8FUCQxKczEWgkl66JQfb3JfJHwUOSsi9wjTxkp_LgKqxFFYBQu2iL8T2LIxpQ7Xuzo0ucEYfjPSUBg==">

It resolved reason being it happend becuase csrf validation via cookie so it not clear cookie properly when user logged out. so easy solution for this is do changes in main.php
'request' => [
'enableCsrfCookie' => false,
],

Related

Gorilla CSRF - Forbidden - CSRF token invalid - fails when there are two forms

I'm adding in CSRF token validation and I'm running into a problem where I have two forms on a page and one of them will submit successfully and the other will not. I'm not doing AJAX requests, I'm simply using hidden input fields. If I submit the form when it is the only one on the page, it submits without issue. If I submit it on a page with more than one form, it fails.
Below is the template code for my two forms
{{if .IsAuthenticated}}
<form action='/admin/logout' method='POST'>
<button>Logout</button>
{{.CsrfField}}
</form>
{{end}}
<form action='/admin/stuff/create' method='POST'>
{{with .Form}}
<div>
<label>Title:</label>
<input type='text' name='title' value='{{.Get "title"}}'>
</div>
<div>
<input type='submit' value='Publish stuff'>
</div>
{{end}}
{{.CsrfField}}
</form>
And this is what the generated HTML looks like. Both appear to be valid.
When I click the "Logout" button though, I get the Forbidden - CSRF token invalid error, but clicking the create input value in the second form always works.
The logout button is correctly validated when I attempt to use it on the home page which is "/admin/" but it does not work on any of the other pages "/admin/snippet/:id" or "/admin/snippet/create". The Logout button is part of a base template, so it appears on every page, so there shouldn't be anything different in how it appears on any page.
I've read other SO posts about multiple forms & CSRF tokens on a page and I understand there should be no issue with multiple forms with the same information as long as you have each one in it's own form, it should be fine. So I am not sure where I am going wrong.
I found the issue. Currently the way that gorilla/csrf works, it does not like creating the masked token from one path and then sending that token off to another path. So in my situation, going from /admin/snippet/create to /admin/logout threw an error because it was expecting the path for the token to be /admin/snippet/<something> and so it threw an error.
This issue has been addressed in this PR: https://github.com/gorilla/csrf/pull/147 and essentially the solution is to set the default path yourself to something which all of your routes will contain, so in my case that was /admin
This is what my CSRF declaration looks like now in main.go
var csrfMiddleWare = csrf.Protect(
[]byte("<put your 32 character key here>"),
csrf.Path("/admin"),
csrf.Secure(false),
)
A note, if you had this issue and then apply this fix and it doesn't resolve the problem, trying testing in a separate browser as there may be some caching issues.

Joomla 3 redirect after wrong login try

Iam using the login module of Joomla. Login and Logout redirects to the pages which are set in the modul settings.
My problem is the status, where a user tries to login with wrong user credentials. In this case, the user will be redirected to component/users/?view=login page. In my case, this page is not in use and also not designed like the rest of the pages. Therefore I would like to redirect the user, after a wrong login, to the previous page.
Does anybody have a clue, how to solve that?
thx
You will need to modify users controller. But to keep it "update proof" you cannot modify the core code, thats why we will make an override:
Go to the components/com_users/controllers/ and duplicate a file called user.php, you can call a new file user2.php
Open user2.php file and rename controller class to UsersControllerUser2
Create a template override of your login module (to make it update proof also), create a templates/YOUR_TEMPLATE/html/mod_login folder and copy modules/mod_login/tmpl/default.php file there.
Open file created in step 3 and change login module task from <input type="hidden" name="task" value="user.login" /> to <input type="hidden" name="task" value="user2.login" />
Open user2.php file once again, and modify this part of code (around lines 77-82):
$app->redirect(JRoute::_('index.php?option=com_users&view=login',
false));
Change $app->redirect route to whatever you want :)
The best way to do this is with a template override for the mod_login module. This link details the specifics of how to do that.
http://docs.joomla.org/Layout_Overrides_in_Joomla
Basically, you copy the file located at /modules/mod_login/tmpl/default_login.php to /templates/{YOUR_TEMPLATE}/html/mod_login and this is what Joomla will use to render any mod_login modules as long as you keep the file name the same.
At line 116 you will see this line of code:
<input type="hidden" name="return" value="<?php echo $return; ?>" />
You now have full programmatic control of what the return value should be. I usually pass the base64 encoded return param in the URL, which I in turn parse and insert as the value of the return hidden input in my module template override
A side note, you should never alter core files or place custom files along side core files for a variety a reason, the primary being any subsequent Joomla update could wipe out your changes breaking your website.
In Joomla 3.6.1 in order to stay in the same page after a wrong login, you have to change a line in /components/com_users/controllers/user.php
Find:
if (true !== $app->login($credentials, $options))
{
// Login failed !
// Clear user name, password and secret key before sending the login form back to the user.
$data['remember'] = (int) $options['remember'];
$data['username'] = '';
$data['password'] = '';
$data['secretkey'] = '';
$app->setUserState('users.login.form.data', $data);
$app->redirect(JRoute::_('index.php?option=com_users&view=login', false));
and just comment the last line:
// $app->redirect(JRoute::_('index.php?option=com_users&view=login', false));
That's all.
di3sel great override, still working on 2019, in your step 3 you could add:
Create a template override of your login module (to make it update proof also), create a templates/YOUR_TEMPLATE/html/mod_login folder and copy modules/mod_login/tmpl/default.php file there with a different name like altlogin.php
In the admin area open yout mod_login, in the advanced tab you'll find "Presentation", and select the view you created in step 3 "altlogin" from your template.
Thanks.

Can't get the user session to be reset when CSRF token authenticity is not verified

After a couple of weeks playing with rails app and completing the rails tutorial, I wanted to learn about some common web attack in web applications.
I managed to perform a CSRF attack type using the below chunk of code in a .html file.
<form action="http://localhost:3000/users/2" method="post">
<input type="hidden" name="_method" value="delete">
<div>
<input type="submit" value="Delete">
</div>
</form>
Being logged in as an admin, I run the attack against my own code that was based on same session mechanism as Railtutorial and I succeed deleting the user where it should have been stopped as the authenticity token was missing.
The default behavior should be a session reset thus preventing the user being deleted outside of the web application.
I can see the 'Can't verify CSRF token authenticity' in the log, but the session is not reset.
Overriding the handle_unverified_request method, that should by default reset the session, with
def handle_unverified_request
raise(ActionController::InvalidAuthenticityToken)
end
the error get raised properly.
Running the attack on Railstutorial git code from railstutorial/sample_app_2nd_ed freshly install, I faced the exact same issue: the session is not reset as it should be. That mean the tutorial app is vulnerable to that kind of attack.
I dig a bit deeper into the code (http://api.rubyonrails.org/classes/ActionDispatch/Request.html#method-i-reset_session) but cannot figure out why in the context Railstutorial it doesn't seem to work.
Could anyone verify, If the tutiral is indeed vulnerable to CSRF attck? if yes would the solution be to rewrite the handle_unverified_request to do proper signout in that case? Finally why is it not working as it should be?
Thanks for your help.
I figure out how to force the signout of the user if the CSRF token can't be verify.
It seems related to the fact that we empty the session but not the remember token of the cookie.
Override handle_unverified_request in your application (so that all controller benefit from it) and add the sign_out method to clean the remember token.
class ApplicationController < ActionController::Base
protect_from_forgery
include SessionsHelper
def handle_unverified_request
sign_out
super
end
end

Post form, signed_request and session in Facebook Canvas

I'm developing a Facebook app that will run in canvas. This is the scenario (I think it's very common). This is all server-side implementation.
Being:
APP_URL: https://apps.facebook.com/xxxxxx/
CANVAS_URL: https://myexample.com/facebookApp/
Step 1 (index of the app) has a form. It has action="CANVAS_URL/step2" (note that is not the app Url). In order to use signed_request in the next step, it has an hidden field <input type="hidden" name="signed_request" value="<?php echo $_POST['signed_request'] ?>" />
Step 2: it receives the info of the form and stores it in a Session, then parses the signed_request. This works OK. I store it in the Session because I want to save it to a database after the user is authenticated. If user was logged on to the app, I redirect him to APP_URL/step3; if not, I redirect him to login dialog, with &redirect_uri=APP_URL/step3 . In both cases, note that the step 3 is APP_URL/step3 (as I need signed_request again to check if user has authenticated and another data). All redirections are made with JavaScript: <script type="text/javascript">window.top.location = "URL";</script>
Step 3: now I want to save the data previously stored in the Session. BUT as the user is navigating through FB canvas, the session data is not available.
I tried several combinations. If the form is sent to APP_URL/step2 (instead of CANVAS_URL/step2, in order to create the session for APP_URL), I can't retrieve the posted data (because it is sent to FB, not to the CANVAS_URL).
I thought about using the session_id to recreate the Session in APP_URL, but I'm afraid that it isn't a very secure approach. I'm sure that there must be a better workaround.

How to clear the form when the user doesn't provide valid username/password

I designed a form as follows:
User Name: _______________
Password: _______________
Login
I also use jQuery Form Plugin to submit the form to the server side.
It will return if the server script finds some errors. The data returned by server is in JSON format. I would like to know how I can reset the user name + password when I know the username/password is invalid in a decent way.
In other words, I can manually use jQuery to empty the username/password field if the returned result indicates a failure. In fact, I am looking for a decent way built in Form Plugin or sth else that can do this part me for automatically. The only thing I have to do is to set a flag so that if the submission is failed, then the form will be resetted.
Thank you
You cam simply do:
$('#form_id').reset();
I don't think you need a plugin for such simple task. You simply call above code based on the response.
Run this.form.reset() when a form button (e.g. Reset) is being pressed.
e.g.
<form>
...
<input type="button" value="Reset!" onclick="this.form.reset();">
</form>