11 ms·
IOS 6 injecting should_group_accessibility_children to POST requests
- ubernostrum 14y agoSo... the story here is 1. They were blindly throwing the entire set of POST data into a Rails model. 2. This started throwing errors when they got an unexpected key in POST. 3. They "solved" the problem by writing a middleware to filter out that specific key from POST. I don't even know where to begin.
- est 14y agolike you are holding iphone4 wrong? If it's an app doing RESTful API calls via HTTP POST then it should have 100% control on HTTP parameters. Watch next time Apple alter some http headers and break your API.
- mpyne 14y agoAlthough I agree with you that Apple should not alter HTTP POST parameters in-flight, the server side application must expect the client to be untrusted. Anything can connect to the server socket, not just its RESTful app on iOS.
- jmcnevin 14y agoWhat does this have to do with client trust? They're expecting the client to access their API a certain way, and the client is sending what is arguably a malformed request. This is, surprise, causing an error to occur.
- BigZaphod 14y agoYou never ever ever ever blindly trust the client to behave a certain way.
- tomjen3 14y agoThey are not. They give an error. The only issue is that a middle man is fucking with them.
- masklinn 14y agoExcept they "give an error" because the provided field doesn't exist in the database. Ignore for a second that half the reposts would break websites if an unexpected parameter yield an error instead of being ignored, if an untrusted client sent an "id" field, that would go through like hot steel through melted butter.
- ubernostrum 14y agoWell. The likeliest thing is that there is no "middle man fucking with them". The likeliest thing, since it's an iOS app posting to their API, is that they're introspecting a client-side object to get the values they care about. And that they're blacklisting values they know they don't want, rather than whitelisting values they know they do want. Which meant that when a new property showed up their app blindly submitted it to their web API, and their web API blindly accepted it because it was doing mass assignment, and that's when the API broke. Which really just hammers home the point people have been trying to get you to see, which is that these types of idioms -- mass assignment, blind trust of client-supplied data, blacklisting instead of whitelisting -- are really serious problems that should not be encouraged, and should not be swept under the rug.
- huxley 14y agoHard to tell from the post, but it sounds like Rails gave an Exception because it couldn't find should_group_accessibility_children, but that suggests that it would act on something it could find. If there was a parameter that gave a user admin access, then Rails might accept such a parameter and that might be used to take control of the app. It's similar to what happened to Github. https://github.com/rails/rails/issues/5228 https://github.com/rails/rails/issues/5228 I would think that the API would validate the POST parameters, ignore unexpected parameters and give errors for malformed expected ones. Taking it a bit further the developer should then be notified of malformed POST parameters being present and decide if it is a bug or an attack.
- BrandonSmith 14y agoForm fields by way of application/x-www-form-urlencoded generally shouldn't be trusted wholesale. In the Wild, Wild Internet, you'll see things like 3rd party JavaScript add hidden fields, etc. Instead of modifying at the middleware or persistence layers, copy relevant fields out of the POST hash into an intermediate hash. Which, generally, will be more secure anyways.
- headShrinker 14y agoIf your API breaks because an extra unrecognized parameter is included, Apple didn't break your API, you did.
- phaylon 14y agoCan you elaborate on why you think invalid API parameters should be silently ignored? I can see arguments for both sides, but none of them would make the API "broken" in my mind.
- headShrinker 14y ago"The programmer should always have complete control", if the API is broke, the programmer has lost control. From a security and usability perspective, the programmer must always be in ultimate control of what code is being executed. If it's "parameters", an API should be explicitly requesting any or all parameters, and completely ignoring unknowns. If the API is scanning for unknown parameters or even worse scanning for parameters to invoke variable named function calls (it happens a lot), at best; your API is wide open for attack. (This was a major attack vector in some Wordpress APIs in the recent past.) In the meantime, the unknown parameter just causes the program to break, and why would any programmer allow that if it's so easily preventable.
- jcromartie 14y agoApple isn't injecting this into the request. It's an object property and the application developers are doing something in their app that is iterating over and Objective-C object and creating a POST request from it. I guarantee it.
- jmcnevin 14y agoThis (mass-assignment) is fairly standard Rails-fu, so its fair to assume that this could affect a lot of apps out there.
- ubernostrum 14y agoYou say "standard Rails-fu", I say security hole. Let's call the whole thing off?
- tomjen3 14y agoNo because you don't know what you are talking about.
- ubernostrum 14y agoI see. So that whole big mass-assignment security issue that exposed GitHub a while back -- that just didn't happen? Writing code in this style is perfectly safe?
- bryanlarsen 14y agoWriting code in this style is perfectly safe if you do it correctly. GitHub didn't, so the defaults were changed to make it harder to do it incorrectly. UPDATE: editing to reply since hn won't let me reply directly because the thread is to deep, yet I'm getting downvotes It's not a tautology. Some things are safe even if you do them wrong. Some things are unsafe no matter how you do them. Rails changed the defaults so that now you have to deliberately decide to do things unsafely. Rails before 3.2.3 fails un-safe in this scenario, but later versions fail safe. Rails 4 uses a different solution that's even harder to screw up.
- jerf 14y ago"Writing code in this style is perfectly safe if you do it correctly." That's a tautology. In general you can't count on code being written "correctly", so this isn't a defense. It is better to have systems that degrade gracefully in the face of humans and their idiosyncrasies, rather than those that fail-unsafe, because you can't build your security system on the assumption that your code will be written by superhumans.
- kalleboo 14y agoIsn't this default Rails behavior? (despite sounding like something people would make fun of PHP for doing)
- masklinn 14y agoIt used to be, and was recently changed after they realized that even PHP had disabled `register_globals` years ago (also, after they realized even Github, one of the biggest Rails site out there, had left this hole wide open and a guy used it to demonstrate the issues on the rails repo/account, which was very funny drama: https://github.com/rails/rails/issues/5239 https://github.com/rails/rails/issues/5239 http://erratasec.blogspot.be/2012/03/rubygithub-hack-translated.html http://erratasec.blogspot.be/2012/03/rubygithub-hack-transla...)
- tomjen3 14y agoBegin by reading up on Rails. Mass assignment is a fairly normal thing to do, any parameters you want the model to ignore can be marked as so in the model and then mass assignment will work anywhere. Rails loves DRY. Since the only way in which one can get wrong arguments is if somebody is hacking you (or attempting to do so) in which case just throwing an error at them is a fair thing to do.
- untog 14y agoI'm not a Rails guy, so you'll have to forgive ignorance here. Are you telling me that Rails only lets you blacklist parameters, not whitelist? Because that seems entirely the wrong way around. EDIT: looked at the link posted elsewhere here[1] and ound that it is possible to whitelist using "attr_accessible". Please tell me people know about and use this. [1] http://guides.rubyonrails.org/security.html#mass-assignment http://guides.rubyonrails.org/security.html#mass-assignment
- bryanlarsen 14y agoYou can do either. The default used to be blacklist, but that was changed to whitelist recently.
- bob_p 14y agoYou can do either. Whitelist is obviously preferred.
- alanpca 14y agoIt allows either.
- Pewpewarrows 14y agoBlanket accepting POST data to insert into your database is a terrible idea. Rails gives you attr_accessible and attr_protected to alleviate this problem. Protip: the one from those two that you suggested to use is just as terrible an idea as allowing blind POST into your database. Blacklisting is always the wrong approach to security. I don't care if you have to repeat yourself and type more characters: use the whitelisting of attr_accessible.
- ejs 14y agoThis should not be an issue if you avoid mass-assignment with dumping all params, which is a security vulnerability anyway. If you do something like: @user = User.new(params[:user].slice(:name)) It will be safer, and avoid the problem.
- eli 14y agoDoes this parameter serve a documented purpose? It's weird that iOS is doing that... but (at the risk of piling on) browsers do all sorts of weird stuff. Your app needs to deal with it.
- brown9-2 14y agoYeah, the discussion here seems to be missing the forest for the trees. For non-Rails programmers an idea such as mass assignment sounds very strange, but if you ignore that, it still sounds odd at first request than an OS would inject parameters into a HTTP post request.
- tilsammans 14y agoThis has been solved already and will be part of Rails 4. Use strong parameters: https://github.com/rails/strong_parameters https://github.com/rails/strong_parameters
- jcromartie 14y agoWill this be a default in Rails 4? I feel like people should need to go through a lot of work to do something as dangerous as Rails/AR mass assignment...
- Legion 14y ago> Will this be a default in Rails 4? Yes.
- mobwill 14y agoMost likely, their native client is blindly adding the objective c properties to the POST request, by using introspection. Apple is not adding anything to the POST request. This is similar to the problems people used to run into when the javascript object prototype was overridden and everyone's code would break because they were just doing for (var prop in object)
- jcromartie 14y agoIndeed. Why in the world would Apple inject this into POST requests? http://developer.apple.com/library/ios/documentation/uikit/reference/UIAccessibility_Protocol/Introduction/Introduction.html#//apple_ref/occ/instp/NSObject/shouldGroupAccessibilityChildren http://developer.apple.com/library/ios/documentation/uikit/r...
- coob 14y agoWilling to bet it's a bug.
- lancefisher 14y agoI'm sure this is what's happening. Their serializer is perhaps filtering out properties they knew about, but shouldGroupAccessibilityChildren is a new property on the UIAccessibility Protocol which is adopted by NSObject. A good short-term fix is to update the web service, but they should update it to only use the POST parameters it expects. When they release an update to the iOS app, they can fix their serializer to only serialize the properties they need. Apple isn't injecting this - their code is.
- asg 14y agoI'm amazed at how the discussion here has devolved into the merits of mass assignment. While that is a worthwhile topic in itself, specially given the recent github issues, any suggestion that the this issue would have been mitigated by the OP not using mass assignment is flawed. Any webapp that I would consider secure MUST validate all input from clients. This includes white listing any and all parameters names, preferably in middleware, but at least in the controller. Allowing random keys in your input seems recipe for disaster, when you consider a multi layer app security policy. While this may seem like an overkill to some, this is best practice I've seen implemented in any project that deals with real money. Hence, such a change in iOS WILL break any such application. Irrespective of your views on the sanity of mass assignment. I would like to see a discussion on why apple thought it would be a good idea to introduce a new parameter to every request. Any ideas?
- masklinn 14y ago"Validating input" can yield a number of results, and ignoring incorrect data (keys) altogether is not only a valid reaction, it's a perfectly safe one and it's how the vast majority of systems work. Indeed, a number of usual patterns would break if that didn't work. Mass-assignment and similar patterns (of shoving all request parameters into your trusted content, see also `extract` and `register_globals`) "allow random keys into your input", ignoring said keys doesn't.
- jcromartie 14y agoThese folks are claiming that this is an issue without creating a minimal program that reproduces the issue. If it were a real issue it would be trivial to make an app that POSTs to an API and inspect the traffic. I have inspected several POST requests from iOS 6 apps and have not seen anything like this yet.