Skip to content

Files

Latest commit

4475ace · Oct 25, 2021

History

History
544 lines (420 loc) · 28.4 KB

12.md

File metadata and controls

544 lines (420 loc) · 28.4 KB

十二、社会工程

社会工程是指攻击者操纵或欺骗受害者执行某项行动或提供私人信息。这通常是通过模仿一个受信任的人,制造一种紧迫感,或者制造一个虚假的借口来迫使受害者采取行动。这种行为可能像泄露信息一样简单,也可能像下载和执行恶意软件一样复杂。

在本章中我们将介绍蜜罐,尽管它们有时是用来欺骗机器人而不是人类的。目的是故意欺骗,这是社会工程的核心。我们提供了基本的蜜罐示例,包括 TCP 和 HTTP 蜜罐。

还有许多其他类型的社会工程没有在本书中介绍。这包括实际或面对面的情况,如尾随和假装是维修人员,以及其他数字和远程方法,如电话、短信和社交媒体消息。

社会工程在法律上可能是一个灰色地带。例如,即使一家公司向您提供对其员工进行社会工程的全部权限,它也不允许您对员工的个人电子邮件凭据进行网络钓鱼。意识到法律和道德的界限。

在本章中,我们将具体介绍以下主题:

  • 使用 Reddit 的 JSON REST API 收集个人信息
  • Sending phishing emails with SMTP
  • 生成 QR 码和 base64 编码图像
  • 蜜罐

通过 JSON REST API 收集 intel

REST 和 JSON 正在成为 web API 的实际接口。每个 API 都是不同的,因此本例的主要目标是展示如何处理来自 REST 端点的 JSON 数据。

本例将以 Reddit 用户名为参数,打印该用户最近的帖子和评论,了解他们讨论的主题。本例选择 Reddit 是因为某些端点不需要身份验证,因此易于测试。其他提供 RESTAPI 的服务包括 Twitter 和 LinkedIn,您可以查询这些 API 以进行英特尔收集。

请记住,本示例的重点是提供一个从 REST 端点解析 JSON 的示例。因为每个 API 都是不同的,所以在编写自己的程序与 JSON API 交互时,这个示例应该作为参考。必须定义数据结构以匹配来自 JSON 端点的响应。在本例中,创建的数据结构与 Reddit 响应匹配。

在 Go 中使用 JSON 时,首先需要定义数据结构,然后使用MarshalUnmarshal函数在原始字符串和结构化数据格式之间进行编码和解码。下面的示例创建一个与 Reddit 返回的 JSON 结构匹配的数据结构。然后使用Unmarshal函数将字符串转换为 Go 数据对象。您不必为 JSON 中的每一条数据都创建一个变量。您可以省略不需要的字段。

JSON 响应中的数据嵌套到许多级别,因此我们将使用匿名结构。这避免了我们必须为每个嵌套级别创建单独的命名类型。此示例创建一个命名结构,其中所有嵌套级别都存储为嵌入式匿名结构。

Go 数据结构中的变量名与 JSON 响应中提供的变量名不匹配,因此 JSON 变量名在结构中定义数据类型之后立即提供。这允许将变量从 JSON 数据正确映射到 Go 结构。这通常是必要的,因为 Go 数据结构中的变量名区分大小写。

请注意,每个 web 服务都有自己的服务条款,这些条款可能会限制或限制您访问其网站的方式。一些网站有禁止刮擦的规定,而另一些网站有费率限制。虽然这可能不是刑事犯罪,但该服务可能会因违反服务条款而阻止您的帐户或 IP 地址。请务必阅读与您互动的每个网站或 API 的服务条款。

此示例的代码如下所示:

package main

import (
   "encoding/json"
   "fmt"
   "io/ioutil"
   "log"
   "net/http"
   "os"
   "time"
)

// Define the structure of the JSON response
// The json variable names are specified on
// the right since they do not match the
// struct variable names exactly
type redditUserJsonResponse struct {
   Data struct {
      Posts []struct { // Posts & comments
         Data struct {
            Subreddit  string  `json:"subreddit"`
            Title      string  `json:"link_title"`
            PostedTime float32 `json:"created_utc"`
            Body       string  `json:"body"`
         } `json:"data"`
      } `json:"children"`
   } `json:"data"`
}

