From 2955b9a3d9ac518eaba6aa92a1612cca7ec5c584 Mon Sep 17 00:00:00 2001 From: Julien Date: Sat, 20 Aug 2022 23:54:26 +0200 Subject: [PATCH 1/2] New version --- Config.txt | 2 +- TeamsIntelBot.py | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Config.txt b/Config.txt index fd677de56b..5880bdd25d 100644 --- a/Config.txt +++ b/Config.txt @@ -93,7 +93,7 @@ redcanary = 2022-08-18T21:53:55 daixin = 2022-08-09 10:44:27.550608 babuk = 2021-09-09 23:46:57.346780 leak-lookup = 2022-08-19T02:00:02 -cyber-news = 2022-08-20T20:33:52 +cyber-news = 2022-08-20T21:33:52 eu-enisa publications = 2022-07-27T10:00:00 att = 2022-08-17T10:00:00 microsoft sentinel = 2022-08-18T15:31:51 diff --git a/TeamsIntelBot.py b/TeamsIntelBot.py index 0cba1b94b6..923746042f 100644 --- a/TeamsIntelBot.py +++ b/TeamsIntelBot.py @@ -98,8 +98,9 @@ def GetRansomwareUpdates(): Title = "🏴‍☠️ 🔒 " Title += Entries["post_title"].replace("*.", "") - Send_Teams(Url,OutputMessage,Title) - #DEBUG# print(Title) + # Send_Teams(Url,OutputMessage,Title) + #DEBUG# + print(Title) time.sleep(3) FileConfig.set('main', Entries["group_name"], Entries["discovered"]) @@ -113,8 +114,8 @@ def GetRansomwareUpdates(): # --------------------------------------------------------------------------- def GetRssFromUrl(RssItem): NewsFeed = feedparser.parse(RssItem[0]) - DateActivity = "" - IsInitialRun = False + #DateActivity = "" + #IsInitialRun = False for RssObject in NewsFeed.entries: @@ -129,12 +130,10 @@ def GetRssFromUrl(RssItem): except: FileConfig.set('main', RssItem[1], " = ?") TmpObject = FileConfig.get('main', RssItem[1]) - + if "?" in TmpObject: - IsInitialRun = True FileConfig.set('main', RssItem[1], DateActivity) - - if IsInitialRun is False: + else: if(TmpObject >= DateActivity): continue else: @@ -177,8 +176,9 @@ def GetRssFromUrl(RssItem): Title = '📢 ' Title += RssItem[1] - Send_Teams(Url,OutputMessage,Title) - #DEBUG# print(Title) + #Send_Teams(Url,OutputMessage,Title) + #DEBUG# + print(Title) time.sleep(3) with open(ConfigurationFilePath, 'w') as FileHandle: From 7375fc4a6f19c943b3229696ebf424699f86f210 Mon Sep 17 00:00:00 2001 From: Julien Date: Sun, 21 Aug 2022 11:02:38 +0200 Subject: [PATCH 2/2] Initate v2.0.0 --- CHANGELOG.md | 30 ++++++++++++++++++ Config.txt | 5 +-- Feed.csv | 1 + README.md | 23 +++++++++----- TeamsIntelBot.py | 81 +++++++++++++++++++++++++++++++----------------- 5 files changed, 102 insertions(+), 38 deletions(-) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000000..ff197b3fa2 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,30 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +## Changed + +- None + +## Add + +- Create this CHANGELOG.md file + +## [2.0.0] - 2022-08-22 + +## Changed + +- None + +## Add + +- Options for CLI + - Debug mode for screen output only + - Quiet mode +- Check python version in the script +- And much more :) \ No newline at end of file diff --git a/Config.txt b/Config.txt index 5880bdd25d..86bb8f466d 100644 --- a/Config.txt +++ b/Config.txt @@ -74,7 +74,7 @@ blackshadow = 2021-12-18 16:06:44.948812 mosesstaff = 2021-12-18 16:06:45.338411 atomsilo = 2021-12-21 20:28:18.355635 nightsky = 2022-01-04 19:14:52.100985 -vicesociety = 2022-08-19 05:25:46.332830 +vicesociety = 2022-08-21 08:42:43.724864 pandora = 2022-03-30 19:26:24.820390 stormous = 2022-05-09 20:30:39.007872 leaktheanalyst = 2022-03-29 16:52:32.802514 @@ -98,6 +98,7 @@ eu-enisa publications = 2022-07-27T10:00:00 att = 2022-08-17T10:00:00 microsoft sentinel = 2022-08-18T15:31:51 ncc = 2022-08-19T14:30:21 -sans = 2022-08-20T08:50:36 +sans = 2022-08-20T21:51:02 icefire = 2022-08-20 09:50:02.102837 +version = 2022-08-20T21:49:31 diff --git a/Feed.csv b/Feed.csv index c5c448bcdf..5d7608ae6e 100644 --- a/Feed.csv +++ b/Feed.csv @@ -35,3 +35,4 @@ https://www.enisa.europa.eu/publications/RSS,EU-ENISA Publications https://techcommunity.microsoft.com/plugins/custom/microsoft/o365/custom-blog-rss?tid=8149516204242144484&board=MicrosoftSentinelBlog&size=25,Microsoft Sentinel https://research.nccgroup.com/category/threat-intelligence/feed/,NCC https://isc.sans.edu/rssfeed.xml,SANS +https://github.com/JMousqueton/CTI-MSTEAMS-Bot/releases.atom,VERSION diff --git a/README.md b/README.md index 7878c3c2f6..f9cd19eead 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ TITB is a fork from [Threat Intelligence Discord Bot from vx-underground](https: > The vx-underground Threat Intelligence Discord Bot gets updates from various clearnet domains, ransomware threat actor domains This bot will check for updates in intervals of 1800 seconds. -[![MIT License](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) ![Version](https://img.shields.io/badge/version-1.7.1-blue.svg) [![Twitter: JMousqueton](https://img.shields.io/twitter/follow/JMousqueton.svg?style=social)](https://twitter.com/JMousqueton) [![Last Run](https://github.com/JMousqueton/CTI-MSTeams-Bot/actions/workflows/fetchCTI.yml/badge.svg)](.github/workflows/fetchCTI.yml) [![CodeQL](https://github.com/JMousqueton/CTI-MSTeams-Bot/actions/workflows/codeql-analysis.yml/badge.svg)](.github/workflows/codeql-analysis.yml) +[![MIT License](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) ![Version](https://img.shields.io/badge/version-2.0.0-blue.svg) [![Twitter: JMousqueton](https://img.shields.io/twitter/follow/JMousqueton.svg?style=social)](https://twitter.com/JMousqueton) [![Last Run](https://github.com/JMousqueton/CTI-MSTeams-Bot/actions/workflows/fetchCTI.yml/badge.svg)](.github/workflows/fetchCTI.yml) [![CodeQL](https://github.com/JMousqueton/CTI-MSTeams-Bot/actions/workflows/codeql-analysis.yml/badge.svg)](.github/workflows/codeql-analysis.yml) ## Description @@ -29,9 +29,13 @@ The change I've made : * Check that python 3.10+ is present (needed for some functions) * Add a [requirements.txt](requirements.txt) * Add a [feedCheck.py](checkFeed.py) script to check the health of the feed from [Feed.csv](Feed.csv) file +* Add Options for command line [usage](#usage) +* Check if a new version is available I've decided to remove the TelegramBot because it was not relevant for my needs. +![](Screenshot.png) + ## Installation Clone the repository or download the [latest release](https://github.com/JMousqueton/CTI-MSTeams-Bot/releases/latest) @@ -67,7 +71,16 @@ python3 TeamIntelBot.py ## Usage -![](Screenshot.png) +``` +python3 TeamsIntelBot.py -h +Usage: TeamsIntelBot.py [options] + +Options: + --version show program's version number and exit + -h, --help show this help message and exit + -q, --quiet Quiet mode + -D, --debug Debug mode : only output on screen nothing send to MS Teams +``` I've also add a script called ```checkFeed.py``` to check if feeds are valids and what is the last published date. This script read the ```Feed.csv```file. @@ -118,12 +131,6 @@ I've added the following sources : ## ToDo -* ~~Modify code to accept RSS Feed without "pubdate" but dc:date~~ -* ~~Extract the RSS Feeds from the main program to an external configuration file~~ -* ~~Add more sources~~ -* ~~Add support of Python 3.10 for support of match functions~~ -* ~~Change emoji depending on source~~ (version 1.6) -* ~~No need to make an entry in Config.txt~~ (version 1.7) ## Credit diff --git a/TeamsIntelBot.py b/TeamsIntelBot.py index 923746042f..f073111245 100644 --- a/TeamsIntelBot.py +++ b/TeamsIntelBot.py @@ -3,11 +3,10 @@ #---------------------------------------------------------------------------- # Created By : Julien Mousqueton @JMousqueton # Original By : VX-Underground -# Created Date: 18/08/2022 -# version : 1.7.1 +# Created Date: 22/08/2022 +# Version : 2.0.0 # --------------------------------------------------------------------------- - # --------------------------------------------------------------------------- # Imports # --------------------------------------------------------------------------- @@ -19,18 +18,8 @@ from configparser import ConfigParser import requests import os # Webhook OS Variable and Github action - -# --------------------------------------------------------------------------- -# Read the Config.txt file -# --------------------------------------------------------------------------- -ConfigurationFilePath = "./Config.txt" ##path to configuration file -FileConfig = ConfigParser() -FileConfig.read(ConfigurationFilePath) - -# --------------------------------------------------------------------------- -# Get Microsoft Teams Webhook from Github Action CI:Env. -# --------------------------------------------------------------------------- -Url=os.getenv('MSTEAMS_WEBHOOK') +from os.path import exists +from optparse import OptionParser # --------------------------------------------------------------------------- # Function to send MS-Teams card @@ -58,7 +47,6 @@ def Send_Teams(webhook_url:str, content:str, title:str, color:str="000000") -> i ) return response.status_code # Should be 200 - # --------------------------------------------------------------------------- # Fetch Ransomware attacks from https://ransomwatch.mousqueton.io # --------------------------------------------------------------------------- @@ -98,9 +86,10 @@ def GetRansomwareUpdates(): Title = "🏴‍☠️ 🔒 " Title += Entries["post_title"].replace("*.", "") - # Send_Teams(Url,OutputMessage,Title) - #DEBUG# - print(Title) + if options.Debug: + print(Title + " / " + Entries["discovered"]) + else: + Send_Teams(Url,OutputMessage,Title) time.sleep(3) FileConfig.set('main', Entries["group_name"], Entries["discovered"]) @@ -114,8 +103,8 @@ def GetRansomwareUpdates(): # --------------------------------------------------------------------------- def GetRssFromUrl(RssItem): NewsFeed = feedparser.parse(RssItem[0]) - #DateActivity = "" - #IsInitialRun = False + DateActivity = "" + IsInitialRun = False for RssObject in NewsFeed.entries: @@ -130,10 +119,12 @@ def GetRssFromUrl(RssItem): except: FileConfig.set('main', RssItem[1], " = ?") TmpObject = FileConfig.get('main', RssItem[1]) - + if "?" in TmpObject: + IsInitialRun = True FileConfig.set('main', RssItem[1], DateActivity) - else: + + if IsInitialRun is False: if(TmpObject >= DateActivity): continue else: @@ -176,9 +167,14 @@ def GetRssFromUrl(RssItem): Title = '📢 ' Title += RssItem[1] - #Send_Teams(Url,OutputMessage,Title) - #DEBUG# - print(Title) + + if RssItem[1] == "VERSION": + Title ='🔥 A NEW VERSION IS AVAILABLE : ' + RssObject.title + + if options.Debug: + print(Title) + else: + Send_Teams(Url,OutputMessage,Title) time.sleep(3) with open(ConfigurationFilePath, 'w') as FileHandle: @@ -191,7 +187,8 @@ def GetRssFromUrl(RssItem): def CreateLogString(RssItem): LogString = "[*]" + time.ctime() LogString += " " + "checked " + RssItem - print(LogString) + if not options.Quiet: + print(LogString) time.sleep(2) @@ -199,10 +196,38 @@ def CreateLogString(RssItem): # Main # --------------------------------------------------------------------------- if __name__ == '__main__': - + parser = OptionParser(usage="usage: %prog [options]", + version="%prog 2.0.0") + parser.add_option("-q", "--quiet", + action="store_true", + dest="Quiet", + default=False, + help="Quiet mode") + parser.add_option("-D", "--debug", + action="store_true", + dest="Debug", + default="False", + help="Debug mode : only output on screen nothing send to MS Teams",) + (options, args) = parser.parse_args() + + # Get Microsoft Teams Webhook from Github Action CI:Env. + Url=os.getenv('MSTEAMS_WEBHOOK') + + # Make some simple checks before starting if sys.version_info < (3, 10): sys.exit("Please use Python 3.10+") + if (str(Url) == "None" and options.Debug == 'False'): + sys.exit("Please use a MSTEAMS_WEBHOOK variable") + if not exists("./Config.txt"): + sys.exit("Please add a Config.txt file") + if not exists("./Feed.csv"): + sys.exit("Please add the Feed.cvs file") + # Read the Config.txt file + ConfigurationFilePath = "./Config.txt" ##path to configuration file + FileConfig = ConfigParser() + FileConfig.read(ConfigurationFilePath) + with open('Feed.csv', newline='') as f: reader = csv.reader(f) RssFeedList = list(reader)