#!/bin/bash # # Copyright 2014,2015,2016,2017,2018,2019,2020,2021 Security Onion Solutions, LLC # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . COMMON="/usr/sbin/so-common" if ! [ -f $COMMON ]; then echo "$COMMON not found." echo "This script requires Security Onion 16.04 or later." exit fi source $COMMON # check to see if this is a sensor before continuing if [ -f /root/.ssh/securityonion_ssh.conf ]; then echo "This machine appears to be a sensor connected to a distributed deployment." echo "This script was designed for standalone systems designated for so-import-pcap." exit fi HOST_ORIG=`hostname` HOSTNAME=${HOST_ORIG,,} SENSORNAME="$HOSTNAME-import" SENSOR="$HOSTNAME-import" SENSORCONF="/etc/nsm/$SENSORNAME/sensor.conf" # if the system hasn't been configured for so-import-pcap, then run so-import-pcap-configure if ! [ -f /etc/nsm/so-import-pcap.conf ]; then . /usr/sbin/so-import-pcap-configure fi # display usage if no valid pcap files are passed function usage { cat << EOF Usage: Please supply at least one pcap file. For example, to import a single pcap named import.pcap: so-import-pcap import.pcap To import multiple pcaps: so-import-pcap import1.pcap import2.pcap EOF } # if no parameters supplied, display usage if [ $# -eq 0 ]; then usage exit fi # verify that all parameters are files for i in "$@"; do if ! [ -f "$i" ]; then usage echo "\"$i\" is not a valid file!" exit fi done echo "Please wait while:" echo # track any temporary pcaps so they can be deleted when finished TEMP_PCAPS=() # track if we have any valid or invalid pcaps INVALID_PCAPS="no" VALID_PCAPS="no" # track oldest start and newest end so that we can generate the Kibana search hyperlink at the end START_OLDEST="2030-12-31" END_NEWEST="1971-01-01" # paths must be quoted in case they include spaces for PCAP in "$@"; do PCAP=$(/usr/bin/realpath "$PCAP") echo "- checking ${PCAP}" if ! /usr/bin/capinfos "${PCAP}" >/dev/null 2>&1; then # try to fix pcap and then process the fixed pcap directly PCAP_FIXED=`mktemp /tmp/so-import-pcap-XXXXXXXXXX.pcap` echo "- attempting to recover ${PCAP} to ${PCAP_FIXED}." /usr/bin/pcapfix "${PCAP}" -o "${PCAP_FIXED}" >/dev/null PCAP="${PCAP_FIXED}" TEMP_PCAPS+=(${PCAP_FIXED}) fi # check to see if file is a valid PCAP if /usr/bin/capinfos "${PCAP}" |egrep -q "Last packet time: 1970-01-01|Last packet time: n/a"; then echo "Invalid pcap file!" INVALID_PCAPS="yes" else VALID_PCAPS="yes" CONF="/etc/nsm/securityonion.conf" source $CONF # check to see if another instance of so-import-pcap is already writing IDS alerts LOCK="/var/lock/so-import-pcap-ids" if [ -f $LOCK ] ; then echo -n "- waiting for another instance of so-import-pcap to finish writing IDS alerts..." while [ -f $LOCK ]; do sleep 1s echo -n "." done echo fi # create a new lock file before writing IDS alerts to prevent others from trying to write at same time touch $LOCK # generate IDS alerts and write them to standard pipeline for consumption via Sguil agents if [ "$ENGINE" = "snort" ]; then echo "- analyzing traffic with Snort" /usr/bin/snort --daq pcap -c /etc/nsm/$SENSORNAME/snort.conf -u sguil -g sguil -l /nsm/sensor_data/$SENSORNAME/snort-1 -k none -r "${PCAP}" >/dev/null 2>&1 else echo "- analyzing traffic with Suricata" /usr/bin/suricata --user sguil --group sguil -c /etc/nsm/$SENSORNAME/suricata.yaml -l /nsm/sensor_data/$SENSORNAME --runmode single -k none -r "${PCAP}" >/dev/null 2>&1 fi # remove lock file to allow others to write IDS alerts rm $LOCK # generate Zeek logs and write them to a unique subdirectory in /nsm/import/bro/ # since each run writes to a unique subdirectory, there is no need for a lock file BRODIR="/nsm/import/bro" echo "- analyzing traffic with Zeek" mkdir -p $BRODIR BROLOGDIR=$(mktemp -d -p $BRODIR -t bro-XXXXXXXX) chown $(stat $BRODIR -c %u:%g) $BROLOGDIR chmod $(stat $BRODIR -c %a) $BROLOGDIR cd $BROLOGDIR /opt/bro/bin/bro -C -r "${PCAP}" local >/dev/null 2>&1 cd - >/dev/null source $SENSORCONF # split traffic into daily directories so that sguil's pcap_agent can find it if [ "$PCAP_AGENT_ENABLED" = "yes" ] ; then # check to see if another instance of so-import-pcap is already writing to pcap store LOCK="/var/lock/so-import-pcap" if [ -f $LOCK ] ; then echo -n "- waiting for another instance of so-import-pcap to release its lock on the pcap store..." while [ -f $LOCK ]; do sleep 1s echo -n "." done echo fi # create a new lock file before writing to pcap store to prevent others from trying to write at same time touch $LOCK START=`/usr/bin/capinfos "${PCAP}" -a |grep "First packet time:" | awk '{print $4}'` END=`/usr/bin/capinfos "${PCAP}" -e |grep "Last packet time:" | awk '{print $4}'` ENDNEXT=`date +%Y-%m-%d --date="$END 1 day"` CURRENT="$START" # compare $START to $START_OLDEST echo "- processing pcap dates $START through $END" START_COMPARE=$(date -d $START +%s) START_OLDEST_COMPARE=$(date -d $START_OLDEST +%s) if [ $START_COMPARE -lt $START_OLDEST_COMPARE ]; then START_OLDEST=$START fi # compare $ENDNEXT to $END_NEWEST ENDNEXT_COMPARE=$(date -d $ENDNEXT +%s) END_NEWEST_COMPARE=$(date -d $END_NEWEST +%s) if [ $ENDNEXT_COMPARE -gt $END_NEWEST_COMPARE ]; then END_NEWEST=$ENDNEXT fi while [ "$CURRENT" != "$ENDNEXT" ]; do echo " - processing $CURRENT" EPOCH=`date +%s --date="$CURRENT"` PCAPDIR="/nsm/sensor_data/$SENSORNAME/dailylogs/$CURRENT" FILE="$PCAPDIR/snort.log.$EPOCH" mkdir -p $PCAPDIR CURRENTNEXT=`date +%Y-%m-%d --date="$CURRENT 1 day"` if [ -f $FILE ]; then PCAPNEW=`mktemp /tmp/so-import-pcap-XXXXXXXXXX.pcap` echo " - copying traffic to $PCAPNEW" /usr/bin/editcap -F libpcap -A "$CURRENT 00:00:00" -B "$CURRENTNEXT 00:00:00" "${PCAP}" "${PCAPNEW}" FILEOLD=`mktemp /tmp/so-import-pcap-XXXXXXXXXX.pcap` echo " - copying $FILE to $FILEOLD" cp $FILE $FILEOLD echo " - merging $FILEOLD and $PCAPNEW into $FILE" /usr/bin/mergecap -F pcap -w $FILE $FILEOLD "${PCAPNEW}" echo " - removing $FILEOLD and $PCAPNEW" rm $FILEOLD "${PCAPNEW}" else echo " - writing $FILE" /usr/bin/editcap -F libpcap -A "$CURRENT 00:00:00" -B "$CURRENTNEXT 00:00:00" "${PCAP}" $FILE fi CURRENT=`date +%Y-%m-%d --date="$CURRENT 1 day"` done # remove lock file to allow others to write to the pcap store rm $LOCK fi # end of pcap slicing fi # end of valid pcap echo done # end of for-loop processing pcap files # remove temp files for TEMP_PCAP in ${TEMP_PCAPS[@]}; do echo "- removing temporary pcap $TEMP_PCAP" rm -f $TEMP_PCAP done # output final messages if [ "$INVALID_PCAPS" = "yes" ]; then echo echo "Please note! One or more pcaps was invalid! You can scroll up to see which ones were invalid." fi if [ "$VALID_PCAPS" = "yes" ]; then cat << EOF Import complete! You can use the following hyperlink to view data in the time range of your import. You can triple-click to quickly highlight the entire hyperlink and you can then copy it into your browser: https://localhost/app/kibana#/dashboard/94b52620-342a-11e7-9d52-4f090484f59e?_g=(refreshInterval:(display:Off,pause:!f,value:0),time:(from:'${START_OLDEST}T00:00:00.000Z',mode:absolute,to:'${END_NEWEST}T00:00:00.000Z')) or you can manually set your Time Range to be: From: $START_OLDEST To: $END_NEWEST Please note that it may take 30 seconds or more for events to appear in Kibana. EOF fi