Security Application Static Analysis applied to iOS and Gitlab CI

Security is a big topic in software engineering but how does it apply to mobile development? We care about user experience or mobile performance, security issues are rarely prioritized. This week, I’ll share how to integrate security tools into your CI pipeline to stay aware of your codebase health.

Disclaimer: I’m not a security expert, just security enthusiast engineer :)

Security in mobile application

It all started earlier this year when I was exploring different tools to detect security issues into one of my mobile apps, mostly by curiosity.

Before diving into the technical aspect, we need to understand why security is a concern in mobile development. With more and more apps available to us, mobile application is one of the entry point to your system for malicious users to exploit it. The bigger your app or your business gets, the bigger target it becomes.

From mobile app vulnerabilities can come data leaks, lost of money and reputations and so on.

Thankfully, there are also “good guys” in the community that keep track of the vulnerabilities, sharing documentations and resources to educate engineers. OWASP Foundation is the main contributor and frequently share the top 10 most critical risks for web and mobile applications.

In the Mobile top 10 report, we can find many risks like insecure authentication, insufficient cryptography, examples of exploits and to prevent them.

Finally, they also published a Mobile Security Testing Guide for mobile engineers to not only understand the risk, but also detect them and make sure our mobile apps stays secured.

So now, we know why security is important, we have access to guidelines and documentations to recognize vulnerabilities and how to test them. So how we detect those issues ahead, during development for instance?

Application Security Testing

One way to detects security issues includes Static Application Security Testing (SAST). It’s a testing methodology to analyze your source code and detect vulnerabilities based on code patterns.

It’s pretty similar to any lint tools, like SwiftLint, but applied to security issues.

One mobile security tool that is recommended by OWASP and free to use is MobSF. It includes whole suite of integration, including SAST for iOS and Android. It also includes DAST (Dynamic Application Security Testing) but we won’t look into it today.

Part of that suite is a lightweight client mobsfscan, that’s the one we’ll integrate today.

From a command line, it can run through your codebase, and create a report with all vulnerabilities found. It supports Swift and Kotlin but also Java and Objective-C. It can also generate different type of reports depending of what your CI needs.

mobsfscan .

Here is the kind of output

{
    'results': {
        'android_logging': {
            'files': [{
                'file_path': 'tests/assets/src/java/java_vuln.java',
                'match_position': (13, 73),
                'match_lines': (19, 19),
                'match_string': '            Log.d("htbridge", "getAllRecords(): " + records.toString());'
            }],
        }
    }
}

We can also go further and add rules to ignore files or filter out severity. We can setup a .mobsf configuration file at the root of the directory to drive the security scanner.

---
- ignore-filenames:
  - skip.java

  ignore-paths:
  - __MACOSX

  ignore-rules:
  - android_kotlin_logging

  severity-filter:
  - WARNING
  - ERROR

So we got a tool to integrate and analyze codebase for iOS and Android, let’s dive into the integration.

Integration with Gitlab

Mobsfscan includes a section dedicated to CI/CD integration which, in most of cases, might work for you for cloud-based solution and docker image.

For self-hosted runners, it’s a different story. In my case, with Gitlab CI runner, it gets a bit more complicated.

First thing first, the tool has to be installed ahead on the machine. We don’t leverage any docker image as suggested in the default integration.

Since my goal is to raise awareness of security issues on the project, I need a JSON format that will be attach to future pull request.

stages:
    - security

mobsfscan:
    stage: security
    script:
        - mobsfscan --json --output security-report.json .
    artifacts:
        reports:
            sast: security-report.json

So far so good.

Digging further, security reports aren’t displayed for all types of Gitlab account. So we cannot leverage the same type of widget.

Thankfully, there are other ways to create reports, for instance creating Code Quality report in Gitlab. It’s not the best, but would allow me to transform the security report into a code quality one to still display it for future code changes.

Since the generated security report is a JSON, I can use other tooling like Ruby and fastlane, both already available in my iOS project, to make it into the right format.

I simplified the code a lot, so we focus on the essential part here.

module Fastlane
  module Actions
    class MobsfscanTransformAction < Action
      def self.run(params)
        require 'json'
        require 'securerandom'

        # Getting input file and output destination
        input_file = params[:input_file]
        output_file = params[:output_file]

        # Read input json into hash
        raw_data = File.read(input_file)
        json_data = JSON.parse(raw_data)

        results = json_data['results']
        issues = Array.new

        # For each risk detected
        for key in results.keys do 
            item = results[key]
            metadata = item['metadata']

            # Create issue
            issue = {
            type: "issue",
            description: metadata['description'],
            categories: ["Security"]
            }

            # Map severity
            if metadata['severity'] == "WARNING" ||
            metadata['severity'] == "HIGH" then
            issue["severity"] = "major"
            else 
            issue["severity"] = "info"
            end

            # Add unique fingerprint
            issue["fingerprint"] = SecureRandom.uuid
            issues.push(issue)

        end

        # Create new json as output
        File.write(output_file, JSON.dump(issues))
      end

    end
  end
end

This would transform our security report into a CodeClimate one, the expected format supported by Gitlab.

[
  {
    "description": "This app does not have Certificate Pinning implemented in code.",
    "fingerprint": "7815696ecbf1c96e6894b779456d330e",
    "severity": "major",
    "categories": ["Security"],
  },
  { ... }
]

For production usage, I would add more validations, like checking the input and output format are valid, as well as attach files location for each issue found.

From there, I can run this new action from fastlane.

fastlane run mobsfscan_transform input_file:security-report.json output_file:security-code-report.json

Now I can update the Gitlab configuration to include this new report.

stages:
    - security

mobsfscan:
    stage: security
    script:
        - mobsfscan --json --output security-report.json .
        - fastlane run mobsfscan_transform input_file:security-report.json output_file:security-code-report.json
    artifacts:
        reports:
            sast: security-report.json
            codequality: security-code-report.json

Now, we have finally publish the security report part of the code quality of the merge request and can go around the account limitation.

Moving forward, any new code change request will display more information and highlight new security issues (or issues resolved) to make sure new issues aren’t introduced anymore.

mobsfscan-gitlab

Drawbacks

SAST isn’t foolproof but it can play a part of a broader security strategy. It can complete other tools and initiatives like advocating and training engineers to security issues, but also DAST, to automatically analyze binaries.

On the other hand, SAST is based on code pattern and security vulnerabilities keep involving over the years, so we need to keep track of new patterns to stay up to date.

Conclusion

Making sure mobile apps are safe and secure to use should definitely be a concern for mobile engineers. It can be easy to discard those concerns and blame it on lack of tools or knowledge, but there are still plenty of resources for us to get better at it.

If some sound very complex to set up or automate, mobsfscan is a simple step forward that we can include in our continuous integration pipeline to create awareness and not ignore anymore those issues.

Happy coding!

© 2022 Benoit Pasquier. All Rights Reserved
Author's picture

Benoit Pasquier

iOS Software engineer πŸ‡«πŸ‡·, writing about Swift, iOS and more.

ShopBack πŸ’°

Singapore πŸ‡ΈπŸ‡¬