狩猎破碎的社交媒体链接与Go
#安全 #tooling #go #socialmedia

让我们编写一个简单的Golang程序,该程序爬网,发现可以被劫持的社交媒体链接破裂。破裂的社会联系可能会使攻击者能够进行网络钓鱼攻击,这可能导致数据泄露和其他安全事件。
Finder当前支持Twitter,Facebook,Instagram和Tiktok等等。

步骤1

首先,我们创建一个文件夹名称:

finder

然后我们将运行:

go mod init github.com/ayoubzulfiqar/finder

对我而

依赖性

github.com/fatih/color v1.15.0
github.com/gammazero/workerpool v1.1.3
github.com/gocolly/colly v1.2.0

步骤-2用户代理

此用户代理字符串可用于模仿这些浏览器在爬行网站时提出的请求。

const (
    chromeMajorVersion  = "109"
    firefoxMajorVersion = "109"
)

// var userAgent string = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:" + firefoxMajorVersion + ") Gecko/20100101 Firefox/" + firefoxMajorVersion

// Or for Chrome:
var UserAgent string = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/" + chromeMajorVersion + ".0 Safari/537.36"

爬行者

此功能使用Colly软件包来爬网网站并找到与特定域匹配的社交媒体链接,同时还基于拒绝列表和其他条件实施了一些限制和过滤。
它着重于在指定域和路径中找到社交媒体链接,同时应用各种过滤器和约束。


import (
    "net/url"
    "strings"
    "time"

    "github.com/gocolly/colly"
)

func Visitor(visitURL string, maxDepth int) []string {
    socialDomains := []string{"twitter.com", "instagram.com", "facebook.com", "twitch.tv", "tiktok.com"}
    var socialLinks []string
    var visitedLinks []string
    denyList := []string{".js", ".jpg", ".jpeg", ".png", ".gif", ".bmp", ".svg", ".mp4", ".webm", ".mp3", ".csv", ".ogg", ".wav", ".flac", ".aac", ".wma", ".wmv", ".avi", ".mpg", ".mpeg", ".mov", ".mkv", ".zip", ".rar", ".7z", ".tar", ".iso", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".rtf", ".odt", ".ods", ".odp", ".odg", ".odf", ".odb", ".odc", ".odm", ".avi", ".mpg", ".mpeg", ".mov", ".mkv", ".zip", ".rar", ".7z", ".tar", ".iso", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".rtf", ".odt", ".ods", ".odp", ".odg", ".odf", ".odb", ".odc", ".odm", ".mp4", ".webm", ".mp3", ".ogg", ".wav", ".flac", ".aac", ".wma", ".wmv", ".avi", ".mpg", ".mpeg", ".mov", ".mkv", ".zip", ".rar", ".7z", ".tar", ".iso", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".rtf", ".odt", ".ods", ".odp", ".odg", ".odf", ".odb", ".odc", ".odm", ".mp4", ".webm", ".mp3", ".ogg", ".wav", ".flac", ".aac", ".wma", ".wmv", ".avi", ".mpg", ".mpeg", ".mov", ".mkv", ".zip", ".rar", ".7z", ".tar", ".iso", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".rtf", ".odt"}

    c := colly.NewCollector()
    c.UserAgent = UserAgent
    c.SetRequestTimeout(5 * time.Second)
    c.MaxDepth = maxDepth
    c.AllowURLRevisit = false
    u, err := url.Parse(visitURL)
    if err != nil {
        panic(err)
    }
    domain := u.Host
    path := u.Path
    c.OnHTML("a[href]", func(e *colly.HTMLElement) {
        link := e.Request.AbsoluteURL(e.Attr("href"))
        u2, err := url.Parse(link)
        if err != nil {
            panic(err)
        }
        linkDomain := u2.Host
        for _, domain := range socialDomains {
            if strings.Contains(linkDomain, domain) {
                socialLinks = append(socialLinks, e.Request.URL.String()+"|"+link)
            }
        }
        if strings.Contains(linkDomain, domain) {
            visitFlag := true
            for _, extension := range denyList {
                if strings.Contains(strings.ToLower(link), extension) {
                    visitFlag = false
                }
            }
            for _, value := range visitedLinks {
                if strings.ToLower(link) == value {
                    visitFlag = false
                }
            }

            if !strings.HasPrefix(u2.Path, path) {
                visitFlag = false
            }
            // if it's True it will append
            if visitFlag {
                visitedLinks = append(visitedLinks, link)
                err := e.Request.Visit(link)
                if err != nil {
                    panic(err)
                }

            }
        }

    })

    visError := c.Visit(visitURL)
    if visError != nil {
        panic(visError)
    }
    return socialLinks
}

检查和可能的收购

此功能将社交媒体链接切成片段作为输入,并根据某些条件检查可能收购的可能性。

  1. 对于Facebook链接,它构建了临时链接并发送HTTP请求以检查页面是否返回“未找到404”响应。如果确实如此,它将打印一条表示“可能接管”的消息。

  2. 对于tiktok链接,它将带有提供的用户的http请求,并检查响应状态代码是否为404。 >

  3. 对于Instagram链接,它构建了临时链接并发送HTTP请求以检查404响应。

  4. 对于Twitter链接,它构建了一个临时链接,并使用NITTER.NET域作为代理发送HTTP请求。如果响应状态代码为404,则打印一条“可能的接管”消息。

它的重点是确定基于每个社交媒体平台的特定条件可能容易接管的社交媒体链接。
但是,此类检查的有效性可能会有所不同,在生产环境中适当处理误报和负面因素很重要。

import (
    "crypto/tls"
    "io"
    "net/http"
    "net/url"
    "strings"

    "github.com/fatih/color"
)

func CheckTakeOver(socialLinks []string) {
    var alreadyChecked []string
    for _, value := range socialLinks {
        foundLink := strings.Split(value, "|")[0]
        socialLink := strings.Split(value, "|")[1]
        if StringInSlice(socialLink, &alreadyChecked) {
            continue
        }
        alreadyChecked = append(alreadyChecked, socialLink)
        if len(socialLink) > 60 || strings.Contains(socialLink, "intent/tweet") || strings.Contains(socialLink, "twitter.com/share") || strings.Contains(socialLink, "twitter.com/privacy") || strings.Contains(socialLink, "facebook.com/home") || strings.Contains(socialLink, "instagram.com/p/") {
            continue
        }
        u, err := url.Parse(socialLink)
        if err != nil {
            continue
        }
        domain := u.Host
        tr := &http.Transport{
            TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
        }
        if strings.Contains(domain, "facebook.com") {
            if strings.Count(socialLink, ".") > 1 {
                socialLink = "https://" + strings.Split(socialLink, ".")[1] + "." + strings.Split(socialLink, ".")[2]
            }
            socialLink = strings.Replace(socialLink, "www.", "", -1)
            tempLink := strings.Replace(socialLink, "facebook.com", "tr-tr.facebook.com", -1)
            resp, err := http.Get(tempLink)
            if err != nil {
                continue
            }
            defer resp.Body.Close()
            body, err := io.ReadAll(resp.Body)
            if err != nil {
                continue
            }
            if strings.Contains(string(body), "404 Not Found") {
                color.Green("Possible Takeover: " + socialLink + " at " + foundLink)

            }

        }
        if strings.Contains(domain, "tiktok.com") {
            if strings.Count(strings.Replace(socialLink, "www.", "", -1), ".") > 1 {
                continue
            }
            client := &http.Client{Transport: tr}

            req, err := http.NewRequest("GET", socialLink, nil)
            if err != nil {
                continue
            }

            req.Header.Set("User-Agent", UserAgent)

            resp, err := client.Do(req)
            if err != nil {
                continue
            }
            defer resp.Body.Close()

            if resp.StatusCode == 404 {
                color.Green("Possible Takeover: " + socialLink + " at " + foundLink)
            }
        }
        if strings.Contains(domain, "instagram.com") {

            if strings.Count(strings.Replace(socialLink, "www.", "", -1), ".") > 1 {
                continue
            }
            if !strings.Contains(socialLink, "instagram.com/") {
                continue
            }
            tempLink := "https://www.picuki.com/profile/" + strings.Split(socialLink, "instagram.com/")[1]
            client := &http.Client{Transport: tr}
            req, err := http.NewRequest("GET", tempLink, nil)
            if err != nil {
                continue
            }

            req.Header.Set("User-Agent", UserAgent)

            resp, err := client.Do(req)
            if err != nil {
                continue
            }
            defer resp.Body.Close()

            if resp.StatusCode == 404 {
                color.Green("Possible Takeover: " + socialLink + " at " + foundLink)
            }
        }
        if strings.Contains(domain, "twitter.com") {
            if strings.Count(strings.Replace(socialLink, "www.", "", -1), ".") > 1 {
                continue
            }
            u, err := url.Parse(socialLink)
            if err != nil {
                panic(err)
            }
            userName := u.Path
            tempLink := "https://nitter.net" + userName
            client := &http.Client{}
            req, err := http.NewRequest("GET", tempLink, nil)
            if err != nil {
                continue
            }

            req.Header.Set("User-Agent", UserAgent)

            resp, err := client.Do(req)
            if err != nil {
                continue
            }
            defer resp.Body.Close()

            if resp.StatusCode == 404 {
                color.Green("Possible Takeover: " + socialLink + " at " + foundLink)
            }
        }
    }
}
func StringInSlice(a string, list *[]string) bool {
    for _, b := range *list {
        if b == a {
            return true
        }
    }
    return false
}

