IPA's I just love IPA's

India Pale Ale has always been a favorite of mine, I've had so many different styles/flavors and still get excited every time I find a new one. Some of my go to IPA's are;

Ok ok, joking aside. During a Friday beers Discord call with a few friends I thought it would be a good idea to mix up the "drink and talk rubbish" that we normally do, in favor for doing something productive. I thought it could be cool to play with Gitpod to collaborate. The only question left to answer was "what?", what are we going to collaborate on? I'd just finished a mobile application assessment and I looked at my testing iPhone and thought, "Lets do static analysis of all the .ipa's on this device". With that, we started writing some horrible bash, had latency issues, and the drinking was not helping much, so we left it very much how we started it.

Nursing a hangover, I messages my friends to see if they wanted to continue with the small side project, and as expected they said "No". But I had an idea, I don't like mobSF, on mobile application assessments I do what it does manually using radare2, so why not reinvent the wheel to understand why its round, by using r2pipe to parse out the specific information from r2 commands, this played nicely because I'd been looking for an excuse to use golang for something.

go2ipa

Did you know that you can pass a ipa:// schema to radare2 ? I did not, I would always extract the content and then throw the binary into r2. After getting the r2pipe library installed, I began to write most likely really shoddy golang. But it worked, it did what I wanted it to do, it was just I had a nagging feeling that it seemed a bit useless. It would be quicker and easier just to use the r2 commands. So with that in mind, if you really want to use my wrapper and see my shoddy golang, the repo is here.

Getting the IPA's

I don't use many mobile applications, I prefer a keyboard. So one weekend I just went on a rampage within the App Store, downloading anything and everything that I could find. I ended up with ~60 mobile applications, Now all I had to do was pull them off the device, that should be simple enough. Using bagbak and this one liner I was able to pull all the .ipa's off the device.

for app in $(bagbak -l | awk '{print $4}' | grep -v 'apple|Cydia|portswigger|jxtx' | tr -d "'"); do bagbak -z $app ; done

ipas-pull.gif

Analysis

If I was going to put some effort into this, I wanted to make it worth it. A while ago I went through the iOS quickstart video series by hackerone, this series went through both static and dynamic analysis, so I reviewed my notes and built the following list of requirements that I wanted to extract from each .ipa.

  • Info.plist
  • File Contents
  • Entitlements
  • Sections
  • Linked libraries
  • Strings
  • Classes

With that list I then wrote a bash script using rabin2 to automate the r2 commands, and then build out a markdown file for each .ipa. Although markdown is cool (org is better), a bunch of markdown files does not help anyone. What I needed was to over engineer displaying the extracted information, so it would be easier to consume.

Seeing as the analysis side was already being ran by a gitlab pipeline I googled around to see if I could do anything within the pipeline to display or parse out the markdown files.

Publishing

I'm a fan of the read the docs theme so mkdocs with the read the docs theme made sense, adding this to the pipeline was simple enough, I just needed to add the following stages.

test:
  stage: test
  image: python:3.8-buster
  before_script:
  - pip install mkdocs>=1.1.2
  script:
  - mkdocs build --strict --verbose --site-dir $CI_PROJECT_DIR/test
  artifacts:
    paths:
    - $CI_PROJECT_DIR/test

pages:
  stage: deploy
  image: python:3.8-buster
  before_script:
  - pip install mkdocs>=1.1.2
  script:
  - mkdocs build --strict --verbose
  artifacts:
    paths:
    - public

Once the job finished, I enabled gitlab pages for the repo, and well look for yourself.

There are a few gotchas, first off, the analysis stage runs the analysis over each .ipa every time, which means adding additional .ipa's takes a long time for the job to complete. Secondly, as its markdown any string extracted from the .ipa that starts with a # gets rendered as a heading. Both of which I can live with for now.

Findings

First off, every application ran on a jailbroken device, and every application was pulled off with bagbak which uses Frida, so I guess you have two findings right there :)

  • 32 application had app transport security restrictions disabled.
  • 54 applications had URL schemas that could potentially be fuzzed
  • 41 applications supported the lowest OS as 13.0