feat: 16 funciones cybersecurity — análisis, crypto e IO de seguridad
12 funciones puras con implementación real: HashSHA256, HashMD5, EntropyShannon, IsBase64, IsHex, ExtractURLs, ParseIPCIDR, IPInRange, NormalizeURL, DetectSQLInjection, LevenshteinDistance, JaccardSimilarity 4 funciones impuras con implementación real (stdlib): LookupWhois, ResolveDNS, FetchHTTPHeaders, ScanPortTCP Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,33 @@
|
|||||||
|
package cybersecurity
|
||||||
|
|
||||||
|
import (
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var sqliPatterns = []struct {
|
||||||
|
name string
|
||||||
|
re *regexp.Regexp
|
||||||
|
}{
|
||||||
|
{"union_select", regexp.MustCompile(`(?i)\bunion\s+(all\s+)?select\b`)},
|
||||||
|
{"or_1_eq_1", regexp.MustCompile(`(?i)\bor\s+1\s*=\s*1`)},
|
||||||
|
{"comment_injection", regexp.MustCompile(`(--|#|/\*)\s*$`)},
|
||||||
|
{"single_quote_or", regexp.MustCompile(`(?i)'\s*(or|and)\s+'`)},
|
||||||
|
{"drop_table", regexp.MustCompile(`(?i)\bdrop\s+(table|database)\b`)},
|
||||||
|
{"sleep_benchmark", regexp.MustCompile(`(?i)\b(sleep|benchmark)\s*\(`)},
|
||||||
|
{"exec_xp", regexp.MustCompile(`(?i)\b(exec|xp_)\w*`)},
|
||||||
|
{"tautology", regexp.MustCompile(`(?i)\bor\s+['"]?\w+['"]?\s*=\s*['"]?\w+['"]?`)},
|
||||||
|
{"stacked_query", regexp.MustCompile(`;\s*(select|insert|update|delete|drop|alter)\b`)},
|
||||||
|
}
|
||||||
|
|
||||||
|
// DetectSQLInjection analiza un input en busca de patrones heuristicos de inyeccion SQL.
|
||||||
|
// Devuelve si se detecto una amenaza y el nombre del patron encontrado.
|
||||||
|
func DetectSQLInjection(input string) (isThreat bool, pattern string) {
|
||||||
|
normalized := strings.TrimSpace(input)
|
||||||
|
for _, p := range sqliPatterns {
|
||||||
|
if p.re.MatchString(normalized) {
|
||||||
|
return true, p.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false, ""
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
name: detect_sql_injection
|
||||||
|
kind: function
|
||||||
|
lang: go
|
||||||
|
domain: cybersecurity
|
||||||
|
version: "1.0.0"
|
||||||
|
purity: pure
|
||||||
|
signature: "func DetectSQLInjection(input string) (isThreat bool, pattern string)"
|
||||||
|
description: "Analiza un input en busca de patrones heuristicos de inyeccion SQL y devuelve si se detecto amenaza y el patron encontrado."
|
||||||
|
tags: [cybersecurity, sqli, detection, security]
|
||||||
|
uses_functions: []
|
||||||
|
uses_types: []
|
||||||
|
returns: []
|
||||||
|
returns_optional: false
|
||||||
|
error_type: ""
|
||||||
|
imports: [regexp, strings]
|
||||||
|
tested: false
|
||||||
|
tests: []
|
||||||
|
test_file_path: ""
|
||||||
|
file_path: "functions/cybersecurity/detect_sql_injection.go"
|
||||||
|
---
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package cybersecurity
|
||||||
|
|
||||||
|
import "math"
|
||||||
|
|
||||||
|
// EntropyShannon calcula la entropia de Shannon de los datos proporcionados.
|
||||||
|
// Devuelve un valor entre 0 (datos uniformes) y 8 (datos completamente aleatorios para bytes).
|
||||||
|
func EntropyShannon(data []byte) float64 {
|
||||||
|
if len(data) == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
var freq [256]float64
|
||||||
|
for _, b := range data {
|
||||||
|
freq[b]++
|
||||||
|
}
|
||||||
|
|
||||||
|
n := float64(len(data))
|
||||||
|
entropy := 0.0
|
||||||
|
for _, f := range freq {
|
||||||
|
if f > 0 {
|
||||||
|
p := f / n
|
||||||
|
entropy -= p * math.Log2(p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return entropy
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
name: entropy_shannon
|
||||||
|
kind: function
|
||||||
|
lang: go
|
||||||
|
domain: cybersecurity
|
||||||
|
version: "1.0.0"
|
||||||
|
purity: pure
|
||||||
|
signature: "func EntropyShannon(data []byte) float64"
|
||||||
|
description: "Calcula la entropia de Shannon de un slice de bytes. Retorna un valor entre 0 y 8 bits por byte."
|
||||||
|
tags: [cybersecurity, entropy, shannon, analysis]
|
||||||
|
uses_functions: []
|
||||||
|
uses_types: []
|
||||||
|
returns: []
|
||||||
|
returns_optional: false
|
||||||
|
error_type: ""
|
||||||
|
imports: [math]
|
||||||
|
tested: false
|
||||||
|
tests: []
|
||||||
|
test_file_path: ""
|
||||||
|
file_path: "functions/cybersecurity/entropy_shannon.go"
|
||||||
|
---
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package cybersecurity
|
||||||
|
|
||||||
|
import "regexp"
|
||||||
|
|
||||||
|
var urlRegex = regexp.MustCompile(`https?://[^\s<>"'` + "`" + `\)\]\}]+`)
|
||||||
|
|
||||||
|
// ExtractURLs extrae todas las URLs (http/https) encontradas en el texto proporcionado.
|
||||||
|
func ExtractURLs(text string) []string {
|
||||||
|
matches := urlRegex.FindAllString(text, -1)
|
||||||
|
if matches == nil {
|
||||||
|
return []string{}
|
||||||
|
}
|
||||||
|
return matches
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
name: extract_urls
|
||||||
|
kind: function
|
||||||
|
lang: go
|
||||||
|
domain: cybersecurity
|
||||||
|
version: "1.0.0"
|
||||||
|
purity: pure
|
||||||
|
signature: "func ExtractURLs(text string) []string"
|
||||||
|
description: "Extrae todas las URLs HTTP/HTTPS de un texto usando expresiones regulares."
|
||||||
|
tags: [cybersecurity, extract, url, parse]
|
||||||
|
uses_functions: []
|
||||||
|
uses_types: []
|
||||||
|
returns: []
|
||||||
|
returns_optional: false
|
||||||
|
error_type: ""
|
||||||
|
imports: [regexp]
|
||||||
|
tested: false
|
||||||
|
tests: []
|
||||||
|
test_file_path: ""
|
||||||
|
file_path: "functions/cybersecurity/extract_urls.go"
|
||||||
|
---
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package cybersecurity
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FetchHTTPHeaders realiza una solicitud HTTP HEAD a la URL y devuelve los headers de respuesta.
|
||||||
|
func FetchHTTPHeaders(url string) (map[string][]string, error) {
|
||||||
|
client := &http.Client{
|
||||||
|
Timeout: 10 * time.Second,
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.Head(url)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error realizando solicitud HEAD a %s: %w", url, err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
headers := make(map[string][]string, len(resp.Header))
|
||||||
|
for k, v := range resp.Header {
|
||||||
|
headers[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
return headers, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
name: fetch_http_headers
|
||||||
|
kind: function
|
||||||
|
lang: go
|
||||||
|
domain: cybersecurity
|
||||||
|
version: "1.0.0"
|
||||||
|
purity: impure
|
||||||
|
signature: "func FetchHTTPHeaders(url string) (map[string][]string, error)"
|
||||||
|
description: "Realiza una solicitud HTTP HEAD a una URL y devuelve los headers de la respuesta."
|
||||||
|
tags: [cybersecurity, io, http, headers]
|
||||||
|
uses_functions: []
|
||||||
|
uses_types: []
|
||||||
|
returns: []
|
||||||
|
returns_optional: false
|
||||||
|
error_type: "error_go_core"
|
||||||
|
imports: [fmt, net/http, time]
|
||||||
|
tested: false
|
||||||
|
tests: []
|
||||||
|
test_file_path: ""
|
||||||
|
file_path: "functions/cybersecurity/fetch_http_headers.go"
|
||||||
|
---
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package cybersecurity
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/md5"
|
||||||
|
"encoding/hex"
|
||||||
|
)
|
||||||
|
|
||||||
|
// HashMD5 calcula el hash MD5 de los datos proporcionados y devuelve el resultado como string hexadecimal.
|
||||||
|
func HashMD5(data []byte) string {
|
||||||
|
h := md5.Sum(data)
|
||||||
|
return hex.EncodeToString(h[:])
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
name: hash_md5
|
||||||
|
kind: function
|
||||||
|
lang: go
|
||||||
|
domain: cybersecurity
|
||||||
|
version: "1.0.0"
|
||||||
|
purity: pure
|
||||||
|
signature: "func HashMD5(data []byte) string"
|
||||||
|
description: "Calcula el hash MD5 de un slice de bytes y devuelve el resultado como string hexadecimal."
|
||||||
|
tags: [cybersecurity, hash, md5, crypto]
|
||||||
|
uses_functions: []
|
||||||
|
uses_types: []
|
||||||
|
returns: []
|
||||||
|
returns_optional: false
|
||||||
|
error_type: ""
|
||||||
|
imports: [crypto/md5, encoding/hex]
|
||||||
|
tested: false
|
||||||
|
tests: []
|
||||||
|
test_file_path: ""
|
||||||
|
file_path: "functions/cybersecurity/hash_md5.go"
|
||||||
|
---
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package cybersecurity
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/sha256"
|
||||||
|
"encoding/hex"
|
||||||
|
)
|
||||||
|
|
||||||
|
// HashSHA256 calcula el hash SHA-256 de los datos proporcionados y devuelve el resultado como string hexadecimal.
|
||||||
|
func HashSHA256(data []byte) string {
|
||||||
|
h := sha256.Sum256(data)
|
||||||
|
return hex.EncodeToString(h[:])
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
name: hash_sha256
|
||||||
|
kind: function
|
||||||
|
lang: go
|
||||||
|
domain: cybersecurity
|
||||||
|
version: "1.0.0"
|
||||||
|
purity: pure
|
||||||
|
signature: "func HashSHA256(data []byte) string"
|
||||||
|
description: "Calcula el hash SHA-256 de un slice de bytes y devuelve el resultado como string hexadecimal."
|
||||||
|
tags: [cybersecurity, hash, sha256, crypto]
|
||||||
|
uses_functions: []
|
||||||
|
uses_types: []
|
||||||
|
returns: []
|
||||||
|
returns_optional: false
|
||||||
|
error_type: ""
|
||||||
|
imports: [crypto/sha256, encoding/hex]
|
||||||
|
tested: false
|
||||||
|
tests: []
|
||||||
|
test_file_path: ""
|
||||||
|
file_path: "functions/cybersecurity/hash_sha256.go"
|
||||||
|
---
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package cybersecurity
|
||||||
|
|
||||||
|
import "net"
|
||||||
|
|
||||||
|
// IPInRange verifica si una direccion IP esta dentro de un rango CIDR dado.
|
||||||
|
func IPInRange(ip, cidr string) bool {
|
||||||
|
parsedIP := net.ParseIP(ip)
|
||||||
|
if parsedIP == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
_, ipNet, err := net.ParseCIDR(cidr)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return ipNet.Contains(parsedIP)
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
name: ip_in_range
|
||||||
|
kind: function
|
||||||
|
lang: go
|
||||||
|
domain: cybersecurity
|
||||||
|
version: "1.0.0"
|
||||||
|
purity: pure
|
||||||
|
signature: "func IPInRange(ip, cidr string) bool"
|
||||||
|
description: "Verifica si una direccion IP se encuentra dentro de un rango CIDR dado."
|
||||||
|
tags: [cybersecurity, network, cidr, check]
|
||||||
|
uses_functions: []
|
||||||
|
uses_types: []
|
||||||
|
returns: []
|
||||||
|
returns_optional: false
|
||||||
|
error_type: ""
|
||||||
|
imports: [net]
|
||||||
|
tested: false
|
||||||
|
tests: []
|
||||||
|
test_file_path: ""
|
||||||
|
file_path: "functions/cybersecurity/ip_in_range.go"
|
||||||
|
---
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package cybersecurity
|
||||||
|
|
||||||
|
import "encoding/base64"
|
||||||
|
|
||||||
|
// IsBase64 verifica si el string proporcionado es una cadena base64 valida (standard encoding).
|
||||||
|
func IsBase64(s string) bool {
|
||||||
|
if len(s) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
_, err := base64.StdEncoding.DecodeString(s)
|
||||||
|
return err == nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
name: is_base64
|
||||||
|
kind: function
|
||||||
|
lang: go
|
||||||
|
domain: cybersecurity
|
||||||
|
version: "1.0.0"
|
||||||
|
purity: pure
|
||||||
|
signature: "func IsBase64(s string) bool"
|
||||||
|
description: "Valida si un string es una cadena base64 valida segun el encoding estandar."
|
||||||
|
tags: [cybersecurity, validation, base64, format]
|
||||||
|
uses_functions: []
|
||||||
|
uses_types: []
|
||||||
|
returns: []
|
||||||
|
returns_optional: false
|
||||||
|
error_type: ""
|
||||||
|
imports: [encoding/base64]
|
||||||
|
tested: false
|
||||||
|
tests: []
|
||||||
|
test_file_path: ""
|
||||||
|
file_path: "functions/cybersecurity/is_base64.go"
|
||||||
|
---
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package cybersecurity
|
||||||
|
|
||||||
|
// IsHex verifica si el string proporcionado es una cadena hexadecimal valida.
|
||||||
|
// Requiere longitud par y que todos los caracteres sean digitos hex (0-9, a-f, A-F).
|
||||||
|
func IsHex(s string) bool {
|
||||||
|
if len(s) == 0 || len(s)%2 != 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, c := range s {
|
||||||
|
if !((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
name: is_hex
|
||||||
|
kind: function
|
||||||
|
lang: go
|
||||||
|
domain: cybersecurity
|
||||||
|
version: "1.0.0"
|
||||||
|
purity: pure
|
||||||
|
signature: "func IsHex(s string) bool"
|
||||||
|
description: "Valida si un string es una cadena hexadecimal valida (longitud par, caracteres 0-9 a-f A-F)."
|
||||||
|
tags: [cybersecurity, validation, hex, format]
|
||||||
|
uses_functions: []
|
||||||
|
uses_types: []
|
||||||
|
returns: []
|
||||||
|
returns_optional: false
|
||||||
|
error_type: ""
|
||||||
|
imports: []
|
||||||
|
tested: false
|
||||||
|
tests: []
|
||||||
|
test_file_path: ""
|
||||||
|
file_path: "functions/cybersecurity/is_hex.go"
|
||||||
|
---
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package cybersecurity
|
||||||
|
|
||||||
|
// JaccardSimilarity calcula la similitud de Jaccard entre dos conjuntos de tokens.
|
||||||
|
// Devuelve un valor entre 0.0 (sin interseccion) y 1.0 (conjuntos identicos).
|
||||||
|
func JaccardSimilarity(a, b []string) float64 {
|
||||||
|
if len(a) == 0 && len(b) == 0 {
|
||||||
|
return 1.0
|
||||||
|
}
|
||||||
|
if len(a) == 0 || len(b) == 0 {
|
||||||
|
return 0.0
|
||||||
|
}
|
||||||
|
|
||||||
|
setA := make(map[string]struct{}, len(a))
|
||||||
|
for _, s := range a {
|
||||||
|
setA[s] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
setB := make(map[string]struct{}, len(b))
|
||||||
|
for _, s := range b {
|
||||||
|
setB[s] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
intersection := 0
|
||||||
|
for k := range setA {
|
||||||
|
if _, ok := setB[k]; ok {
|
||||||
|
intersection++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Union = |A| + |B| - |A intersect B| (usando conjuntos sin duplicados)
|
||||||
|
union := len(setA) + len(setB) - intersection
|
||||||
|
if union == 0 {
|
||||||
|
return 0.0
|
||||||
|
}
|
||||||
|
|
||||||
|
return float64(intersection) / float64(union)
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
name: jaccard_similarity
|
||||||
|
kind: function
|
||||||
|
lang: go
|
||||||
|
domain: cybersecurity
|
||||||
|
version: "1.0.0"
|
||||||
|
purity: pure
|
||||||
|
signature: "func JaccardSimilarity(a, b []string) float64"
|
||||||
|
description: "Calcula la similitud de Jaccard entre dos conjuntos de tokens. Retorna un valor entre 0.0 y 1.0."
|
||||||
|
tags: [cybersecurity, similarity, jaccard, tokens]
|
||||||
|
uses_functions: []
|
||||||
|
uses_types: []
|
||||||
|
returns: []
|
||||||
|
returns_optional: false
|
||||||
|
error_type: ""
|
||||||
|
imports: []
|
||||||
|
tested: false
|
||||||
|
tests: []
|
||||||
|
test_file_path: ""
|
||||||
|
file_path: "functions/cybersecurity/jaccard_similarity.go"
|
||||||
|
---
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package cybersecurity
|
||||||
|
|
||||||
|
// LevenshteinDistance calcula la distancia de edicion (Levenshtein) entre dos strings.
|
||||||
|
func LevenshteinDistance(a, b string) int {
|
||||||
|
ra := []rune(a)
|
||||||
|
rb := []rune(b)
|
||||||
|
la := len(ra)
|
||||||
|
lb := len(rb)
|
||||||
|
|
||||||
|
if la == 0 {
|
||||||
|
return lb
|
||||||
|
}
|
||||||
|
if lb == 0 {
|
||||||
|
return la
|
||||||
|
}
|
||||||
|
|
||||||
|
// Usar solo dos filas para optimizar memoria
|
||||||
|
prev := make([]int, lb+1)
|
||||||
|
curr := make([]int, lb+1)
|
||||||
|
|
||||||
|
for j := 0; j <= lb; j++ {
|
||||||
|
prev[j] = j
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 1; i <= la; i++ {
|
||||||
|
curr[0] = i
|
||||||
|
for j := 1; j <= lb; j++ {
|
||||||
|
cost := 1
|
||||||
|
if ra[i-1] == rb[j-1] {
|
||||||
|
cost = 0
|
||||||
|
}
|
||||||
|
del := prev[j] + 1
|
||||||
|
ins := curr[j-1] + 1
|
||||||
|
sub := prev[j-1] + cost
|
||||||
|
|
||||||
|
m := del
|
||||||
|
if ins < m {
|
||||||
|
m = ins
|
||||||
|
}
|
||||||
|
if sub < m {
|
||||||
|
m = sub
|
||||||
|
}
|
||||||
|
curr[j] = m
|
||||||
|
}
|
||||||
|
prev, curr = curr, prev
|
||||||
|
}
|
||||||
|
|
||||||
|
return prev[lb]
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
name: levenshtein_distance
|
||||||
|
kind: function
|
||||||
|
lang: go
|
||||||
|
domain: cybersecurity
|
||||||
|
version: "1.0.0"
|
||||||
|
purity: pure
|
||||||
|
signature: "func LevenshteinDistance(a, b string) int"
|
||||||
|
description: "Calcula la distancia de edicion de Levenshtein entre dos strings. Util para deteccion de typosquatting."
|
||||||
|
tags: [cybersecurity, string, distance, typosquatting]
|
||||||
|
uses_functions: []
|
||||||
|
uses_types: []
|
||||||
|
returns: []
|
||||||
|
returns_optional: false
|
||||||
|
error_type: ""
|
||||||
|
imports: []
|
||||||
|
tested: false
|
||||||
|
tests: []
|
||||||
|
test_file_path: ""
|
||||||
|
file_path: "functions/cybersecurity/levenshtein_distance.go"
|
||||||
|
---
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package cybersecurity
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// LookupWhois realiza una consulta WHOIS para el dominio proporcionado conectandose al servidor whois.iana.org.
|
||||||
|
func LookupWhois(domain string) (string, error) {
|
||||||
|
conn, err := net.DialTimeout("tcp", "whois.iana.org:43", 10*time.Second)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("error conectando al servidor WHOIS: %w", err)
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
_ = conn.SetDeadline(time.Now().Add(10 * time.Second))
|
||||||
|
|
||||||
|
_, err = fmt.Fprintf(conn, "%s\r\n", domain)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("error enviando consulta WHOIS: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var sb strings.Builder
|
||||||
|
_, err = io.Copy(&sb, conn)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("error leyendo respuesta WHOIS: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.String(), nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
name: lookup_whois
|
||||||
|
kind: function
|
||||||
|
lang: go
|
||||||
|
domain: cybersecurity
|
||||||
|
version: "1.0.0"
|
||||||
|
purity: impure
|
||||||
|
signature: "func LookupWhois(domain string) (string, error)"
|
||||||
|
description: "Realiza una consulta WHOIS para un dominio conectandose al servidor whois.iana.org por TCP."
|
||||||
|
tags: [cybersecurity, io, whois, recon]
|
||||||
|
uses_functions: []
|
||||||
|
uses_types: []
|
||||||
|
returns: []
|
||||||
|
returns_optional: false
|
||||||
|
error_type: "error_go_core"
|
||||||
|
imports: [fmt, io, net, strings, time]
|
||||||
|
tested: false
|
||||||
|
tests: []
|
||||||
|
test_file_path: ""
|
||||||
|
file_path: "functions/cybersecurity/lookup_whois.go"
|
||||||
|
---
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package cybersecurity
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// trackingParams lista de parametros de tracking comunes a eliminar.
|
||||||
|
var trackingParams = map[string]bool{
|
||||||
|
"utm_source": true,
|
||||||
|
"utm_medium": true,
|
||||||
|
"utm_campaign": true,
|
||||||
|
"utm_term": true,
|
||||||
|
"utm_content": true,
|
||||||
|
"fbclid": true,
|
||||||
|
"gclid": true,
|
||||||
|
"ref": true,
|
||||||
|
"mc_cid": true,
|
||||||
|
"mc_eid": true,
|
||||||
|
}
|
||||||
|
|
||||||
|
// NormalizeURL normaliza una URL: convierte el host a minusculas, elimina fragmentos
|
||||||
|
// y remueve parametros de tracking comunes.
|
||||||
|
func NormalizeURL(rawURL string) string {
|
||||||
|
u, err := url.Parse(rawURL)
|
||||||
|
if err != nil {
|
||||||
|
return rawURL
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lowercase host
|
||||||
|
u.Host = strings.ToLower(u.Host)
|
||||||
|
|
||||||
|
// Eliminar fragmento
|
||||||
|
u.Fragment = ""
|
||||||
|
|
||||||
|
// Eliminar parametros de tracking
|
||||||
|
q := u.Query()
|
||||||
|
for param := range trackingParams {
|
||||||
|
q.Del(param)
|
||||||
|
}
|
||||||
|
u.RawQuery = q.Encode()
|
||||||
|
|
||||||
|
return u.String()
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
name: normalize_url
|
||||||
|
kind: function
|
||||||
|
lang: go
|
||||||
|
domain: cybersecurity
|
||||||
|
version: "1.0.0"
|
||||||
|
purity: pure
|
||||||
|
signature: "func NormalizeURL(rawURL string) string"
|
||||||
|
description: "Normaliza una URL: convierte el host a minusculas, elimina fragmentos y remueve parametros de tracking comunes."
|
||||||
|
tags: [cybersecurity, url, normalize, sanitize]
|
||||||
|
uses_functions: []
|
||||||
|
uses_types: []
|
||||||
|
returns: []
|
||||||
|
returns_optional: false
|
||||||
|
error_type: ""
|
||||||
|
imports: [net/url, strings]
|
||||||
|
tested: false
|
||||||
|
tests: []
|
||||||
|
test_file_path: ""
|
||||||
|
file_path: "functions/cybersecurity/normalize_url.go"
|
||||||
|
---
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package cybersecurity
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ParseIPCIDR parsea una notacion CIDR y devuelve la direccion de red, broadcast, cantidad de hosts y error.
|
||||||
|
func ParseIPCIDR(cidr string) (network string, broadcast string, hosts int, err error) {
|
||||||
|
ip, ipNet, err := net.ParseCIDR(cidr)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", 0, fmt.Errorf("CIDR invalido: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Solo soportamos IPv4
|
||||||
|
ip4 := ip.To4()
|
||||||
|
if ip4 == nil {
|
||||||
|
return "", "", 0, fmt.Errorf("solo se soporta IPv4")
|
||||||
|
}
|
||||||
|
|
||||||
|
mask := ipNet.Mask
|
||||||
|
networkIP := ipNet.IP.To4()
|
||||||
|
network = networkIP.String()
|
||||||
|
|
||||||
|
// Calcular broadcast
|
||||||
|
broadcastIP := make(net.IP, 4)
|
||||||
|
for i := 0; i < 4; i++ {
|
||||||
|
broadcastIP[i] = networkIP[i] | ^mask[i]
|
||||||
|
}
|
||||||
|
broadcast = broadcastIP.String()
|
||||||
|
|
||||||
|
// Calcular hosts usables
|
||||||
|
netInt := binary.BigEndian.Uint32(networkIP)
|
||||||
|
bcastInt := binary.BigEndian.Uint32(broadcastIP)
|
||||||
|
total := int(bcastInt - netInt + 1)
|
||||||
|
if total > 2 {
|
||||||
|
hosts = total - 2 // excluir network y broadcast
|
||||||
|
} else {
|
||||||
|
hosts = total // /31 o /32
|
||||||
|
}
|
||||||
|
|
||||||
|
return network, broadcast, hosts, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
name: parse_ip_cidr
|
||||||
|
kind: function
|
||||||
|
lang: go
|
||||||
|
domain: cybersecurity
|
||||||
|
version: "1.0.0"
|
||||||
|
purity: pure
|
||||||
|
signature: "func ParseIPCIDR(cidr string) (network string, broadcast string, hosts int, err error)"
|
||||||
|
description: "Parsea una notacion CIDR IPv4 y devuelve la direccion de red, broadcast y cantidad de hosts usables."
|
||||||
|
tags: [cybersecurity, network, cidr, parse]
|
||||||
|
uses_functions: []
|
||||||
|
uses_types: []
|
||||||
|
returns: []
|
||||||
|
returns_optional: false
|
||||||
|
error_type: ""
|
||||||
|
imports: [encoding/binary, fmt, net]
|
||||||
|
tested: false
|
||||||
|
tests: []
|
||||||
|
test_file_path: ""
|
||||||
|
file_path: "functions/cybersecurity/parse_ip_cidr.go"
|
||||||
|
---
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package cybersecurity
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ResolveDNS resuelve un hostname a sus direcciones IP usando el resolver del sistema.
|
||||||
|
func ResolveDNS(host string) ([]string, error) {
|
||||||
|
ips, err := net.LookupHost(host)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error resolviendo DNS para %s: %w", host, err)
|
||||||
|
}
|
||||||
|
return ips, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
name: resolve_dns
|
||||||
|
kind: function
|
||||||
|
lang: go
|
||||||
|
domain: cybersecurity
|
||||||
|
version: "1.0.0"
|
||||||
|
purity: impure
|
||||||
|
signature: "func ResolveDNS(host string) ([]string, error)"
|
||||||
|
description: "Resuelve un hostname a sus direcciones IP usando el resolver DNS del sistema."
|
||||||
|
tags: [cybersecurity, io, dns, resolve]
|
||||||
|
uses_functions: []
|
||||||
|
uses_types: []
|
||||||
|
returns: []
|
||||||
|
returns_optional: false
|
||||||
|
error_type: "error_go_core"
|
||||||
|
imports: [fmt, net]
|
||||||
|
tested: false
|
||||||
|
tests: []
|
||||||
|
test_file_path: ""
|
||||||
|
file_path: "functions/cybersecurity/resolve_dns.go"
|
||||||
|
---
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package cybersecurity
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ScanPortTCP intenta conectarse a un puerto TCP y devuelve el estado ("open", "closed", "filtered"),
|
||||||
|
// un banner si el puerto esta abierto, y un posible error.
|
||||||
|
func ScanPortTCP(host string, port int, timeoutMs int) (status string, banner string, err error) {
|
||||||
|
address := fmt.Sprintf("%s:%d", host, port)
|
||||||
|
timeout := time.Duration(timeoutMs) * time.Millisecond
|
||||||
|
|
||||||
|
conn, err := net.DialTimeout("tcp", address, timeout)
|
||||||
|
if err != nil {
|
||||||
|
// Distinguir entre conexion rechazada (closed) y timeout (filtered)
|
||||||
|
if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
|
||||||
|
return "filtered", "", nil
|
||||||
|
}
|
||||||
|
return "closed", "", nil
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
// Intentar leer un banner con timeout corto
|
||||||
|
_ = conn.SetReadDeadline(time.Now().Add(2 * time.Second))
|
||||||
|
buf := make([]byte, 1024)
|
||||||
|
n, _ := conn.Read(buf)
|
||||||
|
if n > 0 {
|
||||||
|
banner = string(buf[:n])
|
||||||
|
}
|
||||||
|
|
||||||
|
return "open", banner, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
name: scan_port_tcp
|
||||||
|
kind: function
|
||||||
|
lang: go
|
||||||
|
domain: cybersecurity
|
||||||
|
version: "1.0.0"
|
||||||
|
purity: impure
|
||||||
|
signature: "func ScanPortTCP(host string, port int, timeoutMs int) (status string, banner string, err error)"
|
||||||
|
description: "Escanea un puerto TCP en un host dado. Devuelve el estado (open/closed/filtered) y un banner si esta abierto."
|
||||||
|
tags: [cybersecurity, io, port, scan]
|
||||||
|
uses_functions: []
|
||||||
|
uses_types: []
|
||||||
|
returns: []
|
||||||
|
returns_optional: false
|
||||||
|
error_type: "error_go_core"
|
||||||
|
imports: [fmt, net, time]
|
||||||
|
tested: false
|
||||||
|
tests: []
|
||||||
|
test_file_path: ""
|
||||||
|
file_path: "functions/cybersecurity/scan_port_tcp.go"
|
||||||
|
---
|
||||||
Reference in New Issue
Block a user