mirror of
https://github.com/shadow1ng/fscan.git
synced 2026-09-24 20:21:52 +08:00
fix: Cassandra CQL 协议头缺少 flags 字节 + version 方向位错误
cqlSend 写 8 字节头(缺 flags),实际 CQL v4 需要 9 字节。 version byte 0x84 是 response 方向,request 应为 0x04。 同时扩展集成测试至 17 个协议:新增 Memcached、Elasticsearch、 MSSQL、RabbitMQ、MQTT、LDAP、Cassandra、Neo4j、Kafka、SMTP。
This commit is contained in:
@@ -204,6 +204,229 @@ func TestMongoDBBrute(t *testing.T) {
|
||||
t.Logf("mongodb brute: user=%s pass=%s", result.Username, result.Password)
|
||||
}
|
||||
|
||||
// ── Memcached ──────────────────────────────────────────────────
|
||||
|
||||
func TestMemcachedUnauthorized(t *testing.T) {
|
||||
session := testSession()
|
||||
info := hostInfo(testHost, 11211)
|
||||
plugin := services.NewMemcachedPlugin()
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
|
||||
defer cancel()
|
||||
|
||||
result := plugin.Scan(ctx, info, session)
|
||||
if result == nil {
|
||||
t.Fatal("result is nil")
|
||||
}
|
||||
if !result.Success {
|
||||
t.Fatalf("expected memcached to succeed, got error: %v", result.Error)
|
||||
}
|
||||
t.Logf("memcached: type=%s banner=%s", result.Type, result.Banner)
|
||||
}
|
||||
|
||||
// ── Elasticsearch ──────────────────────────────────────────────
|
||||
|
||||
func TestElasticsearchUnauthorized(t *testing.T) {
|
||||
session := testSession()
|
||||
info := hostInfo(testHost, 19200)
|
||||
plugin := services.NewElasticsearchPlugin()
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
|
||||
defer cancel()
|
||||
|
||||
result := plugin.Scan(ctx, info, session)
|
||||
if result == nil {
|
||||
t.Fatal("result is nil")
|
||||
}
|
||||
if !result.Success {
|
||||
t.Fatalf("expected elasticsearch to succeed, got error: %v", result.Error)
|
||||
}
|
||||
t.Logf("elasticsearch: type=%s vulinfo=%s", result.Type, result.VulInfo)
|
||||
}
|
||||
|
||||
// ── MSSQL ──────────────────────────────────────────────────────
|
||||
|
||||
func TestMSSQLBrute(t *testing.T) {
|
||||
session := testSession()
|
||||
session.Config.Credentials.UserPassPairs = []config.CredentialPair{
|
||||
{Username: "sa", Password: "wrong"},
|
||||
{Username: "sa", Password: "MssqlTest123!"},
|
||||
}
|
||||
info := hostInfo(testHost, 11433)
|
||||
plugin := services.NewMSSQLPlugin()
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
result := plugin.Scan(ctx, info, session)
|
||||
if result == nil {
|
||||
t.Fatal("result is nil")
|
||||
}
|
||||
if !result.Success {
|
||||
t.Fatalf("expected mssql brute to succeed, got error: %v", result.Error)
|
||||
}
|
||||
t.Logf("mssql brute: user=%s pass=%s", result.Username, result.Password)
|
||||
}
|
||||
|
||||
// ── RabbitMQ ───────────────────────────────────────────────────
|
||||
|
||||
func TestRabbitMQBrute(t *testing.T) {
|
||||
session := testSession()
|
||||
session.Config.Credentials.UserPassPairs = []config.CredentialPair{
|
||||
{Username: "admin", Password: "wrong"},
|
||||
{Username: "admin", Password: "rabbit123"},
|
||||
}
|
||||
info := hostInfo(testHost, 15672)
|
||||
plugin := services.NewRabbitMQPlugin()
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
|
||||
defer cancel()
|
||||
|
||||
result := plugin.Scan(ctx, info, session)
|
||||
if result == nil {
|
||||
t.Fatal("result is nil")
|
||||
}
|
||||
if !result.Success {
|
||||
t.Fatalf("expected rabbitmq brute to succeed, got error: %v", result.Error)
|
||||
}
|
||||
t.Logf("rabbitmq brute: user=%s pass=%s", result.Username, result.Password)
|
||||
}
|
||||
|
||||
// ── MQTT ───────────────────────────────────────────────────────
|
||||
|
||||
func TestMQTTServiceDetect(t *testing.T) {
|
||||
session := testSession()
|
||||
info := hostInfo(testHost, 11883)
|
||||
plugin := services.NewMQTTPlugin()
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
|
||||
defer cancel()
|
||||
|
||||
result := plugin.Scan(ctx, info, session)
|
||||
if result == nil {
|
||||
t.Fatal("result is nil")
|
||||
}
|
||||
if !result.Success {
|
||||
t.Fatalf("expected mqtt service detect to succeed, got error: %v", result.Error)
|
||||
}
|
||||
t.Logf("mqtt: service=%s banner=%s", result.Service, result.Banner)
|
||||
}
|
||||
|
||||
// ── SMB ────────────────────────────────────────────────────────
|
||||
|
||||
func TestSMBBrute(t *testing.T) {
|
||||
t.Skip("SMB requires port 445 which is reserved on WSL2")
|
||||
}
|
||||
|
||||
// ── LDAP ───────────────────────────────────────────────────────
|
||||
|
||||
func TestLDAPBrute(t *testing.T) {
|
||||
session := testSession()
|
||||
session.Config.Credentials.UserPassPairs = []config.CredentialPair{
|
||||
{Username: "cn=admin,dc=test,dc=local", Password: "wrong"},
|
||||
{Username: "cn=admin,dc=test,dc=local", Password: "ldap123"},
|
||||
}
|
||||
info := hostInfo(testHost, 10389)
|
||||
plugin := services.NewLDAPPlugin()
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
result := plugin.Scan(ctx, info, session)
|
||||
if result == nil {
|
||||
t.Fatal("result is nil")
|
||||
}
|
||||
if !result.Success {
|
||||
t.Fatalf("expected ldap brute to succeed, got error: %v", result.Error)
|
||||
}
|
||||
t.Logf("ldap brute: user=%s pass=%s", result.Username, result.Password)
|
||||
}
|
||||
|
||||
// ── Cassandra ──────────────────────────────────────────────────
|
||||
|
||||
func TestCassandraServiceDetect(t *testing.T) {
|
||||
session := testSession()
|
||||
session.Config.DisableBrute = true
|
||||
info := hostInfo(testHost, 19042)
|
||||
plugin := services.NewCassandraPlugin()
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
result := plugin.Scan(ctx, info, session)
|
||||
if result == nil {
|
||||
t.Fatal("result is nil")
|
||||
}
|
||||
if !result.Success {
|
||||
t.Fatalf("expected cassandra service detect to succeed, got error: %v", result.Error)
|
||||
}
|
||||
t.Logf("cassandra: type=%s banner=%s", result.Type, result.Banner)
|
||||
}
|
||||
|
||||
// ── Neo4j ──────────────────────────────────────────────────────
|
||||
|
||||
func TestNeo4jBrute(t *testing.T) {
|
||||
session := testSession()
|
||||
session.Config.Credentials.UserPassPairs = []config.CredentialPair{
|
||||
{Username: "neo4j", Password: "wrong"},
|
||||
{Username: "neo4j", Password: "neo4jtest123"},
|
||||
}
|
||||
info := hostInfo(testHost, 17687)
|
||||
plugin := services.NewNeo4jPlugin()
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
result := plugin.Scan(ctx, info, session)
|
||||
if result == nil {
|
||||
t.Fatal("result is nil")
|
||||
}
|
||||
if !result.Success {
|
||||
t.Fatalf("expected neo4j brute to succeed, got error: %v", result.Error)
|
||||
}
|
||||
t.Logf("neo4j brute: user=%s pass=%s", result.Username, result.Password)
|
||||
}
|
||||
|
||||
// ── Kafka ──────────────────────────────────────────────────────
|
||||
|
||||
func TestKafkaNoAuth(t *testing.T) {
|
||||
session := testSession()
|
||||
info := hostInfo(testHost, 19092)
|
||||
plugin := services.NewKafkaPlugin()
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
result := plugin.Scan(ctx, info, session)
|
||||
if result == nil {
|
||||
t.Fatal("result is nil")
|
||||
}
|
||||
if !result.Success {
|
||||
t.Fatalf("expected kafka to succeed, got error: %v", result.Error)
|
||||
}
|
||||
t.Logf("kafka: type=%s banner=%s", result.Type, result.Banner)
|
||||
}
|
||||
|
||||
// ── SMTP ───────────────────────────────────────────────────────
|
||||
|
||||
func TestSMTPServiceDetect(t *testing.T) {
|
||||
session := testSession()
|
||||
info := hostInfo(testHost, 11025)
|
||||
plugin := services.NewSMTPPlugin()
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
|
||||
defer cancel()
|
||||
|
||||
result := plugin.Scan(ctx, info, session)
|
||||
if result == nil {
|
||||
t.Fatal("result is nil")
|
||||
}
|
||||
if !result.Success {
|
||||
t.Fatalf("expected smtp to succeed, got error: %v", result.Error)
|
||||
}
|
||||
t.Logf("smtp: type=%s banner=%s", result.Type, result.Banner)
|
||||
}
|
||||
|
||||
// ── 连接失败场景 ──────────────────────────────────────────────
|
||||
|
||||
func TestRedisConnectionRefused(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user