http://www.kalzumeus.com/2010/06/17/falsehoods-programmers-b...
If you try to validate names, or if you don't safely escape names along with your other user-input strings, you're gonna have a bad time.
http://www.kalzumeus.com/2010/06/17/falsehoods-programmers-b...
If you try to validate names, or if you don't safely escape names along with your other user-input strings, you're gonna have a bad time.
My given names in English are Mark Jason, and that's on my birth certificate. In Greek, they're Μάρκος Ιάσονας, which are the equivalents, and that's on my municipal birth records there (registered as a foreign birth at the time of baptism). There seems to be a move towards wanting to use "accurate" transliterations, though, rather than the more traditional method of translating names to equivalents (Mark<->Markos, George<->Georgios, Paul<->Pavlos, etc.). Sometimes people desire that: maybe someone named Михаил in Russian really doesn't want to be turned into Michael, but wants to go by Mikhail. That's fine, if they prefer. But in my case, I consider each of these translated forms to be my name in the respective languages, and do not consider the transliterated forms to be my name.
But in trying to sort out some paperwork, it appears that what I am supposed to do is one of these two things: 1) change my name in English from Mark Jason to Markos Iasonas, the transliteration of my Greek name; or 2) change my name in Greek from Μάρκος Ιάσονας to Μαρκ Τζέισον, the transliteration of my English name. But I don't want to do either of those things. #2 in particular is ridiculous, because it doesn't decline properly, and is trying to approximate a 'j' sound with 'tz'.
CSB: My mom signed me up for a book club when I was 6 or 7. For the Firstname field, she wrote, "R Edward" for reasons known only to her. For the next three years, every couple months, I'd get a package addressed to Redward <Lastname>. I could just imagine the shipping clerk in that company reading my shipping label and saying to himself, "Redward... what a goofy name."
To compound the problems caused by this, I switched to using my first name as my primary name around the same time as I switched coast. People on the east coast know me as my middle name, people from the west coast know me as my first name. This can come in handy sometimes as it gives me a very quick indication of where I know somebody from, but gave me a good deal of trouble recently at a west-coast wedding with lots of east-coast people attending... The fact that some of my friends were introducing me to other people with just my last name made it quite... interesting.
Not to mention it casts serious doubt as to your organic nature.
Safeway checkout clerks are apparently required to thank me by name, using the name that pops up on their screens when I swipe my card. For nearly twenty years now, all over the country, every harried Safeway checker has sent me on my way with, "Thank you Mr., uh, Asperger", or "Thanks, um, Mr. Ostrich", or whatever that bizarre cluster of letters randomly turned into on the way out of their mouths.
At first, I thought I should fix it, but I quickly grew to enjoy the show. I also enjoy the thought of them trying to cross-match Mr. Asperger with other consumer databases.
One example: Many years ago I subscribed to TIME and filled out a form where I checked "Mr." Apparently the person who typed in my name decided to "correct" this error and I became a "Mrs."... and I wasn't even married :-)
The company I work at has offices in different cities, so most of the communication are done by email and instant messaging. I see a clear difference between the messages from people who know my gender, and those who probably think I'm female. Even attempts at flirting...
http://en.wikipedia.org/wiki/Kim_Edward_Beazley
Except now when I go to networking events or interviews, I tell people my middle name L* and then they point that out that my name tag or application says my first name is M* and I have to go through the whole song and dance of explaining the situation.
I'm frustrated enough to be looking into getting it legally changed. You might want to consider that as well if only to not have to deal with those phone calls any more.
1. If they're working for me, like at the doctor's office, I ask them to please call me by my middle name. They're generally respectful about it and are used to dealing with nicknames and other aliases anyway.
2. In the DMV and other situations, I just grit my teeth and answer by my first name. It's not worth the hassle of explaining and they don't care anyway.
3. If I'm being hired, I fill out my paperwork "officially" and give it to HR, with the explanation that I go by my middle name for all legal purposes.
4. Banks are kind of weird because they perform official government functions, but they're still ultimately working for me. I've only had one bank flat-out refuse to put my middle name on my debit card and checks, and I explained to the branch manager why I was walking out the door before we'd finished opening my account.
Speaking of which, why don't all companies just move to automated support systems already? These guys are doing it right http://www.zocdoc.com/
I kid you not, at his wedding when the celebrant said, "Do you Susan, take this man Brian..." his bride exclaimed, "Who's Brian?"
It is Hélder Maurício Gomes Ferreira Filho
Common reasons for failure is being too long and having non ASCII characters, but sometimes it fails for other reasons, for example do not allow me to register without a middle name ( I don't haven't one actually... ), me confused and not knowing how to register Filho ( it is not a family name, neither a surname or a last name, but it is still part of my name. It means Son, my father has the same name as me, without the Filho part), or breaking when it cross check with somewhere ( for several reasons I ended registering my name in several different ways, usually omitting Hélder, that I did not even knew was on my name until I got to school and got forced to use because of stupid rules that assume your first name is your typical name )
Accented vowels are ASCII characters but in the extended set which people sometimes don't take account.
I love how sometimes even on the same company, each place account ASCII differently.
I remember registering for a IM, and in one info screen my name was Maur&cio and in the site info screen Maur€cio and in the search screen was Maur£cio and so on...
Seriously though, most other code pages are pretty transparent to/from unicode... IBM PC-DOS extended ascii (classic ANSI-BBS) isn't so transparent.
By contrast, there were national variants of ISO/IEC 646 (also a 7-bit character set, and essentially the internationalized version of ASCII) that included accented characters within those 128 code points. Generally these swapped out things like the at-sign (@) and the curly braces and vertical pipe character for accented vowels instead.
There were also lots of 8-bit character sets in ISO/IEC 8859 (e.g. Latin-1, or ISO/IEC 8859 part 1) that included accented characters within the "extended" set of code points 128-255.
ASCII is the 7-bit encoding ANSI_X3.4-1968, composed of 95 printable and 33 control characters.
Interesting, that's similar to Junior in the US, but there it generally isn't part of the "official" name, only informal.
By your reasoning, there is no such person. If there can be a "Norman John Harman Sr." then there can also be a "Norman John Harman Jr." who does not have it listed on official documents.
(also we have "Neto" that means Grandson, it is quite popular, I know a bunch of guys like that, I don't think dro down boxes in other countries will expect that)
The thing is Dutch...
I am Hélder because of my father.
He is Hélder, because of the priest "Dom Hélder Câmara" (my Grandma was very Catholic)
Dom Hélder Câmara was named after the city of Den Helder in the Netherlands: http://en.wikipedia.org/wiki/Den_Helder
The result is kinda wonky (lots of people write it wrong, usually "Elder" that of course resulted into video game savy friends nicknaming me "Mr. Scrolls")
If text is truly free form then you don't need to validate or white list anything. Just make sure it's valid UTF-8 (or whatever encoding you're using) and escape it when you display it. That combined with using prepared statements with bind variables (aka named parameters) and you don't have any issues with user inputs.
One other benefit of this approach is that you end up with proper i18n support without doing anything special. From your apps perspective all text is the same. If user's want to use unicode characters or put html tags in their descriptions then let them. If you escape it then there's no XSS issue. Plus it's WYSIWYG[2] from a user's perspective.
Who am I to judge that a user putting "<script>alert('Haxors!');</script>" as the name of an object is a bad idea?
[1]: "Names" don't include usernames which generally should have a whitelisted character set (ex: ASCII [a-z][a-z0-9+]) or email addresses (use a a real validator ... not a regex!).
Unicode lets you represent lots of abstract characters, from different languages and societies, in one character set. That doesn't quite tell you how to render the characters. For that, you need to know what language the text is in. Unicode wants you to provide that information out-of-band, e.g. in an HTML "lang" attribute, which the renderer can use to paint the proper glyphs.
For example, the Arabic digits 4 through 7 (۴ U+06F4 .. ۷ U+06F7) have different glyphs in Persian, Sindhi, and Urdu. And a character like 直 (U+76F4) has Chinese and Japanese glyphs that may not be mutually recognizable.
Bottom line: if you want an internationalized system that can store and render multilingual text, storing the text in Unicode is a good start, but you will need to store additional info (like the language) to be able to properly render the text.
You probably need to know the language to do things like sorting, comparison, regex, etc. But if you're just storing and displaying user-entered strings and your software has no need to understand the meaning of the strings, I think it's enough to do what the parent says.
But what I'm talking about are the different glyphs used to represent the bottom row (U+06F0 .. U+06F9) depending on whether the text is in Persian, Sindhi, or Urdu. See http://www.unicode.org/versions/Unicode6.2.0/ch08.pdf, table 8-2.
There is also the issue I mentioned about Chinese vs. Japanese glyphs for the same coded character, which is at least as important in practice.
I've lately been coming around to the belief that anyone who uses the term "sanitize" in this domain, as in, "sanitize user input" really doesn't know what they are talking about (at least on average). The approach you describe is the generally correct approach; you need to ensure that the proper levels of escaping are being applied. Unfortunately this is nontrivial in practice, but it's still the correct solution.
The "sanitization" meme has resulted in me smacking down at least 3 commits from developers in my organization trying to "solve" XSS by scrubbing out all less than characters across all input from the user, or eliminating all quotes, apostrophes, less than, greater than, backticks (for shell interpolation problems), etc etc. Unfortunately, the problem is, these are in general all perfectly valid input values, and some of them really smack you in the face immediately. (For instance, names may contain apostrophes. You can't "sanitize" them away; you need to write your SQL layer to handle that correctly, such as with binding.) You handle them by managing your encoding layers correctly, not by "sanitizing" them.
(There's still some sanitization components in the resulting solution, I just don't think they are the way you should think about it. For instance, there are some characters that are flat-out forbidden in, say, an HTML attribute, and the right thing to do is just strip them out of any incoming string. But that should be thought of as a "sanitization" step being a importent element of proper encoding, but not the actual "answer".)
I've had this view for a long while. I think there's a common sense to it that either clicks or it doesn't. Plus people hear/read "escape your inputs!" so often it becomes a cargo cult.
> You can't "sanitize" them away; you need to write your SQL layer to handle that correctly, such as with binding.) You handle them by managing your encoding layers correctly, not by "sanitizing" them.
Exactly. Whitelisting the values that can be stored in field should be done to maintain the data integrity of the field. It's not an approach to solve security problems or prevent SQL injection.
> For instance, there are some characters that are flat-out forbidden in, say, an HTML attribute, and the right thing to do is just strip them out of any incoming string. But that should be thought of as a "sanitization" step being a importent element of proper encoding, but not the actual "answer".)
We ran into something like this in our app as well. When displaying meta data for an object we create related objects in the dom and reference them by id. Originally the ids were generated by simply escaping the name of the raw object but that doesn't work because as you mention there are additional restrictions on what can be used in an "id" field. The solution? Hash it! Obviously that's a very specific solution as we only cared about it being unique and tied to the other object on the same page but it worked.
Maybe you will output a data dump for someone else to print mailouts. Or you'll share the user database with a vendor's web forum. Or payment processing. Or any SaaS.
I unsubscribed from the newsletter eventually.
And ó isn't even a difficult character, it's in ISO 8859-1 for crying out loud.
http://www.i18nqa.com/debug/utf8-debug.html
I expect Vimeo used a Linux system to collect your data, and I bet the thing that blasts emails out is ultimately Linux as well. So the Windows-1252 bungle probably happened in a third system in between, maybe a Windows system chosen for its ease of administration by the community managers.
Not that this is relevant to data sanitization (they're just being fuckups here) but it shows how complex this can get.
To "sanitize" for "every possible use" is pretty much to remove everything that isn't an ASCII letter. Even unexpected spaces can cause crazy behavior. Commas can cause CSV-injections. And you might still have length problems even so. Oh, and you still can't guarantee something won't screw up even so! https://news.ycombinator.com/item?id=6140631
You can not, at the time input comes in to a system, even pretend to know where all the data might end up, someday, given the whims of who knows whom, and who knows when. The only thing that works is for each system to correctly encode its output as needed, and if you output the correct thing and a subsequent system blows it up, it's the subsequent system's fault. You can't prevent it. You only think you can, but you're wrong.
To be clear, if you could defend against those systems messing up, I'd be willing to consider it. But you can't. It's impossible, both in theory and in practice.
There's no easy answer to writing secure code. (Though it would help a lot of people used type systems to better effect in this problem.) Filtering out certain "dirty" characters isn't an easy answer either, on the grounds that it isn't even an answer. (It turns out to often become not easy, too, because as you gradually and inevitably learn exactly how it isn't working for you, the subsequent frantically flailing addition of heuristics becomes very not easy itself. It is easier in the long run to do it correctly.)
The byte sequence I need to store to communicate the name "Kei$ha O'Shaughnessey, Jr." in a UTF-8 JSON string literal, a UTF-8 HTML attribute, a UTF-16 bigendian CSV file, or an ISO-8859 SQL parameter, are going to be different - but so long as all the characters I need to pass are representable in all of those domains all I have to do is perform the correct escaping and encoding. At no point do I need to 'sanitize' the name. It's a name, it's not dirty.
If there are characters there that I can't represent in the target domain, then I need to handle the loss of information.
For instance, it may be perfectly fine in my system to have a user named '<script>alert("ha!")</script>'. Are you sure that's okay in your PHP-based web forum? Really sure? Every place they've ever shown a username to the user, it's well-escaped?
And even if that's true today, what about the day when someone decides to change the web forum software to something else? What about the day when someone turns on a feature that copies certain forum threads to an internal support system, also provided by a third party?
Not XSS, but you need to be careful about allowing through things like the LTR/RTL override characters.
If you can't use a regexp to recognize the general case of email addresses, no finite automaton can..
This is what a proper email-validation regexp looks like: http://www.ex-parrot.com/pdw/Mail-RFC822-Address.html
Similar example: Do you lock your door, or does that make no sense to you? (Because if there's no absolute, perfect, 100% protection, there's apparently no difference at all between locked, closed and wide open; right?)