MacOS.Sys.BashHistory

This artifact is a modified version of the Linux.Sys.BashHistory artifact that enables grep of Bash and alternate shell history and session files.

Session files can be helpful in determining an approximate timeframe in which certain commands were run (the session start/end time), as traditional history files do not provide this information.

http://www.swiftforensics.com/2018/05/bash-sessions-in-macos.html

This artifact can also be used to target other files located in the user profile such as _profile and rc files. shell history: /{root,home/}/._history profile: /{root,home/}/._profile rc file: /{root,home/}/.*rc

tags: .bash_history .bash_profile .bashrc


name: MacOS.Sys.BashHistory
author: Wes Lambert - @therealwlambert
description: |
  This artifact is a modified version of the Linux.Sys.BashHistory artifact that enables grep of Bash and alternate shell history and *session* files.

  Session files can be helpful in determining an approximate timeframe in which certain commands were run (the session start/end time), as traditional history files do not provide this information. 
  
  http://www.swiftforensics.com/2018/05/bash-sessions-in-macos.html

  This artifact can also be used to target other files located in the user profile such as
  *_profile and *rc files.
  shell history: /{root,home/*}/.*_history
  profile: /{root,home/*}/.*_profile
  *rc file: /{root,home/*}/.*rc

  tags: .bash_history .bash_profile .bashrc

reference:
  - http://www.swiftforensics.com/2018/05/bash-sessions-in-macos.html

parameters:
  - name: HistoryGlob
    default: /Users/*/.*_history
  - name: SessionsGlob
    default: /Users/*/.{bash,zsh}_sessions/*.history
  - name: SearchRegex
    type: regex
    description: "Regex of strings to search in line."
    default: '.'
  - name: WhitelistRegex
    type: regex
    description: "Regex of strings to leave out of output."
    default:

sources:
  - name: History
    query: |
      SELECT * FROM Artifact.Linux.Sys.BashHistory(TargetGlob=HistoryGlob,SearchRegex=SearchRegex,WhitelistRegex=WhitelistRegex)
          
  - name: Sessions
    query: |
      LET files = SELECT FullPath, Btime FROM glob(globs=SessionsGlob)
      SELECT * FROM foreach(row=files,
        query={
          SELECT Line,
            {SELECT Btime FROM glob(globs=FullPath + 'new')} AS SessionStarted, 
            Btime AS SessionEnded,
            timestamp(
              string=grok(
                data=read_file(
                  filename=split(
                    string=FullPath, 
                    sep='''\.history''')[0] + '.session'), grok='''echo Restored session: "\$\(/bin/date -r %{DATA:date}\)"''').date) AS SessionResumed,
            FullPath 
          FROM parse_lines(filename=FullPath)
          WHERE Line =~ SearchRegex 
          AND NOT if(condition= WhitelistRegex, then= Line =~ WhitelistRegex, else= FALSE)
        })