func printUsage() {
   fmt.Println(os.Args[0] + ` - Print recent Reddit posts by a user

Usage: ` + os.Args[0] + ` <username>
Example: ` + os.Args[0] + ` nanodano
`)
}

func main() {
   if len(os.Args) != 2 {
      printUsage()
      os.Exit(1)
   }
   url := "https://www.reddit.com/user/" + os.Args[1] + ".json"

   // Make HTTP request and read response
   response, err := http.Get(url)
   if err != nil {
      log.Fatal("Error making HTTP request. ", err)
   }
   defer response.Body.Close()
   body, err := ioutil.ReadAll(response.Body)
   if err != nil {
      log.Fatal("Error reading HTTP response body. ", err)
   }

   // Decode response into data struct
   var redditUserInfo redditUserJsonResponse
   err = json.Unmarshal(body, &redditUserInfo)
   if err != nil {
      log.Fatal("Error parson JSON. ", err)
   }

   if len(redditUserInfo.Data.Posts) == 0 {
      fmt.Println("No posts found.")
      fmt.Printf("Response Body: %s\n", body)
   }

   // Iterate through all posts found
   for _, post := range redditUserInfo.Data.Posts {
      fmt.Println("Subreddit:", post.Data.Subreddit)
      fmt.Println("Title:", post.Data.Title)
      fmt.Println("Posted:", time.Unix(int64(post.Data.PostedTime), 
         0))
      fmt.Println("Body:", post.Data.Body)
      fmt.Println("========================================")
   }
} 

使用 SMTP 发送网络钓鱼电子邮件

网络钓鱼是指攻击者试图通过伪造电子邮件或其他通信形式获取敏感信息的过程,这些通信形式看起来像来自可信来源的合法电子邮件。

网络钓鱼通常通过电子邮件进行,但也可以通过电话、社交媒体或短信进行。我们关注的是电子邮件方法。网络钓鱼可以大规模进行,即向大量收件人发送一封普通电子邮件,希望有人上钩。尼日利亚王子电子邮件骗局是一场流行的网络钓鱼活动。其他提供奖励的电子邮件也很受欢迎,而且效果相对较好,例如,如果他们参与并遵循您提供的链接并使用他们的凭据登录,则提供 iPhone 赠品或礼品卡。网络钓鱼电子邮件还经常使用真实签名和公司徽标模仿合法发件人。通常会产生一种紧迫感,以说服受害者在不遵循标准程序的情况下迅速采取行动。

您可以使用第 10 章网页抓取中的程序收集电子邮件,该程序从网页中提取电子邮件。将电子邮件提取功能与提供的 web 爬虫示例相结合,您就拥有了一个强大的工具,可以从域中删除电子邮件。

鱼叉式网络钓鱼是一个针对目标网络钓鱼的术语,主要针对少数目标,甚至可能只是一个特定目标。鱼叉式网络钓鱼需要更多的研究和定位,针对特定的人定制一封电子邮件,创造一个可信的借口,也许是模仿他们认识的人。矛式网络钓鱼需要更多的工作,但它增加了欺骗用户的可能性,并减少了被垃圾邮件过滤器捕获的机会。

在尝试矛式网络钓鱼活动时,您应该首先收集尽可能多的有关目标的信息,然后再制作电子邮件。在本章前面,我们讨论了使用 JSON REST API 收集目标上的数据。如果您的目标个人或组织有网站,您还可以使用第 10 章网页抓取中的单词计数程序和标题抓取程序。收集网站上最常见的单词和标题可以快速了解目标公司所属的行业或他们可能提供的产品和服务。

