mirror of
https://github.com/lunchcat/sif.git
synced 2026-06-30 02:03:44 -07:00
fix(frameworks): make Phoenix and AdonisJS detection specific (#153)
the phoenix and adonis detectors matched bare substrings ("phx-", "phoenix",
"adonis") that fire on unrelated pages: a "phx-" css class on a phoenix,
arizona site, or any markup containing the word "adonis". replace them with
markers the frameworks actually emit. phoenix keys on the liveview container
attributes data-phx-main, data-phx-session and data-phx-static; adonis on its
default adonis-session cookie.
this narrows detection: plain (non-liveview) phoenix and session-less adonis
apis are no longer matched. the markers we now key on (liveview's container
attributes, adonis's default session cookie) are ones ordinary prose cannot
forge. each detector gains a true-positive test and a false-positive tripwire.
This commit is contained in:
@@ -424,6 +424,113 @@ func TestDetectFramework_Joomla(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestDetectFramework_AdonisJS(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Set-Cookie", "adonis-session=s%3Aabc.def; Path=/; HttpOnly")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte(`<!DOCTYPE html><html><body>Welcome</body></html>`))
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
result, err := frameworks.DetectFramework(server.URL, 5*time.Second, "")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if result == nil {
|
||||
t.Fatal("expected result, got nil")
|
||||
}
|
||||
if result.Name != "AdonisJS" {
|
||||
t.Errorf("expected framework 'AdonisJS', got '%s'", result.Name)
|
||||
}
|
||||
}
|
||||
|
||||
// a cosmetics brand page that merely contains "adonis" in its markup (CSS
|
||||
// classes, asset paths, links) must not be fingerprinted as AdonisJS, as the
|
||||
// old bare "adonis" substring signature did.
|
||||
func TestDetectFramework_AdonisFalsePositive(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte(`
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Adonis Cosmetics</title>
|
||||
<link rel="stylesheet" href="/assets/adonis-theme.css">
|
||||
</head>
|
||||
<body class="adonis-store">
|
||||
<h1>Adonis Cosmetics</h1>
|
||||
<a href="/adonis/collections">Shop the adonis collection</a>
|
||||
</body>
|
||||
</html>
|
||||
`))
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
result, err := frameworks.DetectFramework(server.URL, 5*time.Second, "")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if result != nil && result.Name == "AdonisJS" {
|
||||
t.Errorf("false positive: plain page mentioning 'Adonis' detected as AdonisJS (%.2f)", result.Confidence)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDetectFramework_Phoenix(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte(`
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head><title>Phoenix App</title></head>
|
||||
<body>
|
||||
<div data-phx-main data-phx-session="abc" data-phx-static="def" id="phx-F1a2B3">
|
||||
<span>Content</span>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
`))
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
result, err := frameworks.DetectFramework(server.URL, 5*time.Second, "")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if result == nil {
|
||||
t.Fatal("expected result, got nil")
|
||||
}
|
||||
if result.Name != "Phoenix" {
|
||||
t.Errorf("expected framework 'Phoenix', got '%s'", result.Name)
|
||||
}
|
||||
}
|
||||
|
||||
// a Phoenix, Arizona business page using "phx-" CSS class prefixes must not be
|
||||
// fingerprinted as the Phoenix framework, as the old bare "phx-" signature did.
|
||||
func TestDetectFramework_PhoenixFalsePositive(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte(`
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head><title>Phoenix AZ Roofing</title></head>
|
||||
<body class="phx-page">
|
||||
<nav class="phx-nav"><a href="/">Phoenix Home</a></nav>
|
||||
<section class="phx-hero">Serving Phoenix, Arizona since 1998.</section>
|
||||
</body>
|
||||
</html>
|
||||
`))
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
result, err := frameworks.DetectFramework(server.URL, 5*time.Second, "")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if result != nil && result.Name == "Phoenix" {
|
||||
t.Errorf("false positive: phx- CSS class page detected as Phoenix (%.2f)", result.Confidence)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDetectFramework_Astro(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
@@ -375,9 +375,9 @@ func (d *phoenixDetector) Name() string { return "Phoenix" }
|
||||
|
||||
func (d *phoenixDetector) Signatures() []fw.Signature {
|
||||
return []fw.Signature{
|
||||
{Pattern: "_csrf_token", Weight: 0.4, HeaderOnly: true},
|
||||
{Pattern: "phx-", Weight: 0.3},
|
||||
{Pattern: "phoenix", Weight: 0.2},
|
||||
{Pattern: "data-phx-main", Weight: 0.4},
|
||||
{Pattern: "data-phx-session", Weight: 0.3},
|
||||
{Pattern: "data-phx-static", Weight: 0.3},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -424,8 +424,7 @@ func (d *adonisDetector) Name() string { return "AdonisJS" }
|
||||
|
||||
func (d *adonisDetector) Signatures() []fw.Signature {
|
||||
return []fw.Signature{
|
||||
{Pattern: "adonis", Weight: 0.4},
|
||||
{Pattern: "_csrf", Weight: 0.2, HeaderOnly: true},
|
||||
{Pattern: "adonis-session", Weight: 0.4, HeaderOnly: true},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user