refactor: 完成全局状态到 session 的完整迁移

将 plugins/services、plugins/local、plugins/web、webscan 层的日志输出、
漏洞结果保存和 TCP 计数器从全局 common.Log*/GetGlobalState() 迁移到
session 实例方法,确保 SDK 并发扫描时各实例完全隔离。

- 50 个文件,所有插件日志走 session.Log*
- DoRequest 加入 session 参数,计数器走 session.State
- POC 执行器通过 POCContext.Session 传递
- 仅保留 init() 和 CEL runtime 等无 session 场景的全局回退
This commit is contained in:
ZacharyZcR
2026-06-01 08:13:23 +08:00
parent 569d21a8bc
commit d6d323854a
50 changed files with 256 additions and 225 deletions
+2 -2
View File
@@ -55,7 +55,7 @@ func (p *ActiveMQPlugin) Scan(ctx context.Context, info *common.HostInfo, sessio
result := TestCredentialsConcurrently(ctx, credentials, authFn, "activemq", testConfig)
if result.Success {
common.LogVuln(i18n.Tr("activemq_credential", target, result.Username, result.Password))
session.LogVuln(i18n.Tr("activemq_credential", target, result.Username, result.Password))
}
return result
@@ -254,7 +254,7 @@ func (p *ActiveMQPlugin) identifyService(ctx context.Context, info *common.HostI
}
}
common.LogSuccess(i18n.Tr("activemq_service", target, banner))
session.LogSuccess(i18n.Tr("activemq_service", target, banner))
return &ScanResult{
Success: true,
+12 -8
View File
@@ -32,11 +32,11 @@ func (p *CassandraPlugin) Scan(ctx context.Context, info *common.HostInfo, sessi
target := info.Target()
if config.DisableBrute {
return p.identifyService(ctx, info, config, state)
return p.identifyService(ctx, info, session)
}
// 先尝试无认证连接
if result := p.tryNoAuthConnection(ctx, info, config, state); result != nil && result.Success {
if result := p.tryNoAuthConnection(ctx, info, session); result != nil && result.Success {
return result
}
@@ -55,7 +55,7 @@ func (p *CassandraPlugin) Scan(ctx context.Context, info *common.HostInfo, sessi
result := TestCredentialsConcurrently(ctx, credentials, authFn, "cassandra", testConfig)
if result.Success {
common.LogVuln(i18n.Tr("cassandra_credential", target, result.Username, result.Password))
session.LogVuln(i18n.Tr("cassandra_credential", target, result.Username, result.Password))
}
return result
@@ -249,7 +249,9 @@ func classifyCassandraErrorType(err error) ErrorType {
// ── 无认证 + 服务识别 ──────────────────────────────────────────
func (p *CassandraPlugin) tryNoAuthConnection(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult {
func (p *CassandraPlugin) tryNoAuthConnection(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult {
config := session.Config
state := session.State
target := info.Target()
addr := info.Target()
timeout := config.Timeout
@@ -286,7 +288,7 @@ func (p *CassandraPlugin) tryNoAuthConnection(ctx context.Context, info *common.
state.IncrementTCPSuccessPacketCount()
dummy := extractClusterName(body)
common.LogVuln(i18n.Tr("cassandra_unauth", target))
session.LogVuln(i18n.Tr("cassandra_unauth", target))
return &ScanResult{
Type: plugins.ResultTypeService,
Success: true,
@@ -295,7 +297,9 @@ func (p *CassandraPlugin) tryNoAuthConnection(ctx context.Context, info *common.
}
}
func (p *CassandraPlugin) identifyService(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult {
func (p *CassandraPlugin) identifyService(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult {
config := session.Config
state := session.State
target := info.Target()
addr := info.Target()
timeout := config.Timeout
@@ -323,12 +327,12 @@ func (p *CassandraPlugin) identifyService(ctx context.Context, info *common.Host
if opcode == cqlOpAuthChl {
banner := i18n.GetText("cassandra_auth_required")
common.LogSuccess(i18n.Tr("cassandra_service", target, banner))
session.LogSuccess(i18n.Tr("cassandra_service", target, banner))
return &ScanResult{Type: plugins.ResultTypeService, Success: true, Service: "cassandra", Banner: banner}
}
banner := "Cassandra"
common.LogSuccess(i18n.Tr("cassandra_service", target, banner))
session.LogSuccess(i18n.Tr("cassandra_service", target, banner))
return &ScanResult{Type: plugins.ResultTypeService, Success: true, Service: "cassandra", Banner: banner}
}
+3 -3
View File
@@ -35,7 +35,7 @@ func (p *ElasticsearchPlugin) Scan(ctx context.Context, info *common.HostInfo, s
// 首先检测未授权访问
if p.testCredential(ctx, info, Credential{Username: "", Password: ""}, session) {
common.LogVuln(i18n.Tr("elasticsearch_unauth", target))
session.LogVuln(i18n.Tr("elasticsearch_unauth", target))
return &ScanResult{
Success: true,
Type: plugins.ResultTypeVuln,
@@ -56,7 +56,7 @@ func (p *ElasticsearchPlugin) Scan(ctx context.Context, info *common.HostInfo, s
for _, cred := range credentials {
if p.testCredential(ctx, info, cred, session) {
common.LogVuln(i18n.Tr("elasticsearch_credential", target, cred.Username, cred.Password))
session.LogVuln(i18n.Tr("elasticsearch_credential", target, cred.Username, cred.Password))
return &ScanResult{
Success: true,
Type: plugins.ResultTypeCredential,
@@ -124,7 +124,7 @@ func (p *ElasticsearchPlugin) identifyService(ctx context.Context, info *common.
if p.testCredential(ctx, info, Credential{Username: "", Password: ""}, session) {
banner := "Elasticsearch"
common.LogSuccess(i18n.Tr("elasticsearch_service", target, banner))
session.LogSuccess(i18n.Tr("elasticsearch_service", target, banner))
return &ScanResult{
Success: true,
Type: plugins.ResultTypeService,
+1 -1
View File
@@ -86,7 +86,7 @@ func (p *FindNetPlugin) Scan(ctx context.Context, info *common.HostInfo, session
}
// 一次性输出所有行
if len(lines) > 0 {
common.LogSuccess(strings.Join(lines, "\n"))
session.LogSuccess(strings.Join(lines, "\n"))
}
}
+7 -5
View File
@@ -30,7 +30,7 @@ func (p *KafkaPlugin) Scan(ctx context.Context, info *common.HostInfo, session *
config := session.Config
state := session.State
if config.DisableBrute {
return p.identifyService(ctx, info, config, state)
return p.identifyService(ctx, info, session)
}
target := info.Target()
@@ -50,7 +50,7 @@ func (p *KafkaPlugin) Scan(ctx context.Context, info *common.HostInfo, session *
result := TestCredentialsConcurrently(ctx, credentials, authFn, "kafka", testConfig)
if result.Success {
common.LogVuln(i18n.Tr("kafka_credential", target, result.Username, result.Password))
session.LogVuln(i18n.Tr("kafka_credential", target, result.Username, result.Password))
}
return result
@@ -229,7 +229,9 @@ func classifyKafkaErrorType(err error) ErrorType {
// ── 服务识别 ────────────────────────────────────────────────────
func (p *KafkaPlugin) identifyService(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult {
func (p *KafkaPlugin) identifyService(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult {
config := session.Config
state := session.State
target := info.Target()
timeout := config.Timeout
@@ -255,7 +257,7 @@ func (p *KafkaPlugin) identifyService(ctx context.Context, info *common.HostInfo
state.IncrementTCPFailedPacketCount()
if p.isKafkaError(err) {
banner := i18n.GetText("kafka_auth_required")
common.LogSuccess(i18n.Tr("kafka_service", target, banner))
session.LogSuccess(i18n.Tr("kafka_service", target, banner))
return &ScanResult{Type: plugins.ResultTypeService, Success: true, Service: "kafka", Banner: banner}
}
return &ScanResult{Success: false, Service: "kafka", Error: fmt.Errorf("%s", i18n.Tr("service_not_identified", "Kafka"))}
@@ -263,7 +265,7 @@ func (p *KafkaPlugin) identifyService(ctx context.Context, info *common.HostInfo
state.IncrementTCPSuccessPacketCount()
banner := "Kafka"
common.LogSuccess(i18n.Tr("kafka_service", target, banner))
session.LogSuccess(i18n.Tr("kafka_service", target, banner))
return &ScanResult{Type: plugins.ResultTypeService, Success: true, Service: "kafka", Banner: banner}
}
+3 -3
View File
@@ -55,7 +55,7 @@ func (p *LDAPPlugin) Scan(ctx context.Context, info *common.HostInfo, session *c
result := TestCredentialsConcurrently(ctx, credentials, authFn, "ldap", testConfig)
if result.Success {
common.LogVuln(i18n.Tr("ldap_credential", target, result.Username, result.Password))
session.LogVuln(i18n.Tr("ldap_credential", target, result.Username, result.Password))
}
return result
@@ -146,7 +146,7 @@ func (p *LDAPPlugin) tryHashAuth(ctx context.Context, info *common.HostInfo, ses
if len(hash) > 16 {
displayHash = hash[:16] + "..."
}
common.LogVuln(i18n.Tr("ldap_hash_credential", target, domain, user, displayHash))
session.LogVuln(i18n.Tr("ldap_hash_credential", target, domain, user, displayHash))
return &ScanResult{
Type: plugins.ResultTypeVuln,
Success: true,
@@ -268,7 +268,7 @@ func (p *LDAPPlugin) identifyService(ctx context.Context, info *common.HostInfo,
defer func() { _ = conn.Close() }()
banner := "LDAP"
common.LogSuccess(i18n.Tr("ldap_service", target, banner))
session.LogSuccess(i18n.Tr("ldap_service", target, banner))
return &ScanResult{
Type: plugins.ResultTypeService,
+2 -2
View File
@@ -34,7 +34,7 @@ func (p *MemcachedPlugin) Scan(ctx context.Context, info *common.HostInfo, sessi
// 检测未授权访问
if result := p.testUnauthorizedAccess(ctx, info, session); result != nil && result.Success {
common.LogVuln(i18n.Tr("memcached_unauth", target))
session.LogVuln(i18n.Tr("memcached_unauth", target))
return result
}
@@ -128,7 +128,7 @@ func (p *MemcachedPlugin) identifyService(ctx context.Context, info *common.Host
if p.testBasicCommand(conn, session.Config) {
banner := "Memcached"
common.LogSuccess(i18n.Tr("memcached_service", target, banner))
session.LogSuccess(i18n.Tr("memcached_service", target, banner))
return &ScanResult{
Type: plugins.ResultTypeService,
Success: true,
+4 -4
View File
@@ -44,7 +44,7 @@ func (p *MongoDBPlugin) Scan(ctx context.Context, info *common.HostInfo, session
}
if isUnauth {
common.LogVuln(i18n.Tr("mongodb_unauth", target))
session.LogVuln(i18n.Tr("mongodb_unauth", target))
return &ScanResult{
Type: plugins.ResultTypeVuln,
Success: true,
@@ -68,7 +68,7 @@ func (p *MongoDBPlugin) Scan(ctx context.Context, info *common.HostInfo, session
result := TestCredentialsConcurrently(ctx, credentials, authFn, "mongodb", testConfig)
if result.Success {
common.LogVuln(i18n.Tr("mongodb_credential", target, result.Username, result.Password))
session.LogVuln(i18n.Tr("mongodb_credential", target, result.Username, result.Password))
}
return result
@@ -375,11 +375,11 @@ func (p *MongoDBPlugin) identifyService(ctx context.Context, info *common.HostIn
}
if isUnauth {
common.LogVuln(i18n.Tr("mongodb_unauth", target))
session.LogVuln(i18n.Tr("mongodb_unauth", target))
return &ScanResult{Type: plugins.ResultTypeVuln, Success: true, Service: "mongodb", VulInfo: i18n.GetText("unauthorized_access")}
}
common.LogSuccess(i18n.Tr("mongodb_auth_required", target))
session.LogSuccess(i18n.Tr("mongodb_auth_required", target))
return &ScanResult{Type: plugins.ResultTypeService, Success: true, Service: "mongodb", Banner: i18n.GetText("auth_required")}
}
+5 -5
View File
@@ -62,9 +62,9 @@ func (p *MS17010Plugin) Scan(ctx context.Context, info *common.HostInfo, session
if osVersion != "" {
msg += fmt.Sprintf(" [%s]", osVersion)
}
common.LogVuln(msg)
session.LogVuln(msg)
if hasBackdoor {
common.LogVuln(fmt.Sprintf("MS17-010 %s has DOUBLEPULSAR SMB IMPLANT", target))
session.LogVuln(fmt.Sprintf("MS17-010 %s has DOUBLEPULSAR SMB IMPLANT", target))
}
return &ScanResult{
@@ -86,7 +86,7 @@ func (p *MS17010Plugin) Scan(ctx context.Context, info *common.HostInfo, session
func (p *MS17010Plugin) Exploit(ctx context.Context, info *common.HostInfo, creds Credential, session *common.ScanSession) *ExploitResult {
config := session.Config
target := info.Target()
common.LogSuccess(i18n.Tr("ms17010_start", target))
session.LogSuccess(i18n.Tr("ms17010_start", target))
var output strings.Builder
output.WriteString(i18n.Tr("ms17010_exploit_header", target) + "\n")
@@ -157,7 +157,7 @@ func (p *MS17010Plugin) Exploit(ctx context.Context, info *common.HostInfo, cred
output.WriteString(i18n.GetText("ms17010_exploit_supported_modes") + "\n")
}
common.LogSuccess(i18n.Tr("ms17010_complete", target))
session.LogSuccess(i18n.Tr("ms17010_complete", target))
return &ExploitResult{
Success: true,
@@ -473,7 +473,7 @@ func (p *MS17010Plugin) executeMS17010Exploit(info *common.HostInfo, session *co
return fmt.Errorf("MS17-010 exp failed: %w", err)
}
common.LogSuccess(i18n.Tr("ms17010_shellcode_complete", info.Host, len(scBytes)))
session.LogSuccess(i18n.Tr("ms17010_shellcode_complete", info.Host, len(scBytes)))
return nil
}
+6 -4
View File
@@ -27,7 +27,7 @@ func (p *MSSQLPlugin) Scan(ctx context.Context, info *common.HostInfo, session *
config := session.Config
state := session.State
if config.DisableBrute {
return p.identifyService(ctx, info, config, state)
return p.identifyService(ctx, info, session)
}
target := info.Target()
@@ -48,7 +48,7 @@ func (p *MSSQLPlugin) Scan(ctx context.Context, info *common.HostInfo, session *
result := TestCredentialsConcurrently(ctx, credentials, authFn, "mssql", testConfig)
if result.Success {
common.LogVuln(i18n.Tr("mssql_credential", target, result.Username, result.Password))
session.LogVuln(i18n.Tr("mssql_credential", target, result.Username, result.Password))
}
return result
@@ -124,7 +124,9 @@ func classifyMSSQLErrorType(err error) ErrorType {
return ClassifyError(err, mssqlAuthErrors, mssqlNetworkErrors)
}
func (p *MSSQLPlugin) identifyService(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult {
func (p *MSSQLPlugin) identifyService(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult {
config := session.Config
state := session.State
target := info.Target()
identifyCtx, cancel := context.WithTimeout(ctx, config.Timeout)
@@ -157,7 +159,7 @@ func (p *MSSQLPlugin) identifyService(ctx context.Context, info *common.HostInfo
}
}
common.LogSuccess(i18n.Tr("mssql_service", target, banner))
session.LogSuccess(i18n.Tr("mssql_service", target, banner))
return &ScanResult{
Type: plugins.ResultTypeService,
+2 -2
View File
@@ -62,7 +62,7 @@ func (p *MySQLPlugin) Scan(ctx context.Context, info *common.HostInfo, session *
result := TestCredentialsConcurrently(ctx, credentials, authFn, "mysql", testConfig)
if result.Success {
common.LogVuln(i18n.Tr("mysql_credential", target, result.Username, result.Password))
session.LogVuln(i18n.Tr("mysql_credential", target, result.Username, result.Password))
}
return result
@@ -154,7 +154,7 @@ func (p *MySQLPlugin) identifyService(ctx context.Context, info *common.HostInfo
defer func() { _ = conn.Close() }()
if banner := p.readMySQLBanner(conn, session.Config); banner != "" {
common.LogSuccess(i18n.Tr("mysql_service", target, banner))
session.LogSuccess(i18n.Tr("mysql_service", target, banner))
return &ScanResult{
Type: plugins.ResultTypeService,
Success: true,
+3 -3
View File
@@ -35,7 +35,7 @@ func (p *Neo4jPlugin) Scan(ctx context.Context, info *common.HostInfo, session *
// 先测试未授权访问
if result := p.testUnauthorizedAccess(ctx, info, session); result != nil && result.Success {
common.LogVuln(i18n.Tr("neo4j_unauth", target))
session.LogVuln(i18n.Tr("neo4j_unauth", target))
return result
}
@@ -55,7 +55,7 @@ func (p *Neo4jPlugin) Scan(ctx context.Context, info *common.HostInfo, session *
result := TestCredentialsConcurrently(ctx, credentials, authFn, "neo4j", testConfig)
if result.Success {
common.LogVuln(i18n.Tr("neo4j_credential", target, result.Username, result.Password))
session.LogVuln(i18n.Tr("neo4j_credential", target, result.Username, result.Password))
}
return result
@@ -246,7 +246,7 @@ func (p *Neo4jPlugin) identifyService(ctx context.Context, info *common.HostInfo
}
}
common.LogSuccess(i18n.Tr("neo4j_service", target, banner))
session.LogSuccess(i18n.Tr("neo4j_service", target, banner))
return &ScanResult{
Type: plugins.ResultTypeService,
+1 -1
View File
@@ -76,7 +76,7 @@ func (p *NetBIOSPlugin) Scan(ctx context.Context, info *common.HostInfo, session
if netbiosInfo.Summary() != "" {
msg += fmt.Sprintf(" %s", netbiosInfo.Summary())
}
common.LogSuccess(msg)
session.LogSuccess(msg)
return &ScanResult{
Success: true,
+8 -6
View File
@@ -32,8 +32,8 @@ func (p *OraclePlugin) Scan(ctx context.Context, info *common.HostInfo, session
}
// 先测试未授权访问
if result := p.testUnauthorizedAccess(ctx, info, config, state); result != nil && result.Success {
common.LogSuccess(i18n.Tr("oracle_service", target, result.Banner))
if result := p.testUnauthorizedAccess(ctx, info, session); result != nil && result.Success {
session.LogSuccess(i18n.Tr("oracle_service", target, result.Banner))
return result
}
@@ -53,7 +53,7 @@ func (p *OraclePlugin) Scan(ctx context.Context, info *common.HostInfo, session
result := TestCredentialsConcurrently(ctx, credentials, authFn, "oracle", testConfig)
if result.Success {
common.LogVuln(i18n.Tr("oracle_credential", target, result.Username, result.Password))
session.LogVuln(i18n.Tr("oracle_credential", target, result.Username, result.Password))
}
return result
@@ -133,7 +133,9 @@ func classifyOracleErrorType(err error) ErrorType {
}
// testUnauthorizedAccess 测试Oracle未授权访问
func (p *OraclePlugin) testUnauthorizedAccess(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult {
func (p *OraclePlugin) testUnauthorizedAccess(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult {
config := session.Config
state := session.State
target := info.Target()
defaultAccounts := []Credential{
@@ -148,7 +150,7 @@ func (p *OraclePlugin) testUnauthorizedAccess(ctx context.Context, info *common.
if result.Conn != nil {
_ = result.Conn.Close()
}
common.LogVuln(i18n.Tr("oracle_default_account", target, cred.Username, cred.Password))
session.LogVuln(i18n.Tr("oracle_default_account", target, cred.Username, cred.Password))
return &ScanResult{
Type: plugins.ResultTypeVuln,
Success: true,
@@ -177,7 +179,7 @@ func (p *OraclePlugin) identifyService(ctx context.Context, info *common.HostInf
_ = conn.Close()
banner := "Oracle"
common.LogSuccess(i18n.Tr("oracle_service", target, banner))
session.LogSuccess(i18n.Tr("oracle_service", target, banner))
return &ScanResult{
Type: plugins.ResultTypeService,
+7 -5
View File
@@ -33,12 +33,12 @@ func (p *PostgreSQLPlugin) Scan(ctx context.Context, info *common.HostInfo, sess
target := info.Target()
if config.DisableBrute {
return p.identifyService(ctx, info, config, state)
return p.identifyService(ctx, info, session)
}
// 先测试未授权访问
if result := p.testUnauthorizedAccess(ctx, info, config, state); result != nil && result.Success {
common.LogVuln(i18n.Tr("postgresql_vuln", target, result.VulInfo))
session.LogVuln(i18n.Tr("postgresql_vuln", target, result.VulInfo))
return result
}
@@ -58,7 +58,7 @@ func (p *PostgreSQLPlugin) Scan(ctx context.Context, info *common.HostInfo, sess
result := TestCredentialsConcurrently(ctx, credentials, authFn, "postgresql", testConfig)
if result.Success {
common.LogVuln(i18n.Tr("postgresql_credential", target, result.Username, result.Password))
session.LogVuln(i18n.Tr("postgresql_credential", target, result.Username, result.Password))
}
return result
@@ -219,7 +219,9 @@ func (p *PostgreSQLPlugin) testUnauthorizedAccess(ctx context.Context, info *com
}
}
func (p *PostgreSQLPlugin) identifyService(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult {
func (p *PostgreSQLPlugin) identifyService(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult {
config := session.Config
state := session.State
target := info.Target()
connStr := postgreSQLConnString("invalid", "invalid", info, int64(config.Timeout.Seconds()))
@@ -267,7 +269,7 @@ func (p *PostgreSQLPlugin) identifyService(ctx context.Context, info *common.Hos
banner = "PostgreSQL"
}
common.LogSuccess(i18n.Tr("postgresql_service", target, banner))
session.LogSuccess(i18n.Tr("postgresql_service", target, banner))
return &ScanResult{
Type: plugins.ResultTypeService,
+4 -4
View File
@@ -38,7 +38,7 @@ func (p *RabbitMQPlugin) Scan(ctx context.Context, info *common.HostInfo, sessio
// 先检测未授权访问
if result := p.testUnauthorizedAccess(ctx, info, session); result != nil && result.Success {
common.LogSuccess(i18n.Tr("rabbitmq_service", target, result.Banner))
session.LogSuccess(i18n.Tr("rabbitmq_service", target, result.Banner))
return result
}
@@ -58,7 +58,7 @@ func (p *RabbitMQPlugin) Scan(ctx context.Context, info *common.HostInfo, sessio
result := TestCredentialsConcurrently(ctx, credentials, authFn, "rabbitmq", testConfig)
if result.Success {
common.LogVuln(i18n.Tr("rabbitmq_credential", target, result.Username, result.Password))
session.LogVuln(i18n.Tr("rabbitmq_credential", target, result.Username, result.Password))
}
return result
@@ -236,7 +236,7 @@ func (p *RabbitMQPlugin) testAMQPProtocol(ctx context.Context, info *common.Host
if string(buffer[:4]) == "AMQP" || (n >= 8 && buffer[0] == 0x01) {
banner := "RabbitMQ AMQP"
common.LogSuccess(i18n.Tr("rabbitmq_service", target, banner))
session.LogSuccess(i18n.Tr("rabbitmq_service", target, banner))
return &ScanResult{
Type: plugins.ResultTypeService,
Success: true,
@@ -297,7 +297,7 @@ func (p *RabbitMQPlugin) testManagementInterface(ctx context.Context, info *comm
}
if strings.Contains(strings.ToLower(string(body)), "rabbitmq") {
banner := "RabbitMQ Management"
common.LogSuccess(i18n.Tr("rabbitmq_detected", target, banner))
session.LogSuccess(i18n.Tr("rabbitmq_detected", target, banner))
return &ScanResult{
Type: plugins.ResultTypeService,
Success: true,
+6 -6
View File
@@ -56,7 +56,7 @@ func (p *RDPPlugin) Scan(ctx context.Context, info *common.HostInfo, session *co
if !isSingleCredentialTest {
osInfo = p.probeOSInfo(target, config, state)
if len(osInfo) > 0 {
p.logOSInfo(target, osInfo)
p.logOSInfo(target, osInfo, session)
}
}
@@ -68,11 +68,11 @@ func (p *RDPPlugin) Scan(ctx context.Context, info *common.HostInfo, session *co
if osInfo == nil {
osInfo = p.probeOSInfo(target, config, state)
if len(osInfo) > 0 {
p.logOSInfo(target, osInfo)
p.logOSInfo(target, osInfo, session)
}
}
banner := p.buildBanner(osInfo)
common.LogSuccess(i18n.Tr("rdp_service", target, banner))
session.LogSuccess(i18n.Tr("rdp_service", target, banner))
return &ScanResult{
Success: true,
Type: plugins.ResultTypeService,
@@ -126,7 +126,7 @@ func (p *RDPPlugin) Scan(ctx context.Context, info *common.HostInfo, session *co
}
result := fmt.Sprintf("RDP %s %s\\%s %s", target, displayDomain, cred.Username, cred.Password)
common.LogVuln(result)
session.LogVuln(result)
return &ScanResult{
Success: true,
@@ -197,7 +197,7 @@ func (p *RDPPlugin) probeOSInfo(host string, config *common.Config, state *commo
}
// logOSInfo 输出系统信息
func (p *RDPPlugin) logOSInfo(target string, osInfo map[string]any) {
func (p *RDPPlugin) logOSInfo(target string, osInfo map[string]any, session *common.ScanSession) {
var parts []string
// 提取关键信息
@@ -235,7 +235,7 @@ func (p *RDPPlugin) logOSInfo(target string, osInfo map[string]any) {
if len(parts) > 0 {
info := fmt.Sprintf("RDP %s [%s]", target, strings.Join(parts, ", "))
common.LogSuccess(info)
session.LogSuccess(info)
}
}
+17 -17
View File
@@ -42,7 +42,7 @@ func (p *RedisPlugin) Scan(ctx context.Context, info *common.HostInfo, session *
// 首先检查未授权访问
if result := p.testUnauthorizedAccess(ctx, info, session); result != nil && result.Success {
common.LogVuln(i18n.Tr("redis_unauth_success", target)) //nolint:govet
session.LogVuln(i18n.Tr("redis_unauth_success", target)) //nolint:govet
// 如果需要利用,重新建立连接执行
if p.shouldExploit(config) {
@@ -63,7 +63,7 @@ func (p *RedisPlugin) Scan(ctx context.Context, info *common.HostInfo, session *
// 如果成功,记录并执行利用
if result.Success {
common.LogVuln(i18n.Tr("redis_scan_success", target, result.Password)) //nolint:govet
session.LogVuln(i18n.Tr("redis_scan_success", target, result.Password)) //nolint:govet
// 如果需要利用,重新建立连接执行
if p.shouldExploit(config) {
@@ -225,7 +225,7 @@ func (p *RedisPlugin) exploitWithPassword(ctx context.Context, info *common.Host
conn, err := session.DialTCP(ctx, "tcp", target, session.Config.Timeout)
if err != nil {
common.LogError(i18n.Tr("redis_reconnect_failed", err))
session.LogError(i18n.Tr("redis_reconnect_failed", err))
return
}
defer func() { _ = conn.Close() }()
@@ -244,7 +244,7 @@ func (p *RedisPlugin) exploitWithPassword(ctx context.Context, info *common.Host
}
}
p.exploit(ctx, info, conn, password, session.Config)
p.exploit(ctx, info, conn, password, session.Config, session)
}
// identifyService 服务识别
@@ -297,7 +297,7 @@ func (p *RedisPlugin) identifyService(ctx context.Context, info *common.HostInfo
banner = i18n.GetText("redis_service_plain")
}
common.LogSuccess(i18n.Tr("redis_service_identified", target, banner)) //nolint:govet
session.LogSuccess(i18n.Tr("redis_service_identified", target, banner)) //nolint:govet
return &ScanResult{
Type: plugins.ResultTypeService,
@@ -321,7 +321,7 @@ func (p *RedisPlugin) shouldExploit(config *common.Config) bool {
}
// exploit 执行Redis漏洞利用
func (p *RedisPlugin) exploit(ctx context.Context, info *common.HostInfo, conn net.Conn, password string, config *common.Config) {
func (p *RedisPlugin) exploit(ctx context.Context, info *common.HostInfo, conn net.Conn, password string, config *common.Config, session *common.ScanSession) {
if config.Redis.Disabled {
return
}
@@ -330,7 +330,7 @@ func (p *RedisPlugin) exploit(ctx context.Context, info *common.HostInfo, conn n
dbfilename, dir, err := p.getConfig(conn)
if err != nil {
common.LogError(i18n.Tr("redis_config_failed", err))
session.LogError(i18n.Tr("redis_config_failed", err))
return
}
@@ -346,9 +346,9 @@ func (p *RedisPlugin) exploit(ctx context.Context, info *common.HostInfo, conn n
fileName := path.Base(config.Redis.WritePath)
if success, _, writeErr := p.writeCustomFile(conn, dirPath, fileName, config.Redis.WriteContent); writeErr != nil {
common.LogError(i18n.Tr("redis_write_failed", writeErr))
session.LogError(i18n.Tr("redis_write_failed", writeErr))
} else if success {
common.LogVuln(i18n.Tr("redis_write_success", config.Redis.WritePath))
session.LogVuln(i18n.Tr("redis_write_success", config.Redis.WritePath))
}
}
@@ -356,15 +356,15 @@ func (p *RedisPlugin) exploit(ctx context.Context, info *common.HostInfo, conn n
if config.Redis.WritePath != "" && config.Redis.WriteFile != "" {
fileContent, readErr := os.ReadFile(config.Redis.WriteFile)
if readErr != nil {
common.LogError(i18n.Tr("redis_read_failed", readErr))
session.LogError(i18n.Tr("redis_read_failed", readErr))
} else {
dirPath := path.Dir(config.Redis.WritePath)
fileName := path.Base(config.Redis.WritePath)
if success, _, writeErr := p.writeCustomFile(conn, dirPath, fileName, string(fileContent)); writeErr != nil {
common.LogError(i18n.Tr("redis_write_failed", writeErr))
session.LogError(i18n.Tr("redis_write_failed", writeErr))
} else if success {
common.LogVuln(i18n.Tr("redis_file_write_success", config.Redis.WriteFile, config.Redis.WritePath))
session.LogVuln(i18n.Tr("redis_file_write_success", config.Redis.WriteFile, config.Redis.WritePath))
}
}
}
@@ -372,24 +372,24 @@ func (p *RedisPlugin) exploit(ctx context.Context, info *common.HostInfo, conn n
// SSH密钥写入
if config.Redis.File != "" {
if success, _, keyErr := p.writeKey(conn, config.Redis.File); keyErr != nil {
common.LogError(i18n.Tr("redis_ssh_key_failed", keyErr))
session.LogError(i18n.Tr("redis_ssh_key_failed", keyErr))
} else if success {
common.LogVuln(i18n.GetText("redis_ssh_key_success"))
session.LogVuln(i18n.GetText("redis_ssh_key_success"))
}
}
// 定时任务写入
if config.Redis.Shell != "" {
if success, _, cronErr := p.writeCron(conn, config.Redis.Shell); cronErr != nil {
common.LogError(i18n.Tr("redis_cron_failed", cronErr))
session.LogError(i18n.Tr("redis_cron_failed", cronErr))
} else if success {
common.LogVuln(i18n.GetText("redis_cron_success"))
session.LogVuln(i18n.GetText("redis_cron_success"))
}
}
// 恢复配置
if err = p.recoverDB(dbfilename, dir, conn); err != nil {
common.LogError(i18n.Tr("redis_restore_failed", err))
session.LogError(i18n.Tr("redis_restore_failed", err))
}
}
+3 -3
View File
@@ -40,7 +40,7 @@ func (p *RsyncPlugin) Scan(ctx context.Context, info *common.HostInfo, session *
// 检测未授权访问
if result := p.testUnauthorizedAccess(ctx, info, session); result != nil && result.Success {
common.LogSuccess(i18n.Tr("rsync_service", target, result.Banner))
session.LogSuccess(i18n.Tr("rsync_service", target, result.Banner))
findings = append(findings, result.Banner)
}
@@ -75,7 +75,7 @@ func (p *RsyncPlugin) Scan(ctx context.Context, info *common.HostInfo, session *
result := TestCredentialsConcurrently(ctx, creds, authFn, "rsync", testConfig)
if result.Success {
common.LogVuln(i18n.Tr("rsync_credential", target, result.Username, result.Password))
session.LogVuln(i18n.Tr("rsync_credential", target, result.Username, result.Password))
return result
}
@@ -390,7 +390,7 @@ func (p *RsyncPlugin) identifyService(ctx context.Context, info *common.HostInfo
}
}
common.LogSuccess(i18n.Tr("rsync_service", target, banner))
session.LogSuccess(i18n.Tr("rsync_service", target, banner))
return &ScanResult{
Success: true,
+7 -7
View File
@@ -49,13 +49,13 @@ func (p *SmbPlugin) Scan(ctx context.Context, info *common.HostInfo, session *co
}
// 输出信息收集结果
p.logSMBInfo(target, smbTarget)
p.logSMBInfo(target, smbTarget, session)
// 2. 漏洞检测 (仅SMBv2+且端口445)
if smbTarget.Protocol == SMBProtocol2 && info.Port == 445 {
if checkSMBGhost(ctx, info.Host, config.Timeout, session) {
smbTarget.Vulnerable = &SMBVuln{CVE20200796: true}
common.LogVuln(i18n.Tr("smbghost_vuln", target))
session.LogVuln(i18n.Tr("smbghost_vuln", target))
}
}
@@ -75,7 +75,7 @@ func (p *SmbPlugin) Scan(ctx context.Context, info *common.HostInfo, session *co
} else {
successMsg = i18n.Tr("smb_unauth_access", target, result.Username, result.Password)
}
common.LogVuln(successMsg)
session.LogVuln(successMsg)
return result
}
@@ -102,7 +102,7 @@ func (p *SmbPlugin) Scan(ctx context.Context, info *common.HostInfo, session *co
} else {
successMsg = fmt.Sprintf("SMB %s %s:%s", target, result.Username, result.Password)
}
common.LogVuln(successMsg)
session.LogVuln(successMsg)
}
return result
@@ -148,7 +148,7 @@ func (p *SmbPlugin) testUnauthorizedAccess(ctx context.Context, info *common.Hos
fmt.Fprintf(&output, "\n%s", share)
}
common.LogSuccess(output.String())
session.LogSuccess(output.String())
return &ScanResult{
Success: true,
@@ -165,7 +165,7 @@ func (p *SmbPlugin) testUnauthorizedAccess(ctx context.Context, info *common.Hos
}
// logSMBInfo 输出SMB信息
func (p *SmbPlugin) logSMBInfo(target string, info *SMBTarget) {
func (p *SmbPlugin) logSMBInfo(target string, info *SMBTarget, session *common.ScanSession) {
msg := fmt.Sprintf("SMBInfo %s", target)
if info.OSVersion != "" {
msg += fmt.Sprintf(" [%s]", info.OSVersion)
@@ -174,7 +174,7 @@ func (p *SmbPlugin) logSMBInfo(target string, info *SMBTarget) {
msg += fmt.Sprintf(" %s", info.ComputerName)
}
msg += fmt.Sprintf(" %s", info.Protocol.String())
common.LogSuccess(msg)
session.LogSuccess(msg)
}
// buildInfoResult 构建信息收集结果
+1 -1
View File
@@ -222,7 +222,7 @@ func probeTarget(ctx context.Context, host string, port int, timeout time.Durati
// 读取SMBv1协商响应
r1, err := readSMBMessage(conn)
if err != nil {
common.LogDebug(i18n.Tr("smbv1_negotiate_read_failed", err))
session.LogDebug(i18n.Tr("smbv1_negotiate_read_failed", err))
}
// 检查是否支持SMBv1
+3 -3
View File
@@ -35,7 +35,7 @@ func (p *SMTPPlugin) Scan(ctx context.Context, info *common.HostInfo, session *c
// 检测未授权访问
if result := p.testUnauthorizedAccess(ctx, info, session); result != nil && result.Success {
common.LogSuccess(i18n.Tr("smtp_service", target, result.Banner))
session.LogSuccess(i18n.Tr("smtp_service", target, result.Banner))
return result
}
@@ -62,7 +62,7 @@ func (p *SMTPPlugin) Scan(ctx context.Context, info *common.HostInfo, session *c
result := TestCredentialsConcurrently(ctx, creds, authFn, "smtp", testConfig)
if result.Success {
common.LogVuln(i18n.Tr("smtp_credential", target, result.Username, result.Password))
session.LogVuln(i18n.Tr("smtp_credential", target, result.Username, result.Password))
}
return result
@@ -536,7 +536,7 @@ func (p *SMTPPlugin) identifyService(ctx context.Context, info *common.HostInfo,
banner = i18n.GetText("smtp_mail_service")
}
common.LogSuccess(i18n.Tr("smtp_service", target, banner))
session.LogSuccess(i18n.Tr("smtp_service", target, banner))
return &ScanResult{
Success: true,
+4 -4
View File
@@ -41,7 +41,7 @@ func (p *SSHPlugin) Scan(ctx context.Context, info *common.HostInfo, session *co
// 如果指定了SSH密钥,优先使用密钥认证
if config.Credentials.SSHKeyPath != "" {
if result := p.scanWithKey(ctx, info, session); result != nil && result.Success {
common.LogVuln(i18n.Tr("ssh_key_auth_success", target, result.Username)) //nolint:govet
session.LogVuln(i18n.Tr("ssh_key_auth_success", target, result.Username)) //nolint:govet
return result
}
}
@@ -71,7 +71,7 @@ func (p *SSHPlugin) Scan(ctx context.Context, info *common.HostInfo, session *co
// 记录成功
if result.Success {
common.LogVuln(i18n.Tr("ssh_pwd_auth_success", target, result.Username, result.Password)) //nolint:govet
session.LogVuln(i18n.Tr("ssh_pwd_auth_success", target, result.Username, result.Password)) //nolint:govet
}
return result
@@ -182,7 +182,7 @@ func (p *SSHPlugin) scanWithKey(ctx context.Context, info *common.HostInfo, sess
config := session.Config
keyData, err := os.ReadFile(config.Credentials.SSHKeyPath)
if err != nil {
common.LogError(i18n.Tr("ssh_key_read_failed", err)) //nolint:govet
session.LogError(i18n.Tr("ssh_key_read_failed", err)) //nolint:govet
return nil
}
@@ -236,7 +236,7 @@ func (p *SSHPlugin) identifyService(ctx context.Context, info *common.HostInfo,
defer func() { _ = conn.Close() }()
if banner := p.readSSHBanner(conn, session.Config); banner != "" {
common.LogSuccess(i18n.Tr("ssh_service_identified", target, banner)) //nolint:govet
session.LogSuccess(i18n.Tr("ssh_service_identified", target, banner)) //nolint:govet
return &ScanResult{
Type: plugins.ResultTypeService,
Success: true,
+7 -7
View File
@@ -61,10 +61,10 @@ func (p *TelnetPlugin) Scan(ctx context.Context, info *common.HostInfo, session
// 检测未授权访问
if result := p.testUnauthAccess(ctx, info, session); result != nil && result.Success {
common.LogVuln(i18n.Tr("telnet_service", target, result.Banner))
session.LogVuln(i18n.Tr("telnet_service", target, result.Banner))
// 验证命令执行能力
if ok, osType, evidence := p.verifyCommandExecution(ctx, info, "", "", session); ok {
common.LogVuln(i18n.Tr("telnet_unauth_rce", target, osType, evidence))
session.LogVuln(i18n.Tr("telnet_unauth_rce", target, osType, evidence))
}
return result
}
@@ -97,10 +97,10 @@ func (p *TelnetPlugin) Scan(ctx context.Context, info *common.HostInfo, session
result := TestCredentialsConcurrently(ctx, creds, authFn, "telnet", testConfig)
if result.Success {
common.LogVuln(i18n.Tr("telnet_credential", target, result.Username, result.Password))
session.LogVuln(i18n.Tr("telnet_credential", target, result.Username, result.Password))
// 验证命令执行能力
if ok, osType, evidence := p.verifyCommandExecution(ctx, info, result.Username, result.Password, session); ok {
common.LogVuln(i18n.Tr("telnet_credential_rce", target, result.Username, result.Password, osType, evidence))
session.LogVuln(i18n.Tr("telnet_credential_rce", target, result.Username, result.Password, osType, evidence))
}
}
@@ -559,9 +559,9 @@ func (p *TelnetPlugin) identifyService(ctx context.Context, info *common.HostInf
}
if p.isShellPrompt(cleaned) {
common.LogVuln(i18n.Tr("telnet_service", target, banner))
session.LogVuln(i18n.Tr("telnet_service", target, banner))
} else {
common.LogSuccess(i18n.Tr("telnet_service", target, banner))
session.LogSuccess(i18n.Tr("telnet_service", target, banner))
}
resultChan <- &ScanResult{
@@ -798,7 +798,7 @@ func (p *TelnetPlugin) checkCVE202624061Concurrent(ctx context.Context, info *co
if hit, ok := <-ch; ok {
target := info.Target()
common.LogVuln(i18n.Tr("telnet_cve202624061", target, hit.user, hit.evidence))
session.LogVuln(i18n.Tr("telnet_cve202624061", target, hit.user, hit.evidence))
return &ScanResult{
Success: true,
Type: plugins.ResultTypeVuln,
+2 -2
View File
@@ -30,7 +30,7 @@ func (p *VNCPlugin) Scan(ctx context.Context, info *common.HostInfo, session *co
// 检查未授权访问
if result := p.testUnauthAccess(ctx, info, session); result != nil && result.Success {
common.LogVuln(i18n.Tr("vnc_unauth", target))
session.LogVuln(i18n.Tr("vnc_unauth", target))
return result
}
@@ -54,7 +54,7 @@ func (p *VNCPlugin) Scan(ctx context.Context, info *common.HostInfo, session *co
result := TestCredentialsConcurrently(ctx, credentials, authFn, "vnc", testConfig)
if result.Success {
common.LogVuln(i18n.Tr("vnc_credential", target, result.Password))
session.LogVuln(i18n.Tr("vnc_credential", target, result.Password))
}
return result