How to fix log forging in C# - c#

I am using Log4net for logging into my web api application. I am using below code to log warnings and error in database.
public async Task<int> ExecuteNonQuery(string procedureName,params SqlParameter[] parameters)
{
try
{
this.logger.DebugFormat("{0} stating call",procedureName);
......
......
......
}
further code
When i ran fortify scan it gives me log forging issue. Is there any idea how we can resolve this issue. I tried below code but didn't work
procedureName = Regex.Replace(procedureName, "[^ A - Za - z0 - 9 $]", string.Empty);

Fortify is guarding against Log Forging/Log Injection, where a malicious user could get unescaped input into your system in such a way that it's written to your log file. The idea would be to add in mis-leading log entries that would throw automated or manual intrusion detection or intrusion investigation attempts off the scent of the malicious user and what they are really trying to accomplish.
In order to combat this, one must carefully control which portions of user input end up being used in a log file. How to do this varies by how strict you are. You could simply escape all user input in your log, stripping out things like newlines or control characters. To be extremely strict, one removes all user input from their logging statements and uses a set of pre-developed events that form a "whitelist" of events that can be logged in the system.
In your case, it sounds like Fortify isn't smart enough to know if procedureName comes from user input or not, so it flags your logging statement as potentially containing dynamic/user content. If you are positive that you know where procedureName comes from, then you can ignore this as a false positive. Otherwise, you can use one of the mitigation techniques I've listed to make your logging statement more secure.

The answer from Seafish might be a bit hard to dissect. For that I am going to try and answer this.
As Fortify will explain, the Log Forging issue is because Fortify believes you are using a value/property that came directly from a user. In such a case, the user, if they were a bad actor, might have set that value to confuse your logs which messes with your ability to perform a proper audit.
The resolutions are usually one or multiple of the following:
Stripping out newlines or control characters from all properties or variables coming from a user before it hits your logs.
Remove all User input from being put into the logs, and instead using predefined messages to output.
Along with the first method, you can wrap all user defined values within certain markers to identify a true log entry.
The last suggestion is more of something that Fortify will likely not understand, which is why I recommended doing so in combination with the first solution. Just like using double quotes to quote someone, you can use a series of brackets around values in logs to help make it harder to forge, as well as even encrypting the Date/time thats on each line and using that to start the line so you can confirm that the start of a line is where you have a properly decrypted date/time that matches the date/time in the output message.

Related

C# Potentially Dangerous Error, Apostrophe during Form Submission

Please help me understand why this is happening. My Web Application retrieves text that contains Apostrophe from the database to display using a Label in a Web Form. However, it is getting a Potentially Dangerous Error when I submit the Web Form.
I can solve this error by using HttpUtility.HtmlDecode() on the value before I set it to Label.Text
I have been Googling, and I cannot understand the flow that causes this problem.
I understand that Potentially Dangerous Error occurs when submitting potential HTML tags like '', and it also filters some encoded characters like "'"
However, what I cannot understand are:
Does the string value automatically HTML encodes when it displays on the Web Form? Because the value from my database is not HTML encoded.
Why does decoding it solves the error when my value from the database is not encoded in the first place? If that is the case, should I decode all values from database?
I think you are looking for something like this -> How to allow apostrophe in asp.net website
The main reason this occurs is mostly due to fact that accepting apostrophes without handling it properly could lead to SQL Injection . By Default Microsoft enables a validation that occurs with every request, this occurs even before it reaches the normal page lifecycle, and checks if there is anything in the form that could potentially lead to SQL Injection or other OWASP vulnerabilities (In no way I am saying Microsoft protects you from everything, but at least tries to cover the basics and make you aware). By the end it is up to you to disable that functionality (based on my first link) but you should be aware and protect yourself in a proper manner.
On your questions enconding as the name says will take care of the apostrophe as a proper character not a special character that could still be used for a SQL query for instance. And obviously depending on the scenario you might want to decode or encode it again when you present it. If you want to display rich html then you probably need to decode, etc, etc.
Bottom line I think you should go back to my first paragraph and understand when this starts and only then you will be able to understand what would be the right solution for your case as I assume you dont want to risk creating a vulnerable website :)

Exception handling for user input outside of normal interaction

Edit: I think my question's rambled on a bit, possibly detracting from the point. So, as concisely as possible: Should I be concerned with avoiding exceptions caused by users who fiddle with their HTML request?
I'm using a drop-down field in HTML which is backed by an integer value. This value gets parsed in the back office. Currently, if the integer parsing fails, the site gives a generic error (due to top-level exception handling) and places an entry into the audit trail containing the integer parse error.
Normally, I wouldn't want an un-handled exception to be thrown by bad user input, but in this case the bad input can only be produced by a bot or a clever user. In either of these cases, the error message will not be unexpected, and should not be a security concern.
Is there any compelling reason to handle the exception? If I do this, I'll need to formalise what I want to happen when the user commits this crime. Do I show bots and malicious users their own little validation error? Do I default their values and allow the form to submit?
The answer I have: It depends.
For example, if you're writing a bank account management system and find out that user is trying to move "Lorem ipsum" U.S. dollars from one of his accunts to another, then that is probably very bad and you should not let this operation happen. User message of a generic error would be fine.
On the other hand, if you are writing a "reverse polish notation online calculator" and encounter a ";" character, you can show the exact reason to the user.
If you are validating user's age, hope it is an integer between 0 and 100, but you get a 2,147,483,647 value, then it should be fine to simply substitute it by 10.
This is more like a project-dependent question rather than a technology-dependent.

