Last November I hacked together a script that continually monitored your network and sent a slack alert when something change. It worked but I was never 100% happy with it so I spent some time this weekend and rewrote it so that is hopefully more user friendly and functional. Some changes in this version includes the ability to set timeouts between scans, better output on the machine running the script, better logging and the start of a framework to add new tools.
All you need to run this project for yourself is a Ubuntu install with NMap, Prips, SlackCLI and a copy of the script.
Once running here are what a slack alert looks like:
Here is what the script looks like running:
Here is a copy of the script:
#!/bin/bash -u # # Requires NMAP, NDIFF, PRIPS and Slackcli # https://candrholdings.github.io/slack-cli/ # NETOWORKS should be the list of networks you want to monitor. # INTERVAL how many seconds to wait between scans # SLACKTOKEN from here https://api.slack.com/web # NETWORKS="192.168.0.0/24" TARGETS=$(for NETWORK in ${NETWORKS}; do prips $NETWORK; done) INTERVAL="1800" SLACKTOKEN="Get This From https://api.slack.com/web" OPTIONS='-T4 --open --exclude-ports 25' cd ~/scan LAST_RUN_FILE='.lastrun' while true; do # If the last run file exists, we should only sleep for the time # specified minus the time that's already elapsed. if [ -e "${LAST_RUN_FILE}" ]; then LAST_RUN_TS=$(date -r ${LAST_RUN_FILE} +%s) NOW_TS=$(date +%s) LAST_RUN_SECS=$(expr ${NOW_TS} - ${LAST_RUN_TS}) SLEEP=$(expr ${INTERVAL} - ${LAST_RUN_SECS}) if [ ${SLEEP} -gt 0 ]; then UNTIL_SECS=$(expr ${NOW_TS} + ${SLEEP}) echo $(date) "- sleeping until" $(date --date="@${UNTIL_SECS}") "(${SLEEP}) seconds" sleep ${SLEEP} fi fi START_TIME=$(date +%s) echo '' echo '==================' echo '' DATE=`date +%Y-%m-%d_%H-%M-%S` for TARGET in ${TARGETS}; do CUR_LOG=scan-${TARGET/\//-}-${DATE} PREV_LOG=scan-${TARGET/\//-}-prev DIFF_LOG=scan-${TARGET/\//-}-diff echo '' echo $(date) "- starting ${TARGET}" # Scan the target nmap ${OPTIONS} ${TARGET} -oX ${CUR_LOG} >/dev/null # If there's a previous log, diff it if [ -e ${PREV_LOG} ]; then # Exclude the Nmap version and current date - the date always changes ndiff ${PREV_LOG} ${CUR_LOG} | egrep -v '^(\+|-)N' > ${DIFF_LOG} if [ -s ${DIFF_LOG} ]; then printf "Changes Detected, Sending to Slack." nmap -sV ${TARGET} | grep open | grep -v "#" > openports.txt slackcli -t $SLACKTOKEN -h nmap -m "Changes were detected on ${TARGET}. The following ports are now open: " sleep 1 cat openports.txt | slackcli -t $SLACKTOKEN -h nmap -c rm openports.txt # Set the current nmap log file to reflect the last date changed ln -sf ${CUR_LOG} ${PREV_LOG} else # No changes so remove our current log printf "No Changes Detected." rm ${CUR_LOG} fi rm ${DIFF_LOG} else # Create the previous scan log ln -sf ${CUR_LOG} ${PREV_LOG} fi done touch ${LAST_RUN_FILE} END_TIME=$(date +%s) echo echo $(date) "- finished all targets in" $(expr ${END_TIME} - ${START_TIME}) "second(s)" done
Some Quick Notes:
- You will want to run this in screen so that it runs continually.
- I excluded port 25 because it was reporting as “filtered” every other scan causing false alerts.
- Find NMAP options that you like. Here is a good guide.
- NDIFF really needs to be updated. Its output is ridiculously bad.
- Let me know on twitter if you have any questions.