
bluemonday: ein schneller HTML-Sanitizer für Golang (inspiriert vom OWASP Java HTML Sanitizer), um nutzergenerierte Inhalte von XSS zu bereinigen
bluemonday ist ein in Go implementierter HTML-Sanitizer. Er ist schnell und in hohem Maße konfigurierbar.
bluemonday nimmt nicht vertrauenswürdige, nutzergenerierte Inhalte als Eingabe und gibt HTML zurück, das anhand einer Allowlist zugelassener HTML-Elemente und -Attribute bereinigt wurde, sodass du die Inhalte sicher in deine Webseite einbinden kannst.
Wenn du nutzergenerierte Inhalte akzeptierst und dein Server Go verwendet, brauchst du bluemonday.
Die Standard-Policy für nutzergenerierte Inhalte (bluemonday.UGCPolicy().Sanitize()) macht aus diesem:
Hello <STYLE>.XSS{background-image:url("javascript:alert('XSS')");}</STYLE><A CLASS=XSS></A>World
Ein harmloses:
Hello World
Und es macht aus diesem:
<a href="javascript:alert('XSS1')" onmouseover="alert('XSS2')">XSS<a>
Dieses:
XSS
Während es weiterhin dieses:
<a href="http://www.google.com/">
<img src="https://ssl.gstatic.com/accounts/ui/logo_2x.png"/>
</a>
weitgehend unverändert durchlässt (es erhält ein rel="nofollow", was bei nutzergenerierten Inhalten eine gute Sache ist):
<a href="http://www.google.com/" rel="nofollow">
<img src="https://ssl.gstatic.com/accounts/ui/logo_2x.png"/>
</a>
Es schützt Webseiten vor XSS-Angriffen. Es gibt viele Vektoren für einen XSS-Angriff, und der beste Weg, das Risiko zu verringern, ist, Nutzereingaben anhand einer bekannten sicheren Liste von HTML-Elementen und -Attributen zu bereinigen.
Du solltest bluemonday immer nach jeder anderen Verarbeitung ausführen.
Wenn du blackfriday oder Pandoc verwendest, sollte bluemonday nach diesen Schritten ausgeführt werden. So wird sichergestellt, dass später in deinem Prozess kein unsicheres HTML eingeführt wird.
bluemonday ist stark vom OWASP Java HTML Sanitizer und vom HTML Purifier inspiriert.
Allowlist-basiert: Du musst entweder eine Policy erstellen, die die zu erlaubenden HTML-Elemente und -Attribute beschreibt (sowie die regexp-Muster der Attribute), oder eine der mitgelieferten Policies verwenden, die gute Standardwerte darstellen.
Die Policy mit der Allowlist wird mithilfe eines schnellen, nicht validierenden, nur vorwärts gerichteten, tokenbasierten Parsers angewendet, der im Go net/html Paket vom Go-Kernteam implementiert wurde.
Wir erwarten wohlgeformtes HTML (schließende Elemente für jedes zutreffende offene Element, korrekt verschachtelt) und konzentrieren uns daher nicht darauf, schlecht verschachteltes oder unvollständiges HTML zu reparieren. Wir stellen lediglich sicher, dass alle vorhandenen Elemente in der Policy-Allowlist beschrieben sind und dass Attribute und Links für die Verwendung auf deiner Webseite sicher sind. GIGO gilt auch hier: Wenn du schlechtes HTML eingibst, ist es nicht die Aufgabe von bluemonday, herauszufinden, wie man es wieder gut macht.
Ja
Wir verwenden bluemonday in der Produktion, nachdem wir vom weit verbreiteten und intensiv getesteten OWASP Java HTML Sanitizer migriert sind.
Wir bestehen unsere umfangreiche Testsuite (einschließlich AntiSamy-Tests sowie Tests für alle gemeldeten Probleme). Prüfe die ungelösten Issues, um zu sehen, ob etwas für dich ein Hindernis sein könnte.
Wir laden zu Pull Requests und Issues ein, um sicherzustellen, dass wir umfassenden Schutz gegen verschiedene Angriffe über nutzergenerierte Inhalte bieten.
Installation mit go get github.com/microcosm-cc/bluemonday
Danach aufrufen:
package main
import (
"fmt"
"github.com/microcosm-cc/bluemonday"
)
func main() {
// Do this once for each unique policy, and use the policy for the life of the program
// Policy creation/editing is not safe to use in multiple goroutines
p := bluemonday.UGCPolicy()
// The policy can then be used to sanitize lots of input and it is safe to use the policy in multiple goroutines
html := p.Sanitize(
`<a onblur="alert(secret)" href="http://www.google.com">Google</a>`,
)
// Output:
// <a href="http://www.google.com" rel="nofollow">Google</a>
fmt.Println(html)
}
Wir bieten drei Möglichkeiten, Sanitize aufzurufen:
p.Sanitize(string) string
p.SanitizeBytes([]byte) []byte
p.SanitizeReader(io.Reader) bytes.Buffer
Wenn du auf Performance stehst, gibt p.SanitizeReader(r).Bytes() ein []byte zurück, ohne unnötige Typumwandlungen der Ein- oder Ausgaben vorzunehmen. Der Unterschied ist jedoch so vernachlässigbar, dass du dich nie darum kümmern musst.
Du kannst deine eigenen Policies erstellen:
package main
import (
"fmt"
"github.com/microcosm-cc/bluemonday"
)
func main() {
p := bluemonday.NewPolicy()
// Require URLs to be parseable by net/url.Parse and either:
// mailto: http:// or https://
p.AllowStandardURLs()
// We only allow <p> and <a href="">
p.AllowAttrs("href").OnElements("a")
p.AllowElements("p")
html := p.Sanitize(
`<a onblur="alert(secret)" href="http://www.google.com">Google</a>`,
)
// Output:
// <a href="http://www.google.com">Google</a>
fmt.Println(html)
}
Wir liefern zwei Standard-Policies mit:
bluemonday.StrictPolicy(), die als Äquivalent zum Entfernen aller HTML-Elemente und ihrer Attribute betrachtet werden kann, da ihre Allowlist leer ist. Ein Beispielszenario wären Blog-Post-Titel, bei denen HTML-Tags überhaupt nicht erwartet werden; falls sie doch vorkommen, sollten die Elemente und der Inhalt der Elemente entfernt werden. Dies ist eine sehr strenge Policy.bluemonday.UGCPolicy(), die eine breite Auswahl an HTML-Elementen und -Attributen erlaubt, die für nutzergenerierte Inhalte sicher sind. Beachte, dass diese Policy keine iframes, object, embed, Styles, script usw. erlaubt. Ein Beispielszenario wären Blog-Post-Inhalte, bei denen eine Vielzahl von Formatierungen sowie die Möglichkeit von TABLEs und IMGs erwartet wird.Das Wesentliche beim Erstellen einer Policy ist zu bestimmen, welche HTML-Elemente und -Attribute für dein Szenario als sicher gelten. OWASP bietet einen Spickzettel zur XSS-Prävention an, um die Risiken zu erklären, aber im Wesentlichen:
script-, style-, iframe-, object-, embed-, base-Elemente, die es ermöglichen, dass Code vom Client ausgeführt wird oder dass Inhalte Dritter eingebunden werden, die Code ausführen könnenGrundsätzlich solltest du in der Lage sein zu beschreiben, welches HTML für dein Szenario in Ordnung ist. Wenn du dir nicht sicher bist, dass du deine Policy beschreiben kannst, ziehe in Betracht, eine der mitgelieferten Policies wie bluemonday.UGCPolicy() zu verwenden.
Um eine neue Policy zu erstellen:
p := bluemonday.NewPolicy()
Um Elemente zu einer Policy hinzuzufügen, füge entweder nur die Elemente hinzu:
p.AllowElements("b", "strong")
Oder mit einem Regex:
Hinweis: Wenn ein Element wie oben gezeigt mit Namen hinzugefügt wird, wird ein passendes Regex ignoriert