HP Fortify Cookie Error of Header Manipulation - c#

I am using Fortify to scan my code. It is identifying the error "Header Manipulation: Cookies". Further it says "includes unvalidated data in an HTTP cookie". My code is below.
String cookieName = "Foo";
System.Text.RegularExpressions.Regex rgx = new System.Text.RegularExpressions.Regex("[^a-zA-Z0-9 -]");
String FullCookieName = ".OmniPro" + cookieName;
FullCookieName = rgx.Replace(FullCookieName, "");
HttpCookie oldCookie = Request.Cookies[FullCookieName] ;
if ( oldCookie != null )
{
oldCookie.Expires = DateTime.Now.AddDays( -1 );
Response.Cookies.Add( oldCookie );
}
The error is identified on "Cookies.Add".
My intention is to just expire the old cookie. I have found no way to make Fortify happy. Any help would be appreciated.

The problem is taking the old cookie and then sending it back out. Cookies are not considered a trusted input for Fortify because they can be edited by the user. You would want to validate what is inside the cookie before adding it to the response. Even when you do this, Fortify will still likely report the issue. When doing input validation Fortify doesn't trust your validation inherently. You have to create a custom rule to do that. Once you think the input is sufficiently sanitized you could also just suppress the issue.
Fortify has a user community at https://protect724.hp.com that is also monitored by support. You may get quicker answers there.

I changed the code to be like below and Fortify accepted it.
String cookieName = "Foo"
System.Text.RegularExpressions.Regex rgx = new System.Text.RegularExpressions.Regex("[^a-zA-Z0-9 -]");
String FullCookieName = ".OmniPro" + cookieName;
HttpCookie oldCookie = Request.Cookies[FullCookieName];
if (oldCookie != null)
{
String DeleteCookieName = rgx.Replace(FullCookieName, "");
HttpCookie expiredCookie = new HttpCookie(DeleteCookieName) { Expires = DateTime.Now.AddDays(-1) };
HttpContext.Current.Response.Cookies.Add(expiredCookie); // overwrite it
}
Thanks

It seems to me that the extension .OmniPro has a very specific use case, which I don't question. However, the regular expression doesn't seem to be essential.
Much simpler code passes the HP's Fortify scan for header manipulation prevention:
HttpCookie expiredCookie = new HttpCookie(DeleteCookieName)
{ Expires = DateTime.Now.AddDays(-1) };
HttpContext.Current.Response.Cookies.Add(expiredCookie); // Overwrite cookie.
Moreover, for these kind of cookies which expire immediately (see DateTime.Now.AddDays(-1)) I'm a bit sceptical if it's not a false positive, because this cookie can be never fetched - it simply expires before it has been created.

Related

Changing HttpContext.Current.User.Identity.Name

During SetAuthCookie part we are manipulating user name slightly like this
string userInfo = identity.Name + "|" + Util.GetIPAddress();
FormsAuthentication.SetAuthCookie(userInfo, isPersistent);
this is in order to make some checks with users IP Address inside Application_AuthenticateRequest
Later on I want to revert the name back to its normal (without "|" and IP address) but couldn't find a way to do it.
Questions I came across generally handled the user name not updating correctly but what I need is to reassign the name.
I tried to set a new cookie and set a new Authcookie but they didnt work, HttpContext.Current.User.Identity.Name doesn't change.
How can I do this?
It is a better aproach to build your own authentication cookie to add the custom values you need, that way you keep the username unchanged wich is more consistent and the expected behavior.
Take into account doing this, you have the userdata (the ip) encrypted in the cookie.
var cookie = FormsAuthentication.GetAuthCookie(name, rememberMe);
var ticket = FormsAuthentication.Decrypt(cookie.Value);
var newTicket = new FormsAuthenticationTicket(ticket.Version, ticket.Name, ticket.IssueDate, ticket.Expiration,ticket.IsPersistent, userData, ticket.CookiePath);
var encTicket = FormsAuthentication.Encrypt(newTicket);
cookie.Value = encTicket;
//and add the cookie to the current HttpContext.Response
response.Cookies.Add(cookie);
Additionaly, you can retrieve this userData back from the current User.Identity
var data = (HttpContext.Current?.User.Identity as FormsIdentity)?.Ticket.UserData

Making server cookies secure

