Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

scanner.provider.traversal returned exception error. #426

Open
thesinghsec opened this issue Apr 5, 2024 · 3 comments · Fixed by #427
Open

scanner.provider.traversal returned exception error. #426

thesinghsec opened this issue Apr 5, 2024 · 3 comments · Fixed by #427

Comments

@thesinghsec
Copy link

  • It was working well in previous version of Drozer, upon updating I got this error again and again.

dz> run scanner.provider.traversal -a com.mwr.example.sieve
Attempting to run shell module
Scanning com.mwr.example.sieve...
Exception occured: No files supported by provider at content://com.mwr.example.sieve.DBContentProvider/Passwords//../../../../../../../../../../../../../../../../etc/hosts

image

@thesinghsec thesinghsec changed the title scanner.provider.traversal returned expecption error. scanner.provider.traversal returned exception error. Apr 5, 2024
@Yogehi
Copy link
Collaborator

Yogehi commented Apr 5, 2024

root@d7feae1123d5:/# drozer console connect --server host.docker.internal --debug
Selecting ebe9fcc0c47b28da (Google sdk_gphone64_x86_64 12)

            ..                    ..:.
           ..o..                  .r..
            ..a..  . ....... .  ..nd
              ro..idsnemesisand..pr
              .otectorandroidsneme.
           .,sisandprotectorandroids+.
         ..nemesisandprotectorandroidsn:.
        .emesisandprotectorandroidsnemes..
      ..isandp,..,rotecyayandro,..,idsnem.
      .isisandp..rotectorandroid..snemisis.
      ,andprotectorandroidsnemisisandprotec.
     .torandroidsnemesisandprotectorandroid.
     .snemisisandprotectorandroidsnemesisan:
     .dprotectorandroidsnemesisandprotector.

drozer Console (v3.0.1 debug mode)
dz> run scanner.provider.traversal --uri content://com.withsecure.example.sieve.provider.DBContentProvider
Attempting to run shell module
exception in module: ReflectionException: No files supported by provider at content://com.withsecure.example.sieve.provider.DBContentProvider/../../../../../../../../../../../../../../../../etc/hosts
Traceback (most recent call last):
  File "/usr/local/lib/python3.10/dist-packages/drozer/console/session.py", line 402, in do_run
    module.run(argv[1:])
  File "/usr/local/lib/python3.10/dist-packages/drozer/modules/base.py", line 183, in run
    result = self.execute(arguments)
  File "/usr/local/lib/python3.10/dist-packages/drozer/modules/scanner/provider/traversal.py", line 26, in execute
    self.__test_uri(arguments.package_or_uri, vulnerable)
  File "/usr/local/lib/python3.10/dist-packages/drozer/modules/scanner/provider/traversal.py", line 53, in __test_uri
    data = self.contentResolver().read(uri + "/../../../../../../../../../../../../../../../../etc/hosts")
  File "/usr/local/lib/python3.10/dist-packages/drozer/modules/common/provider.py", line 127, in read
    fd = client.openFile(self.parseUri(uri), "r")
  File "/usr/local/lib/python3.10/dist-packages/pysolar/reflection/types/reflected_object.py", line 64, in _invoker
    result = self._reflector.invoke(self, method_name,
  File "/usr/local/lib/python3.10/dist-packages/pysolar/reflection/reflector.py", line 83, in invoke
    raise ReflectionException(response.reflection_response.errormessage)
pysolar.reflection.exceptions.ReflectionException: No files supported by provider at content://com.withsecure.example.sieve.provider.DBContentProvider/../../../../../../../../../../../../../../../../etc/hosts

yup legit. we'll look into it

@cyberMilosz
Copy link
Contributor

cyberMilosz commented Apr 6, 2024

So, this is a fun one.

At its core, the problem boils down to the logic of the __test_uri() function of the scanner.provider.traversal module. In drozer 2, this was implemented as follows:

    def __test_uri(self, uri, vulnerable):
        try:
            data = self.contentResolver().read(uri + "/../../../../../../../../../../../../../../../../etc/hosts")
        except ReflectionException as e:
            if e.message.find("java.io.FileNotFoundException") >= 0 or \
                e.message.find("java.lang.IllegalArgumentException") >= 0 or \
                e.message.find("java.lang.SecurityException") >= 0 or \
                e.message.find("No content provider") >= 0 or \
                e.message.find("RuntimeException"):
                data = ""
            else:
                raise
    
        if data != None and len(data) > 0:
            vulnerable.add(uri)

A cursory read of the try/except block makes it seem like an exception should be suppressed if it contains one of five strings, and raised otherwise. So, it got ported to drozer 3 as:

    def __test_uri(self, uri, vulnerable):
        try:
            data = self.contentResolver().read(uri + "/../../../../../../../../../../../../../../../../etc/hosts")
        except ReflectionException as e:
            if "java.io.FileNotFoundException" in str(e) or \
                "java.lang.IllegalArgumentException" in str(e) or \
                "java.lang.SecurityException" in str(e) or \
                "No content provider" in str(e) or \
                "RuntimeException" in str(e):
                data = ""
            else:
                raise
    
        if data != None and len(data) > 0:
            vulnerable.add(uri)

This is all sensible at a glance, but the drozer 2 logic was actually flawed due to a missing >= 0 - if the string RuntimeException was NOT found, string.find() would return -1, causing the entire if statement to evaluate as True. In practice, this means that it set data to "" if e.message contained one of the first four strings OR didn't start with RuntimeException. The only way for it to really go False would be to start with RuntimeException and not contain any of the other four strings. This probably always evaluated as True, and so the exception was likely never raised.

Now, drozer 3's logic attempts to implement the same intention, but without the same error. As a result it ends up with a statement that throws the exception much more often. My suspicion is that drozer 2 worked by accident.

The obvious solution here appears to be to remove the if statement entirely, and to gracefully handle all exceptions that come from the content provider. In the future, we may add handlers for scenarios like a non-existent provider (to give a meaningful message to the user), but for now this will make the module work as it did before.

Once pull request #427 is merged, please try building drozer 3 and see if this works for you. I strongly suspect it will.

We'll keep the issue open, because ideally we should add a few exception type checks here and there.

@cyberMilosz
Copy link
Contributor

Keeping this open as a reminder to do further work on those exception checks

@Yogehi Yogehi added the Feature label Apr 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants