mirror of
https://github.com/anotherhadi/github-recon.git
synced 2026-10-05 10:58:25 +02:00
+8
-3
@@ -10,7 +10,8 @@ type EmailResult struct {
|
||||
Target string
|
||||
TargetType github_recon_settings.TargetType
|
||||
|
||||
Commit recon.CommitsResult
|
||||
Commits recon.CommitsResult
|
||||
Spoofing recon.SpoofingResult
|
||||
}
|
||||
|
||||
func email(settings github_recon_settings.Settings, datetime string) {
|
||||
@@ -21,6 +22,10 @@ func email(settings github_recon_settings.Settings, datetime string) {
|
||||
}
|
||||
|
||||
printTitle(settings.Silent, "👤 Commits author")
|
||||
result.Commit = recon.Email(settings)
|
||||
printStruct(settings, result.Commit, 0)
|
||||
result.Commits = recon.Commits(settings)
|
||||
printStruct(settings, result.Commits, 0)
|
||||
|
||||
printTitle(settings.Silent, "🎭 Spoofing test")
|
||||
result.Spoofing = recon.Spoofing(settings)
|
||||
printStruct(settings, result.Spoofing, 0)
|
||||
}
|
||||
|
||||
@@ -42,6 +42,8 @@ func printStruct(settings github_recon_settings.Settings, s any, indent int) {
|
||||
return
|
||||
}
|
||||
|
||||
printed := 0
|
||||
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
field := t.Field(i).Name
|
||||
value := v.Field(i)
|
||||
@@ -55,6 +57,7 @@ func printStruct(settings github_recon_settings.Settings, s any, indent int) {
|
||||
if (field == "FirstFoundIn" || field == "FoundIn") && !settings.ShowSource {
|
||||
continue
|
||||
}
|
||||
printed++
|
||||
|
||||
switch value.Kind() {
|
||||
case reflect.Struct, reflect.Slice, reflect.Array, reflect.Ptr:
|
||||
@@ -66,6 +69,9 @@ func printStruct(settings github_recon_settings.Settings, s any, indent int) {
|
||||
fmt.Printf("%s%s %s\n", prefix, greyStyle.Render(field+":"), greenStyle.Render(fmt.Sprintf("%v", value.Interface())))
|
||||
}
|
||||
}
|
||||
if printed == 0 {
|
||||
fmt.Println(prefix + greyStyle.Render("No data found"))
|
||||
}
|
||||
fmt.Println("")
|
||||
|
||||
case reflect.Slice, reflect.Array:
|
||||
|
||||
@@ -1 +1,120 @@
|
||||
package recon
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
|
||||
github_recon_settings "github.com/anotherhadi/github-recon/settings"
|
||||
"github.com/anotherhadi/github-recon/utils"
|
||||
"github.com/google/go-github/v72/github"
|
||||
)
|
||||
|
||||
type SpoofingResult struct {
|
||||
Username string
|
||||
Name string
|
||||
Email string
|
||||
Url string
|
||||
}
|
||||
|
||||
func RandomString(n int) string {
|
||||
letters := []rune("abcdefghijklmnopqrstuvwxyz")
|
||||
|
||||
b := make([]rune, n)
|
||||
for i := range b {
|
||||
b[i] = letters[rand.Intn(len(letters))]
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func Spoofing(s github_recon_settings.Settings) (response SpoofingResult) {
|
||||
// 1) Create repo (auto-init pour avoir une branche par défaut)
|
||||
name := "gh-recon-spoofing-" + RandomString(8)
|
||||
private := true
|
||||
autoInit := true
|
||||
repo, resp, err := s.Client.Repositories.Create(s.Ctx, "", &github.Repository{
|
||||
Name: &name,
|
||||
Private: &private,
|
||||
AutoInit: &autoInit,
|
||||
})
|
||||
if err != nil {
|
||||
s.Logger.Error("Error while creating repo", "err", err)
|
||||
return
|
||||
}
|
||||
utils.WaitForRateLimit(s, resp)
|
||||
|
||||
// branche par défaut (fallback "main")
|
||||
branch := repo.GetDefaultBranch()
|
||||
if branch == "" {
|
||||
branch = "main"
|
||||
}
|
||||
refName := "heads/" + branch
|
||||
|
||||
// 2) Commit vide avec auteur spoofé (tree identique au parent)
|
||||
author := &github.CommitAuthor{
|
||||
Name: github.String("Spoofed Name"),
|
||||
Email: github.String(s.Target),
|
||||
}
|
||||
|
||||
ref, resp, err := s.Client.Git.GetRef(s.Ctx, repo.Owner.GetLogin(), name, refName)
|
||||
if err != nil {
|
||||
s.Logger.Error("Error while getting ref", "err", err)
|
||||
s.Logger.Warn("The temp repo was left undeleted", "repo", repo.GetHTMLURL())
|
||||
return
|
||||
}
|
||||
utils.WaitForRateLimit(s, resp)
|
||||
|
||||
parentCommit, resp, err := s.Client.Git.GetCommit(s.Ctx, repo.Owner.GetLogin(), name, ref.GetObject().GetSHA())
|
||||
if err != nil {
|
||||
s.Logger.Error("Error while getting parent commit", "err", err)
|
||||
s.Logger.Warn("The temp repo was left undeleted", "repo", repo.GetHTMLURL())
|
||||
return
|
||||
}
|
||||
utils.WaitForRateLimit(s, resp)
|
||||
|
||||
commit := &github.Commit{
|
||||
Author: author,
|
||||
Message: github.String("Spoofed empty commit"),
|
||||
Tree: &github.Tree{SHA: parentCommit.Tree.SHA}, // même tree => commit vide
|
||||
Parents: []*github.Commit{parentCommit},
|
||||
}
|
||||
|
||||
newCommit, resp, err := s.Client.Git.CreateCommit(s.Ctx, repo.Owner.GetLogin(), name, commit, nil)
|
||||
if err != nil {
|
||||
s.Logger.Error("Error while creating spoofed empty commit", "err", err)
|
||||
s.Logger.Warn("The temp repo was left undeleted", "repo", repo.GetHTMLURL())
|
||||
return
|
||||
}
|
||||
utils.WaitForRateLimit(s, resp)
|
||||
|
||||
ref.Object.SHA = newCommit.SHA
|
||||
_, resp, err = s.Client.Git.UpdateRef(s.Ctx, repo.Owner.GetLogin(), name, ref, false)
|
||||
if err != nil {
|
||||
s.Logger.Error("Error while updating ref to spoofed commit", "err", err)
|
||||
s.Logger.Warn("The temp repo was left undeleted", "repo", repo.GetHTMLURL())
|
||||
return
|
||||
}
|
||||
utils.WaitForRateLimit(s, resp)
|
||||
|
||||
// 3) Get user
|
||||
commits, _, err := s.Client.Repositories.ListCommits(s.Ctx, repo.Owner.GetLogin(), name, nil)
|
||||
if err != nil {
|
||||
s.Logger.Error("Error while listing commits", "err", err)
|
||||
s.Logger.Warn("The temp repo was left undeleted", "repo", repo.GetHTMLURL())
|
||||
return
|
||||
}
|
||||
|
||||
if len(commits) > 0 {
|
||||
last := commits[0]
|
||||
response.Username = last.GetAuthor().GetLogin()
|
||||
response.Name = last.GetAuthor().GetName()
|
||||
response.Email = last.GetAuthor().GetEmail()
|
||||
response.Url = last.GetAuthor().GetHTMLURL()
|
||||
}
|
||||
|
||||
// 4) Cleanup
|
||||
_, err = s.Client.Repositories.Delete(s.Ctx, repo.Owner.GetLogin(), name)
|
||||
if err != nil {
|
||||
s.Logger.Error("Error while deleting repo", "err", err)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
+1
-1
@@ -110,7 +110,7 @@ func LevenshteinDistance(s1, s2 string) int {
|
||||
}
|
||||
|
||||
func SkipResult(name, email string) bool {
|
||||
if name == "github-actions[bot]" || name == "dependabot[bot]" || name == "github-actions" {
|
||||
if name == "github-actions[bot]" || name == "dependabot[bot]" || name == "github-actions" || name == "GitHub Actions" {
|
||||
return true
|
||||
}
|
||||
if email == "github-actions[bot]@users.noreply.github.com" || email == "[email protected]" ||
|
||||
|
||||
Reference in New Issue
Block a user