I've been trying to figure out how to set the secure flag on all the server cookies for our website. We're running .NET 4.5. I tried adding <httpCookies requireSSL="true" /> to the web.config file. I tried adding <authentication><forms requireSSL="true" /></authentication>. I tried setting the secure flag in code. Nothing had any effect. Adding the following c# function to Global.asax.cs was supposed to work, but didn't:
protected void Application_EndRequest()
{
string authCookie = FormsAuthentication.FormsCookieName;
foreach (string sCookie in Response.Cookies)
{
if (sCookie.Equals(authCookie))
{
// Set the cookie to be secure. Browsers will send the cookie
// only to pages requested with https
var httpCookie = Response.Cookies[sCookie];
if (httpCookie != null) httpCookie.Secure = true;
}
}
It finally started working after I got rid of the "if (sCookie.Equals(authCookie))..." statement. So this is the working version:
protected void Application_EndRequest()
{
string authCookie = FormsAuthentication.FormsCookieName;
foreach (string sCookie in Response.Cookies)
{
// Set the cookie to be secure. Browsers will send the cookie
// only to pages requested with https
var httpCookie = Response.Cookies[sCookie];
if (httpCookie != null) httpCookie.Secure = true;
}
}
I have several questions. First, what is the logic behind putting this in the Application_EndRequest method? Second, why did I have to get rid of the sCookie.Equals(authCookie)) part? Finally, has anyone found a more elegant solution? Thanks.
If you are executing the request over HTTP and not HTTPS then I do not think you can set Secure = true. Can you verify that you are running over a secure connection? You can do some google / bing searches on how to generate a local certificate if you are testing on your dev box. Also do not forget to encrypt your cookie so its not readable on the client side.
Here is some sample code.
var userName = "userName";
var expiration = DateTime.Now.AddHours(3);
var rememberMe = true;
var ticketValueAsString = generateAdditionalTicketInfo(); // get additional data to include in the ticket
var ticket = new FormsAuthenticationTicket(1, userName, DateTime.Now, expiration, rememberMe, ticketValueAsString);
var encryptedTicket = FormsAuthentication.Encrypt(ticket); // encrypt the ticket
var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket)
{
HttpOnly = true,
Secure = true,
};
EDIT - Added link
Also take a look at this previous answer and how you can configure your web.config to ensure that cookies are always marked as secure.

Cookie not allowing multiple key/value pairs

I've got a simple scheme for keeping a user logged in using a cookie. I want the cookie to contain two name value pairs when i am done. I've used this basic implementation before, I can't understand why it isn't working for me this time.
protected void SetAuthCookie(string EventCode, string id)
{
SHA1 sha = SHA1.Create();
byte[] data = sha.ComputeHash(Encoding.UTF8.GetBytes(id));
HttpCookie AuthCookie = new HttpCookie("MyCookie");
StringBuilder sBuilder = new StringBuilder();
for (int i = 0; i < data.Length; i++)
{
sBuilder.Append(data[i].ToString("x2"));
}
AuthCookie["eventcode"] = EventCode;
AuthCookie["id"] = sBuilder.ToString();
Response.Cookies.Add(AuthCookie);
}
Here's what i've discovered so far: If I comment out "AuthCookie["eventcode"] = EventCode;" then in my browser i see that MyCookie is left with value "id=foo".
Likewise, if I comment out "AuthCookie["id"] = sBuilder.ToString();" I see MyCookie is left with value "eventcode=foo".
What I want is MyCookie to have a value of "eventcode=foo&id=bar". If i leave neither line commented out, however, In my browswer, i see that MyCookie has no\empty value. What gives?
The only difference in previous implementations is thatI haven't processed the 'id' parameter - it was already a guid. I think the fact that it is a cryptographically hashed string is a red herring, because hard coding 'foo' as the value for cookie value for 'id' or 'eventcode' leads to the same outcome. I may be wrong about that
HttpCookie AuthCookie = new HttpCookie("MyCookie");
AuthCookie.Values["eventcode"] = EventCode;
AuthCookie.Values["id"] = sBuilder.ToString();
AuthCookie.Expires = DateTime.Now.AddDays(1);
Response.Cookies.Add(aCookie);
This should work, says MSDN
I've found Google Chrome to have a few weird issues with localhost/dev websites. Could this be the case?

Delete cookie on clicking sign out

