Fixed CSV Parsing to allow emails in <email@example.com> syntax. Fixes #764

pull/843/merge
Jordan Wright 2017-09-24 17:50:58 -05:00
parent 10ff5c181b
commit 0d03d01fa5
2 changed files with 84 additions and 7 deletions

View File

@ -8,7 +8,6 @@ import (
"crypto/x509/pkix" "crypto/x509/pkix"
"encoding/csv" "encoding/csv"
"encoding/pem" "encoding/pem"
"errors"
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
@ -94,7 +93,11 @@ func ParseCSV(r *http.Request) ([]models.Target, error) {
ln = record[li] ln = record[li]
} }
if ei != -1 { if ei != -1 {
ea = record[ei] csvEmail, err := mail.ParseAddress(record[ei])
if err != nil {
continue
}
ea = csvEmail.Address
} }
if pi != -1 { if pi != -1 {
ps = record[pi] ps = record[pi]
@ -133,7 +136,7 @@ func CheckAndCreateSSL(cp string, kp string) error {
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
if err != nil { if err != nil {
return errors.New(fmt.Sprintf("TLS Certificate Generation: Failed to generate a random serial number: %s", err)) return fmt.Errorf("TLS Certificate Generation: Failed to generate a random serial number: %s", err)
} }
template := x509.Certificate{ template := x509.Certificate{
@ -151,24 +154,24 @@ func CheckAndCreateSSL(cp string, kp string) error {
derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, priv.Public(), priv) derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, priv.Public(), priv)
if err != nil { if err != nil {
return errors.New(fmt.Sprintf("TLS Certificate Generation: Failed to create certificate: %s", err)) return fmt.Errorf("TLS Certificate Generation: Failed to create certificate: %s", err)
} }
certOut, err := os.Create(cp) certOut, err := os.Create(cp)
if err != nil { if err != nil {
return errors.New(fmt.Sprintf("TLS Certificate Generation: Failed to open %s for writing: %s", cp, err)) return fmt.Errorf("TLS Certificate Generation: Failed to open %s for writing: %s", cp, err)
} }
pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
certOut.Close() certOut.Close()
keyOut, err := os.OpenFile(kp, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) keyOut, err := os.OpenFile(kp, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil { if err != nil {
return errors.New(fmt.Sprintf("TLS Certificate Generation: Failed to open %s for writing", kp)) return fmt.Errorf("TLS Certificate Generation: Failed to open %s for writing", kp)
} }
b, err := x509.MarshalECPrivateKey(priv) b, err := x509.MarshalECPrivateKey(priv)
if err != nil { if err != nil {
return errors.New(fmt.Sprintf("TLS Certificate Generation: Unable to marshal ECDSA private key: %v", err)) return fmt.Errorf("TLS Certificate Generation: Unable to marshal ECDSA private key: %v", err)
} }
pem.Encode(keyOut, &pem.Block{Type: "EC PRIVATE KEY", Bytes: b}) pem.Encode(keyOut, &pem.Block{Type: "EC PRIVATE KEY", Bytes: b})

74
util/util_test.go Normal file
View File

@ -0,0 +1,74 @@
package util
import (
"bytes"
"fmt"
"mime/multipart"
"net/http"
"reflect"
"testing"
"github.com/gophish/gophish/config"
"github.com/gophish/gophish/models"
"github.com/stretchr/testify/suite"
)
type UtilSuite struct {
suite.Suite
}
func (s *UtilSuite) SetupSuite() {
config.Conf.DBName = "sqlite3"
config.Conf.DBPath = ":memory:"
config.Conf.MigrationsPath = "../db/db_sqlite3/migrations/"
err := models.Setup()
if err != nil {
s.T().Fatalf("Failed creating database: %v", err)
}
s.Nil(err)
}
func buildCSVRequest(csvPayload string) (*http.Request, error) {
csvHeader := "First Name,Last Name,Email\n"
body := new(bytes.Buffer)
writer := multipart.NewWriter(body)
part, err := writer.CreateFormFile("files[]", "example.csv")
if err != nil {
return nil, err
}
part.Write([]byte(csvHeader))
part.Write([]byte(csvPayload))
err = writer.Close()
if err != nil {
return nil, err
}
r, err := http.NewRequest("POST", "http://127.0.0.1", body)
if err != nil {
return nil, err
}
r.Header.Set("Content-Type", writer.FormDataContentType())
return r, nil
}
func (s *UtilSuite) TestParseCSVEmail() {
expected := models.Target{
FirstName: "John",
LastName: "Doe",
Email: "johndoe@example.com",
}
csvPayload := fmt.Sprintf("%s,%s,<%s>", expected.FirstName, expected.LastName, expected.Email)
r, err := buildCSVRequest(csvPayload)
s.Nil(err)
got, err := ParseCSV(r)
s.Nil(err)
s.Equal(len(got), 1)
if !reflect.DeepEqual(expected, got[0]) {
s.T().Fatalf("Incorrect targets received. Expected: %#v\nGot: %#v", expected, got)
}
}
func TestUtilSuite(t *testing.T) {
suite.Run(t, new(UtilSuite))
}