Beispiel #1
0
	def collectMiscArtifacts(self):
		self.pathsToCollect.append("/var/at/jobs")
		self.pathsToCollect.append("/etc/security/audit_warn")
		self.pathsToCollect.append("/etc/rc.common")
		self.pathsToCollect.append("/etc/launchd.conf")
		for user in self.userList:
			userFolder = util.safePathJoin("/Users", user)
			self.pathsToCollect.append(util.safePathJoin(userFolder, ".launchd.conf"))
Beispiel #2
0
 def collectSafariAppExtensions(self):
     lsregisterInfoPath = util.safePathJoin(self.collectionPath,
                                            "lsregister.txt")
     extensions = os.popen(
         """egrep -i -10 'NSExtensionPointIdentifier\s*=\s*"com\.apple\.Safari' {0}"""
         .format(lsregisterInfoPath)).read().rstrip()
     return extensions
Beispiel #3
0
 def collectHiddenLoginItems(self):
     lsregisterInfoPath = util.safePathJoin(self.collectionPath,
                                            "lsregister.txt")
     logins = os.popen(
         "egrep -oi '(/[^/]+)*/Contents/Library/LoginItems/.+\.app' {0} | grep -v '/Volumes/.*\.backupdb/'"
         .format(lsregisterInfoPath)).read().rstrip()
     return logins
Beispiel #4
0
	def collectUserLaunchAgents(self):
		userFolderPaths = []
		for user in self.userList:
			userFolderPaths.append(util.safePathJoin("/Users", user))
		
		output = ""
		collectFolders = []
		for userFolder in userFolderPaths:
			userLaunchAgentsFolder = util.safePathJoin(userFolder, "Library/LaunchAgents")
			if os.path.exists(userLaunchAgentsFolder):
				output += userLaunchAgentsFolder + "\n"
				output += os.popen("ls -aleO {0}".format(userLaunchAgentsFolder)).read().rstrip()
				output += "\n\n"
				self.pathsToCollect.append(userLaunchAgentsFolder)
					
		return output.rstrip()
Beispiel #5
0
    def getChromeExtensionList(self):
        extensionsDict = {}

        for user in self.userList:
            extensionsForUser = {}

            profileList = util.getChromeProfilesForUser(user)

            # Iterate over all profiles
            for profile in profileList:
                extensionsForProfile = []
                extFolder = util.safePathJoin(profileList[profile],
                                              "Extensions")
                if not os.path.exists(extFolder):
                    continue
                extensionList = os.listdir(extFolder)
                if not extensionList:
                    continue

                # Iterate extensions for profile
                for extension in extensionList:
                    extPath = util.safePathJoin(extFolder, extension)
                    if not os.path.isdir(extPath):
                        continue
                    manifestPath = ""
                    folderList = os.listdir(extPath)
                    versFolderPath = ""
                    for folder in folderList:
                        versFolderPath = util.safePathJoin(extPath, folder)
                        manifestPath = util.safePathJoin(
                            versFolderPath, "manifest.json")
                        if os.path.isfile(manifestPath):
                            break
                    if manifestPath == "":
                        continue

                    # A manifest.json file was found, this must be a valid extension
                    extensionsForProfile.append(extPath)
                #end for extension

                extensionsForUser[profile] = extensionsForProfile
            #end for profile

            extensionsDict[user] = extensionsForUser
        #end for user

        return extensionsDict
Beispiel #6
0
    def getFirefoxExtensionList(self):
        extensionsDict = {}

        for user in self.userList:
            extensionsForUser = {}

            profileList = util.getFirefoxProfilesForUser(user)

            # Iterate over all profiles
            for profile in profileList:
                extensionsForProfile = []
                extFolder = util.safePathJoin(profileList[profile],
                                              "extensions")
                if not os.path.exists(extFolder):
                    continue
                extensionList = os.listdir(extFolder)
                if not extensionList:
                    continue

                # Iterate extensions for profile
                for extension in extensionList:
                    if extension == ".DS_Store":
                        continue
                    extPath = util.safePathJoin(extFolder, extension)
                    if os.path.isdir(extPath):
                        # Older extension, is there an install.rdf?
                        installrdfPath = util.safePathJoin(
                            extPath, "install.rdf")
                        if not os.path.isfile(installrdfPath):
                            continue
                    else:
                        # Is it a .xpi?
                        if not extension.endswith(".xpi"):
                            continue

                    # If we're still here, this must be a valid extension
                    extensionsForProfile.append(extPath)
                #end for extension

                extensionsForUser[profile] = extensionsForProfile
            #end for profile

            extensionsDict[user] = extensionsForUser
        #end for user

        return extensionsDict
