I used VeraCode to validate my code, in the validation, I found a vulnerability type CRLF Injection, because, I used some cookies. I tried to solve, with the tag httpOnlyCookies=true in web.config file, or with CookieName.HttpOnly = true in C# code behind, but It is not passing the validation in VeraCode. Do you have any idea?
This is my code, I declared the cookie in a superclass UserInfo.cs:
private HttpCookie httpCookie = null;
public UserInfo()
{
if (this.httpCookie == null)
{
this.httpCookie = this.Context.Request.Cookies["ExampleCookie"];
}
if (this.httpCookie == null)
{
this.httpCookie = new HttpCookie("ExampleCookie");
this.httpCookie.HttpOnly = true; //I tried with this too
this.Context.Response.Cookies.Set(this.httpCookie);
}
}
static public UserInfo GetCurrent
{
get
{
return new UserInfo();
}
}
public string UserName
{
set
{
this.httpCookie.Values["UserName"] = value.ToString();
this.Context.Response.SetCookie(this.httpCookie);
}
get
{
return this.httpCookie["UserName"] == null ? string.Empty : this.httpCookie["UserName"].ToString();
}
}
web.config:
<system.web>
<httpCookies httpOnlyCookies="true" />
Related
I want to know what is the correct way of doing this: lets say I have a login method that receives username and password, and log ins the user or return invalid username/password or not enough permissions. What is the correct way of doing this?
Way #1: throwing exception and handling in the user interface to display the error
public void Login(string username, string password)
{
if (SessionService.GetSession.IsLoggedIn)
{
throw new Exception("User is already logged in");
}
var user = GetByUsername(username);
if (user == null)
{
throw new LoginException(LoginResultEnum.InvalidUsername);
}
var hashPass = EncryptionService.Hash(password);
if (hashPass != user.password)
{
throw new LoginException(LoginResultEnum.InvalidPassword);
}
if (!user.HasPermission(PermissionTypeEnum.CanLogIn))
{
throw new MissingPermissionException(TipoPermisoEnum.CanLogIn);
}
SessionService.GetSession.Login(user);
}
Way #2: returning boolean true/false and handle the error in the UI (success or fail)
public bool Login(string username, string password)
{
if (SessionService.GetSession.IsLoggedIn)
{
return false;
}
var user = GetByUsername(username);
if (user == null)
{
return false;
}
var hashPass = EncryptionService.Hash(password);
if (hashPass != user.password)
{
return false;
}
if (!user.HasPermission(PermissionTypeEnum.CanLogIn))
{
return false;
}
SessionService.GetSession.Login(user);
return true;
}
Way #3: returning a LoginResult enum and handle in the UI
public LoginResult Login(string username, string password)
{
if (SessionService.GetSession.IsLoggedIn)
{
return LoginResult.AlreadyLoggedIn;
}
var user = GetByUsername(username);
if (user == null)
{
return LoginResult.InvalidUsername;
}
var hashPass = EncryptionService.Hash(password);
if (hashPass != user.password)
{
return LoginResult.InvalidPassword;
}
if (!user.HasPermission(PermissionTypeEnum.CanLogIn))
{
return LoginResult.Forbidden;
}
SessionService.GetSession.Login(user);
return LoginResult.OK;
}
In my view it better to create some dto if it is eligible for your case. So this dto will have the following properties:
public class LoginResponseDto
{
public bool Success { get; set; }
public string Error { get; set; }
}
And then you will return your response something like this:
public LoginResponseDto Login(string username, string password)
{
if (SessionService.GetSession.IsLoggedIn)
{
return new LoginResponseDto { Error = "User is already logged in" };
}
var user = GetByUsername(username);
if (user == null)
{
return new LoginResponseDto { Error = "There is no such user" };
}
var hashPass = EncryptionService.Hash(password);
if (hashPass != user.password)
{
return new LoginResponseDto { Error = "Incorrect password or username" };
}
if (!user.HasPermission(PermissionTypeEnum.CanLogIn))
{
return new LoginResponseDto { Error = "There is no permission to log in" };
}
SessionService.GetSession.Login(user);
return new LoginResponseDto { Success = true };
}
It is possible to see this tutorial "Create a secure ASP.NET MVC 5 web app with log in, email confirmation and password reset". Author of article use ViewBag in this article to send errors from controller and Succeeded to check whether login is okay.
In addition, try to avoid to show message about what is exactly wrong username or password.
I would say #3 is the best way.
#1 you are using Exception for non-exceptional circumstances. The control path is expected, so don't use Exceptions.
#2 By using a bool you are discarding information, is it InvalidPassword or Forbidden?
#3 Returns all information, allowing the UI to surface that information to the User.
Fortify has tool has reported a "API Abuse - Mass Assignment: Insecure Binder Configuration" for below code I appreciate someone's help to identify the security flaws in the below code. The below code is used to create an Application session in global context, Do we have any other best approach to achieve the same session with OWASP standard
public class SessionKeys
{
public const string AppHistory = "my_History ";
}
public class AppSession : IAppSession
{
public AppHistoryViewModel AppHistory
{
get
{
AppHistoryViewModel appHistory = null;
if ((HttpContext.Current != null) && (HttpContext.Current.Session[SessionKeys.AppHistory] != null))
{
appHistory = HttpContext.Current.Session[SessionKeys.AppHistory] as AppHistoryViewModel;
}
return appHistory;
}
set
{
if (HttpContext.Current != null)
{
HttpContext.Current.Session[SessionKeys.AppHistory] = value;
}
}
}
}
[UserProfileAuthorizationFilter(Order = 0)]
public class MyController : BaseController
{
#region Setter Injection
private IAppSession _appSession;
public IAppSession AppSession
{
get { return _appSession ?? (_appSession = new AppSession()); }
set
{
if (_appSession == null)
{
_appSession = value;
}
}
}
#endregion
}
Thank You!!
After removing setter property from AppHistoryViewModel it worked.
I removed below set of lines from the code and I can see no longer Vulnerability in sonarQube report
set
{
if (HttpContext.Current != null)
{
HttpContext.Current.Session[SessionKeys.AppHistory] = value;
}
}
I have a simple issue, I am trying to check if the connection string in App.config is valid and the server & database inside of it are accessible. I have tried the following code but still it doesn't work:-
public static bool checkConnectionString(string con)
{
if (ConfigurationManager.ConnectionStrings[con].ConnectionString == "" && !checkConnectionStringValidity(con))
{
return false;
}
else
{
return true;
}
}
public static bool checkConnectionStringValidity(string con)
{
try {
using(var connection = new SqlConnection(con)) {
connection.Open();
return true;
}
} catch {
return false;
}
}
And then I use the above methods in the main screen:-
if (Data.checkConnectionString("Utilities"))
{
Application.Run(new Log_In());
}
else
{
Application.Run(new ApplicationMainSettings());
}
I want that when I write wrong information in the app.config the program directs me to ApplicationMainSettings() screen.
Your method looks fine and working, the issue is && operator in the if, Due to its presents the method checkConnectionStringValidity will called only if the connection string is "" I thing it is not needed to check for "" here you can directly use like the following:
if(checkConnectionStringValidity(ConfigurationManager.ConnectionStrings[con].ConnectionString))
{
// Proceed the connection is valid
}
else
{
// Stop here the connection is invalid
}
Or else you can try with != "" && checkConnectionStringValidity(con) so the method will called only if the connection string is non-empty(because, the method will definitely return false if the value is empty). So you can try like this:
if (ConfigurationManager.ConnectionStrings[con].ConnectionString != "" && checkConnectionStringValidity(con))
{
// Proceed the connection is valid
}
else
{
// Stop here the connection is invalid
}
Refactor the code to apply the intended logic...
public static bool checkConnectionString(string key) {
var connectionSetting = ConfigurationManager.ConnectionStrings[key];
return connectionSetting != null && checkConnectionStringValidity(connectionSetting.ConnectionString);
}
We first check that the connect settings actually exist.
If it does then you can check the connection string.
If it does not then you run the chance of getting a null exception.
You can try this solution.
public static bool checkConnectionStringValidity(string con)
{
var _testConnection=false;
try {
using(var connection = new SqlConnection(con)) {
if (con.State == ConnectionState.Closed)
{
con.Open();
_testConnection = true;
con.Close();
}
}
} catch {
_testConnection = false;
}
return _testConnection ;
}
also you need to change checkConnectionString function as per below.
public static bool checkConnectionString(string con)
{
if(ConfigurationManager.ConnectionStrings[con] !=null)
{
if (Convert.Tostring( ConfigurationManager.ConnectionStrings[con].ConnectionString) == "" && !checkConnectionStringValidity(con)
{
return false;
}
else
{
return true;
}
}
else
{
return false;
}
}
Let me know if you have any query.
I have a cookie helper class that gets and sets data for a cookie.
In my controller action I'm trying to update a List collection and persist that to the cookie.
UPDATE: It seems using HttpContext.Current.Response.Cookies.Add() even if the cookie exists or not it will do an upsert on it and work correctly.
So what's the purpose of Reponse.Cookie.Set() then?
private List<int> _TestNumbers = new List<int>();
cookie = new CookieHelper(_searchCookieName);
cookie.SetData("testNumbers", _TestNumbers);
_TestNumbers.Add(1);
cookie.SetData("testNumbers", _TestNumbers);
_TestNumbers.Add(2);
cookie.SetData("testNumbers", _TestNumbers);
_TestNumbers.Add(3);
cookie.SetData("testNumbers", _TestNumbers);
The cookie helper class
public class CookieHelper
{
public CookieHelper(string cookieName = null, HttpContext context = null)
{
// Set param defaults
context = context ?? HttpContext.Current;
if (cookieName != null)
_cookieName = cookieName;
// Load cookie if it exists, if not create one.
_cookie = context.Request.Cookies[_cookieName] ?? new HttpCookie(_cookieName);
Save();
}
public object GetData(string name)
{
return _cookie[name] == null ? null : new Base64Serializer().Deserialize(_cookie[name]);
}
public void SetData(string name, object value)
{
_cookie[name] = new Base64Serializer().Serialize(value);
Save();
}
public void Save()
{
_cookie.Expires = DateTime.UtcNow.AddDays(_cookieExpiration);
// Create the cookie if it doesn't exist
if(HttpContext.Current.Request.Cookies.Get(_cookieName) == null)
HttpContext.Current.Response.Cookies.Add(_cookie);
else
HttpContext.Current.Response.Cookies.Set(_cookie);
}
}
I'm trying to create my one custom Validation class, for logging users in and out. however.
When i log out, the Verafy Bool does not return false. (The cookie is not deleted)
What am i doing wrong? And is there anything i should be doing differently?
Hope you can help!
public static class Security
{
private static HttpCookie cookie = HttpContext.Current.Request.Cookies["Login"];
//Tells weather you are logged in or not
public static bool Verafy {
get
{
if (cookie != null)
return true;
else
return false;
}
}
//Removes cookie, (doesn't work!)
public static void signOut()
{
cookie = new HttpCookie("Login");
cookie.Expires = DateTime.Now.AddDays(-1);
HttpContext.Current.Response.Cookies.Add(cookie);
}
//Creates a cookie for x days.
public static void SignIn(int Days)
{
cookie = new HttpCookie("Login");
cookie.Name = "Login";
cookie.Expires.AddDays(Days);
HttpContext.Current.Response.Cookies.Add(cookie);
}
//This is just temporarily..
public static bool VerafyUser(string Username, string Password)
{
if (Username == "123" && Password == "123")
{
return true;
}
else
{
return false;
}
}
}
You have static field for cookie here, so it will be shared between all users of your app, dude! If someone else logged in after you leave the app, cookie will be restored.
Read the article http://mikehadlow.blogspot.com/2008/03/forms-authentication-with-mvc-framework.html. Should help.
I think you have taken the wrong approach here by storing a static variable for your cookie. As you never set the reference to null your property will never return false.
Get rid of the static field and have your property actually check if the cookie exists e.g.
public bool LoggedIn
{
get { return HttpContext.Current.Request.Cookies["Login"] != null; }
}