Go 标准库附带用于发送电子邮件的 SMTP 包。Go 还有一个用于解析电子邮件的net/mail包(https://golang.org/pkg/net/mail/ )。mail包相对较小,本书没有介绍,但它允许您将电子邮件的全文解析为消息类型,从而可以分别提取正文和标题。本例重点介绍如何使用 SMTP 包发送电子邮件。

配置变量都在源代码的顶部定义。请确保设置正确的 SMTP 主机、端口、发件人和密码。常用 SMTP 端口为25用于未加密访问,端口465587通常用于加密访问。这些设置都取决于 SMTP 服务器的配置。如果不先设置正确的服务器和凭据,此示例将无法正确运行。如果你有一个 Gmail 帐户,你可以重复使用大多数预先填充的值,只需替换发送者和密码。

如果您使用 Gmail 和双因素身份验证发送邮件,则需要在处创建特定于应用的密码 https://security.google.com/settings/security/apppasswords 。如果您未使用双因素身份验证,请在启用不太安全的应用 https://myaccount.google.com/lesssecureapps

这个程序创建并发送两个示例电子邮件,一个文本和一个 HTML。还可以发送组合文本和 HTML 电子邮件,由电子邮件客户端选择要呈现的版本。这可以通过使用Content-Type标题到multipart/alternative并设置边界来区分文本电子邮件结束和 HTML 电子邮件开始的位置来完成。这里不包括发送文本和 HTML 组合电子邮件,但值得一提。您可以在了解更多关于multipart内容类型RFC 1341的信息 https://www.w3.org/Protocols/rfc1341/7_2_Multipart.html

Go 还提供了一个template包,允许您使用变量占位符创建模板文件,然后使用结构中的数据填充占位符。如果希望将模板文件与源代码分离,则模板非常有用,从而允许您修改模板而无需重新编译应用。下面的示例不使用模板,但您可以在上阅读有关模板的更多信息 https://golang.org/pkg/text/template/

package main

import (
   "log"
   "net/smtp"
   "strings"
)

var (
   smtpHost   = "smtp.gmail.com"
   smtpPort   = "587"
   sender     = "sender@gmail.com"
   password   = "SecretPassword"
   recipients = []string{
      "recipient1@example.com",
      "recipient2@example.com",
   }
   subject = "Subject Line"
)

func main() {
   auth := smtp.PlainAuth("", sender, password, smtpHost)

   textEmail := []byte(
      `To: ` + strings.Join(recipients, ", ") + `
Mime-Version: 1.0
Content-Type: text/plain; charset="UTF-8";
Subject: ` + subject + `

Hello,

This is a plain text email.
`)

   htmlEmail := []byte(
      `To: ` + strings.Join(recipients, ", ") + `
Mime-Version: 1.0
Content-Type: text/html; charset="UTF-8";
Subject: ` + subject + `

<html>
<h1>Hello</h1>
<hr />
<p>This is an <strong>HTML</strong> email.</p>
</html>
`)

   // Send text version of email
   err := smtp.SendMail(
      smtpHost+":"+smtpPort,
      auth,
      sender,
      recipients,
      textEmail,
   )
   if err != nil {
      log.Fatal(err)
   }

   // Send HTML version
   err = smtp.SendMail(
      smtpHost+":"+smtpPort,
      auth,
      sender,
      recipients,
      htmlEmail,
   )
   if err != nil {
      log.Fatal(err)
   }
}

Generating QR codes

快速响应QR码)是二维条码。它比传统的一维线条条形码存储更多的信息。它们最初是在日本汽车行业开发的,但已被其他行业采用。QR 码于 2000 年被 ISO 批准为国际标准。最新规格见https://www.iso.org/standard/62021.html

二维码可以在一些广告牌、海报、讲义和其他广告材料上找到。二维码在交易中也经常使用。您可能会在火车票上或在发送和接收加密货币(如比特币)时看到二维码。一些身份验证服务(如双因素身份验证)使用 QR 码以方便使用。

二维码有利于社会工程,因为人类无法通过查看二维码来判断它是否恶意。通常情况下,二维码中包含的 URL 会立即加载,从而使用户面临风险。如果你创造了一个可信的借口,你可以说服用户相信二维码。

本例中使用的软件包名为go-qrcode,可在处获得 https://github.com/skip2/go-qrcode 。这是 GitHub 上提供的第三方库,不受 Google 或 Go 团队的支持。go-qrcode包使用标准库映像包:imageimage/colorimage/png

使用以下命令安装go-qrcode包:

go get github.com/skip2/go-qrcode/...