Beispiel #7
0
    def collect(self):
        filename = "persistence.txt"
        filePath = util.safePathJoin(self.collectionPath, filename)
        f = open(filePath, "w+")

        f.write(
            "PICT - Persistence information\n==============================\n\n"
        )

        f.write("Login items (current user)\n------------------------------\n")
        logins = self.collectLoginItems()
        f.write(logins + "\n\n")

        f.write("Hidden login items\n------------------------------\n")
        logins = self.collectHiddenLoginItems()
        f.write(logins + "\n\n")

        f.write("Kernel extensions\n------------------------------\n")
        output = self.collectKexts()
        f.write(output + "\n\n")

        f.write("Cron jobs\n------------------------------\n")
        output = self.collectCronJobs()
        f.write(output + "\n\n")

        f.write("Startup items\n------------------------------\n")
        output = self.collectStartupItems()
        f.write(output + "\n\n")

        f.write("Login hooks\n------------------------------\n")
        output = self.collectLoginHooks()
        f.write(output + "\n\n")

        f.write("Launch agents\n------------------------------\n")
        output = self.collectLaunchAgents()
        f.write(output + "\n\n")

        f.write("Launch daemons\n------------------------------\n")
        output = self.collectLaunchDaemons()
        f.write(output + "\n\n")

        f.write("User launch agents\n------------------------------\n")
        output = self.collectUserLaunchAgents()
        f.write(output + "\n\n")

        f.write("launchctl list\n------------------------------\n")
        output = self.collectLaunchctlList()
        f.write(output + "\n\n")

        f.close

        self.collectMiscArtifacts()

        Collector.collect(self)
Beispiel #8
0
    def collectSafari(self):
        try:
            os.listdir(os.path.expanduser("~/Library/Safari/Extensions"))
        except Exception as e:
            if "Operation not permitted" in str(e):
                return "Unable to access due to TCC restrictions"

        output = ""
        extensionsForUsers = self.getSafariExtensionList()

        for user in extensionsForUsers:
            output += "Extensions for {0}:\n".format(user)
            extensionList = extensionsForUsers[user]

            # Iterate extensions for user
            for extPath in extensionList:
                # Mark this path for collection
                self.pathsToCollect.append(extPath)
                tempdir = tempfile.mkdtemp()
                err = os.system("cd {0}; xar -xf {1}".format(tempdir, extPath))
                if err:
                    extName = "Unknown file format ({0})".format(err)
                else:
                    # Expand the extension
                    tempdirlist = os.listdir(tempdir)
                    for oneItem in tempdirlist:
                        oneItemPath = util.safePathJoin(tempdir, oneItem)
                        if os.path.isdir(oneItemPath):
                            expExtPath = oneItemPath
                            break
                    # Read the name from the Info.plist
                    extInfoPlistPath = util.safePathJoin(
                        expExtPath, "Info.plist")
                    extInfoPlist = plistlib.readPlist(extInfoPlistPath)
                    extName = extInfoPlist["CFBundleDisplayName"]
                # end if
                output += "  Extension: {0}\n".format(extPath)
                output += "  Name: {0}\n\n".format(extName)

        return output.rstrip()
Beispiel #9
0
    def getSafariExtensionList(self):
        extensionsDict = {}

        for user in self.userList:
            extensionsForUser = []

            safariExtFolder = "/Users/{0}/Library/Safari/Extensions".format(
                user)
            if not os.path.isdir(safariExtFolder):
                continue
            safariExtList = os.listdir(safariExtFolder)
            for extension in safariExtList:
                if extension.endswith(".safariextz"):
                    extensionsFolderPath = util.safePathJoin(
                        safariExtFolder, extension)
                    extensionsForUser.append(extensionsFolderPath)
            if extensionsForUser:
                extensionsDict[user] = extensionsForUser

        return extensionsDict
Beispiel #10
0
    def collectFirefox(self):
        output = ""
        for user in self.userList:
            output += "History for user {0}:\n\n".format(user)

            profileList = util.getFirefoxProfilesForUser(user)
            for profile in profileList:
                output += " > History for profile {0}:\n\n".format(profile)

                profilePath = profileList[profile]
                dbFilePath = util.safePathJoin(profilePath, "places.sqlite")
                if os.path.isfile(dbFilePath):
                    self.pathsToCollect.append(dbFilePath)
                else:
                    output += "No history found\n\n"
                    continue

                query = "select strftime('%Y-%m-%d %H:%M:%S', datetime((moz_historyvisits.visit_date / 1000000), 'unixepoch'), 'utc'), moz_places.url from moz_historyvisits, moz_places where moz_historyvisits.place_id=moz_places.id and moz_historyvisits.visit_date/1000000 > (strftime('%s', 'now') - 2592000*3) order by moz_historyvisits.visit_date;"

                output += self.collectForQuery(dbFilePath, query)
                output += "\n\n"

        return output.rstrip()
