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

Maltego viz improvements #901

Open
wants to merge 4 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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Binaries for programs and plugins
amass
*.exe
*.dll
*.so
Expand All @@ -14,4 +15,4 @@
.glide/

# Jetbrains IDE configuration files
.idea
.idea
4 changes: 4 additions & 0 deletions cmd/amass/viz.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,10 @@ func runVizCommand(clArgs []string) {
if args.Options.Maltego {
path := filepath.Join(dir, prefix+"_maltego.csv")
err = writeGraphOutputFile("maltego", path, nodes, edges)
if nil == err {
mtzConfigPath := filepath.Join(dir, prefix+"_maltego_mapping_config_default.mtz")
err = viz.CreateMaltegoConfig(mtzConfigPath)
}
}
if err != nil {
r.Fprintf(color.Error, "Failed to write the output file: %v\n", err)
Expand Down
13 changes: 9 additions & 4 deletions doc/user_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -354,10 +354,15 @@ Here is an example of graph for an enumeration run on example.com:
amass viz -maltego
```

2. Import the CSV file with the correct Connectivity Table settings:
2. Import `amass_maltego_mapping_config_default.mtz` Maltego configuration file into Maltego.
> This step is required only for the first time.

![Connectivity table](../images/maltego_graph_import_wizard.png "Connectivity Table Settings")
![Maltego Config Import Wizard](../images/maltego_config_import_wizard.png "Connectivity Table Settings")

3. All the Amass findings will be brought into your Maltego Graph:
3. Import the CSV file with the mapping configuration imported in the previous step:

![Maltego results](../images/maltego_results.png "Maltego Results")
![Maltego Graph Import Wizard](../images/maltego_graph_import_wizard.png "Connectivity Table Settings")

4. All the Amass findings will be brought into your Maltego Graph:

![Maltego results](../images/maltego_results.png "Maltego Results")
Binary file added images/maltego_config_import_wizard.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified images/maltego_graph_import_wizard.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified images/maltego_results.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion resources/io.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
"strconv"
)

//go:embed scripts ip2asn-combined.tsv.gz alterations.txt namelist.txt user_agents.txt
//go:embed scripts ip2asn-combined.tsv.gz alterations.txt namelist.txt user_agents.txt maltego_mapping_config.tmapping
var resourceFS embed.FS

// IP2ASN is a range record provided by the iptoasn.com service.
Expand Down
81 changes: 81 additions & 0 deletions resources/maltego_mapping_config.tmapping
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<TabularGraph typeRowIndex="0" hasTypeRow="true" headerRowIndex="0" hasHeaderRow="false" name="Amass Graph Data Mapping" numEntities="10" numLinks="23" savedDate="2022-09-28 19:45:33.818 IST">
<description>Default Maltego import mapping configuration for Amass graph data</description>
<Entities>
<TabularGraphEntity type="maltego.Domain" id="0">
<MappedProperties>
<MappedProperty name="fqdn" type="string" nullable="true" hidden="false" readonly="false" column="0" displayName="Domain Name"/>
</MappedProperties>
</TabularGraphEntity>
<TabularGraphEntity type="maltego.DNSName" id="1">
<MappedProperties>
<MappedProperty name="fqdn" type="string" nullable="true" hidden="false" readonly="false" column="1" displayName="DNS Name"/>
</MappedProperties>
</TabularGraphEntity>
<TabularGraphEntity type="maltego.NSRecord" id="2">
<MappedProperties>
<MappedProperty name="fqdn" type="string" nullable="true" hidden="false" readonly="false" column="2" displayName="NS Record"/>
</MappedProperties>
</TabularGraphEntity>
<TabularGraphEntity type="maltego.MXRecord" id="3">
<MappedProperties>
<MappedProperty name="fqdn" type="string" nullable="true" hidden="false" readonly="false" column="3" displayName="MX Record"/>
</MappedProperties>
</TabularGraphEntity>
<TabularGraphEntity type="maltego.IPv4Address" id="4">
<MappedProperties>
<MappedProperty name="ipv4-address" type="string" nullable="true" hidden="false" readonly="false" column="4" displayName="IP Address"/>
</MappedProperties>
</TabularGraphEntity>
<TabularGraphEntity type="maltego.IPv6Address" id="5">
<MappedProperties>
<MappedProperty name="ipv6-address" type="string" nullable="true" hidden="false" readonly="false" column="5" displayName="IP Address"/>
</MappedProperties>
</TabularGraphEntity>
<TabularGraphEntity type="maltego.Netblock" id="6">
<MappedProperties>
<MappedProperty name="ipv4-range" type="string" nullable="true" hidden="false" readonly="false" column="6" displayName="IP Range"/>
</MappedProperties>
</TabularGraphEntity>
<TabularGraphEntity type="maltego.AS" id="7">
<MappedProperties>
<MappedProperty name="as.number" type="string" nullable="true" hidden="false" readonly="false" column="7" displayName="AS Number"/>
</MappedProperties>
</TabularGraphEntity>
<TabularGraphEntity type="maltego.Company" id="8">
<MappedProperties>
<MappedProperty name="title" type="string" nullable="true" hidden="false" readonly="false" column="8" displayName="Name"/>
</MappedProperties>
</TabularGraphEntity>
<TabularGraphEntity type="maltego.DNSName" id="9">
<MappedProperties>
<MappedProperty name="fqdn" type="string" nullable="true" hidden="false" readonly="false" column="9" displayName="DNS Name"/>
</MappedProperties>
</TabularGraphEntity>
</Entities>
<Links>
<TabularGraphLink sourceEntity="0" targetEntity="4" index="1"/>
<TabularGraphLink sourceEntity="0" targetEntity="5" index="2"/>
<TabularGraphLink sourceEntity="0" targetEntity="1" index="3"/>
<TabularGraphLink sourceEntity="0" targetEntity="9" index="4"/>
<TabularGraphLink sourceEntity="0" targetEntity="2" index="5"/>
<TabularGraphLink sourceEntity="0" targetEntity="3" index="6"/>
<TabularGraphLink sourceEntity="6" targetEntity="5" index="7"/>
<TabularGraphLink sourceEntity="6" targetEntity="4" index="8"/>
<TabularGraphLink sourceEntity="7" targetEntity="6" index="9"/>
<TabularGraphLink sourceEntity="8" targetEntity="7" index="10"/>
<TabularGraphLink sourceEntity="9" targetEntity="1" index="11"/>
<TabularGraphLink sourceEntity="1" targetEntity="9" index="12"/>
<TabularGraphLink sourceEntity="1" targetEntity="4" index="13"/>
<TabularGraphLink sourceEntity="1" targetEntity="5" index="14"/>
<TabularGraphLink sourceEntity="2" targetEntity="4" index="15"/>
<TabularGraphLink sourceEntity="2" targetEntity="5" index="16"/>
<TabularGraphLink sourceEntity="3" targetEntity="4" index="17"/>
<TabularGraphLink sourceEntity="3" targetEntity="5" index="18"/>
<TabularGraphLink sourceEntity="9" targetEntity="4" index="19"/>
<TabularGraphLink sourceEntity="9" targetEntity="5" index="20"/>
<TabularGraphLink sourceEntity="8" targetEntity="0" index="21"/>
<TabularGraphLink sourceEntity="8" targetEntity="9" index="22"/>
<TabularGraphLink sourceEntity="8" targetEntity="1" index="23"/>
</Links>
<StrictProperties/>
</TabularGraph>
64 changes: 56 additions & 8 deletions viz/maltego.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,19 @@
package viz

import (
"archive/zip"
"fmt"
"io"
"net"
"os"
"strings"

amassnet "github.com/OWASP/Amass/v3/net"
"github.com/OWASP/Amass/v3/resources"
)

// WriteMaltegoData converts the Amass graph nodes and edges into a
// structured table format (CSV) that can be input by Maltego.
// structured table format (CSV) that can be imported by Maltego.
func WriteMaltegoData(output io.Writer, nodes []Node, edges []Edge) {
filter := make(map[int]struct{})
types := []string{
Expand All @@ -22,14 +25,15 @@ func WriteMaltegoData(output io.Writer, nodes []Node, edges []Edge) {
"maltego.NSRecord",
"maltego.MXRecord",
"maltego.IPv4Address",
"maltego.IPv6Address",
"maltego.Netblock",
"maltego.AS",
"maltego.Company",
"maltego.DNSName",
}
// Print the column types in the first row
fmt.Fprintln(output, strings.Join(types, ","))
// Start the graph tranersal from the autonomous systems
// Start the graph traversal from the autonomous systems
for idx, node := range nodes {
if node.Type == "as" {
traverseTree(output, idx, nodes, edges, filter)
Expand All @@ -54,27 +58,29 @@ func typeToIndex(t string) int {
case "subdomain":
idx = 1
case "ptr":
idx = 8
idx = 9
case "cname":
idx = 8
case "address":
case "v4address":
idx = 4
case "v6address":
idx = 5
case "ns":
idx = 2
case "mx":
idx = 3
case "netblock":
idx = 5
case "as":
idx = 6
case "company":
case "as":
idx = 7
case "company":
idx = 8
}
return idx
}

func writeMaltegoTableLine(out io.Writer, data1, type1, data2, type2 string) {
row := []string{"", "", "", "", "", "", "", "", ""}
row := []string{"", "", "", "", "", "", "", "", "", ""}

idx1 := typeToIndex(type1)
row[idx1] = data1
Expand All @@ -93,6 +99,10 @@ func traverseTree(out io.Writer, id int, nodes []Node, edges []Edge, filter map[
d1 := nodes[id].Label
t1 := nodes[id].Type

if "address" == t1 {
t1 = getIpVersion(d1) // get exact address version
}

var from bool
if t1 == "netblock" || t1 == "as" {
from = true
Expand Down Expand Up @@ -120,6 +130,9 @@ func traverseTree(out io.Writer, id int, nodes []Node, edges []Edge, filter map[
}
d2 := nodes[n].Label
t2 := nodes[n].Type
if "address" == t2 {
t2 = getIpVersion(d2) // get exact address version
}
// Need to properly handle CNAME records
if strings.Contains(edge.Title, "cname") {
if subFrom {
Expand Down Expand Up @@ -156,3 +169,38 @@ func cidrToMaltegoNetblock(cidr string) string {
ip1, ip2 := amassnet.FirstLast(ipnet)
return ip1.String() + "-" + ip2.String()
}

// This function returns the IP address version number that should be used to set exact Maltego
// IP Address Entity type
func getIpVersion(address string) string {
if strings.Contains(address, ":") { // IPv6 address
return "v6address"
}
return "v4address" // all others are considered IPv4 address
}

// CreateMaltegoConfig function creates a default mapping configuration for Maltego that can be used
// to import the Maltego csv
func CreateMaltegoConfig(mtzConfigPath string) error {
if _, err := os.Stat(mtzConfigPath); err == nil { // mtz config already exists
return nil
}
file, err := resources.GetResourceFile("maltego_mapping_config.tmapping")
if nil != err {
return err
}
// *.mtz file is just a zip archive
mtz, err := os.Create(mtzConfigPath)
if nil != err {
return err
}
defer mtz.Close()
archiveWriter := zip.NewWriter(mtz)
defer archiveWriter.Close()
mtzWriter, err := archiveWriter.Create("TabularMappings/Amass Graph Data Mapping.tmapping")
if nil != err {
return err
}
io.Copy(mtzWriter, file)
return nil
}
3 changes: 2 additions & 1 deletion viz/maltego_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ func TestWriteMaltegoData(t *testing.T) {
assert.Contains(t, expectedMaltegoOutput, output, "Maltego output should contain")
}

const expectedMaltegoOutput = `maltego.Domain,maltego.DNSName,maltego.NSRecord,maltego.MXRecord,maltego.IPv4Address,maltego.Netblock,maltego.AS,maltego.Company,maltego.DNSName
const expectedMaltegoOutput = `maltego.Domain,maltego.DNSName,maltego.NSRecord,maltego.MXRecord,maltego.IPv4Address,maltego.IPv6Address,maltego.Netblock,maltego.AS,maltego.Company,maltego.DNSName
`

func TestCidrToMaltegoNetblock(t *testing.T) {
cases := []struct {
label string
Expand Down