I am creating the cookie using the code below, How to read the txtusername value in another page and how to delete the cookie when I click sign out(code for sign out). I am new to programming please help.
string cookiestr;
HttpCookie ck;
tkt = new FormsAuthenticationTicket(1, txtUserName.Value, DateTime.Now,
DateTime.Now.AddMinutes(30), chkPersistCookie.Checked, "your custom data");
cookiestr = FormsAuthentication.Encrypt(tkt);
ck = new HttpCookie(FormsAuthentication.FormsCookieName, cookiestr);
if (chkPersistCookie.Checked)
ck.Expires = tkt.Expiration;
ck.Path = FormsAuthentication.FormsCookiePath;
Response.Cookies.Add(ck);
You should never store password as a cookie. That's a very big security threat. To delete a cookie, you really just need to modify and expire it. You can't really delete it, i.e. remove it from the user's disk. Check out this documentation.
Here is a sample:
HttpCookie aCookie;
string cookieName;
int limit = Request.Cookies.Count;
for (int i=0; i<limit; i++)
{
cookieName = Request.Cookies[i].Name;
aCookie = new HttpCookie(cookieName);
aCookie.Expires = DateTime.Now.AddDays(-1); // make it expire yesterday
Response.Cookies.Add(aCookie); // overwrite it
}
You cannot directly delete a cookie, you have to set it to expire before the current date:
if (Request.Cookies["clienDetails"] != null)
{
HttpCookie myCookie = new HttpCookie("clienDetails");
myCookie.Expires = DateTime.Now.AddDays(-1d);
Response.Cookies.Add(myCookie);
}
You can read more about it here.
Furthermore I really encourage you to not write your own security but to read up on asp.net membership. More secure and easier to use. As I can see many flaws in your security model. Storing the password in plain text in a cookie is really really bad.
EDIT:
As you now changed your code, you have to do this to remove the cookie:
if (Request.Cookies[FormsAuthentication.FormsCookieName] != null)
{
HttpCookie myCookie = new HttpCookie(FormsAuthentication.FormsCookieName);
myCookie.Expires = DateTime.Now.AddDays(-1d);
Response.Cookies.Add(myCookie);
}
FYI this did not work for me using Chrome 69 with the Continue where you left off feature enabled. Similar issue with Firefox. Disabling this feature worked for me.
See
Chrome doesn't delete session cookies
How to delete or expire a cookie in Chrome using Asp.Net
In my case this code worked:
Response.Cookies.Delete("access_token");
return Ok();

weird MVC2 Cookies problem

I am having a cookie problem in the below example. the cookie does get created and when i put a debug point after its creation i can check whats in the cookie with a watch. however, when i restart the website, the cookie is still there, but has become empty and will not create the model (all fields empty are null.)
I looked around and found bugs relating to using response.Cookie and having no expiry date, but i changed things around and it stays empty. Am i doing something wrong or is this because im using localhost?
[HttpGet]
[Autorize]
public ActionResult ManagePaymentRun()
{
ViewData["currentAction"] = "Index";
payments.AccountNo = Request.Cookies["FSCSPayments"]["AccountNo"];
payments.SortCode = Request.Cookies["FSCSPayments"]["SortCode"];
payments.FirstChequeNo = "2";// Request.Cookies["FSCSPayments"]["FirstChequeNo"];
payments.FileName = Request.Cookies["FSCSPayments"]["FileName"];
payments.FRN = Request.Cookies["FSCSPayments"]["FRN"];
payments.JobNumber = Request.Cookies["FSCSPayments"]["JobNumber"];
payments.StartRecNo = Request.Cookies["FSCSPayments"]["StartRecNo"];
return View(payments);
}
internal void CreateCookie()
{
HttpCookie cookie = new HttpCookie("FSCSPayments");
cookie.Values.Add("AccountNo", payments.AccountNo);
cookie.Values.Add("SortCode", payments.SortCode);
cookie.Values.Add("FirstChequeNo", payments.FirstChequeNo);
cookie.Values.Add("FileName", payments.FileName);
cookie.Values.Add("FRN", payments.FRN);
cookie.Values.Add("JobNumber", payments.JobNumber);
cookie.Values.Add("StartRecNo", payments.StartRecNo);
cookie.Expires = DateTime.Now.AddDays(14);
cookie.Path = "/";
Request.Cookies.Add(cookie);
}
cookie.Path = "C:\\Documents and Settings\\Andy\\Cookies";
This is not intended to do what you think it does. You cannot specify where the cookie will be stored on the client computer. That's absolutely browser dependent and you have no control over it. It is to restrict the access of this cookie to certain parts of your site. So if you don't want restriction simply set it to cookie.Path = "/".
Also your ManagePaymentRun action method looks strange. Why testing whether the user is authenticated when there's the [Autorize] attribute:
[HttpGet]
[Authorize]
public ActionResult ManagePaymentRun()
{
ViewData["currentAction"] = "Index";
var payments = new Payments();
payments.AccountNo = Request.Cookies["FSCSPayments"]["AccountNo"];
payments.SortCode = Request.Cookies["FSCSPayments"]["SortCode"];
payments.FirstChequeNo = "2";// Request.Cookies["FSCSPayments"]["FirstChequeNo"];
payments.FileName = Request.Cookies["FSCSPayments"]["FileName"];
payments.FRN = Request.Cookies["FSCSPayments"]["FRN"];
payments.JobNumber = Request.Cookies["FSCSPayments"]["JobNumber"];
payments.StartRecNo = Request.Cookies["FSCSPayments"]["StartRecNo"];
return View(payments);
}
I think you should trobleshoot the problem, I have 3 suggestions:
1) cookie.Expires = DateTime.Now.AddDays (14);
2) be careful with the .Add(Key, Value), Values should be safe not contain some symbols, althoug i think an exception is raised
3) specify the cookie.path
but my bet is the first one.
This problem is solved and was due to the fact that i used IIS 5 and MVC. we copied this project over to a IIS7 pc now and we got the cookies working.

Categories

Resources