Beispiel #11
0
    def collectChrome(self):
        output = ""
        for user in self.userList:
            output += "History for user {0}:\n\n".format(user)

            profileList = util.getChromeProfilesForUser(user)
            for profile in profileList:
                output += " > History for profile {0}:\n\n".format(profile)

                profilePath = profileList[profile]
                dbFilePath = util.safePathJoin(profilePath, "History")
                if os.path.isfile(dbFilePath):
                    self.pathsToCollect.append(dbFilePath)
                else:
                    output += "No history found\n\n"
                    continue

                query = "select strftime('%Y-%m-%d %H:%M:%S', datetime((strftime('%s','1601-01-01 00:00:00') + (visits.visit_time / 1000000)), 'unixepoch'), 'utc'), urls.url from visits, urls where visits.url=urls.id and visits.visit_time > (strftime('%s', 'now') - strftime('%s', '1601-01-01 00:00:00') - 2592000*3) order by visits.visit_time;"

                output += self.collectForQuery(dbFilePath, query)
                output += "\n\n"

        return output.rstrip()
Beispiel #12
0
	def collectFileList(self, pathList, collectionDir):
		if not self.collectArtifacts:
			return
		
		if not pathList:
			return
		if not collectionDir:
			return
		if collectionDir == "" or not os.path.isdir(collectionDir):
			return
		artifactsFolder = util.safePathJoin(collectionDir, self.artifactsFolderName)
		for onePath in pathList:
			if os.path.exists(onePath):
				try:
					thisDestPath = os.path.join(artifactsFolder, onePath.lstrip("/"))
					# Use subprocess.call to ensure paths are properly escaped
					err = subprocess.call(["ditto", onePath, thisDestPath], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
					if err:
						print "Error collecting path: {0}".format(onePath)
						print "error = {0}".format(err)
				except Exception as e:
					print "Error collecting path: {0}".format(onePath)
					print e
Beispiel #13
0
    def collectChrome(self):
        output = ""
        extensionsForUsers = self.getChromeExtensionList()

        for user in extensionsForUsers:
            output += "Extensions for {0}:\n".format(user)
            extensionsForProfiles = extensionsForUsers[user]

            # Iterate over all profiles
            for profile in extensionsForProfiles:
                output += "  Profile {0}:\n".format(profile)
                extensionList = extensionsForProfiles[profile]

                # Iterate extensions for profile
                for extPath in extensionList:
                    if not os.path.isdir(extPath):
                        continue
                    manifestPath = ""
                    folderList = os.listdir(extPath)
                    versFolderPath = ""
                    for folder in folderList:
                        versFolderPath = util.safePathJoin(extPath, folder)
                        manifestPath = util.safePathJoin(
                            versFolderPath, "manifest.json")
                        if os.path.isfile(manifestPath):
                            break
                    if manifestPath == "":
                        continue
                    # A manifest.json file was found, this must be a valid extension
                    # Mark this path for collection
                    self.pathsToCollect.append(extPath)
                    f = open(manifestPath, "r")
                    manifestJSON = f.read()
                    f.close
                    manifestDict = json.loads(manifestJSON)
                    extName = manifestDict['name']
                    if extName.startswith("__MSG_") and extName.endswith("__"):
                        # There's a localized name, look for it in English
                        localePath = util.safePathJoin(
                            versFolderPath, "_locales/en/messages.json")
                        if not os.path.exists(localePath):
                            localePath = util.safePathJoin(
                                versFolderPath, "_locales/en_US/messages.json")
                        if not os.path.exists(localePath):
                            extName = "Unknown name"
                        else:
                            nameKey = extName[6:][:-2]
                            f = open(localePath, "r")
                            localeJSON = f.read()
                            f.close
                            localeDict = json.loads(localeJSON)
                            extName = dict(
                                (key.lower(), value)
                                for key, value in localeDict.iteritems())[
                                    nameKey.lower()]['message']
                    #end if extName.startswith("__MSG_")

                    output += "    Extension: {0}\n".format(extPath)
                    output += "    Name: {0}\n\n".format(extName)
                #end for extension
            #end for profile
        #end for user

        return output.rstrip()
Beispiel #14
0
    def collectFirefox(self):
        output = ""
        extensionsForUsers = self.getFirefoxExtensionList()

        for user in extensionsForUsers:
            output += "Extensions for {0}:\n".format(user)
            extensionsForProfiles = extensionsForUsers[user]

            # Iterate over all profiles
            for profile in extensionsForProfiles:
                output += "  Profile {0}:\n".format(profile)
                extensionList = extensionsForProfiles[profile]

                # Iterate extensions for profile
                for extPath in extensionList:
                    if extPath.endswith(".DS_Store"):
                        continue
                    # Mark this path for collection
                    self.pathsToCollect.append(extPath)
                    if os.path.isdir(extPath):
                        # Older extension, look for name in install.rdf
                        installrdfPath = util.safePathJoin(
                            extPath, "install.rdf")
                        if not os.path.isfile(installrdfPath):
                            extName = "Unknown extension type"
                        else:
                            f = open(installrdfPath, "r")
                            installrdfData = f.read()
                            f.close
                            m = re.search("<em:name>([^<]*)</em:name>",
                                          installrdfData, re.I)
                            if m:
                                extName = m.group(1)
                            else:
                                extName = "Unknown name"
                    else:
                        # Is it a .xpi? If so, decompress and get name
                        if extPath.endswith(".xpi"):
                            tempdir = tempfile.mkdtemp()
                            zipf = open(extPath, "rb")
                            zip = zipfile.ZipFile(zipf)
                            zip.extract("manifest.json", tempdir)
                            zipf.close
                            manifestPath = util.safePathJoin(
                                tempdir, "manifest.json")
                            f = open(manifestPath, "r")
                            manifestJSON = f.read()
                            f.close
                            manifestDict = json.loads(manifestJSON)
                            extName = dict((key.lower(), value) for key, value
                                           in manifestDict.iteritems())['name']
                        else:
                            extName = "Unknown extension type"

                    output += "    Extension: {0}\n".format(extPath)
                    output += "    Name: {0}\n\n".format(extName)
                #end for extension
            #end for profile
        #end for user

        return output.rstrip()
Beispiel #15
0
    def collect(self):
        basicsFilename = "basic_info.txt"
        basicsFilePath = util.safePathJoin(self.collectionPath, basicsFilename)
        f = open(basicsFilePath, "w+")

        user = os.popen("logname").read().rstrip()
        when = datetime.utcnow().strftime("%-d %b %Y @ %H:%M:%S UTC")
        whenlocal = datetime.now().strftime("%-d %b %Y @ %H:%M:%S")
        f.write("Collected by user {0} on {1} (local {2})\n".format(
            user, when, whenlocal))
        uptime = os.popen("uptime").read().rstrip()
        f.write("Uptime: {0}\n".format(uptime))
        hostname = os.popen("hostname").read().rstrip()
        f.write("Hostname: {0}\n".format(hostname))
        spctlStatus = os.popen("spctl --status").read().rstrip()
        f.write("System policy security: {0}\n".format(spctlStatus))
        if spctlStatus != "assessments enabled":
            f.write("  Gatekeeper is disabled!\n")
        sipStatus = os.popen("csrutil status").read().rstrip() + "\n"
        f.write(sipStatus)
        filevaultStatus = os.popen("fdesetup status").read().rstrip()
        f.write("FileVault status: {0}\n".format(filevaultStatus))
        firewallStatus = os.popen(
            "defaults read /Library/Preferences/com.apple.alf globalstate"
        ).read().rstrip()
        if firewallStatus == "0":
            f.write("Application firewall is not enabled\n")
        else:
            f.write("Application firewall is enabled\n")

        # Concerning things...
        if os.path.exists("/private/etc/kcpassword"):
            f.write("WARNING! Automatic login is enabled by user!\n")
        result = os.system(
            "egrep -i '127\.0\.0\.1\s*.*activate.*\.adobe\.com' /Users/thomas/Desktop/hosts &>/dev/null"
        )
        if result == 0:
            f.write("WARNING! Hosts file shows signs of piracy activity!\n")

        # System profiler stuff
        f.write("\n")
        systemOverview = os.popen(
            "system_profiler SPSoftwareDataType").read().rstrip()
        f.write(systemOverview)
        f.write("\n\n")
        hardwareOverview = os.popen(
            "system_profiler SPHardwareDataType").read().rstrip()
        f.write(hardwareOverview)
        f.write("\n\n")

        # Users
        f.write("User list\n-----------------------------\n")
        users = os.popen("dscl . list /Users | grep -v '_'").read().rstrip()
        userlist = users.split("\n")
        for user in userlist:
            if user != "daemon" and user != "nobody":
                userInfo = os.popen("dscacheutil -q user -a name {0}".format(
                    user)).read().rstrip()
                f.write(userInfo + "\n\n")

        f.write("Admin users\n-----------------------------\n")
        users = os.popen(
            "dscl . -read /Groups/admin GroupMembership").read().rstrip()
        userlist = users.split()[1:]
        for user in userlist:
            f.write(user + "\n")
        f.write("\n")

        # Login activity

        f.write("Users logged in\n-----------------------------\n")
        users = os.popen("w").read().rstrip()
        f.write(users + "\n\n")

        f.write("Last logins\n-----------------------------\n")
        users = os.popen("last").read().rstrip()
        f.write(users + "\n\n")

        f.close

        Collector.collect(self)