mirror of
https://github.com/Li4n0/revsuit.git
synced 2026-09-22 06:40:43 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
284db90c16 | ||
|
|
223c14ab33 | ||
|
|
c53ec79ccd | ||
|
|
7dde3936d1 | ||
|
|
a4ffaa7350 | ||
|
|
eee9c7be70 | ||
|
|
b76757da33 | ||
|
|
b33de11ba8 |
@@ -23,6 +23,10 @@ jobs:
|
||||
uses: actions/checkout@v2
|
||||
- name: create dist directory
|
||||
run: mkdir frontend/dist && touch frontend/dist/revsuit
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: 1.19.x
|
||||
- name: Run golangci-lint
|
||||
uses: golangci/golangci-lint-action@v3
|
||||
with:
|
||||
|
||||
@@ -28,15 +28,15 @@ jobs:
|
||||
run: echo ::set-output name=VERSION::$(echo $GITHUB_REF | cut -d / -f 3)
|
||||
|
||||
- name: compile linux amd64
|
||||
run: GOARCH="amd64" go build -ldflags="-s -w -X 'github.com/li4n0/revsuit/pkg/server.VERSION=${{ steps.get_version.outputs.VERSION }}'" -tags netgo -trimpath -o "bin/revsuit_linux_amd64" ./cmd/revsuit/revsuit.go
|
||||
run: CGO_ENABLE=0 GOARCH="amd64" go build -ldflags="-s -w -X 'github.com/li4n0/revsuit/pkg/server.VERSION=${{ steps.get_version.outputs.VERSION }}'" -tags netgo -trimpath -o "bin/revsuit_linux_amd64" ./cmd/revsuit/revsuit.go
|
||||
- name: compile linux arm64
|
||||
run: GOARCH="arm64" go build -ldflags="-s -w -X 'github.com/li4n0/revsuit/pkg/server.VERSION=${{ steps.get_version.outputs.VERSION }}'" -tags netgo -trimpath -o "bin/revsuit_linux_arm64" ./cmd/revsuit/revsuit.go
|
||||
run: CGO_ENABLE=0 GOARCH="arm64" go build -ldflags="-s -w -X 'github.com/li4n0/revsuit/pkg/server.VERSION=${{ steps.get_version.outputs.VERSION }}'" -tags netgo -trimpath -o "bin/revsuit_linux_arm64" ./cmd/revsuit/revsuit.go
|
||||
- name: compile darwin amd64
|
||||
run: GOOS="darwin" GOARCH="amd64" go build -ldflags="-s -w -X 'github.com/li4n0/revsuit/pkg/server.VERSION=${{ steps.get_version.outputs.VERSION }}'" -trimpath -o "bin/revsuit_darwin_amd64" ./cmd/revsuit/revsuit.go
|
||||
run: CGO_ENABLE=0 GOOS="darwin" GOARCH="amd64" go build -ldflags="-s -w -X 'github.com/li4n0/revsuit/pkg/server.VERSION=${{ steps.get_version.outputs.VERSION }}'" -trimpath -o "bin/revsuit_darwin_amd64" ./cmd/revsuit/revsuit.go
|
||||
- name: compile darwin arm64
|
||||
run: GOOS="darwin" GOARCH="arm64" go build -ldflags="-s -w -X 'github.com/li4n0/revsuit/pkg/server.VERSION=${{ steps.get_version.outputs.VERSION }}'" -trimpath -o "bin/revsuit_darwin_arm64" ./cmd/revsuit/revsuit.go
|
||||
run: CGO_ENABLE=0 GOOS="darwin" GOARCH="arm64" go build -ldflags="-s -w -X 'github.com/li4n0/revsuit/pkg/server.VERSION=${{ steps.get_version.outputs.VERSION }}'" -trimpath -o "bin/revsuit_darwin_arm64" ./cmd/revsuit/revsuit.go
|
||||
- name: compile windows amd64
|
||||
run: GOOS="windows" GOARCH="amd64" go build -ldflags="-s -w -X 'github.com/li4n0/revsuit/pkg/server.VERSION=${{ steps.get_version.outputs.VERSION }}' " -trimpath -o "bin/revsuit_windows_amd64.exe" ./cmd/revsuit/revsuit.go
|
||||
run: CGO_ENABLE=0 GOOS="windows" GOARCH="amd64" go build -ldflags="-s -w -X 'github.com/li4n0/revsuit/pkg/server.VERSION=${{ steps.get_version.outputs.VERSION }}' " -trimpath -o "bin/revsuit_windows_amd64.exe" ./cmd/revsuit/revsuit.go
|
||||
|
||||
- name: Upload the artifacts
|
||||
uses: li4n0/upload-release-action@v2
|
||||
|
||||
+4
-1
@@ -28,4 +28,7 @@ package-lock.json
|
||||
node_modules/
|
||||
|
||||
## frontend dist
|
||||
dist/
|
||||
dist/
|
||||
|
||||
## received files
|
||||
revsuit-files
|
||||
|
||||
@@ -2,6 +2,25 @@
|
||||
|
||||
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
||||
|
||||
## [0.7.0](https://github.com/Li4n0/revsuit/compare/v0.6.0...v0.7.0) (2023-05-23)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add `value` field to the dns log ([#67](https://github.com/Li4n0/revsuit/issues/67)) ([223c14a](https://github.com/Li4n0/revsuit/commit/223c14ab33757e06b0d8177091982582e08e70c4))
|
||||
|
||||
## [0.6.0](https://github.com/Li4n0/revsuit/compare/v0.5.2...v0.6.0) (2023-03-24)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* support for using `Flag-Filter` request headers to filter the flags that the client expects to receive ([#64](https://github.com/Li4n0/revsuit/issues/64)) ([b33de11](https://github.com/Li4n0/revsuit/commit/b33de11ba8f126b03a45ad15cae69331ad59b865)) (Thanks to @whwlsfb)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix static resource loading failure after modifying `admin_path_prefix` ([b76757d](https://github.com/Li4n0/revsuit/commit/b76757da331b56f240ec2a0c69d479f3184bc4c2)), closes [#63](https://github.com/Li4n0/revsuit/issues/63)
|
||||
|
||||
### [0.5.2](https://github.com/Li4n0/revsuit/compare/v0.5.1...v0.5.2) (2022-11-16)
|
||||
|
||||
|
||||
|
||||
@@ -8,9 +8,10 @@ token: # Authentication Token, both the admin pag
|
||||
domains: [] # The domain names used by the platform
|
||||
external_ip: # The external IP of the platform, you need to make sure that the target you want to test can access the platform through this IP
|
||||
admin_path_prefix: "/revsuit" # The http path prefix for the admin page, the page will be located at: /admin_path_prefix/admin
|
||||
database: revsuit.db # Database connection information, support using Sqlite3, MySQL, Postgres
|
||||
# database: "mysql://root:password@tcp(127.0.0.1:3306)/revsuit?charset=utf8mb4&parseTime=True&loc=Local"
|
||||
# Database connection information, support using MySQL, Postgres, Sqlite3
|
||||
database: "mysql://root:password@tcp(127.0.0.1:3306)/revsuit?charset=utf8mb4&parseTime=True&loc=Local"
|
||||
# database: "postgres://host=127.0.0.1 user=root password=password dbname=revsuit port=5432 sslmode=disable TimeZone=Asia/Shanghai"
|
||||
#database: revsuit.db # The use of sqlite databases on some systems may cause `SQLITE BUSY` problems in concurrent scenarios, so it is not recommended for use in a formal environment
|
||||
|
||||
log_level: info # Output log levels, divided into: debug, info, warning, error, fatal
|
||||
check_upgrade: true # Whether to automatically check for updates
|
||||
@@ -43,4 +44,4 @@ notice:
|
||||
lark: https://open.feishu.cn/open-apis/bot/v2/hook/{token} # Webhook of Lark Bot
|
||||
weixin: https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key={key} # Webhook of Weixin Bot
|
||||
slack: https://hooks.slack.com/services/{id}/{token} # Webhook of Slack Bot
|
||||
```
|
||||
```
|
||||
|
||||
+4
-3
@@ -7,9 +7,10 @@ token: # 鉴权Token,管理页面和客户端
|
||||
domains: [] # 反连平台绑定的域名
|
||||
external_ip: # 反连平台的外部IP,需要确保你想测试的目标能通过该 IP 访问到平台
|
||||
admin_path_prefix: "/revsuit" # 管理页面的 http path 前缀,管理页面将位于:/admin_path_prefix/admin
|
||||
database: revsuit.db # 数据库连接信息 支持Sqlite3、MySQL、Postgres
|
||||
# database: "mysql://root:password@tcp(127.0.0.1:3306)/revsuit?charset=utf8mb4&parseTime=True&loc=Local"
|
||||
# 数据库连接信息 支持MySQL、Postgres、SQLite3
|
||||
database: "mysql://root:password@tcp(127.0.0.1:3306)/revsuit?charset=utf8mb4&parseTime=True&loc=Local"
|
||||
# database: "postgres://host=127.0.0.1 user=root password=password dbname=revsuit port=5432 sslmode=disable TimeZone=Asia/Shanghai"
|
||||
#database: revsuit.db # 在部分系统上使用 sqlite 数据库时,在并发场景下可能会出现 `SQLITE BUSY` 的问题,因此不推荐在正式环境中使用该类型数据库
|
||||
|
||||
log_level: info # 输出日志的级别,分为:debug、info、warning、error、fatal
|
||||
check_upgrade: false # 是否自动检查更新
|
||||
@@ -43,4 +44,4 @@ notice:
|
||||
weixin: https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key={key} # 企业微信机器人webhook地址
|
||||
slack: https://hooks.slack.com/services/{id}/{token} # slack机器人webhook地址
|
||||
|
||||
```
|
||||
```
|
||||
|
||||
@@ -158,6 +158,11 @@ example.
|
||||
As shown above, RevSuit supports multiple clients, and each client **in the connected state** receives a push of `flag`,
|
||||
so distributed scanning can be supported.
|
||||
|
||||
If you don't want every client to receive all `flag` pushes, you can use the `Flag-Filter` request header when creating an sse connection to set the format(regular expressions) of the `flag` you want that client to receive:
|
||||
|
||||

|
||||
|
||||
|
||||
#### Temporary storage queue
|
||||
|
||||
RevSuit will store `flag` temporarily in the queue when there is no client connection and send it when the client
|
||||
|
||||
+6
-1
@@ -140,6 +140,11 @@ RevSuit
|
||||
|
||||
如上一节的图片里所展示的,RevSuit 支持多个客户端,每个在**连接状态**的客户端都会接收到 `flag` 的推送,因此分布式扫描也是支持的。
|
||||
|
||||
如果你不希望每个客户端都收到全部的 `flag` 推送,你可以在创建 sse 连接时,使用 `Flag-Filter` 请求头设置希望该客户端接受的 `flag` 的格式(支持正则表达式),例如:
|
||||
|
||||

|
||||
|
||||
|
||||
#### 暂存队列
|
||||
|
||||
当没有客户端连接的时候,RevSuit 会把 `flag` 暂时存储到队列里,当有客户端连接的时候再进行推送。因此你不必担心因为客户端与 RevSuit 断开连接就错过漏洞。(这对发现延时触发的漏洞尤为有帮助)
|
||||
@@ -225,4 +230,4 @@ payload,最后被扫描器发出的请求是:`['https://www.testvuln.com?url
|
||||
|
||||
## 开源许可协议
|
||||
|
||||
@Apache License 2.0
|
||||
@Apache License 2.0
|
||||
|
||||
@@ -2,7 +2,7 @@ import axios from 'axios'
|
||||
import {store} from "@/main";
|
||||
|
||||
const service = axios.create({
|
||||
baseURL: location.pathname.slice(0, -'/admin/'.length) + "/api", // api的base_url
|
||||
baseURL: "../api", // api的base_url
|
||||
timeout: 5000, // request timeout
|
||||
validateStatus: function (status) {
|
||||
if (status === 403) {
|
||||
@@ -12,4 +12,4 @@ const service = axios.create({
|
||||
}
|
||||
})
|
||||
|
||||
export default service
|
||||
export default service
|
||||
|
||||
@@ -82,6 +82,15 @@ const columns = [
|
||||
filterIcon: 'filterIcon',
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'VALUE',
|
||||
dataIndex: 'value',
|
||||
key: 'value',
|
||||
scopedSlots: {
|
||||
filterDropdown: 'filterDropdown',
|
||||
filterIcon: 'filterIcon',
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'REMOTE IP',
|
||||
key: 'remote_ip',
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
<a-tag
|
||||
v-if="file"
|
||||
color="#f5222d"
|
||||
><a target="_blank" :href="'/revsuit/api/file/ftp/'+file.id">TRUE</a> </a-tag>
|
||||
><a target="_blank" :href="'../api/file/ftp/'+file.id">TRUE</a> </a-tag>
|
||||
<a-tag v-else color="#722ed1">
|
||||
FALSE
|
||||
</a-tag>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
>
|
||||
<div v-if="record.files.length" slot="expandedRowRender" slot-scope="record" style="margin: 0">
|
||||
<b v-if="record.files.length" style="color: gray">FILES:</b><br>
|
||||
<a v-for="file in record.files" :key="file.name+record.id" :href="'/revsuit/api/file/mysql/'+file.id"
|
||||
<a v-for="file in record.files" :key="file.name+record.id" :href="'../api/file/mysql/'+file.id"
|
||||
target="_blank">{{ file.name }} </a>
|
||||
</div>
|
||||
<div slot="selectDropdown"
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
<a-space size="middle">
|
||||
<a-upload
|
||||
name="rules"
|
||||
action="/revsuit/api/setting/importRules"
|
||||
action="../api/setting/importRules"
|
||||
@change="handleChange"
|
||||
:showUploadList="false"
|
||||
>
|
||||
<a-button type="primary" icon="upload">Import</a-button>
|
||||
</a-upload>
|
||||
<a-button type="primary" icon="download" onclick="window.open('/revsuit/api/setting/exportRules')">Export
|
||||
<a-button type="primary" icon="download" onclick="window.open('../api/setting/exportRules')">Export
|
||||
</a-button>
|
||||
</a-space>
|
||||
<a-result v-if="status"
|
||||
|
||||
@@ -10,15 +10,12 @@ module.exports = {
|
||||
devServer: {
|
||||
proxy: {
|
||||
'/api': {
|
||||
target: 'http://localhost:10000',
|
||||
pathRewrite: {
|
||||
'^/api': '/revsuit/api'
|
||||
}
|
||||
target: 'http://127.0.0.1:10000/revsuit/',
|
||||
}
|
||||
},
|
||||
},
|
||||
productionSourceMap: false,
|
||||
runtimeCompiler: true,
|
||||
filenameHashing: false,
|
||||
publicPath: '/revsuit/admin/',
|
||||
publicPath: '',
|
||||
}
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 894 KiB |
+16
-12
@@ -126,7 +126,7 @@ func (s *Server) newZone(name string) *newdns.Zone {
|
||||
"ns2.hostmaster.com.",
|
||||
"ns3.hostmaster.com.",
|
||||
},
|
||||
Handler: func(lookedName, remoteAddr string) ([]newdns.Set, error) {
|
||||
Handler: func(lookedName, remoteAddr string) (set []newdns.Set, err error) {
|
||||
ip := strings.Split(remoteAddr, ":")[0]
|
||||
|
||||
for _, _rule := range s.getRules() {
|
||||
@@ -135,12 +135,24 @@ func (s *Server) newZone(name string) *newdns.Zone {
|
||||
continue
|
||||
}
|
||||
|
||||
r, err := newRecord(_rule, flag, domain, ip, ipinfo.Area(ip))
|
||||
if _rule.Value != "" {
|
||||
_type := _rule.Type
|
||||
if _rule.Type == newdns.REBINDING {
|
||||
_type = newdns.A
|
||||
}
|
||||
set = newSet(_rule, name, rule.CompileTpl(_rule.Value, vars), ip, _type)
|
||||
}
|
||||
|
||||
var value string
|
||||
if len(set) > 0 && len(set[0].Records) > 0 {
|
||||
value = set[0].Records[0].Address
|
||||
}
|
||||
r, err := newRecord(_rule, flag, domain, value, ip, ipinfo.Area(ip))
|
||||
if err != nil {
|
||||
log.Warn("DNS record(rule_id:%s) created failed :%s", _rule.Name, err)
|
||||
return nil, nil
|
||||
}
|
||||
log.Info("DNS record[id:%d rule:%s remote_ip:%s] has been created", r.ID, _rule.Name, ip)
|
||||
log.Info("DNS record[id:%d rule:%s remote_ip:%s, value:%s] has been created", r.ID, _rule.Name, ip, value)
|
||||
|
||||
//only send to client or notify user when this connection recorded first time.
|
||||
var count int64
|
||||
@@ -168,15 +180,7 @@ func (s *Server) newZone(name string) *newdns.Zone {
|
||||
}()
|
||||
}
|
||||
}
|
||||
if _rule.Value != "" {
|
||||
value := rule.CompileTpl(_rule.Value, vars)
|
||||
_type := _rule.Type
|
||||
if _rule.Type == newdns.REBINDING {
|
||||
_type = newdns.A
|
||||
}
|
||||
|
||||
return newSet(_rule, name, value, ip, _type), nil
|
||||
}
|
||||
return set, err
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
|
||||
+6
-1
@@ -17,6 +17,7 @@ var _ record.Record = (*Record)(nil)
|
||||
|
||||
type Record struct {
|
||||
Domain string `gorm:"index" form:"domain" json:"domain"`
|
||||
Value string `form:"value" json:"value"`
|
||||
|
||||
record.BaseRecord
|
||||
Rule Rule `gorm:"foreignKey:RuleName;references:Name;constraint:OnUpdate:CASCADE,OnDelete:SET NULL;" form:"-" json:"-" notice:"-"`
|
||||
@@ -30,7 +31,7 @@ func (r Record) Notice() {
|
||||
notice.Notice(r)
|
||||
}
|
||||
|
||||
func newRecord(rule *Rule, flag, domain, remoteIp, ipArea string) (r *Record, err error) {
|
||||
func newRecord(rule *Rule, flag, domain, value, remoteIp, ipArea string) (r *Record, err error) {
|
||||
r = &Record{
|
||||
BaseRecord: record.BaseRecord{
|
||||
Flag: flag,
|
||||
@@ -39,6 +40,7 @@ func newRecord(rule *Rule, flag, domain, remoteIp, ipArea string) (r *Record, er
|
||||
RequestTime: time.Now(),
|
||||
},
|
||||
Domain: domain,
|
||||
Value: value,
|
||||
Rule: *rule,
|
||||
}
|
||||
|
||||
@@ -89,6 +91,9 @@ func Records(c *gin.Context) {
|
||||
if dnsRecord.RuleName != "" {
|
||||
db.Where("rule_name = ?", dnsRecord.RuleName)
|
||||
}
|
||||
if dnsRecord.Value != "" {
|
||||
db.Where("address= ?", dnsRecord.Value)
|
||||
}
|
||||
|
||||
//Delete records
|
||||
if c.Request.Method == http.MethodDelete {
|
||||
|
||||
+21
-2
@@ -1,8 +1,10 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"sync"
|
||||
|
||||
"github.com/gin-contrib/sse"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/li4n0/revsuit/internal/database"
|
||||
"github.com/li4n0/revsuit/internal/file"
|
||||
@@ -44,6 +46,8 @@ func (revsuit *Revsuit) addClient(c *gin.Context) int {
|
||||
|
||||
revsuit.clientID++
|
||||
revsuit.clients[revsuit.clientID] = c
|
||||
sse.Event{}.WriteContentType(c.Writer)
|
||||
c.Writer.Flush()
|
||||
revsuit.clientsNum <- struct{}{}
|
||||
return revsuit.clientID
|
||||
}
|
||||
@@ -231,8 +235,23 @@ func (revsuit *Revsuit) Run() {
|
||||
<-revsuit.clientsNum
|
||||
revsuit.clientsLock.RLock()
|
||||
for _, client := range revsuit.clients {
|
||||
client.SSEvent("message", r.GetFlag())
|
||||
client.Writer.Flush()
|
||||
pushIt := false
|
||||
flag := client.Request.Header.Get("Flag-Filter")
|
||||
if len(flag) == 0 || flag == "*" {
|
||||
pushIt = true
|
||||
} else {
|
||||
if catcher, err := regexp.Compile(flag); err != nil {
|
||||
log.Warn("%s[sse flag:%s]", err, flag)
|
||||
continue
|
||||
} else {
|
||||
matched := catcher.FindStringSubmatch(r.GetFlag())
|
||||
pushIt = len(matched) > 0
|
||||
}
|
||||
}
|
||||
if pushIt {
|
||||
client.SSEvent("message", r.GetFlag())
|
||||
client.Writer.Flush()
|
||||
}
|
||||
}
|
||||
revsuit.clientsNum <- struct{}{}
|
||||
revsuit.clientsLock.RUnlock()
|
||||
|
||||
Reference in New Issue
Block a user