Skip to content

MASTG-DEMO-0066: Sensitive Data Logging with idevicesyslog

Download MASTG-DEMO-0066 IPA Open MASTG-DEMO-0066 Folder Build MASTG-DEMO-0066 IPA

Sample

The code snippet below shows sample code that logs a sensitive token:

../MASTG-DEMO-0065/MastgTest.swift
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import SwiftUI
import os
import Darwin

struct MastgTest {
  private static let logger = Logger(
    subsystem: Bundle.main.bundleIdentifier ?? "org.owasp.mas.MastgTest",
    category: "MastgTest"
  )

  static func mastgTest(completion: @escaping (String) -> Void) {
    let token = "TOKEN=123"

    print("print: Leaking \(token) from print")
    debugPrint("debugPrint: Leaking \(token) from debugPrint")
    dump(token, name: "dump: Leaking token from dump")
    NSLog("NSLog: Leaking \(token) from NSLog")
    os_log("os_log: Leaking %{public}@ from os_log",
           log: .default, type: .info, token)

    logger.debug("logger.debug: Leaking \(token)")
    logger.debug("logger.debug (privacy: .public): Leaking \(token, privacy: .public)")
    logger.debug("logger.debug (privacy: .private): Leaking \(token, privacy: .private)")
    logger.debug("logger.debug (privacy: .sensitive): Leaking \(token, privacy: .sensitive)")


    logger.info("logger.info: Leaking \(token)")
    logger.info("logger.info (privacy: .public): Leaking \(token, privacy: .public)")
    logger.info("logger.info (privacy: .private): Leaking \(token, privacy: .private)")
    logger.info("logger.info (privacy: .sensitive): Leaking \(token, privacy: .sensitive)")

    logger.warning("logger.warning: Leaking \(token)")
    logger.warning("logger.warning (privacy: .public): Leaking \(token, privacy: .public)")
    logger.warning("logger.warning (privacy: .private): Leaking \(token, privacy: .private)")
    logger.warning("logger.warning (privacy: .sensitive): Leaking \(token, privacy: .sensitive)")

    logger.error("logger.error: Leaking \(token)")
    logger.error("logger.error (privacy: .public): Leaking \(token, privacy: .public)")
    logger.error("logger.error (privacy: .private): Leaking \(token, privacy: .private)")
    logger.error("logger.error (privacy: .sensitive): Leaking \(token, privacy: .sensitive)")

    logger.fault("logger.fault: Leaking \(token)")
    logger.fault("logger.fault (privacy: .public): Leaking \(token, privacy: .public)")
    logger.fault("logger.fault (privacy: .private): Leaking \(token, privacy: .private)")
    logger.fault("logger.fault (privacy: .sensitive): Leaking \(token, privacy: .sensitive)")


    fputs("fputs: Leaking \(token) from fputs\n", stderr)
    _ = swiftVfprintf(
      stream: stderr,
      format: "vfprintf: Leaking %s from vfprintf\n",
      token
    )
    _ = swiftVdprintf(
      filedes: fileno(stderr),
      format: "vdprintf: Leaking %s from vdprintf\n",
      token
    )
    swiftVsyslog(
      priority: LOG_USER | LOG_INFO,
      format: "vsyslog: Leaking %s from vsyslog\n",
      token
    )

    // To enable ASL logging, add <asl.h> to your bridging header
    // and uncomment the following:
    /*
    let ASL_LEVEL_NOTICE: Int32 = 5
    swiftVaslLog(
      client: nil,
      msg: nil,
      level: ASL_LEVEL_NOTICE,
      format: "asl_vlog: Leaking %s from asl_vlog\n",
      token
    )
    */

    if let data = "FileHandle.standardError: Leaking \(token) from FileHandle.standardError\n"
                  .data(using: .utf8) {
      FileHandle.standardError.write(data)
    }

    completion("Successfully logged a token: \(token)")
  }

  @discardableResult
  static func swiftVfprintf(
    stream: UnsafeMutablePointer<FILE>!,
    format: String,
    _ args: CVarArg...
  ) -> Int32 {
    return withVaList(args) { vfprintf(stream, format, $0) }
  }

  @discardableResult
  static func swiftVdprintf(
    filedes: Int32,
    format: String,
    _ args: CVarArg...
  ) -> Int32 {
    return withVaList(args) { vdprintf(filedes, format, $0) }
  }

  static func swiftVsyslog(
    priority: Int32,
    format: String,
    _ args: CVarArg...
  ) {
    _ = withVaList(args) { vsyslog(priority, format, $0) }
  }

  // ASL logging wrapper (requires <asl.h> in bridging header)
  /*
  static func swiftVaslLog(
    client: aslclient?,
    msg: aslmsg?,
    level: Int32,
    format: String,
    _ args: CVarArg...
  ) {
    _ = withVaList(args) { asl_vlog(client, msg, level, format, $0) }
  }
  */
}

Steps

  1. Install the app on a device ( Installing Apps).
  2. Make sure you have libimobiledevice suite installed on your machine.
  3. Run run.sh to start the log capturing.
  4. Click the Start button.
  5. Stop the script by pressing Ctrl+C to end the log capturing.
