Hi all,
Created an plugin that does this:
https://github.com/edewit/aerogear-reflect-cordova the repository also includes
a example plugin that uses this. Also have a blog describing this a bit more
http://blog.nerdin.ch/2014/07/improved-cordova-android-plugin-api.html
Cheers,
Erik Jan
On 2 Jun,2014, at 4:20 , Terence M. Bandoian <[email protected]> wrote:
> It does get complicated in a hurry. Using the technique in the Google Maps
> plugin:
>
> - getDeclaredMethod is documented to NOT return inherited methods which
> limits exposure
> - the signature passed to getDeclaredMethod also limits exposure
> - annotations, as Andrew suggested, could further limit exposure
>
> - getDeclaredMethod is documented to return private methods which for me
> raises questions
> - setAccessible(true) suppresses normal access checking which also raises
> questions
>
> - invoke throws InvocationTargetException so exceptions thrown by the invoked
> method could be publicized
> - invoke applies overriding which is probably a wash
> - invoke returns an object which would have to be handled correctly
>
> Quite a bit to consider.
>
> -Terence Bandoian
>
>
> On 5/29/2014 11:44 PM, Joe Bowser wrote:
>> On Thu, May 29, 2014 at 9:26 PM, Terence M. Bandoian <[email protected]>
>> wrote:
>>> Please correct me if I'm wrong but, as I understand it, the vulnerability
>>> stems from injecting a Java object into the WebView which, in API levels 16
>>> and below, exposed all of the public methods of the object (small 'o')
>>> including the methods inherited from the Object class.
>>>
>> Yes, you are correct in this case. You can basically use the object
>> methods to reflect into whatever you want. Once you have a single
>> class exposed in this manner, you can then reflect into it, and
>> basically you're done. The reason we don't use reflection is that
>> it's very easy to reflect into things you're not supposed to be in.
>> IMO, It wouldn't be hard to do this if we exposed plugins in the same
>> way. Right now this is an Android Vulnerability, but if we start
>> using reflection for plugins, we could very quickly end up making a
>> similar Cordova exploit if we're not careful.
>>
>> This is also why we use the prompt bridge on API levels below 17.
>>
>>>
>>>
>>> On 5/28/2014 9:54 AM, Joe Bowser wrote:
>>>> In case anyone is curious, here's why we minimize reflection:
>>>>
>>>>
>>>> https://labs.mwrinfosecurity.com/blog/2013/09/24/webview-addjavascriptinterface-remote-code-execution/
>>>>
>>>> On Wed, May 28, 2014 at 7:33 AM, Andrew Grieve <[email protected]>
>>>> wrote:
>>>>> Another reasonable approach would be to use a Map<String, Runnable>, but
>>>>> that can be implemented on top of what is currently exposed. I'm quite
>>>>> wary
>>>>> of Reflection as well.
>>>>>
>>>>>
>>>>> On Wed, May 28, 2014 at 10:06 AM, Joe Bowser <[email protected]> wrote:
>>>>>
>>>>>> The execute command exists for security reasons. We don't want any
>>>>>> methods other than execute exposed to Javascript. I also prefer this
>>>>>> approach because it is less prone to less catastrophic bugs than using
>>>>>> Java reflection. We try and only use reflection when we have to.
>>>>>>
>>>>>> On Wed, May 28, 2014 at 5:50 AM, Erik Jan de Wit <[email protected]>
>>>>>> wrote:
>>>>>>> Hi,
>>>>>>>
>>>>>>> When one is writing a plugin for android ATM the api that you have to
>>>>>> implement has a execute method that has the action as a string:
>>>>>>> @Override
>>>>>>> public boolean execute(String action, JSONArray args,
>>>>>> CallbackContext callbackContext) throws JSONException {
>>>>>>> if ("beep".equals(action)) {
>>>>>>> this.beep(args.getLong(0));
>>>>>>> callbackContext.success();
>>>>>>> return true;
>>>>>>> }
>>>>>>> return false; // Returning false results in a
>>>>>>> "MethodNotFound"
>>>>>> error.
>>>>>>> }
>>>>>>> When you have multiple actions this method gets very long, if you
>>>>>> compare this with iOS here you don’t need a method like this you could
>>>>>> ‘just’ implement the method directly:
>>>>>>> - (void)beep:(CDVInvokedUrlCommand*)command
>>>>>>> {
>>>>>>> CDVPluginResult* pluginResult =;
>>>>>>> NSString* myarg =mmand.arguments objectAtIndex:0];
>>>>>>>
>>>>>>> if (myarg !=) {
>>>>>>> pluginResult �VPluginResult
>>>>>> resultWithStatus:CDVCommandStatus_OK];
>>>>>>> } else {
>>>>>>> pluginResult �VPluginResult
>>>>>> resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Arg was
>>>>>> null"];
>>>>>>> }
>>>>>>> [self.commandDelegate sendPluginResult:pluginResult
>>>>>> callbackId:command.callbackId];
>>>>>>> }
>>>>>>> We could do the same thing for android if we use reflection, making the
>>>>>> API more similar and removing all the string test by the user. What do
>>>>>> you
>>>>>> think?
>>>>>>> Cheers,
>>>>>>> Erik Jan