I want to prevent My Web Application from the CSRF attacks.
I'm applying this solution for the same in Master Page, all the Web Pages are inherited from this Master Page.
public partial class SiteMaster : MasterPage
{
private const string AntiXsrfTokenKey = "__AntiXsrfToken";
private const string AntiXsrfUserNameKey = "__AntiXsrfUserName";
private string _antiXsrfTokenValue;
protected void Page_Init(object sender, EventArgs e)
{
//First, check for the existence of the Anti-XSS cookie
var requestCookie = Request.Cookies[AntiXsrfTokenKey];
Guid requestCookieGuidValue;
//If the CSRF cookie is found, parse the token from the cookie.
//Then, set the global page variable and view state user
//key. The global variable will be used to validate that it matches in the view state form field in the Page.PreLoad
//method.
if (requestCookie != null
&& Guid.TryParse(requestCookie.Value, out requestCookieGuidValue))
{
//Set the global token variable so the cookie value can be
//validated against the value in the view state form field in
//the Page.PreLoad method.
_antiXsrfTokenValue = requestCookie.Value;
//Set the view state user key, which will be validated by the
//framework during each request
Page.ViewStateUserKey = _antiXsrfTokenValue;
}
//If the CSRF cookie is not found, then this is a new session.
else
{
//Generate a new Anti-XSRF token
_antiXsrfTokenValue = Guid.NewGuid().ToString("N");
//Set the view state user key, which will be validated by the
//framework during each request
Page.ViewStateUserKey = _antiXsrfTokenValue;
//Create the non-persistent CSRF cookie
var responseCookie = new HttpCookie(AntiXsrfTokenKey)
{
//Set the HttpOnly property to prevent the cookie from
//being accessed by client side script
HttpOnly = true,
//Add the Anti-XSRF token to the cookie value
Value = _antiXsrfTokenValue
};
//If we are using SSL, the cookie should be set to secure to
//prevent it from being sent over HTTP connections
if (FormsAuthentication.RequireSSL &&
Request.IsSecureConnection)
responseCookie.Secure = true;
//Add the CSRF cookie to the response
Response.Cookies.Set(responseCookie);
}
Page.PreLoad += master_Page_PreLoad;
}
protected void master_Page_PreLoad(object sender, EventArgs e)
{
//During the initial page load, add the Anti-XSRF token and user
//name to the ViewState
if (!IsPostBack)
{
//Set Anti-XSRF token
ViewState[AntiXsrfTokenKey] = Page.ViewStateUserKey;
//If a user name is assigned, set the user name
ViewState[AntiXsrfUserNameKey] =
Context.User.Identity.Name ?? String.Empty;
}
//During all subsequent post backs to the page, the token value from
//the cookie should be validated against the token in the view state
//form field. Additionally user name should be compared to the
//authenticated users name
else
{
//Validate the Anti-XSRF token
if ((string)ViewState[AntiXsrfTokenKey] != _antiXsrfTokenValue
|| (string)ViewState[AntiXsrfUserNameKey] !=
(Context.User.Identity.Name ?? String.Empty))
{
throw new InvalidOperationException("Validation of
Anti-XSRF token failed.");
}
}
}
}
With this Solution I'm not able to achieve what I want.
If User A logs in, does some activity and capture the Request from Fiddler and it logs out and now User B logs in and I fire the captured Request and it successfully does it task. So My application is not prevented.
I can see Request.Cookies[AntiXsrfTokenKey] value is same for a particular session and for a new session Request.Cookies[AntiXsrfTokenKey] value is different.
What should I do insted of this line
throw new InvalidOperationException("Validation of Anti-XSRF token failed.");
On LogOut Button Click I clear each and everything.
FormsAuthentication.SignOut();
Session.Clear();
Session.Abandon();
Session.RemoveAll();
HttpCookie cookies = Context.Request.Cookies[FormsAuthentication.FormsCookieName];//Or Response
cookies.Expires = DateTime.Now.AddDays(-1);
Context.Response.Cookies.Add(cookies);
if (Request.Cookies["ASP.NET_SessionId"] != null)
{
Response.Cookies["ASP.NET_SessionId"].Value = string.Empty;
Response.Cookies["ASP.NET_SessionId"].Expires = DateTime.Now.AddMonths(-20);
}
if (Request.Cookies["AuthToken"] != null)
{
Response.Cookies["AuthToken"].Value = string.Empty;
Response.Cookies["AuthToken"].Expires = DateTime.Now.AddMonths(-20);
}
if (Request.Cookies[AntiXsrfTokenKey] != null)
{
Response.Cookies[AntiXsrfTokenKey].Value = string.Empty;
Response.Cookies[AntiXsrfTokenKey].Expires = DateTime.Now.AddMonths(-20);
}
//Response.Redirect("Logon.aspx");
FormsAuthentication.RedirectToLoginPage();
Just add #Html.AntiForgeryToken() in the form that send the data. Then decorate the action method or controller with the [ValidateAntiForgeryToken]: msdn
Use "AntiForgeryToken" to prevent CSRF attack. For better understanding refer the below links:
http://www.asp.net/web-api/overview/security/preventing-cross-site-request-forgery-(csrf)-attacks
http://www.codeproject.com/Articles/686881/Hack-Proof-Your-ASP-NET-Applica
Related
I tried to prevent user for changing the "ASP.NET_SessionId"
I tried this code:
Response.Cookies["ASP.NET_SessionId"].Value = GenerateHashKey();
But my session (Session["userId"]) was removed when I tried to set the cookie
Here is some code that I tried without success:
protected void Application_BeginRequest(object sender, EventArgs e)
{
//Check If it is a new session or not , if not then do the further checks
if (Request.Cookies["ASP.NET_SessionId"] != null && Request.Cookies["ASP.NET_SessionId"].Value != null)
{
string newSessionID = Request.Cookies["ASP.NET_SessionID"].Value;
//Check the valid length of your Generated Session ID
if (newSessionID.Length <= 24)
{
//Log the attack details here
Response.StatusCode = 401;
}
//Genrate Hash key for this User,Browser and machine and match with the Entered NewSessionID
if (GenerateHashKey() != newSessionID.Substring(24))
{
//Log the attack details here
Response.StatusCode = 401;
//throw new HttpException("401");
}
//Use the default one so application will work as usual//ASP.NET_SessionId
Request.Cookies["ASP.NET_SessionId"].Value = Request.Cookies["ASP.NET_SessionId"].Value.Substring(0, 24);
}
}
private string GenerateHashKey()
{
StringBuilder myStr = new StringBuilder();
myStr.Append(Request.Browser.Browser);
myStr.Append(Request.Browser.Platform);
myStr.Append(Request.Browser.MajorVersion);
myStr.Append(Request.Browser.MinorVersion);
SHA1 sha = new SHA1CryptoServiceProvider();
byte[] hashdata = sha.ComputeHash(Encoding.UTF8.GetBytes(myStr.ToString()));
return Convert.ToBase64String(hashdata);
}
protected void Application_EndRequest(object sender, EventArgs e)
{
//Pass the custom Session ID to the browser.
if (Response.Cookies["ASP.NET_SessionId"] != null)
{
Response.Cookies["ASP.NET_SessionId"].Value = Request.Cookies["ASP.NET_SessionId"].Value + GenerateHashKey();
}
}
How to prevent the user for set session
Looks like you are trying to secure your session value from tampering? If you set the value yourself, you override the session identifier and destroy the purpose of the asp session cookie.
ASP.Net_SessionId is a cookie which is used to identify the users session on the server. The session being an area on the server which can be used to store data in between http requests.
If you are trying to solve the session fixation problem, which is the only vulnerability of asp session cookie, then you need to introduce a new cookie like this: https://medium.com/#grep_security/session-fixation-broken-authentication-and-session-management-c37ce0111bf5
I need to access the cookies to get the user and password and then set them in the text boxes of the Login view because in that view is checked "Remember me".
LogOff method
public ActionResult LogOff()
{
//Session.Abandon();
// sign out.
FormsAuthentication.SignOut();
return RedirectToAction("Index", "Login");
}
Initialization of sessions and cookies after a successful login.
private void InitializeSessionVariables(AgentDTO user)
{
// SessionModel.AgentId = user.ID;
Response.Cookies.Clear();
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1,user.MobilePhone,DateTime.Now,DateTime.Now.AddDays(30),true,"",FormsAuthentication.FormsCookiePath);
// Encrypt the ticket.
string encryptedTicket = FormsAuthentication.Encrypt(ticket);
// Create the cookie.
HttpCookie authenticationCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket); // Name of auth cookie (it's the name specified in web.config) // Hashed ticket
authenticationCookie.Expires = DateTime.Now.AddDays(365);
// Add the cookie to the list for outbound response
Response.Cookies.Add(authenticationCookie);
}
Action Result of Login View
I have problem when I first log out and then try to access the cookie but it returns null because I run "FormsAuthentication.SignOut ();"
public ActionResult Index(LogonDTO model, string message = null, string reason = null)
{
if (SessionModel.AgentMobilePhone != null) return RedirectToAction("Index", "Home");
if (reason != null) message = "Su sessiĆ³n ha expirado. Vuelva a loguearse.";
ViewBag.Message = message;
if (Request.Cookies[FormsAuthentication.FormsCookieName] != null)
{
HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
model.Username = authTicket.Name;
//model.Password = "in progress..."
}
return View(model);
}
You can use javascript to store User information if he click on Remember Me checkbox
use
localStorage.setItem("UserName", "Smith");
to set values
and on Login page on document ready event of Jquery write below code
var UserName = localStorage.getItem("UserName");
if (UserName) $("#username").val(UserName);
Hope this will solve your problem.
My application has a Session Fixation Vulnerability. To fix that vulnerability, I am changing the session id after login.
I am having below web pages in different folders Master and Transaction.
~/Master/Login.aspx : After the credentials validated, I am setting
Response.Cookies["ASPFIXATION"].Value ="xyz";
Session["ASPFIXATION"] = "xyz"
and redirect to ~/Master/Home.aspx
~/Master/Home.aspx : In this page, I am checking the session value with the cookie value on page load event.
string cookie_value = string.Empty;
string session_value = string.Empty;
if (Request.Cookies["ASPFIXATION"] != null)
cookie_value = Request.Cookies["ASPFIXATION"].Value;
if (HttpContext.Current.Session["ASPFIXATION"] != null)
session_value = HttpContext.Current.Session["ASPFIXATION"].ToString();
if (cookie_value != g_SessionFix)
{
if (Request.Cookies["ASP.NET_SessionId"] != null)
{
Response.Cookies["ASP.NET_SessionId"].Value = null;
Response.Cookies["ASP.NET_SessionId"].Expires = DateTime.Now.AddDays(-1);
}
if (Request.Cookies["ASPFIXATION"] != null)
{
Response.Cookies["ASPFIXATION"].Value = null;
Response.Cookies["ASPFIXATION"].Expires = DateTime.Now.AddDays(-1);
}
Response.Redirect("~/Master/Login.aspx", false);
}
Here the Session has the value and it is validated.
~/Transaction/Report.aspx : If i redirect to this page and have to check the same session and cookie value logic in this page load. But here the value of HttpContext.Current.Session["ASPFIXATION"] is null and value of HttpContext.Current.Session.IsNewSession also true
Try to reassign the value after reading the values, sometimes it clears the values after reading from the session:
if (Request.Cookies["ASPFIXATION"] != null)
{
cookie_value = Request.Cookies["ASPFIXATION"].Value;
Request.Cookies["ASPFIXATION"].Value = cookie_value;
}
if (HttpContext.Current.Session["ASPFIXATION"] != null)
{
session_value = HttpContext.Current.Session["ASPFIXATION"].ToString();
HttpContext.Current.Session["ASPFIXATION"] = session_value;
}
If it still doesn't work for you then you have one other option to do it,
if your session data is not confidential then try to pass it in query string and on page redirection retrieve this value.
Response.Redirect("~/Master/Login.aspx?data=" + session_value +");
I have a MVC project that I'm using Forms Authentication, and I had to implement Roles for certain pages, so I got this in global.asax:
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie == null || authCookie.Value == "")
{
return;
}
FormsAuthenticationTicket authTicket;
try
{
authTicket = FormsAuthentication.Decrypt(authCookie.Value);
}
catch
{
return;
}
string[] roles = authTicket.UserData.Split(';');
if (Context.User != null)
{
Context.User = new GenericPrincipal(Context.User.Identity, roles);
}
}
And I save the user roles when I log in my model:
//After checking login/password
HttpCookie cookie = HttpContext.Current.Request.Cookies.Get(FormsAuthentication.FormsCookieName);
if (cookie == null)
{
cookie = new HttpCookie(FormsAuthentication.FormsCookieName);
HttpContext.Current.Response.Cookies.Add(cookie);
}
string userRoles = null;
if (users[i].PerfilID == UserRanks.Admin)
{
userRoles = "Admin;Users";
}
else
{
userRoles = "Users";
}
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(0,
users[i].Name,
DateTime.Now,
DateTime.Now.AddDays(1),
false,
userRoles,
FormsAuthentication.FormsCookiePath
);
cookie.Value = FormsAuthentication.Encrypt(ticket);
HttpContext.Current.Response.Cookies.Set(cookie);
HttpContext.Current.Session["UserID"] = users[i].UserID;
HttpContext.Current.Session["LastLogin"] = users[i].LastLogin;
HttpContext.Current.User = new GenericPrincipal(HttpContext.Current.User.Identity, userRoles.Split(';'));
To retrieve the values of the session variables, I have a static property:
public static int UserID
{
get
{
object sessionData = HttpContext.Current.Session["UserID"];
if (sessionData == null)
{
//I had something here...
return 0;
}
return Convert.ToInt32(sessionData);
}
private set { }
}
Before I implemented roles authorization, I used to save the UserID in the cookie userData, and if the UserID in the session, when requested, was null, I'd retrieve it from the cookie instead (and set it to the session again).
Now the userData is being used to the roles management and I'm having issues with the session dropping faster than the cookie expiration, and I have users logged in which I can't retrieve their UserIDs and thus fails for all operations.
So I have to put a checker in each controller function such as:
if (MyUser.Session.UserID == 0)
{
//redirect to Login
}
...which defeats the whole purpose of using [Authorize] I guess.
Is there a better way to handle login expiration and session variables like this?
I thought about using JSON or some other format and save a bunch of userData in the cookie, but I'd like something simpler, if possible.
Also, I'm doing this in the login:
HttpContext.Current.User = new GenericPrincipal(HttpContext.Current.User.Identity, userRoles.Split(';'));
Which seems to be about the same the AuthenticateRequest does (I got that part from elsewhere, seemed to be the recommended way to handle member roles), but it doesn't work like it should. The user always gets redirected out on the [Authorize(Roles="Admin")] or even the [Authorize] only functions if I leave only that (and remove the global.asax part). Why?
I have built a shopping cart that uses Session State to keep the shopping cart data while the user is browsing the store.
I have an issue where if I leave the browser window open for a long time on step1 of the shopping cart, then press "go to step 2", my actions throw an error because the step2 action assumes the session hasn't expired and the ShopCart object is in the correct state.
I would like this scenario to be nicer for my users, but I think i need to somehow detect if the session has expired so that on next request I can throw them to Step1.
I found the following code that claims to to solve the problem, but it doesn't work for me.
The IsNewSession condition is true but the condition
if ((null != sessionCookie) && (sessionCookie.IndexOf("ASP.NET_SessionId") >= 0)) {
// handle expired session
}
always returns false and it never handles the invalid session. I'm confused.
Is this possible in ASP.NET (and MVC)?
Way 1
Put this code in the Init / Load event of Page 2...
if (Context.Session != null)
{
if (Context.Session.IsNewSession)
{
string sCookieHeader = Request.Headers["Cookie"];
if ((null != sCookieHeader) && (sCookieHeader.IndexOf("ASP.NET_SessionId") >= 0))
{
if (Request.IsAuthenticated)
{
FormsAuthentication.SignOut();
}
Response.Redirect("Error Page");
}
}
}
Way 2
Alternative you can check whether the Session object exists before proceeding to work with it in Page 2, like this:
if (Session["Key"] != null)
{
Object O1 = (Object) Session["Key"];
}
else
{
Response.Redirect("ErrorPage.aspx");
}
The King 's answer does not work for me. I have added FormsAuthentication.SignOut() in OnActionExcuting(). The Response.Redirect will not work!
if (Request.IsAuthenticated)
{
FormsAuthentication.SignOut();
}
This is my complete method
public class SessionExpireFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
HttpContext ctx = HttpContext.Current;
// check if session is supported
if (ctx.Session != null)
{
// check if a new session id was generated
if (ctx.Session.IsNewSession)
{
// If it says it is a new session, but an existing cookie exists, then it must
// have timed out
string sessionCookie = ctx.Request.Headers["Cookie"];
if ((null != sessionCookie) && (sessionCookie.IndexOf("ASP.NET_SessionId") >= 0))
{
string redirectOnSuccess = filterContext.HttpContext.Request.Url.PathAndQuery;
string redirectUrl = string.Format("?ReturnUrl={0}", redirectOnSuccess);
string loginUrl = FormsAuthentication.LoginUrl + redirectUrl;
if (ctx.Request.IsAuthenticated)
{
FormsAuthentication.SignOut();
}
RedirectResult rr = new RedirectResult(loginUrl);
filterContext.Result = rr;
//ctx.Response.Redirect("~/Home/Logon");
}
}
}
base.OnActionExecuting(filterContext);
}
}
You need to create the Session_OnEnd method In Global.asax.cs file in your project.
this is my code and I am able to Detecting Session expiry on ASP.NET MVC
protected void Session_OnEnd(object sender, EventArgs e)
{
int userid = 0;
userid = Convert.ToInt32(Session["UserID"]);
if (userid != 0)
{
var userActivity = DependencyResolver.Current.GetService<IUserRepo>();
var responce = userActivity.LogOutUsers(userid);
if (responce == true)
{
Session.Clear();
Session.Abandon();
}
}
}
more