go get中的省略号(...为通配符。它还将安装所有子包。

根据软件包作者的说法,QR 码的最大容量根据编码内容和错误恢复级别而变化。最大容量为 2953 字节、4296 个字母数字字符、7089 个数字或其组合。

本程序中演示了两个要点。首先是如何以原始 PNG 字节的形式生成 QR 码,然后将要嵌入 HTML 页面中的数据进行 base64 编码。生成完整的 HTMLimg标记,作为标准输出的输出,并可直接复制和粘贴到 HTML 页面中。第二部分演示如何简单地生成二维码并将其直接写入文件。

此示例生成 PNG 图像格式的 QR 码。让我们提供要编码的文本和输出文件名作为命令行参数,程序将输出图像,并将数据编码为 QR 图像:

package main 

import (
   "encoding/base64"
   "fmt"
   "github.com/skip2/go-qrcode"
   "log"
   "os"
)

var (
   pngData        []byte
   imageSize      = 256 // Length and width in pixels
   err            error
   outputFilename string
   dataToEncode   string
)

// Check command line arguments. Print usage
// if expected arguments are not present
func checkArgs() {
   if len(os.Args) != 3 {
      fmt.Println(os.Args[0] + `

Generate a QR code. Outputs a PNG file in <outputFilename>.
Also outputs an HTML img tag with the image base64 encoded to STDOUT.

 Usage: ` + os.Args[0] + ` <outputFilename> <data>
 Example: ` + os.Args[0] + ` qrcode.png https://www.devdungeon.com`)
      os.Exit(1)
   }
   // Because these variables were above, at the package level
   // we don't have to return them. The same variables are
   // already accessible in the main() function
   outputFilename = os.Args[1]
   dataToEncode = os.Args[2]
}

func main() {
   checkArgs()

   // Generate raw binary data for PNG
   pngData, err = qrcode.Encode(dataToEncode, qrcode.Medium, 
      imageSize)
   if err != nil {
      log.Fatal("Error generating QR code. ", err)
   }

   // Encode the PNG data with base64 encoding
   encodedPngData := base64.StdEncoding.EncodeToString(pngData)

   // Output base64 encoded image as HTML image tag to STDOUT
   // This img tag can be embedded in an HTML page
   imgTag := "<img src=\"data:image/png;base64," + 
      encodedPngData + "\"/>"
   fmt.Println(imgTag) // For use in HTML

   // Generate and write to file with one function
   // This is a standalone function. It can be used by itself
   // without any of the above code
   err = qrcode.WriteFile(
      dataToEncode,
      qrcode.Medium,
      imageSize,
      outputFilename,
   )
   if err != nil {
      log.Fatal("Error generating QR code to file. ", err)
   }
} 

Base64 编码数据

在前面的示例中,QR 码是 base64 编码的。由于这是一项常见任务,因此值得介绍如何编码和解码。每当二进制数据需要作为字符串存储或传输时,base64 编码都很有用。

这个例子演示了一个非常简单的编码和解码字节片的用例。base64 编码和解码的两个重要功能是EncodeToString()DecodeString()

package main

import (
   "encoding/base64"
   "fmt"
   "log"
)

func main() {
   data := []byte("Test data")

   // Encode bytes to base64 encoded string.
   encodedString := base64.StdEncoding.EncodeToString(data)
   fmt.Printf("%s\n", encodedString)

   // Decode base64 encoded string to bytes.
   decodedData, err := base64.StdEncoding.DecodeString(encodedString)
   if err != nil {
      log.Fatal("Error decoding data. ", err)
   }
   fmt.Printf("%s\n", decodedData)
} 

蜜罐

蜜罐是你设置的用来抓捕攻击者的假服务。您故意提供一个服务,目的是引诱攻击者,诱使他们认为该服务是真实的,并且包含某种敏感信息。通常,蜜罐被伪装成一个旧的、过时的、易受攻击的服务器。可以将日志记录或警报附加到蜜罐,以快速识别潜在攻击者。在您的内部网络上安装蜜罐可能会在任何系统受损之前提醒您有攻击者。

当攻击者破坏一台机器时,他们通常使用被破坏的机器继续枚举、攻击和旋转。如果您网络上的蜜罐检测到来自您网络上另一台机器的奇怪行为,例如端口扫描或登录尝试,那么表现异常的机器可能会受到危害。

有许多不同种类的蜜罐。它可以是记录任何连接的简单 TCP 侦听器、带有登录表单字段的假 HTML 页面,或者看起来像真正的员工门户的完整 web 应用。如果攻击者认为他们找到了一个关键应用,那么他们很可能会花费时间试图获得访问权限。如果你布置有吸引力的蜜罐,你可能会让攻击者把大部分时间花在一个无用的蜜罐上。如果保留详细的日志记录,您可以了解攻击者使用的方法、他们拥有的工具,甚至可能还有他们的位置。

还有一些其他类型的蜜罐值得一提,但在本书中没有演示:

  • SMTP 蜜罐:这模拟了一个开放式电子邮件中继,垃圾邮件发送者滥用该中继来捕获试图使用您的邮件发送者。
  • 网络爬虫蜜罐:这些是隐藏的网页,不打算让人访问,但链接隐藏在网站的公共场所,如 HTML 评论,以捕捉蜘蛛、爬虫和刮板。
  • 数据库蜜罐:这是一个伪造或真实的数据库,通过详细的日志记录来检测攻击者,其中可能还包含伪造数据,以查看攻击者感兴趣的信息。
  • 蜜罐网:这是一个充满蜜罐的完整网络,使其看起来像一个真实的网络,可以自动或伪造到蜜罐服务的客户端流量,以模拟真实用户。

攻击者可能能够发现明显的蜜罐服务并避开它们。我建议您选择两个极端中的一个:使蜜罐尽可能地模拟真实的服务,或者使服务成为一个不会向攻击者泄露任何信息的完全黑盒。

在本节中,我们将介绍一些非常基本的示例,以帮助您理解蜜罐的概念,并为您提供一个模板来创建您自己的更定制的蜜罐。首先,演示了一个基本的 TCP 套接字蜜罐。这将侦听端口并记录它接收到的任何连接和数据。为了配合本示例,提供了一个 TCP 测试工具。它的行为类似于 Netcat 的原始版本,允许您通过标准输入向服务器发送单个消息。这可用于测试 TCP 蜜罐或扩展并用于其他应用。最后一个例子是 HTTP 蜜罐。它提供了一个登录表单,记录验证尝试,但总是返回错误。

确保您了解网络上蜜罐的风险。如果您在不更新底层操作系统的情况下让蜜罐继续运行,则可能会给您的网络增加真正的风险。

TCP 蜜罐

我们将从 TCP 蜜罐开始介绍最简单的蜜罐。这将记录接收到的任何 TCP 连接和从客户端接收到的任何数据。

它将以身份验证失败消息进行响应。由于它会记录从客户端接收到的任何数据,因此它会记录他们尝试使用的任何用户名和密码。您可以通过检查他们正在尝试的身份验证方法来了解他们的攻击方法,因为它的行为就像一个黑匣子,不会提供任何关于可能使用的身份验证机制的线索。您可以使用这些日志来查看他们是否将其视为 SMTP 服务器,这可能表示垃圾邮件发送者,或者他们试图通过数据库进行身份验证,表明他们正在查找信息。研究攻击者的行为可以非常有见地,甚至可以启发您了解您尚未了解的漏洞。攻击者可能在蜜罐上使用服务指纹工具,您可能能够识别其攻击方法中的模式并找到阻止它们的方法。如果攻击者试图使用真实用户凭据登录,则该用户可能会受到威胁。

此示例将记录高级请求(如 HTTP 请求)以及低级连接(如 TCP 端口扫描程序)。将记录 TCP connect 扫描,但不会检测到仅 TCPSYN扫描(隐藏):

package main

import (
   "bytes"
   "log"
   "net"
)

func handleConnection(conn net.Conn) {
   log.Printf("Received connection from %s.\n", conn.RemoteAddr())
   buff := make([]byte, 1024)
   nbytes, err := conn.Read(buff)
   if err != nil {
      log.Println("Error reading from connection. ", err)
   }
   // Always reply with a fake auth failed message
   conn.Write([]byte("Authentication failed."))
   trimmedOutput := bytes.TrimRight(buff, "\x00")
   log.Printf("Read %d bytes from %s.\n%s\n",
      nbytes, conn.RemoteAddr(), trimmedOutput)
   conn.Close()
}

func main() {
   portNumber := "9001" // or os.Args[1]
   ln, err := net.Listen("tcp", "localhost:"+portNumber)
   if err != nil {
       log.Fatalf("Error listening on port %s.\n%s\n",
          portNumber, err.Error())
   }
   log.Printf("Listening on port %s.\n", portNumber)
   for {
      conn, err := ln.Accept()
      if err != nil {
         log.Println("Error accepting connection.", err)
      }
      go handleConnection(conn)
   }
}

TCP 测试工具

为了测试我们的 TCP 蜜罐,我们需要向它发送一些 TCP 流量。我们可以使用任何现有的网络工具,包括 web 浏览器或 FTP 客户端来实现蜜罐。一个很好的工具也是 Netcat,TCP/IP 瑞士军刀。我们不使用 Netcat,而是创建自己的简单克隆。它只需通过 TCP 读取和写入数据。输入和输出将分别通过标准输入和标准输出,允许您在文件和其他应用中使用键盘和终端或管道数据。

此工具可以用作通用网络测试工具,如果您有任何入侵检测系统或其他要测试的监控,它可能会很有用。该程序将从标准输入中获取数据并通过 TCP 连接发送,然后读取服务器发送回的任何数据并将其打印到标准输出。运行此示例时,必须将主机和端口作为带有冒号分隔符的单个字符串传递,如下所示:localhost:9001。以下是简单 TCP 测试工具的代码:

package main

import (
   "bytes"
   "fmt"
   "log"
   "net"
   "os"
)

func checkArgs() string {
   if len(os.Args) != 2 {
      fmt.Println("Usage: " + os.Args[0] + " <targetAddress>")
      fmt.Println("Example: " + os.Args[0] + " localhost:9001")
      os.Exit(0)
   }
   return os.Args[1]
}

func main() {
   var err error
   targetAddress := checkArgs()
   conn, err := net.Dial("tcp", targetAddress)
   if err != nil {
      log.Fatal(err)
   }
   buf := make([]byte, 1024)

   _, err = os.Stdin.Read(buf)
   trimmedInput := bytes.TrimRight(buf, "\x00")
   log.Printf("%s\n", trimmedInput)

   _, writeErr := conn.Write(trimmedInput)
   if writeErr != nil {
      log.Fatal("Error sending data to remote host. ", writeErr)
   }

   _, readErr := conn.Read(buf)
   if readErr != nil {
      log.Fatal("Error when reading from remote host. ", readErr)
   }
   trimmedOutput := bytes.TrimRight(buf, "\x00")
   log.Printf("%s\n", trimmedOutput)
} 

HTTP POST 表单登录蜜罐

当您在网络上部署它时,除非您正在进行有意的测试,否则任何表单提交都是一个危险信号。这意味着有人试图登录到您的假服务器。因为它没有合法的用途,所以只有攻击者才有任何理由试图获得访问权限。不会有真正的身份验证或授权,只是一个使攻击者认为他们试图登录的假象。Go HTTP 包在 Go 1.6+中默认支持 HTTP 2。在上阅读更多关于net/http套餐的信息 https://golang.org/pkg/net/http/

下面的程序将充当一个带有登录页的 web 服务器,它只将表单提交记录到标准输出。您可以运行此服务器,然后尝试通过浏览器登录,登录尝试将打印到运行服务器的终端:

package main 

import (
   "fmt"
   "log"
   "net/http"
)

// Correctly formatted function declaration to satisfy the
// Go http.Handler interface. Any function that has the proper
// request/response parameters can be used to process an HTTP request.
// Inside the request struct we have access to the info about
// the HTTP request and the remote client.
func logRequest(response http.ResponseWriter, request *http.Request) {
   // Write output to file or just redirect output of this 
   // program to file
   log.Println(request.Method + " request from " +  
      request.RemoteAddr + ". " + request.RequestURI)
   // If POST not empty, log attempt.
   username := request.PostFormValue("username")
   password := request.PostFormValue("pass")
   if username != "" || password != "" {
      log.Println("Username: " + username)
      log.Println("Password: " + password)
   }

   fmt.Fprint(response, "<html><body>")
   fmt.Fprint(response, "<h1>Login</h1>")
   if request.Method == http.MethodPost {
      fmt.Fprint(response, "<p>Invalid credentials.</p>")
   }
   fmt.Fprint(response, "<form method=\"POST\">")
   fmt.Fprint(response, 
      "User:<input type=\"text\" name=\"username\"><br>")
   fmt.Fprint(response, 
      "Pass:<input type=\"password\" name=\"pass\"><br>")
   fmt.Fprint(response, "<input type=\"submit\"></form><br>")
   fmt.Fprint(response, "</body></html>")
}

func main() {
   // Tell the default server multiplexer to map the landing URL to
   // a function called logRequest
   http.HandleFunc("/", logRequest)

   // Kick off the listener using that will run forever
   err := http.ListenAndServe(":8080", nil)
   if err != nil {
      log.Fatal("Error starting listener. ", err)
   }
} 

HTTP 表单域蜜罐

在前面的示例中,我们讨论了创建一个假登录表单来检测试图登录的人。如果我们想确定它是否是机器人呢?在生产站点上,检测试图登录的机器人的功能对于阻止机器人也很有用。识别自动机器人的一种方法是使用蜜罐表单字段。蜜罐表单字段是 HTML 表单上的输入字段,对用户隐藏,当表单由人工提交时预期为空。机器人仍然会在表单中找到蜜罐字段并尝试填写它们。

其目标是欺骗机器人,使其认为表单字段是真实的,同时对用户隐藏表单字段。一些机器人会使用正则表达式来查找诸如useremail之类的关键字,并只填写这些字段;因此,蜜罐字段通常使用诸如email_addressuser_name之类的名称来显示正常字段。如果服务器接收到这些字段中的数据,则可以假定表单是由 bot 提交的。

如果我们使用上一个示例中的登录表单,并添加一个名为email的隐藏表单字段,则机器人可能会尝试填写该表单,而人类不会看到它。表单字段可以使用 CSS 或input元素上的hidden属性隐藏。我建议您使用位于单独样式表中的 CSS 来隐藏蜜罐表单字段,因为机器人可以很容易地确定表单字段是否具有hidden属性,但如果使用样式表来检测输入是否被隐藏,则比较困难。

沙箱

本章中未演示但值得一提的一项相关技术是沙箱。沙箱的用途与蜜罐不同,但它们都努力创建一个看起来合法但实际上受到严格控制和监控的环境。沙箱的一个例子是创建一个没有网络连接的虚拟机,该虚拟机记录所有文件更改和尝试的网络连接,以查看是否发生任何可疑事件。

有时,可以通过查看 CPU 和 RAM 的数量来检测沙箱环境。如果恶意应用检测到一个具有少量资源(例如 1 个 CPU 和 1 GB RAM)的系统,那么它可能不是现代桌面计算机,可能是一个沙箱。恶意软件编写者已经学会了在沙箱环境中建立指纹,并对应用进行编程,以便在怀疑它正在沙箱中运行时绕过任何恶意操作。

总结

阅读本章后,您现在应该了解社会工程的一般概念,并能够提供一些示例。您应该了解如何使用 JSON 与 REST API 交互,如何生成 QR 码和 base64 编码数据,以及如何使用 SMTP 发送电子邮件。您还应该能够解释蜜罐的概念,并了解如何实现您自己的蜜罐或根据您自己的需要扩展这些示例。

你还能想到其他类型的蜜罐吗?哪些公共服务经常受到暴力强迫或攻击?您如何定制或扩展社会工程示例?您能想到其他可以查询以收集信息的服务吗?

在下一章中,我们将介绍开发后的主题,例如部署绑定 shell、反向绑定 shell 或 web shell;交叉编译;查找可写文件;以及修改文件时间戳、权限和所有权。