appknox-python

Documentation for Version 3.x.x

appknox-python provides command-line interface and Python wrapper for the Appknox API.

Quickstart

  1. Install

  2. Creating client instance

  3. Get organizations list

  4. Get projects list

  5. Get files list

  6. Get analysis list

  7. Get vulnerability details

  8. Upload app

  9. Recent Uploads

  10. Rescan

  11. Switch organization

  12. List Reports

  13. Create Report

  14. Get Report Summary CSV URL

  15. Get Report Summary Excel URL

  16. Download Report Data from URL

  17. Complete Reference

Install:

appknox is available via PyPI. It is officially supported on python 3.5 & 3.6.

Install with pip:

pip install appknox

Creating client instance:

Appknox class provides an easy access to the Appknox API.

Instances of this class can be used to interact with the Appknox scanner.

An instance for Appknox class can be obtained in two ways:

1. Using personal access tokens:
import appknox
client = appknox.Appknox(
    access_token='PERSONAL_ACCESS_TOKEN',
    host='API_HOST'
)

Personal access token can be generated from Appknox dashboard (Settings → Developer Settings → Generate token)

2. Using login credentials: (This is not recommended)

import appknox
client = appknox.Appknox(
    username='USERNAME',
    password='PASSWORD',
    host='API_HOST'
)
client.login(otp=013370)

otp is required only for accounts with multi-factor authentication.

Get organizations list:

To list organizations for an authenticated user

client.get_organizations()

Example:

>>> client.get_organizations()
[Organization(id=2, name='MyOrganization')]

All results are Python objects, with its respective attributes.

Get projects list:

To list projects for which the authenticated user has access to in default organization.

client.get_projects()

Example:

>>> client.get_projects()
[Project(id=3, created_on='2017-06-23 07:19:26.720829+00:00', file_count=3,
    package_name='org.owasp.goatdroid.fourgoats', platform=0,
    updated_on='2017-06-23 07:26:55.456744+00:00'),
Project(id=4, created_on='2017-06-27 08:27:54.486226+00:00', file_count=1,
    package_name='com.appknox.mfva', platform=0,
    updated_on='2017-06-27 08:27:54.637432+00:00')]

All results are Python objects, with its respective attributes.

Get files list:

For listing files within a project:

client.get_files(<project_id>)

Example:

>>> client.get_files(4)
[File(id=6, name='MFVA', version='1.0', version_code='5', static_scan_progress=100),]

Get analysis list:

Get the analyses for this new file:

client.get_analyses(<file_id>)

Example:

