Пример #1
0
def scan(filenames):
    """Scan the provided files for vulnerabilities"""

    for filename in filenames:
        click.echo('\nProcessing file: ' + filename)

        # Try to open the provided file as a ZIP, fail otherwise
        zip_file = TruegazeUtils.open_file_as_zip(filename)
        if zip_file is None:
            click.echo(
                'ERROR: Unable to open file - please check to make sure it is an APK or IPA file'
            )
            sys.exit(-1)

        # Detect manifest
        is_android = False
        is_ios = False
        android_manifest = TruegazeUtils.get_android_manifest(zip_file)
        ios_manifest = TruegazeUtils.get_ios_manifest(zip_file)

        # Set flags, error out if no manifest is found
        if android_manifest:
            click.echo(
                'Identified as an Android application via a manifest located at: '
                + android_manifest)
            is_android = True
        elif ios_manifest:
            click.echo(
                'Identified as an iOS application via a manifest located at: '
                + ios_manifest)
            is_ios = True
        else:
            click.echo(
                'ERROR: Unable to identify the file as an Android or iOS application'
            )
            sys.exit(-2)

        # Pass the filename to the individual modules for scanning
        for PLUGIN in ACTIVE_PLUGINS:
            click.echo()
            click.echo('Scanning using the "' + PLUGIN.name + '" plugin')
            instance = PLUGIN(filename, is_android, is_ios)

            # Show error if OS is not supported
            # TODO: Add tests
            if instance.is_os_supported():
                instance.scan()
            else:
                click.echo('-- OS is not supported by this plugin, skipping')

    click.echo("Done!")
Пример #2
0
    def scan(self):
        # On Android, the config file is usually in the assets folder but can be placed elsewhere.
        # On iOS the configuration file can be anywhere.

        # Load file
        self.zip_file = TruegazeUtils.open_file_as_zip(self.filename)

        # Search all paths for the config file
        paths = AdobeMobileSdkPlugin.get_paths(self.zip_file)
        if len(paths) == 0:
            click.echo(
                '-- Cannot find the "ADBMobileConfig.json" file, skipping')
            return

        # Loop through files, parse the JSON and analyze
        click.echo('-- Found ' + str(len(paths)) + ' configuration file(s)')
        for path in paths:
            click.echo('-- Scanning "' + path + "'")

            # Try to parse the data
            parsed_data = AdobeMobileSdkPlugin.parse_data(self.zip_file, path)
            if not parsed_data:
                click.echo(
                    '---- ERROR: Unable to parse config file - will skip. File: '
                    + path)
                continue

            # Validate the file
            messages = AdobeMobileSdkPlugin.validate(parsed_data)
            if len(messages) > 0:
                click.echo("-- Found " + str(len(messages)) + ' issues')
                for message in messages:
                    click.echo(message)
            else:
                click.echo("-- No issues found")
Пример #3
0
 def test_valid_file_in_directory(self):
     zip_file = ZipFile(io.BytesIO(), 'a')
     zip_file.writestr('test/test.txt', 'testdata')
     paths = TruegazeUtils.get_matching_paths_from_zip(
         zip_file, re.compile(r'.*est.*\.txt'))
     assert len(paths) == 1
     assert paths[0] == 'test/test.txt'
Пример #4
0
 def test_valid_one_file(self):
     zip_file = ZipFile(io.BytesIO(), 'a')
     zip_file.writestr('test', '')
     paths = TruegazeUtils.get_matching_paths_from_zip(
         zip_file, re.compile(r'.*'))
     assert len(paths) == 1
     assert paths[0] == 'test'
Пример #5
0
 def test_valid_three_files(self):
     zip_file = ZipFile(io.BytesIO(), 'a')
     zip_file.writestr('test1.txt', '')
     zip_file.writestr('test/test2.doc', '')
     zip_file.writestr('test/test/test3.md', '')
     paths = TruegazeUtils.get_matching_paths_from_zip(
         zip_file, re.compile(r'.*est/test.*\..*'))
     assert len(paths) == 2
     assert paths[0] == 'test/test2.doc'
     assert paths[1] == 'test/test/test3.md'
Пример #6
0
 def test_not_empty(self):
     zip_file = ZipFile(io.BytesIO(), 'a')
     zip_file.writestr("test", 'testdata')
     assert TruegazeUtils.get_android_manifest(zip_file) is None
Пример #7
0
 def test_empty(self):
     zip_file = ZipFile(io.BytesIO(), 'a')
     assert TruegazeUtils.get_android_manifest(zip_file) is None
Пример #8
0
 def test_junk_manifest(self):
     zip_file = ZipFile(io.BytesIO(), 'a')
     zip_file.writestr('Payload/Test.app/Info.plist', '<junk></junk>')
     assert TruegazeUtils.get_ios_manifest(zip_file) is None
Пример #9
0
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
#
import sys

import click
from beautifultable import BeautifulTable

from truegaze.plugins import ACTIVE_PLUGINS
from truegaze.utils import TruegazeUtils


@click.version_option(version=TruegazeUtils.get_version(), prog_name='truegaze')
@click.group()
def cli():
    """
    truegaze - A static analysis tool for Android and iOS applications focusing on security issues
    outside the source code such as resource strings, third party libraries and configuration files.

    Copyright (c) 2019 Nightwatch Cybersecurity.
    Source code: https://github.com/nightwatchcybersecurity/truegaze
    """


@cli.command('list')
def list_plugins():
    """List supported plugins"""
    click.echo("Total active plugins: " + str(len(ACTIVE_PLUGINS)))
Пример #10
0
from setuptools import find_packages, setup
from truegaze.utils import TruegazeUtils

with open("README.md", "r") as fh:
    long_description = fh.read()

