Skip to content
This repository was archived by the owner on Jan 13, 2022. It is now read-only.
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 .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -689,3 +689,4 @@ settings.json
main.tf
builds/**
cinqctl
.scratch
102 changes: 100 additions & 2 deletions cloud-inquisitor/aws_cloudfront_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,58 @@ func (cf *AWSCloudFrontDistributionResource) createDistributionEntries() error {
return nil
}

func (cf *AWSCloudFrontDistributionResource) deleteDistributionEntries() error {
db, err := database.NewDBConnection()
defer db.Close()
if err != nil {
cf.logger.WithFields(cf.GetMetadata()).Error(err.Error())
return err
}

// get account
account := model.Account{AccountID: cf.AccountID}
err = db.FirstOrCreate(&account, account).Error
if err != nil {
cf.logger.WithFields(cf.GetMetadata()).Error(err.Error())
return err
}
cf.logger.WithFields(cf.GetMetadata()).Debugf("account: %#v", account)

distro := model.Distribution{DistributionID: cf.DistributionID, Domain: cf.DomainName, AccountID: account.ID}
err = db.Delete(&distro).Error
if err != nil {
cf.logger.WithFields(cf.GetMetadata()).Error(err.Error())
return err
}

// delete origins
for _, cfOrigin := range cf.Origins {
origin := model.Origin{
OriginID: cfOrigin.ID,
Domain: cfOrigin.Domain,
DistributionID: distro.ID,
}
err = db.Delete(&origin).Error
if err != nil {
cf.logger.WithFields(cf.GetMetadata()).Error(err.Error())
return err
}

// delete origin groups
for _, cfGroup := range cf.OriginGroups {
group := model.OriginGroup{
GroupID: cfGroup.ID,
DistributionID: distro.ID,
}
err = db.Delete(&group).Error
if err != nil {
cf.logger.WithFields(cf.GetMetadata()).Error(err.Error())
return err
}

return nil
}

func (cf *AWSCloudFrontDistributionResource) updateDistributionEntries() error {
db, err := database.NewDBConnection()
defer db.Close()
Expand Down Expand Up @@ -496,6 +548,8 @@ func (cf *AWSCloudFrontDistributionHijackableResource) PublishState() error {
switch cf.EventName {
case "CreateDistribution":
return cf.createDistributionEntries()
case "DeleteDistribution":
return cf.deleteDistributionEntries()
case "UpdateDistribution":
return cf.updateDistributionEntries()
default:
Expand All @@ -505,6 +559,50 @@ func (cf *AWSCloudFrontDistributionHijackableResource) PublishState() error {
return nil
}

func (cf *AWSCloudFrontDistributionHijackableResource) AnalyzeForHijack() (*model.HijackableResourceChain, error) {
return &model.HijackableResourceChain{}, nil
func (cf *AWSCloudFrontDistributionHijackableResource) AnalyzeForHijack() (*model.HijackableResourceRoot, error) {
switch cf.EventName {
case "CreateDistribution":
return cf.analyzeCreateDistributionEntries()
case "DeleteDistribution":
return cf.analyzeDeleteDistributionEntries()
default:
return &model.HijackableResourceRoot{}, nil
}
}

func (cf *AWSCloudFrontDistributionHijackableResource) analyzeDeleteDistributionEntries(*model.HijackableResourceRoot, error) {
return cf.analyzeDeleteDistributionEntries()
}

func (cf *AWSCloudFrontDistributionHijackableResource) analyzeDeleteDistributionEntries(*model.HijackableResourceRoot, error) {
resolver, err := graph.NewResolver()
if err != nil {
cf.GetLogger().Errorf("error creating a new resolver to evaluate cloudfront hijacks: %v", err.Error())
return &model.HijackableResourceRoot{}, err
}

domains := make([]string, len(cf.Origins))
for i, ori := range cf.Origins {
domain[i] = ori.Domain
}

ctx := context.Background()
root, err := resolver.Query().GetHijackMapWithResourceIDAndDomainsAndTypeAndDirectionThenFlattened(
ctx,
fmt.Sprintf(
"cloudfront-%s-%s-%s",
cf.AccountID,
cf.DistributionID,
cf.DomainName,
),
cf.DistributionID,
domains,
model.TypeDistribution,
model.DirectionDownstream,
)
if err != nil {
eb.GetLogger().Errorf("error querying graph for cloudfront hijack analysis: %v", err.Error())
}

return root, err
}
8 changes: 4 additions & 4 deletions cloud-inquisitor/graph/model/models_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion cloud-inquisitor/graph/schema.graphqls
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ type HijackableResource {

type HijackableResourceRoot {
id: ID!
rootResourceID: ID!
rootResource: HijackableResource!
direction: Direction!
maps: [HijackableResourceMap!]!
}
Expand Down
84 changes: 18 additions & 66 deletions cloud-inquisitor/notification/templates.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,87 +15,39 @@ func init() {
}

type HijackChainElement struct {
AccountId string
Resource string
ResourceType string
ResourceReferenced string
ResourceReferencedType string
AccountId string
Resource string
ResourceType string
}

type HijackNotificationContent struct {
PrimaryResource string
PrimaryResourceType string
PrimaryAccountId string
HijackChain []HijackChainElement
HijackChains [][]HijackChainElement
}

func GenerateContent(rawChain *model.HijackableResourceChain) HijackNotificationContent {
func GenerateContent(root *model.HijackableResourceRoot) HijackNotificationContent {
content := HijackNotificationContent{
PrimaryResource: rawChain.Resource.ID,
PrimaryAccountId: rawChain.Resource.Account,
PrimaryResourceType: rawChain.Resource.Type.String(),
PrimaryResource: root.RootResource.ID,
PrimaryAccountId: root.RootResource.Account,
PrimaryResourceType: root.RootResource.Type.String(),
}

chain := []HijackChainElement{}
for idx, resource := range rawChain.Upstream {
if idx == len(rawChain.Upstream)-1 {
chain = append(chain, HijackChainElement{
AccountId: resource.Account,
Resource: resource.ID,
ResourceType: resource.Type.String(),
ResourceReferenced: rawChain.Resource.ID,
ResourceReferencedType: rawChain.Resource.Type.String(),
})
} else {
chain = append(chain, HijackChainElement{
AccountId: resource.Account,
Resource: resource.ID,
ResourceType: resource.Type.String(),
ResourceReferenced: rawChain.Upstream[idx+1].ID,
ResourceReferencedType: rawChain.Upstream[idx+1].Type.String(),
})
}
}

if len(rawChain.Downstream) == 0 {
chain = append(chain, HijackChainElement{
AccountId: rawChain.Resource.Account,
Resource: rawChain.Resource.ID,
ResourceType: rawChain.Resource.Type.String(),
ResourceReferenced: "not applicable",
ResourceReferencedType: "not applicable",
})
} else {
chain = append(chain, HijackChainElement{
AccountId: rawChain.Resource.Account,
Resource: rawChain.Resource.ID,
ResourceType: rawChain.Resource.Type.String(),
ResourceReferenced: rawChain.Downstream[0].ID,
ResourceReferencedType: rawChain.Downstream[0].Type.String(),
})
}

for idx, resource := range rawChain.Downstream {
if idx == len(rawChain.Downstream)-1 {
chain = append(chain, HijackChainElement{
AccountId: resource.Account,
Resource: resource.ID,
ResourceType: resource.Type.String(),
ResourceReferenced: "not applicable",
ResourceReferencedType: "not applicable",
})
} else {
chain = append(chain, HijackChainElement{
AccountId: resource.Account,
Resource: resource.ID,
ResourceType: resource.Type.String(),
ResourceReferenced: rawChain.Downstream[idx+1].ID,
ResourceReferencedType: rawChain.Downstream[idx+1].Type.String(),
var hijackChains [][]HijackChainElement
for _, chain := range root.Maps {
hijackChain := []HijackChainElement{}
for _, element := range chain.Contains {
hijackChain = append(hijackChain, HijackChainElement{
AccountId: element.Resource.Account,
Resource: element.Resource.ID,
ResourceType: element.Resource.Type.String(),
})
}
hijackChains = append(hijackChains, hijackChain)
}

content.HijackChain = chain
content.HijackChains = hijackChains

return content
}
Expand Down
81 changes: 37 additions & 44 deletions cloud-inquisitor/notification/templates/hijack_template.html
Original file line number Diff line number Diff line change
Expand Up @@ -41,53 +41,46 @@

<h1>Potential Domain Hijack Found</h1>
<h2>Deleting resource {{ .PrimaryResourceType }}:{{ .PrimaryResource }} in AWS account {{ .PrimaryAccountId }} has resulted in a potential domain hijack; there is a DNS record pointing to a resource not owned or no longer owned by us.</h2>
<p>The following table includes all resources in the chain that would lead to a potential domain hijack.</p>
<p>The following tables includes all resources in the chain that would lead to a potential domain hijack.</p>

<div>
<table style="border:0px;">
<thead>
<tr class="title">
<th>
Account ID
</th>
<th>
Resource
</th>
<th>
Resource Type
</th>
<th>
Resource Referenced
</th>
<th>
Resource Referenced Type
</th>
</tr>
</thead>
<tbody>
{{- with .HijackChain }}
{{- range $i, $elem := . }}
{{ if isEven $i }}<tr class="even">{{- else }}<tr class="odd">{{- end }}
<td>
{{ $elem.AccountId }}
</td>
<td>
{{ $elem.Resource }}
</td>
<td>
{{ $elem.ResourceType }}
</td>
<td>
{{ $elem.ResourceReferenced }}
</td>
<td>
{{ $elem.ResourceReferencedType }}
</td>
{{- with .HijackChains }}
{{- range $j, $singlechain := . }}
<h3>Chain {{ $j }}</h3>
<table style="border:0px;">
<thead>
<tr class="title">
<th>
Account ID
</th>
<th>
Resource
</th>
<th>
Resource Type
</th>
</tr>
{{- end }}
{{- end }}
</tbody>
</table>
</thead>
<tbody>
{{- with $singlechain }}
{{- range $i, $elem := . }}
{{ if isEven $i }}<tr class="even">{{- else }}<tr class="odd">{{- end }}
<td>
{{ $elem.AccountId }}
</td>
<td>
{{ $elem.Resource }}
</td>
<td>
{{ $elem.ResourceType }}
</td>
</tr>
{{- end }}
{{- end }}
</tbody>
</table>
{{- end }}
{{- end }}
</div>
</body>
</html>
21 changes: 13 additions & 8 deletions cloud-inquisitor/notification/templates/hijack_template.txt
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
Potential Domain Hijack Found

Deleting resource {{ .PrimaryResourceType }}:{{ .PrimaryResource }} in AWS account {{ .PrimaryAccountId }} has resulted in a potential domain hijack;
there is a DNS record pointing to a resource not owned or no longer owned by us.
Deleting resource {{ .PrimaryResourceType }}:{{ .PrimaryResource }} in AWS account {{ .PrimaryAccountId }} has resulted in a potential security risk.
By claiming the corresponding resource an attacker will be able to make Players and Rioters believe they represent part of Riot and do harm to them.

The following table includes all resources in the chain that would lead to a potential domain hijack.
The following table includes all resources in the chain that would lead to a potential hijack.

{{ with .HijackChain }}
{{ range $i, $elem := . }}
{{ with .HijackChains }}
{{ range $j, $singlechain := . }}
==============
Hijack Chain {{ $j }}
==============
{{ with $singlechain }}
{{ range $i, $elem := . }}
Resource {{ $i }}:
Account ID: {{ $elem.AccountId }}
Resource: {{ $elem.Resource }}
Resource Type: {{ $elem.ResourceType }}
Resource Referenced: {{ $elem.ResourceReferenced }}
Resource Referenced Type: {{ $elem.ResourceReferencedType }}
{{ end }}
{{ end }}
{{ end }}
{{ end }}
{{ end }}
Loading