This tool automates the process of creating logon relations from MS Windows Security Events by showing a graphical relation among users domains, source and destination logons as well as session duration.
It has the following output modes:
- Standard output
- CSV file
- JSON file
- Neo4J graph
- Graphviz dot file
- Timesketch
- Preparation
- Command Line
- EVTx Analisys
- Indexing
- Using the tool
- CSV Output
- JSON Output
- Timesketch Output
- Neo4J Export
- Graphviz dot file output
- SQLite import
- Processed events
git clone https://github.com/THIBER-ORG/userline.git
cd userline/src
sudo pip3 install -U -r ../requirements.txt
Optionally you can build a Docker image as follows:
git clone https://github.com/THIBER-ORG/userline.git
cd userline
docker build . -t userline
To work with UserLine when using the Docker image, use the following syntax:
docker run --rm -ti --net=host -v [YOUR_DATA_PATH]:/data userline userline [PARAMETERS]
Example:
docker run --rm -ti --net=host -v $(pwd)/data:/data userline userline -h
Note: --net=host
is only required if you're running ElasticSearch/Neo4J in another container on the same host.
$ ./userline.py -h
/\ /\ ___ ___ _ __ / /(_)_ __ ___
/ / \ \/ __|/ _ \ '__/ / | | '_ \ / _ \
\ \_/ /\__ \ __/ | / /__| | | | | __/
\___/ |___/\___|_| \____/_|_| |_|\___| v0.2.4b
Author: Chema Garcia (aka sch3m4)
@sch3m4
https://github.com/thiber-org/userline
usage: userline.py [-h] [-H ESHOSTS] [-S POOL_SIZE] -i INDEX [-r URL]
(-x | -L | -E | -l | -w DATE) [-c PATH] [-j PATH] [-n BOLT]
[-g PATH] [-K PATH] [-F] [-d] [-f] [-s] [-t MIN_DATE]
[-T MAX_DATE] [-p PATTERN] [-I] [-k] [-v] [-m DATETIME]
optional arguments:
-h, --help show this help message and exit
Required arguments:
-H ESHOSTS, --eshosts ESHOSTS
Single or comma separated list of ElasticSearch hosts
to query (default: localhost)
-S POOL_SIZE, --pool-size POOL_SIZE
Connection pool size (default: 5)
-i INDEX, --index INDEX
Index name/pattern
-r URL, --redis URL Redis URL (format: redis://:pass@host:port/db)
Actions:
-x, --inspect Gets some statistics about the indexed data
-L, --last-shutdown Gets last shutdown data
-E, --last-event Gets last event data
-l, --logons Shows user logon activity
-w DATE, --who-was-at DATE
Shows only logged on users at a given time
Output:
-c PATH, --csv-output PATH
CSV Output file
-j PATH, --json-output PATH
JSON Output file
-n BOLT, --neo4j BOLT
Neo4j bolt with auth (format:
bolt://user:pass@host:port)
-g PATH, --graphviz PATH
Graphviz .dot file
-K PATH, --timesketch PATH
Timesketch CSV file
CSV options:
-F, --disable-timeframe
Do not create timeframe entries
JSON options:
-d, --duplicate-events
Duplicate events (logon & logoff)
Neo4J options:
-f, --neo4j-full-info
Saves full logon/logoff info in Neo4j relations
Graph (Neo4J/Graphviz) options:
-s, --unique-logon-rels
Sets unique logon relations
Optional filtering arguments:
-t MIN_DATE, --min-date MIN_DATE
Searches since specified date (default: 2016-07-23)
-T MAX_DATE, --max-date MAX_DATE
Searches up to specified date (default: 2017-07-23)
-p PATTERN, --pattern PATTERN
Includes pattern in search
-I, --include-local Includes local services logons (default: Excluded)
-k, --include-locks Includes workstation/screensaver lock events (default:
Excluded)
-v, --verbose Enables verbose mode
Extra information:
-m DATETIME, --mark-if-logged-at DATETIME
Marks logged in users at a given time
Analyze EVTx files with plaso
$ docker run -v /mnt/IR/1329585/:/data log2timeline/plaso log2timeline --hashers md5,sha256 -z Europe/Madrid /data/processed/events/windows/security/sec-evtx.plaso /data/evidences/events/windows/security/
Note: psort elastic output is really slow, for better performance upload the .plaso file to TimeSketch
If your image does not already support it, use the included Plaso Dockerfile:
$ cd userline/plaso
$ docker build . -t plaso/es
Process the events and store them into elasticsearch
$ docker run -ti --net="host" -v /mnt/IR/1329585/:/data plaso/es psort.py -o elastic --server 172.21.0.2 --port 9200 --doc_type plaso --index_name ir-1329585-events-security-windows /data/processed/events/windows/security/sec-evtx.plaso
Getting the last shutdown event:
$ ./userline.py -i ir-1329585-events-security-windows --last-shutdown
/\ /\ ___ ___ _ __ / /(_)_ __ ___
/ / \ \/ __|/ _ \ '__/ / | | '_ \ / _ \
\ \_/ /\__ \ __/ | / /__| | | | | __/
\___/ |___/\___|_| \____/_|_| |_|\___| v0.2.4b
Author: Chema Garcia (aka sch3m4)
@sch3m4
https://github.com/thiber-org/userline
INFO - Last shutdown:
INFO - Computer: ws01.evil.corp
INFO - - Datetime: 2016-07-12 18:56:33+00:00
INFO - - Uptime: 124 days, 23:24:03
INFO - - EvtIndex: ir-1329585-events-security-windows
INFO - - EvtId: AVsRMBloEoASMdQErSf-
Getting the last event:
$ ./userline.py -i ir-1329585-events-security-windows --last-event
/\ /\ ___ ___ _ __ / /(_)_ __ ___
/ / \ \/ __|/ _ \ '__/ / | | '_ \ / _ \
\ \_/ /\__ \ __/ | / /__| | | | | __/
\___/ |___/\___|_| \____/_|_| |_|\___| v0.2.4b
Author: Chema Garcia (aka sch3m4)
@sch3m4
https://github.com/thiber-org/userline
INFO - Last event:
INFO - Computer: ws01.evil.corp
INFO - {
"computer": "ws01.evil.corp",
"datetime": "2017-02-14 05:04:36+00:00",
"description": "N/A",
"domain": "N/A",
"eventid": 6006,
"id": "cbc2794961fa5ced4366ef52673479faf4df5a53ca66280263526bbe0bee13af",
"index": "ir-1329585-events-security-windows",
"ipaddress": "N/A",
"logonid": "N/A",
"raw": "<Event xmlns=\"http://schemas.microsoft.com/win/2004/08/events/event\">\n <System>\n <Provider Name=\"EventLog\"/>\n <EventID Qualifiers=\"32768\">6006</EventID>\n <Level>4</Level>\n <Task>0</Task>\n <Keywords>0x0080000000000000</Keywords>\n <TimeCreated SystemTime=\"2017-02-14T05:44:36.000000000Z\"/>\n <EventRecordID>784</EventRecordID>\n <Channel>System</Channel>\n <Computer>ws01.evil.corp</Computer>\n <Security/>\n </System>\n <EventData>\n <Binary>0100000000000000</Binary>\n </EventData>\n</Event>\n",
"sourceid": "AOsBX5IrkRtSdYVCbxr4",
"srcid": "N/A",
"timestamp": 1492458753000,
"type": "N/A",
"username": "N/A"
}
Getting logon relations between two dates into a CSV file:
$ ./userline.py -l -i ir-1329585-events-security-windows -t 2016-11-20T11:00:00 -T 2016-11-21T11:00:00 -c output.csv
/\ /\ ___ ___ _ __ / /(_)_ __ ___
/ / \ \/ __|/ _ \ '__/ / | | '_ \ / _ \
\ \_/ /\__ \ __/ | / /__| | | | | __/
\___/ |___/\___|_| \____/_|_| |_|\___| v0.2.4b
Author: Chema Garcia (aka sch3m4)
@sch3m4
https://github.com/thiber-org/userline
INFO - Building query
INFO - Found 297 events to be processed
INFO - Processing events
[====================] 100.0% Elapsed: 0m 02s ETA: 0m00s
INFO - 44 Logons processed in 0:00:02.051880
Getting logon relations between two dates into a JSON file:
$ ./userline.py -l -i ir-1329585-events-security-windows -t 2016-11-20T11:00:00 -T 2016-11-21T11:00:00 -j output.json
/\ /\ ___ ___ _ __ / /(_)_ __ ___
/ / \ \/ __|/ _ \ '__/ / | | '_ \ / _ \
\ \_/ /\__ \ __/ | / /__| | | | | __/
\___/ |___/\___|_| \____/_|_| |_|\___| v0.2.4b
Author: Chema Garcia (aka sch3m4)
@sch3m4
https://github.com/thiber-org/userline
INFO - Building query
INFO - Found 297 events to be processed
INFO - Processing events
[====================] 100.0% Elapsed: 0m 02s ETA: 0m00s
INFO - 44 Logons processed in 0:00:02.051880
Getting logon relations between two dates into a Timesketch compatible CSV file:
$ ./userline.py -l -i ir-1329585-events-security-windows -t 2016-11-20T11:00:00 -T 2016-11-21T11:00:00 -K output.csv
/\ /\ ___ ___ _ __ / /(_)_ __ ___
/ / \ \/ __|/ _ \ '__/ / | | '_ \ / _ \
\ \_/ /\__ \ __/ | / /__| | | | | __/
\___/ |___/\___|_| \____/_|_| |_|\___| v0.2.4b
Author: Chema Garcia (aka sch3m4)
@sch3m4
https://github.com/thiber-org/userline
INFO - Building query
INFO - Found 297 events to be processed
INFO - Processing events
[====================] 100.0% Elapsed: 0m 02s ETA: 0m00s
INFO - 44 Logons processed in 0:00:02.051880
Getting logon relations into Neo4J graph:
$ docker run -d -p 7474:7474 -p 7687:7687 -e NEO4J_AUTH=none -v $HOME/neo4j/data:/data neo4j
$ ./userline.py -l -i ir-1329585-events-security-windows -t 2016-11-20T11:00:00 -T 2016-11-21T11:00:00 -n "bolt://localhost:7687/"
/\ /\ ___ ___ _ __ / /(_)_ __ ___
/ / \ \/ __|/ _ \ '__/ / | | '_ \ / _ \
\ \_/ /\__ \ __/ | / /__| | | | | __/
\___/ |___/\___|_| \____/_|_| |_|\___| v0.2.4b
Author: Chema Garcia (aka sch3m4)
@sch3m4
https://github.com/thiber-org/userline
INFO - Building query
INFO - Found 297 events to be processed
INFO - Processing events
[====================] 100.0% Elapsed: 0m 02s ETA: 0m00s
INFO - 44 Logons processed in 0:00:02.051880
MATCH(n) RETURN(n)
Query the results using Neo4J CQL
MATCH(n)-[r]-(m) DELETE n,r,m
MATCH(n) DELETE n
$ ./userline.py -l -i ir-1329585-events-security-windows -t 2016-11-20T11:00:00 -T 2016-11-21T11:00:00 -g graph.dot
/\ /\ ___ ___ _ __ / /(_)_ __ ___
/ / \ \/ __|/ _ \ '__/ / | | '_ \ / _ \
\ \_/ /\__ \ __/ | / /__| | | | | __/
\___/ |___/\___|_| \____/_|_| |_|\___| v0.2.4b
Author: Chema Garcia (aka sch3m4)
@sch3m4
https://github.com/thiber-org/userline
INFO - Building query
INFO - Found 297 events to be processed
INFO - Processing events
[====================] 100.0% Elapsed: 0m 02s ETA: 0m00s
INFO - 44 Logons processed in 0:00:02.051880
Once you've generated the .dot file, you can generate an image with the graph as follows:
$ dot -Tpng graph.dot > graph.png
Once you've generated the .dot file, you can import the graph into Gephi:
Once you've generated the CSV output, you can import the data into a SQLite database and query the data through SQL queries:
$ sqlite3 logon.db
SQLite version 3.11.0 2016-02-15 17:29:24
Enter ".help" for usage hints.
sqlite> .mode csv userline
sqlite> .import output.csv userline
sqlite> .tables
userline
sqlite> .q
$ sqliteman logon.db
- EVENT_WORKSTATION_UNLOCKED = 4801
- EVENT_SCREENSAVER_DISMISSED = 4803
- EVENT_LOGON = 4624
- EVENT_LOGON_EXPLICIT = 4648
- EVENT_SESSION_RECONNECTED = 4778
- EVENT_WORKSTATION_LOCKED = 4800
- EVENT_SCREENSAVER_INVOKED = 4802
- EVENT_SHUTDOWN = 4609
- EVENT_LOGOFF = 4634
- EVENT_SESSION_DISCONNECTED = 4779
- EVENT_LOGOFF_INITIATED = 4647