>>> client.get_analyses(273)[:3]
 [Analysis(id = 22248, risk = 2, status = 3, cvss_base = 6.6, cvss_vector = 'CVSS:3.0/AV:A/AC:L/PR:H/UI:R/S:U/C:H/I:H/A:H', cvss_version = 3,         cvss_metrics_humanized = [{
         'key': 'Attack Vector',
         'value': 'Adjacent'
     }, {
         'key': 'Attack Complexity',
         'value': 'Low'
     }, {
         'key': 'Privileges Required',
         'value': 'High'
     }, {
         'key': 'User Interaction',
         'value': 'Required'
     }, {
         'key': 'Scope',
         'value': 'Unchanged'
     }, {
         'key': 'Confidentiality Impact',
         'value': 'High'
     }, {
         'key': 'Integrity Impact',
         'value': 'High'
     }, {
         'key': 'Availability Impact',
         'value': 'High'
 }],
 findings = [{
         'title': 'ssLA5o60a398i7TM5RkofIA1J',
         'description': 'MfmnwBwK2HsWqnZMOJoDvWnhIFdVMn'
     }, {
         'title': 'p9TPfBKLqtlExLklJYnifHO72',
         'description': '0rppCThV5ybdROVlizmG5ryoWd7S7r'
     }, {
         'title': 'DpqNGv4q8ZhrYgyobSpEuqiq7',
         'description': 'BmQkMywysefELpWcG1OGYN9N98PdSi'
     }, {
         'title': 'pcqd88I0ZLpRqKYD7lTrbGEEY',
         'description': '7PYqk3Gg9J3Zr7nu8PKhv1tHH1NhdA'
     }, {
         'title': 'TGdwRQOaFBQ9J046BRB2DJXn4',
         'description': 'skEJq90yDVC5y0zmSD09f1rQyK8KNZ'
 }],
 updated_on = '2023-09-13T06:08:18.384903Z', vulnerability = 1, owasp = ['M1_2016'], pcidss = ['3_2', '3_3', '3_4'], hipaa = ['164_312_a_1'], cwe = ['CWE_926'], mstg = ['MSTG_6_3', 'MSTG_6_4'], masvs = ['MASVS_6_1'], asvs = [], gdpr = ['gdpr_25', 'gdpr_32'], computed_risk = 2, overridden_risk = None),
 Analysis(id = 22247, risk = 2, status = 3, cvss_base = 5.7, cvss_vector = 'CVSS:3.0/AV:P/AC:L/PR:H/UI:N/S:C/C:L/I:H/A:N', cvss_version = 3, cvss_metrics_humanized = [{
         'key': 'Attack Vector',
         'value': 'Physical'
     }, {
         'key': 'Attack Complexity',
         'value': 'Low'
     }, {
         'key': 'Privileges Required',
         'value': 'High'
     }, {
         'key': 'User Interaction',
         'value': 'Not Required'
     }, {
         'key': 'Scope',
         'value': 'Changed'
     }, {
         'key': 'Confidentiality Impact',
         'value': 'Low'
     }, {
         'key': 'Integrity Impact',
         'value': 'High'
     }, {
         'key': 'Availability Impact',
         'value': 'None'
     }],
     findings = [{
         'title': 'y4iutu3KCWb7shg6BsZqu867Y',
         'description': 'cqB9EcXpGrvQbsrGNMProR3J1cbmxw'
     }, {
         'title': 'kPLH7e9juz1wq2JCBJrVR9fnb',
         'description': '2rSLRxGXZbeSZ437l5bzKTTwwSB7il'
     }, {
         'title': 'qUObDBfoIvOSbVgyhQwxBWOY6',
         'description': 'iHdHrlq0dCA1gxjWyo4wnGZ3flmr70'
     }, {
         'title': 'l1i4LxUXU3PaMv1wsYaN7zzLu',
         'description': '5g4ml46nrfndL7M4V43ZbkEXVX0bVn'
     }, {
         'title': 'OgZY2lNjHTPqvNl75bupA3tNH',
         'description': 'IiwQX1xQDjX5t4W6Y9KyWIrMdeREtw'
     }],
 updated_on = '2023-09-13T06:08:21.540225Z', vulnerability = 2, owasp = ['M1_2016'], pcidss = ['3_2', '3_3', '3_4'], hipaa = ['164_312_a_1'], cwe = ['CWE_926'], mstg = ['MSTG_6_1'], masvs = ['MASVS_6_1'], asvs = [], gdpr = ['gdpr_25', 'gdpr_32'], computed_risk = 2, overridden_risk = None), ]

Note the vulnerability_id for Analysis(id=235). To get details about this vulnerability:

Get vulnerability details:

client.get_vulnerability(<vulnerability_id>)

Example:

>>> client.get_vulnerability(2)
Vulnerability(name='Improper Content Provider Permissions',
    description='A content provider permission was set to allow access from any other app on the device.
        Content providers may contain sensitive information about an app and therefore should not be shared.',
    intro="The `ContentProvider` class provides a mechanism for managing and sharing data with other applications.
        When sharing a provider's data with other apps, access control should be carefully implemented to prohibit unauthorized access to sensitive data.")

Upload app:

To upload and scan a new package:

>>> file_id = client.upload_file(<binary_data>)

Example:

>>> f = open('/home/username/apk/mfva_1.0.apk', 'rb')
>>> file_data = f.read()
>>> file_id = client.upload_file(file_data)
>>> client.get_file(file_id)
File(id=11469, name='MFVA', version='1.0', version_code='6', static_scan_progress=100)

Recent Uploads:

Get recent file uploads by the user:

>>> client.recent_uploads()

Example:

>>> client.recent_uploads()
[Submission(id=15506, status=7, file=11469, package_name='com.appknox.mfva', created_on='2019-05-06T16:04:50.094503Z', reason=''),
 Submission(id=15438, status=7, file=11405, package_name='com.appknox.mfva', created_on='2019-05-02T17:36:38.374191Z', reason=''),
 Submission(id=15437, status=7, file=11404, package_name='com.appknox.mfva', created_on='2019-05-02T17:35:29.245553Z', reason=''),
 Submission(id=15436, status=7, file=11403, package_name='com.appknox.mfva', created_on='2019-05-02T17:33:36.399803Z', reason=''),]

Rescan:

To rescan a file:

>>> client.rescan(<file_id>)

This will create a new file under the same project. Once the file has been started, list files to get the latest file id.

Example:

>>> client.rescan(7)

>>> client.get_files(4)
[File(id=8, name='MFVA', version='1.0', version_code='6', static_scan_progress=100),
    File(id=7, name='MFVA', version='1.0', version_code='6', static_scan_progress=100),,
    File(id=6, name='MFVA', version='1.0', version_code='5', static_scan_progress=100),]

Switch organization:

Change default organization for client instance.

>>> client.switch_organization(<organization_id>)

Example:

>>> client.switch_organization(3)
True

List Reports:

List all reports for a given File ID.

>>> client.list_reports(<file_id>)

Example:

>>> client.list_reports(95)
[Report(id=105, language='en', generated_on='2023-01-24T06:37:05.565031Z', progress=100, rating='21.62', preferences=ReportPreference(show_api_scan=True, show_manual_scan=True, show_static_scan=True, show_dynamic_scan=True, show_ignored_analyses=False, show_hipaa=InheritedPreference(value=True, is_inherited=True), show_pcidss=InheritedPreference(value=True, is_inherited=True)))]

Create Report:

Creates a new report for given file ID

>>> client.create_report(<file_id>)

Example:

>>> client.create_report(94)
Report(id=110, language='en', generated_on='2023-01-25T11:52:35.253614Z', progress=0, rating='6.76', preferences=ReportPreference(show_api_scan=True, show_manual_scan=True, show_static_scan=True, show_dynamic_scan=True, show_ignored_analyses=False, show_hipaa=InheritedPreference(value=True, is_inherited=True), show_pcidss=InheritedPreference(value=True, is_inherited=True)))

Get Report Summary CSV URL:

Returns a absolute URL to download report summary in CSV format for given report ID

>>> client.get_summary_csv_report_url(<report_id>)

Example:

>>> client.get_summary_csv_report_url(110)
'https://api.appknox.com/api/v2/reports/110/summary_csv_download?sig=eyJ1c2VyX2lkIjoyLCJ1c2VybmFtZSI6InJhamFuIn0:1pKeRU:U4qF1EQ3QJDFRCf33nvcZiLzmI4jZNlcR4sDqAW2_IM:1pKeRU:70aBOcQY8-Lm75IT4E41wr7oRkyHabZX6a9lO_tdTZk'

Get Report Summary Excel URL

Returns a absolute URL to download report summary in Excel format for given report ID

>>> client.get_summary_excel_report_url(<report_id>)

Example:

>>> client.get_summary_excel_report_url(110)
'https://api.appknox.com/api/v2/reports/110/summary_excel_download?sig=eyJ1c2VyX2lkIjoyLCJ1c2VybmFtZSI6InJhamFuIn0:1pKeTf:skTH0btBf6IWT8TfBZYszT2ymXnT2CJRatKzf_kZwLE:1pKeTf:1Nf1z-lU6V7EMdtnBk0nKKcFH0clrdthBRa1DIbbVFU'

Download Report Data from URL

Returns full HTTP response body from a given absolute URL

>>> client.download_report_data(<url>)

Examples:

>>> client.download_report_data('https://api.appknox.com/api/v2/reports/110/summary_excel_download?sig=eyJ1c2VyX2lkIjoyLCJ1c2VybmFtZSI6InJhamFuIn0:1pKeTf:skTH0btBf6IWT8TfBZYszT2ymXnT2CJRatKzf_kZwLE:1pKeTf:1Nf1z-lU6V7EMdtnBk0nKKcFH0clrdthBRa1DIbbVFU')
b'PK\x03\x04\x14\x00\x00\x00\x08\x00\x00\x00?\x008\x9d\x86\xd8>\x01\x00\x00\x07\x04\x00\x00\x13\x00\x00\x00[Content_Types].xml\xad\x93\xcbn\xc3 \x10E\xf7\xfd\n\xc4\xb62$]TU\x15\'\x8b>\x96m\x16\xe9\x07P\x18\xc7(\x18\x103I\x93\xbf/\xb6\x93H\xad\xd2<\x94n\x8c\xcc\xdc...(Truncated)
>>> client.download_report_data('https://api.appknox.com/api/v2/reports/110/summary_csv_download?sig=eyJ1c2VyX2lkIjoyLCJ1c2VybmFtZSI6InJhamFuIn0:1pKeZL:Rr8IyficPV19ik0GYBX7caY-qCswKCOEecFYbuCuo_w:1pKeZL:D0i-AzRv5IuFy1MhGINuxCQW41zgHiuC1DKsgsfGG8Y')
b'Project ID,Application Name,Application Namespace,Platform,Version,Version Code,File ID,Test Case,Scan Type,Severity,Risk Override,CVSS Score,Findings,Description,Noncompliant Code Example,Compliant Solution,Business Implication,OWASP...(Truncated)

Complete Reference

Indices and tables