命令行并运行

“动作”功能负责处理单个URL。在此功能中,它使用“内部词”功能启动Web爬网,该功能收集社交媒体链接。随后,“内部”功能被调用以评估接管的可能性。该代码还包括进度跟踪,并显示要处理的剩余URL的数量。

核心功能在“运行”函数中。它从解析命令行标志开始,其中包括指定包含要检查的URL的文件的路径和工人例程的数量。该应用程序从指定的文件中读取URL,将其分成切片,并计算要处理的URL的总数。

为了同时执行任务,该代码利用了使用“ WorkerPool”软件包创建的工作池,其工人数量由提供的标志确定。为每个URL提交任务,工人池管理执行。提交了所有任务后,该程序将用“ WP.stopwait()”等待其完成。

package cmd

import (
    "flag"
    "fmt"

    "github.com/ayoubzulfiqar/finder/internals"
    "github.com/fatih/color"
    "github.com/gammazero/workerpool"

    "os"
    "strings"
)

var (
    queue int
)

func Action(url string) {
    sl := internals.Visitor(url, 10)
    internals.CheckTakeOver(internals.RemoveDuplicateStrings(sl))
    color.Magenta("Finished Checking: " + url)
    queue--
    fmt.Println("Remaining URLs:", queue)

}

func Run() {
    internals.LOGO()
    urlFile := flag.String("f", "", "Path of the URL file")
    numWorker := flag.Int("w", 5, "Number of worker.")
    flag.Parse()
    if *urlFile == "" {
        fmt.Println("Please specify all arguments!")
        flag.PrintDefaults()
        os.Exit(1)
    }
    file, err := os.ReadFile(*urlFile)
    if err != nil {
        fmt.Println(err)
        return
    }
    urls := strings.Split(string(file), "\n")
    queue = len(urls)
    fmt.Println("Total URLs:", queue)
    wp := workerpool.New(*numWorker)

    for _, url := range urls {
        url := url
        wp.Submit(func() {
            fmt.Println("Checking:", url)
            Action(url)
        })

    }
    wp.StopWait()

    color.Cyan("Scan Completed")
}
func RemoveDuplicateStrings(strSlice []string) []string {
    allKeys := make(map[string]bool)
    list := make([]string, 0, len(strSlice))

    for _, item := range strSlice {
        if _, value := allKeys[item]; !value {
            allKeys[item] = true
            list = append(list, item)
        }
    }
    return list
}

用法

查找器需要两个参数

  1. -f:包含line的URL的文本文件的路径。
  2. 路径:d:\ url.txt-您必须提供包含所有URL需要扫描的TXT文件的路径
  3. -W:运行的工人人数(例如-W 10)。默认值为5。您可以通过测试系统的功能来增加或降低这一点。

url.txt将包含扫描所需的所有可能的URL。
您可以创建一个本地的TXT文件并将路径扫描。

go run . -f url.txt

目前,它支持Twitter,Facebook,Instagram和Tiktok没有任何API键。
将来将支持其他Socila媒体。

Full Code