Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Notification feature #358

Open
wants to merge 8 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cmd/amass/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ var (
yellow = color.New(color.FgHiYellow).SprintFunc()
green = color.New(color.FgHiGreen).SprintFunc()
blue = color.New(color.FgHiBlue).SprintFunc()
red = color.New(color.FgHiRed).SprintFunc()
)

func commandUsage(msg string, cmdFlagSet *flag.FlagSet, errBuf *bytes.Buffer) {
Expand Down
33 changes: 31 additions & 2 deletions cmd/amass/track.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/OWASP/Amass/v3/graph"
"github.com/OWASP/Amass/v3/requests"
"github.com/OWASP/Amass/v3/stringset"
"github.com/OWASP/Amass/v3/net/smtp"
"github.com/fatih/color"
)

Expand All @@ -29,6 +30,7 @@ type trackArgs struct {
Since string
Options struct {
History bool
Notify bool
}
Filepaths struct {
ConfigFile string
Expand All @@ -37,7 +39,9 @@ type trackArgs struct {
}
}


func runTrackCommand(clArgs []string) {
var newReport = smtp.NewReport(true)
var args trackArgs
var help1, help2 bool
trackCommand := flag.NewFlagSet("track", flag.ContinueOnError)
Expand All @@ -53,10 +57,13 @@ func runTrackCommand(clArgs []string) {
trackCommand.IntVar(&args.Last, "last", 0, "The number of recent enumerations to include in the tracking")
trackCommand.StringVar(&args.Since, "since", "", "Exclude all enumerations before (format: "+timeFormat+")")
trackCommand.BoolVar(&args.Options.History, "history", false, "Show the difference between all enumeration pairs")
trackCommand.BoolVar(&args.Options.Notify, "notify", false, "Receive a report showing the difference between the two enumerations")
trackCommand.StringVar(&args.Filepaths.ConfigFile, "config", "", "Path to the INI configuration file. Additional details below")
trackCommand.StringVar(&args.Filepaths.Directory, "dir", "", "Path to the directory containing the graph database")
trackCommand.StringVar(&args.Filepaths.Domains, "df", "", "Path to a file providing root domain names")

newReport.Domains = args.Domains

if len(clArgs) < 1 {
commandUsage(trackUsageMsg, trackCommand, trackBuf)
return
Expand Down Expand Up @@ -166,10 +173,26 @@ func runTrackCommand(clArgs []string) {
completeHistoryOutput(args.Domains.Slice(), enums, earliest, latest, db)
return
}
cumulativeOutput(args.Domains.Slice(), enums, earliest, latest, db)
cumulativeOutput(args.Domains.Slice(), enums, earliest, latest, db, newReport)

if args.Options.Notify {
apikeys := cfg.GetAPIKey("notification_settings")
sendNotification(args.Domains.Slice(),apikeys.Username, apikeys.Key, newReport)
return
}
}

func cumulativeOutput(domains []string, enums []string, ea, la []time.Time, db *graph.Graph) {
func sendNotification(domain []string, username string, password string, newReport *smtp.Report) {
err := smtp.SendReport(domain[0], username, password, newReport)
if err != nil {
fmt.Fprintf(color.Output, "%s", red("Could not send an email notification"))
return
}

fmt.Fprintf(color.Output, "%s", green("Sent an email notification\n"))
}

func cumulativeOutput(domains []string, enums []string, ea, la []time.Time, db *graph.Graph, newReport *smtp.Report) {
idx := len(enums) - 1
filter := stringset.NewStringFilter()

Expand All @@ -178,6 +201,7 @@ func cumulativeOutput(domains []string, enums []string, ea, la []time.Time, db *
for _, out := range getUniqueDBOutput(enums[i], domains, db) {
if domainNameInScope(out.Name, domains) && !filter.Duplicate(out.Name) {
cum = append(cum, out)
newReport.Found = append(newReport.Found,out.Name)
}
}
}
Expand All @@ -188,13 +212,18 @@ func cumulativeOutput(domains []string, enums []string, ea, la []time.Time, db *
blue("and"), yellow(ea[idx].Format(timeFormat)), blue(" -> "), yellow(la[idx].Format(timeFormat)))
blueLine()

newReport.FromEnumeration = append(newReport.FromEnumeration,ea[0],la[0])
newReport.ToEnumeration = append(newReport.ToEnumeration,ea[idx],la[idx])


var updates bool
out := getUniqueDBOutput(enums[idx], domains, db)
for _, d := range diffEnumOutput(cum, out) {
updates = true
fmt.Fprintln(color.Output, d)
}
if !updates {
newReport.New = false
g.Println("No differences discovered")
}
}
Expand Down
66 changes: 66 additions & 0 deletions net/smtp/smtp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package smtp

import (
"log"
"net/smtp"
"errors"
"github.com/OWASP/Amass/v3/stringset"
"time"
"strings"
)

const (
SmtpServer = "smtp.gmail.com:587"
From = "amasstest1234@gmail.com"
Subject = "Amass report"
timeFormat = "01/02 15:04:05 2006 MST"
)

type Report struct {
Domains stringset.Set
Found []string
New bool
FromEnumeration []time.Time
ToEnumeration []time.Time
}

func NewReport(new bool) *Report {
r := &Report{New: new}
return r
}

func SendReport(domain string, to string, pass string, newReport *Report) (error) {
var wordDomain string
var body string

if !newReport.New {
body = "No new domain was found."
} else {
if len(newReport.Domains.Slice()) == 1 {
wordDomain = "domain "
} else {
wordDomain = "domains "
}
body = "Tracking the " + wordDomain + strings.Join(newReport.Domains.Slice(),",") + "\n\n" +
"Between " + newReport.FromEnumeration[0].Format(timeFormat) + " -> " + newReport.FromEnumeration[1].Format(timeFormat) + "\n" +
"and " + newReport.ToEnumeration[0].Format(timeFormat) + " -> " + newReport.ToEnumeration[1].Format(timeFormat) + "\n\n" +
"Found: " + strings.Join(newReport.Found,"\nFound:")
}


msg := "From: " + From + "\n" +
"To: " + to + "\n" +
"Subject: " + Subject + "\n\n" +
body

err := smtp.SendMail(SmtpServer,
smtp.PlainAuth("", From, pass, "smtp.gmail.com"),
From, []string{to}, []byte(msg))

if err != nil {
log.Printf("smtp error: %s", err)
return errors.New("Could not send the email")
}

return nil
}