run.sh
1
idevicesyslog | grep -i MASTestApp > output.txt

Observation

The output contains all device logs, including the logged strings from the app.

output.txt
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[connected]
Sep 22 11:20:30 MASTestApp(UIKitCore)[32240] <Notice>: TX focusApplication (peekAppEvent) stealKB:Y scene:com.ja5er.test3-A8E224F1-CF5E-4699-9F77-10EACB955D4E
Sep 22 11:20:30 MASTestApp(UIKitCore)[32240] <Notice>: Evaluating dispatch of UIEvent: 0x103528fc0; type: 0; subtype: 0; backing type: 11; shouldSend: 1; ignoreInteractionEvents: 0, systemGestureStateChange: 0
Sep 22 11:20:30 MASTestApp(UIKitCore)[32240] <Notice>: Sending UIEvent type: 0; subtype: 0; to windows: 1
Sep 22 11:20:30 MASTestApp(UIKitCore)[32240] <Notice>: Sending UIEvent type: 0; subtype: 0; to window: <UIWindow: 0x1029c3e10>; contextId: 0x63D3A5C4
Sep 22 11:20:30 MASTestApp(UIKitCore)[32240] <Notice>: Evaluating dispatch of UIEvent: 0x103528fc0; type: 0; subtype: 0; backing type: 11; shouldSend: 0; ignoreInteractionEvents: 0, systemGestureStateChange: 0
Sep 22 11:20:31 MASTestApp(UIKitCore)[32240] <Notice>: Evaluating dispatch of UIEvent: 0x103528fc0; type: 0; subtype: 0; backing type: 11; shouldSend: 0; ignoreInteractionEvents: 0, systemGestureStateChange: 1
Sep 22 11:20:31 MASTestApp(UIKitCore)[32240] <Notice>: Evaluating dispatch of UIEvent: 0x103528fc0; type: 0; subtype: 0; backing type: 11; shouldSend: 1; ignoreInteractionEvents: 0, systemGestureStateChange: 0
Sep 22 11:20:31 MASTestApp(UIKitCore)[32240] <Notice>: Sending UIEvent type: 0; subtype: 0; to windows: 1
Sep 22 11:20:31 MASTestApp(UIKitCore)[32240] <Notice>: Sending UIEvent type: 0; subtype: 0; to window: <UIWindow: 0x1029c3e10>; contextId: 0x63D3A5C4
Sep 22 11:20:31 MASTestApp(Foundation)[32240] <Notice>: NSLog: Leaking TOKEN=123 from NSLog
Sep 22 11:20:31 MASTestApp[32240] <Error>: logger.warning: Leaking <private>
Sep 22 11:20:31 MASTestApp[32240] <Error>: logger.warning (privacy: .public): Leaking TOKEN=123
Sep 22 11:20:31 MASTestApp[32240] <Error>: logger.warning (privacy: .private): Leaking <private>
Sep 22 11:20:31 MASTestApp[32240] <Error>: logger.warning (privacy: .sensitive): Leaking <private>
Sep 22 11:20:31 MASTestApp[32240] <Error>: logger.error: Leaking <private>
Sep 22 11:20:31 MASTestApp[32240] <Error>: logger.error (privacy: .public): Leaking TOKEN=123
Sep 22 11:20:31 MASTestApp[32240] <Error>: logger.error (privacy: .private): Leaking <private>
Sep 22 11:20:31 MASTestApp[32240] <Error>: logger.error (privacy: .sensitive): Leaking <private>
Sep 22 11:20:31 MASTestApp[32240] <Fault>: logger.fault: Leaking <private>
Sep 22 11:20:31 MASTestApp[32240] <Fault>: logger.fault (privacy: .public): Leaking TOKEN=123
Sep 22 11:20:31 MASTestApp[32240] <Fault>: logger.fault (privacy: .private): Leaking <private>
Sep 22 11:20:31 MASTestApp[32240] <Fault>: logger.fault (privacy: .sensitive): Leaking <private>

Evaluation

The test fails because we can see TOKEN=123 in the logs:

Sep 22 11:20:31 MASTestApp(Foundation)[32240] <Notice>: NSLog: Leaking TOKEN=123 from NSLog
Sep 22 11:20:31 MASTestApp[32240] <Error>: logger.warning: Leaking <private>
Sep 22 11:20:31 MASTestApp[32240] <Error>: logger.warning (privacy: .public): Leaking TOKEN=123
Sep 22 11:20:31 MASTestApp[32240] <Error>: logger.error (privacy: .public): Leaking TOKEN=123
Sep 22 11:20:31 MASTestApp[32240] <Fault>: logger.fault (privacy: .public): Leaking TOKEN=123

Note how some of the logs pass the test since they were properly redacted with <private>. For example:

Sep 22 11:20:31 MASTestApp[32240] <Error>: logger.warning (privacy: .private): Leaking <private>
Sep 22 11:20:31 MASTestApp[32240] <Error>: logger.warning (privacy: .sensitive): Leaking <private>