Path Manipulation (security vulnerability)

A Fortify security review informed us of some path manipulation vulnerabilities. Most have been obvious and easy fixes, but I don't understand how to fix the following one.
string[] wsdlFiles = System.IO.Directory.GetFiles(wsdlPath, "*.wsdl");
"wsdlPath" is input from a textbox. Is this something that just can't be fixed? I can validate the path exists, etc. but how is that helping the vulnerability?
If the data is always obtained from a text box whose contents are determined by the user, and the code runs using the permissions of that user, then the only threat is that of the user attacking themselves. That is not an interesting threat.
The vulnerability which the tool is attempting to alert you to is that if low-trust hostile code can determine the contents of that string then the hostile code can mount an attempt to discover facts about the user's machine, like "is such and such a program that I happen to know has a security vulnerability installed and unpatched?" or "is there a user named 'admin' on this machine?" and so on.
You should never feed anything directly into OS API's unfiltered. You should sanitize the input, make sure it doesn't contain paths (ie "../../../somefile" And make sure it truncates long names, and contains only valid filename characters (for instance, there have been various bugs relating to international characters).
With that code, any user that is authenticated and authorized to use that function, is able to access the file system on the server. The access will be done using the credentials of the service account that runs the web application.
Depending on how the returned data is used, a malicious user might be able to get more information or make the server behave in a way that was not intended.
You should limit the set of allowed paths to only consist of one or a few carefully selected directories. Use the functions in the Path class to combine strings into paths - they take care of things like a user entering c:\allowedpath\..\windows\system32 for you.
This kind of scenarios needs encoding and decoding to make sure that data is not manipulated anywhere. Because while decryption if data is changed you will get the wrong results.
You can create your encoding and decoding. I did it using RijndaelManaged and PasswordDeriveBytes classes provided by System.Security.Cryptography;

Send Email in Global Exception Handler?

I want to add global exception handling code to C# WPF apps and, although it seems rather rakish (nobody else seems to do it), I want to send email to the developer with exception info. The main problem I can think of happening here is if the developer ends up changing his email address after the software has been deployed. Perhaps an email to the department (such as a listserv type of email broadcast address) would be more appropriate? Has anybody used this sort of methodology, and if so, what solution have you come up with to make sure that somebody gets the exception-generated email?
Is this the best solution:
// in exception code (pseudocode)
try
SendEmailToTheCoder();
catch
on EmailAddressNotValid:
try
SendEmailToTheListServ()
catch
on EmailNotSent:
LogExceptionDataToLog("Bla");
...or has my brain gone pear-shaped again (I don't know what that means, but it's British, so it must be wickedly funny)
The best thing to do is to keep the details of the messaging outside of the application.
For instance, you may log errors to a text file or some other kind of log, then have an external application or Windows service monitor that log and decide what to do -- such as sending an email, or creating a digest of all messages of the day and emailing it, or a similar action.
This way, you can optimize and modify what happens in case of these errors, without having to change your program code. You can also reuse that system with other applications that also just log errors to a text file, which has a lower probability of error than connecting to an SMTP server and sending a message.
I would just create a distribution group, something like developer#yourcompany.com and add people responsible for the program part of that distribution group. If one developer leaves the company, nothing in your code needs to change and no trying one thing first and then another one.
Better yet, use a logging framework such as log4net (nlog is also popular); you can configure it to log to different places (xml, database, email, etc). If you do log to email, I'd always send it to a distribution group, anyway, even if that distribution group is composed of only one member.

Validating your site

What else needs to be validated apart from what I have below? This is my question.
It is important that any input to a site is properly validated:
Textboxes, etc – use .NET validators (or custom code if the validators aren’t appropriate)
Querystring or Form values – use manual validation (casting to specific types, boundary checking, etc)
This ties into the problems which XSS can reveal.
Basically you have to validate any input that someone could potentially tamper with:
Form Postbacks (mainly .NET Controls – these can be validated with .NET validation controls. Also if you have Request Validation turned on on all pages, this reduces the risk )
QueryString Values
Cookie values
HTTP Headers
Viewstate (automatically done for you as long as you have ViewState MAC enabled)
Javascript (all JS can be viewed and changed, so need to ensure no crucial functionality is handled by JavaScript- i.e. always enable server side validation)
There is a lot that can go wrong with a web application. Your list is pretty comprehensive, although it is duplication. The http spec only states, GET, POST, Cookie and Header. There are many different types of POST, but its all in the same part of the request.
For your list I would also add everything having to do with file upload, which is a type of POST. For instance, file name, mime type and the contents of the file. I would fire up a network monitoring application like Wireshark and everything in the request should be considered potentially harmful.
There will never be a one size fits all validation function. If you are merging sql injection and xss sanitation functions then you maybe in trouble. I recommend testing your site using automation. A free service like Sitewatch or an open source tool like skipfish will detect methods of attack that you have missed.
Also, on a side note. Passing the view state around with a MAC and/or encrypted is a gross misuse of cryptography. Cryptography is tool used when there is no other solution. By using a MAC or encryption you are opening the door for an attacker to brute force this value or use something like oracle padding attack to take advantage of you. A view state should be kept track by the server, period end of story.
I would suggest a different way of looking at the problem that is orthogonal to what you have here (and hence not incompatible, there's no reason why you can't examine it both ways in case you catch with one what you miss with another).
The two things that are important in any validation are:
Things you pay attention to.
Things you pass to another layer untouched.
Now, most of the things you've mentioned so far fit into the first cateogry. Cookies that you ignore fit into the second, as would query & post information if you passed to another handler with Server.Execute or similar.
The second category is the most debatable.
On the one hand, if a given handler (.aspx page, IHttpHandler, etc.) ignores a cookie that may be used by another handler at some point in the future, it's mostly up to that other handler to validate it.
On the other hand, it's always good to have an approach that assumes other layers have security holes and you shouldn't trust them to be correct, even if you wrote them yourself (especially if you wrote them yourself!)
A middle-ground position, is that if there are perhaps 5 different states some persistant data could validly be in, but only 3 make sense when a particular piece of code is hit, it might verify that it is in one of those 3 states, even if that doesn't pose a risk to that particular code.
That done, we'll concentrate on the first category.
Querystrings, form-data, post-backs, headers and cookies all fall under the same category of stuff that came from the user (whether they know it or not). Indeed, they are sometimes different ways of looking at the same thing.
Of this, there is a subset that we will actually work upon in any way.
Of that there is a range of legal values for each such item.
Of that, there is a range of legal combinations of values for the items as a whole.
Validation therefore becomes a matter of:
Identify what input we will act upon.
Make sure that each component of that input is valid in its own right.
Make sure that the combinations are valid (e.g it may be valid to not send a credit card number, but invalid to not send one but set payment type to "credit card").
Now, when we come to this, it's generally best not to try to catch certain attacks. For example, it's not so good to avoid ' in values that will be passed to SQL. Rather, we have three possibilities:
It's invalid to have ' in the value because it doesn't belong there (e.g. a value that can only be "true" or "false", or from a set list of values in which none of them contain '). Here we catch the fact that it isn't in the set of legal values, and ignore the precise nature of the attack (thus being protected also from other attacks we don't even know about!).
It's valid as human input, but not as what we will use. An example here is a large number (in some cultures ' is used to separate thousands). Here we canonicalise both "123,456,789" and "123'456'789" to 123456789 and don't care what it was like before that, as long as we can meaningfully do so (the input wasn't "fish" or a number that is out of the range of legal values for the case in hand).
It's valid input. If your application blocks apostrophes in name fields in an attempt to block SQL-injection, then it's buggy because there are real names with apostrophes out there. In this case we consider "d'Eath" and "O'Grady" to be valid input and deal with the fact that ' is significant in SQL by escaping properly (ideally by using an API for data access that will do this for us.
A classic example of the third point with ASP.NET is code that blocks "suspicious" input with < and > - something that makes a great number of ASP.NET pages buggy. Granted, it's better to be buggy in blocking that inappropriately than buggy by accepting it inappropriately, but the defaults are for people who haven't thought about validation and trying to stop them from hurting themselves too badly. Since you are thinking about validation, you should consider whether it's appropriate to turn that automatic validation off and then treat < and > in a manner appropriate for your given use.
Note also that I haven't said anything about javascript. I don't validate javascript (unless perhaps I was actually receiving it), I ignore it. I pretend it doesn't exist and then I won't miss a case where its validation could be tampered with. Pretend yours doesn't exist at this layer too. Ultimately client-side validation is to save the good guys making honest mistakes time, not to twart the bad guys.
For similar reasons, this is best not tested through a browser. Use Fiddler to construct requests that hit the validation points you want to examine. This way all client-side validation is by-passed, and you're looking at the server the same way an attacker will.
Finally, remember that a page with 100% perfect validation is not necessarily secure. E.g. if your validation is perfect but your authentication poor then someone can send "valid" code to it that will be just - perhaps more - nasty as the more classic SQL-injection of XSS code. That hits onto other topics that are for other questions, except that validation as discussed here is only part of the puzzle.

Categories