I have read this: https://developer.apple.com/library/mac/documentation/security/conceptual/SecureCodingGuide/Articles/ValidatingInput.html
However, I am unclear on how to avoid format String attacks with user entered data when using NSString +stringWithFormat:.
The way this vulnerability is exploited is by accepting a format string from a user.
For example, take this code. You have a simple view with a button and a text field, allowing user input to be NSLogged.
- (void)buttonTouchUpInside:(UIButton *)button
{
NSLog(#"User says:");
NSLog(self.userInputTextField);
}
What will happen if the user types crash! %# into the box and and taps the button? Well, they'll probably get a crash. But as the linked article explains, the user can use this attack vector to manipulate the stack and cause your application to execute arbitrary code. What if this string came in from an internet-based attacker?
You should never allow user input to be used as a format string. The secure way to write this code is as follows.
- (void)buttonTouchUpInside:(UIButton *)button
{
NSLog(#"User says: %#", self.userInputTextField);
}
This way, if the user types crash! %#, you'll see this printed:
User says: crash! %#
Related
I have following string:
soqDi22c2_A-eY4ahWKJV6GAYgmuJBZ3poNNEixha1lOhXxxoucRuuzmcyDD_9ZYp_ECXRPbrBf6issNn23CUDJrh_A5L3Y5dHhB0o_U5Oq_j4rDCXOJ4Q==
It's a query parameter generated by form on a page. (This is done server-side in ASP.net) We are able to submit this form programatically and get the string we need (it just leads to a detail page of an object [realworld parcel/building, publicly accessible]) and redirect our user to it. However I would like to know, if there is a way to decrypt/deobfuscate this string to know what it contains and if we could possibly just generate these without going through the form (it's a multi step form).
The string also has some sort of expiration, so I sadly cannot provide a link to the result page, as it would stop working after like 10 minutes or so.
It feels a bit like it's base64, but after trying to run it through base64 -d, it says it's invalid.
It's likely base64 with + and / replaced with - and _ to make it more browser-friendly.
Though even if it's base64-encoded, it may just be a completely random key. You won't nessesarily be able to decode it to something readable.
I'm using the Authorization header with the Basic type for authentication.
I'm following the HTTP Basic authentication specifications which states that the credentials should follow this form -> userIdentifier:password encoded in base64
We are using an email as the user identifier and according to the email format specification, the colon(':') character is permitted.
The colon(':') is also a valid character in the password.
Knowing this, I'm looking for a creative way to parse the credentials part of the header that uses a colon(':') as the separator between userID and password.
In this case it's simple -> francis#gmail.com:myPassword
This is where it gets complicated -> francis#gmail.com:80:myPasswordWith:Inside
francis#gmail.com:80 is a valid email according to the email format specification even though this is not used very often. So where do I know where to split ?
We have made the decision not to accept an email containing a ':'. But we want to notify the user that his email is not valid, how can we ensure that we are splitting the string at the right place ?
Hope I asked my question in a clear manner, don't hesitate to ask for more details
Thank you
Don’t notify the user that the email is invalid. Split according to the RFC 2617 rules (everything after the first colon is the password), then try to authenticate, fail, and return a generic “authentication failure” message.
A situation where john#example.org:80 has password secret and john#example.org has password 80:secret at the same time, seems unrealistic.
If you require your users to register, you probably do it with some other mechanism (forms?) where you can easily separate the username and tell that it is invalid.
I'm validating input in a asp.net page but the problem is it validates e-mails like hasangürsoy#şşıı.com
My code is:
if (Regex.IsMatch(email, #"\w+([-+.']\w+)*#\w+([-.]\w+)*\.\w+([-.]\w+)*"))
{ valid }
else { invalid }
EDIT:
I've written a question before especially to validate e-mail addresses including Turkish characters but now I don't want users to be able to input mails with Turkish characters because users mostly type Turkish characters by mistake and I cannot send mails to these addresses.
Why don't you just use build-in System.Net.Mail.MailAddress class for email validation?
bool isValidEmail = false;
try
{
var email = new MailAddress("hasangürsoy#şşıı.com");
isValidEmail = true;
{
catch (FormatException x)
{
// gets "An invalid character was found in the mail header: '.'."
}
RFC3692 goes into great detail about how to properly validate e-mail addresses, which currently only correctly handle ASCII characters. However this is due to change, and hence your validation should be as relaxed as possible.
I would likely use an expression such as:
.+#.+
which would ensure you're not turning people away because your regular expression gives them no choice.
If the e-mail is important you should be following it up with verification usually done via sending an e-mail to the supplied address containing a link.
I recommend you reading this:
http://www.codeproject.com/KB/validation/Valid_Email_Addresses.aspx
We have some error reporting code that, when an unhandled exception occurs, we send everything over in an email to our groups. This is great except if an unhandled exception occurs on a page with a password field then it's sent over as plain text.
Is there a way to iterate through Request.Form and figure out which item(s) are passwords? This is done at a low level so we can't look for specific controls.
Naturally, we could check to see what type the input box is but I'm not sure if that's the cleanest way. Advice?
Use a whitelist of field names that you want to email.
There could be hundreds of field names that get POSTed to your server. And password isn't the only field that is sensitive. Depending on your application, there could be other things that should be treated with a little respect.
So, make a list of field names that will assist in you in debugging. These are typically unique identifiers / database keys and such. If you have any parameter names in this list, you can include it in the email.
I've suggested a different solution earlier, but I thought you were going to handle this on the client side. Following your comments I now understand that you need to take care of this on the server side. There may be a way for you to do it, which is not really elegant, but it should work:
Add to all pages a script that collects all password field names into a new client-generated field, like so:
function collectPasswordFields() {
var inputs = document.getElementsByTagName('input'), list = [];
for (var i = 0; i < inputs.length; ++i)
if (inputs[i].type == 'password') list.push(inputs[i].name);
var field = document.createElement('input');
field.name = '__password_fields';
field.value = list.join(',');
document.getElementsByTagName('form')[0].appendChild(field);
}
Then intercept the additional field in the server-side error handler, and remove the named fields from the email.
Can something like this work for you?
The cleanest way is to check the type attribute of the input element.
The HTML5 specification has this to say about input type=password:
The input element with a type attribute whose value is "password" represents a one-line plain-text edit control for entering a password.
Data type: Text with no line breaks (sensitive information)
Control type: Text field that obscures data entry
This is a mandatory requirement from all User Agent implmentations, and it has been so since HTML 2. So this is indeed the cleanest way to do what you want.
If you want to do it on the client side (you talked about sending the data to the server) then it is relatively easy:
function hidePasswords() {
var inputs = document.getElementsByTagName('input');
for (var i = 0; i < inputs.length; ++i)
if (inputs[i].type == 'password') input[i].value = '*****';
}
As Jerome already pointed out in the comments, just keep track of the names of your password input fields and filter them before sending the error/exception report. This is the best solution as the type of the input field is not submitted.
A few solutions, though I'm not sure how bright any of them is:
1) Maintain in the page a List of input control IDs that are passwords, pass this list to the exception handler with the expectation to ignore these fields.
2) Keep a resource file in the website that lists a page name, a field id and have the exception handler check against this resource file (may not work if the exception is related to the ResourceManager)
3) Keep a database table as with idea 2. Same problems exist.
Is it possible to control the format of the password that is automatically generated by a call to MembershipUser.ResetPassword()?
I want to be able to allow or not allow certain special characters in the generated password.
I am using the SqlMembershipProvider with a password format of Hashed.
Thanks.
You may want to do this in two steps, as identified by Mark Fitzpatrick here: http://bytes.com/groups/net-asp/689452-how-reset-users-password-without-having-use-passwordrecovery#post2740740
First Reset the password, then immediately change it to a format of your liking. Obviously using a fixed string as in Mark's example would NOT be recommended - you'd want to implement some random string generator.
user.ChangePassword(user.ResetPassword(), MyMethodToGenerateRandomPassword());
Today you can also use the Membership.GeneratePassword method and pass a MinRequiredPasswordLengthor use the property already defined in Web.config like this:
var newPassword =
// 0 = Number of non alphanumeric characters
Membership.GeneratePassword(Membership.MinRequiredPasswordLength, 0);
user.ChangePassword(user.ResetPassword(), newPassword);
Have a look at this article - Changing the autogenerated password format in the SqlMembershipProvider.
I came up with a quick way to hack the SqlMembershipProvider to generate less complex passwords, and it was as simple as creating a new provider class that inherits from SqlMembershipProvider, then overriding the GeneratePassword method.
This is not a fully resolved solution but it might help.
I was hoping that there would be some configuration setting could use but overriding the GeneratePassword() method works for my situation.
We already had a crypto utility class that would generate the random password strings so it was a pretty quick change.