setup(
    name='truegaze',
    version=TruegazeUtils.get_version(),
    description=
    'Static analysis tool for Android/iOS apps focusing on security issues outside the source code.',
    long_description=long_description,
    long_description_content_type="text/markdown",
    url='https://github.com/nightwatchcybersecurity/truegaze',
    author='Nightwatch Cybersecurity',
    author_email='*****@*****.**',
    license='Apache',
    packages=find_packages(
        exclude=["scripts.*", "scripts", "tests.*", "tests"]),
    include_package_data=True,
    install_requires=open('requirements.txt').read().splitlines(),
    entry_points={'console_scripts': ['truegaze = truegaze.cli:cli']},
    classifiers=[
        'Environment :: Console',
        'Development Status :: 3 - Alpha',
        'License :: OSI Approved :: Apache Software License',
        'Operating System :: OS Independent',
        'Programming Language :: Python :: 3.6',
        'Programming Language :: Python :: 3.7',
    ],
    python_requires='>=3.6',
Пример #11
0
 def test_directory_with_right_name(self):
     info = ZipInfo('assets/' + ANDROID_MANIFEST)
     info.external_attr = 16
     zip_file = ZipFile(io.BytesIO(), 'a')
     zip_file.writestr(info, '')
     assert TruegazeUtils.get_android_manifest(zip_file) is None
Пример #12
0
 def test_empty(self):
     zip_file = ZipFile(io.BytesIO(), 'a')
     paths = TruegazeUtils.get_matching_paths_from_zip(
         zip_file, re.compile(r'.*'))
     assert len(paths) == 0
Пример #13
0
 def test_valid(self):
     zip_file = ZipFile(io.BytesIO(), 'a')
     zip_file.writestr('Payload/Test.app/Info.plist',
                       TestUtilsGetiOSManifest.make_ios_manifest())
     assert TruegazeUtils.get_ios_manifest(
         zip_file) == 'Payload/Test.app/Info.plist'
Пример #14
0
 def test_manifest_with_some_keys3(self):
     buffer = io.BytesIO()
     plistlib.dump(dict(CFBundleShortVersionString='some app'), buffer)
     zip_file = ZipFile(io.BytesIO(), 'a')
     zip_file.writestr('Payload/Test.app/Info.plist', buffer.getvalue())
     assert TruegazeUtils.get_ios_manifest(zip_file) is None
Пример #15
0
 def test_manifest_with_no_keys(self):
     buffer = io.BytesIO()
     plistlib.dump({}, buffer)
     zip_file = ZipFile(io.BytesIO(), 'a')
     zip_file.writestr('Payload/Test.app/Info.plist', buffer.getvalue())
     assert TruegazeUtils.get_ios_manifest(zip_file) is None
Пример #16
0
 def test_empty_manifest(self):
     zip_file = ZipFile(io.BytesIO(), 'a')
     zip_file.writestr(ANDROID_MANIFEST, '')
     assert TruegazeUtils.get_android_manifest(zip_file) is None
Пример #17
0
 def test_wrong_directory(self):
     zip_file = ZipFile(io.BytesIO(), 'a')
     zip_file.writestr('assets/' + ANDROID_MANIFEST, 'manifest data')
     assert TruegazeUtils.get_android_manifest(zip_file) is None
Пример #18
0
 def test_format_valid(self):
     pattern = re.compile(r'^(\d+\.)?(\d+\.)?(\*|\d+)$')
     assert pattern.match(TruegazeUtils.get_version()) is not None
Пример #19
0
 def test_valid(self):
     zip_file = ZipFile(io.BytesIO(), 'a')
     zip_file.writestr(ANDROID_MANIFEST, 'manifest data')
     assert TruegazeUtils.get_android_manifest(zip_file) == ANDROID_MANIFEST
Пример #20
0
 def test_not_found(self):
     assert TruegazeUtils.open_file_as_zip('blablabla') is None
Пример #21
0
 def test_invalid_empty(self):
     assert TruegazeUtils.open_file_as_zip(io.BytesIO()) is None
Пример #22
0
 def test_invalid_not_zip(self):
     assert TruegazeUtils.open_file_as_zip(
         io.StringIO('foobar data')) is None
Пример #23
0
 def get_paths(zip_file):
     return TruegazeUtils.get_matching_paths_from_zip(
         zip_file, CONFIG_FILE_PATTERN)
Пример #24
0
 def test_valid_zip(self):
     zip_buffer = io.BytesIO()
     zip_file = ZipFile(zip_buffer, 'a')
     zip_file.writestr('testfile', 'testdata')
     zip_file.close()
     assert TruegazeUtils.open_file_as_zip(zip_buffer) is not None
Пример #25
0
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
#
import sys

import click
from beautifultable import BeautifulTable

from truegaze.plugins import ACTIVE_PLUGINS
from truegaze.utils import TruegazeUtils


@click.version_option(version=TruegazeUtils.get_version(),
                      prog_name='truegaze')
@click.group()
def cli():
    """
    truegaze - A static analysis tool for Android and iOS applications focusing on security issues
    outside the source code such as resource strings, third party libraries and configuration files.

    Copyright (c) 2019 Nightwatch Cybersecurity.
    Source code: https://github.com/nightwatchcybersecurity/truegaze
    """


@cli.command('list')
def list_plugins():
    """List supported plugins"""
Пример #26
0
 def test_wrong_directory3(self):
     zip_file = ZipFile(io.BytesIO(), 'a')
     zip_file.writestr('Payload/Testapp/Info.plist',
                       TestUtilsGetiOSManifest.make_ios_manifest())
     assert TruegazeUtils.get_ios_manifest(zip_file) is None