Copyedit examples

Fragments suffice for illustration, and the two bad and good examples can be easily combined
This commit is contained in:
Chris Smowton
2021-11-09 10:39:19 +00:00
parent c18b11a470
commit bc9300ebf5
7 changed files with 36 additions and 154 deletions

View File

@@ -4,35 +4,33 @@
<qhelp>
<overview>
<p>If an LDAP query or DN is built using string concatenation or string formatting, and the
components of the concatenation include user input without any proper sanitization, a user
components of the concatenation include user input without any proper sanitization, a user
is likely to be able to run malicious LDAP queries.</p>
</overview>
<recommendation>
<p>If user input must be included in an LDAP query or DN, it should be escaped to
avoid a malicious user providing special characters that change the meaning
of the query. In Go, user input should be escaped with <code>EscapeFilter</code>.
A good practice is to escape filter characters
of the query. In Go, user input should be escaped with <code>EscapeFilter</code>.
A good practice is to escape filter characters
that could change the meaning of the query (https://tools.ietf.org/search/rfc4515#section-3).</p>
</recommendation>
<example>
<p>In the following examples, the code accepts both <code>filter</code> and <code>attr</code> from the user,
<p>In the following examples, the code accepts both <code>filter</code> and <code>attr</code> from the user,
which it then uses to build a LDAP query and DN.</p>
<p>The first and the second example uses the unsanitized user input directly
<p>The following example uses the unsanitized user input directly
in the search filter and DN for the LDAP query.
A malicious user could provide special characters to change the meaning of these
components, and search for a completely different set of values.</p>
<sample src="example/example_bad1.go" />
<sample src="example/example_bad2.go" />
<sample src="example/example_bad.go" />
<p>In the third and four example, the input provided by the user is sanitized before it is included in the search filter or DN.
<p>In the following example, the input provided by the user is sanitized before it is included in the search filter or DN.
This ensures the meaning of the query cannot be changed by a malicious user.</p>
<sample src="example/example_good1.go" />
<sample src="example/example_good2.go" />
<sample src="example/example_good.go" />
</example>
<references>

View File

@@ -0,0 +1,13 @@
package main
func LDAPInjectionVulnerable(untrusted string) {
// ...
searchRequest := ldap.NewSearchRequest(
"dc=example,dc=com", // The base dn to search
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
"(&(objectClass=organizationalPerson)) + untrusted", // BAD: untrusted filter
[]string{"dn", "cn", untrusted}, // BAD: untrusted attribute
nil,
)
// ...
}

View File

@@ -1,36 +0,0 @@
package main
import (
"fmt"
"log"
"github.com/gin-gonic/gin"
"github.com/go-ldap/ldap"
)
// ExampleConnSearch ldap demo
func ExampleConnSearchBad1(c *gin.Context) {
filter := c.Query("name")
l, err := ldap.DialURL("ldap://127.0.0.1:389")
if err != nil {
log.Fatal(err)
}
defer l.Close()
searchRequest := ldap.NewSearchRequest(
"dc=example,dc=com", // The base dn to search
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
"(&(objectClass=organizationalPerson))", // The filter to apply
[]string{"dn", "cn", filter}, // A list attributes to retrieve
nil,
)
sr, err := l.Search(searchRequest)
if err != nil {
log.Fatal(err)
}
for _, entry := range sr.Entries {
fmt.Printf("%s: %v\n", entry.DN, entry.GetAttributeValue("cn"))
}
}

View File

@@ -1,36 +0,0 @@
package main
import (
"fmt"
"log"
"github.com/gin-gonic/gin"
"github.com/go-ldap/ldap"
)
// ExampleConnSearch ldap demo
func ExampleConnSearchBad2(c *gin.Context) {
filter := c.Query("name")
l, err := ldap.DialURL("ldap://127.0.0.1:389")
if err != nil {
log.Fatal(err)
}
defer l.Close()
searchRequest := ldap.NewSearchRequest(
"dc=example,dc=com", // The base dn to search
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
"(&(objectClass=organizationalPerson))"+filter, // The filter to apply
[]string{"dn", "cn", filter}, // A list attributes to retrieve
nil,
)
sr, err := l.Search(searchRequest)
if err != nil {
log.Fatal(err)
}
for _, entry := range sr.Entries {
fmt.Printf("%s: %v\n", entry.DN, entry.GetAttributeValue("cn"))
}
}

View File

@@ -0,0 +1,15 @@
package main
func LDAPInjectionVulnerable(untrusted string) {
// ...
safe := ldap.EscapeFilter(untrusted)
searchRequest := ldap.NewSearchRequest(
"dc=example,dc=com", // The base dn to search
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
"(&(objectClass=organizationalPerson))"+safe, // GOOD: sanitized filter
[]string{"dn", "cn", safe}, // GOOD: sanitized attribute
nil,
)
// ...
}

View File

@@ -1,36 +0,0 @@
package main
import (
"fmt"
"log"
"github.com/gin-gonic/gin"
"github.com/go-ldap/ldap"
)
// ExampleConnSearch ldap demo
func ExampleConnSearchGood1(c *gin.Context) {
filter := c.Query("name")
l, err := ldap.DialURL("ldap://127.0.0.1:389")
if err != nil {
log.Fatal(err)
}
defer l.Close()
searchRequest := ldap.NewSearchRequest(
"dc=example,dc=com", // The base dn to search
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
"(&(objectClass=organizationalPerson))", // The filter to apply
[]string{"dn", "cn", ldap.EscapeFilter(filter)}, // A list attributes to retrieve
nil,
)
sr, err := l.Search(searchRequest)
if err != nil {
log.Fatal(err)
}
for _, entry := range sr.Entries {
fmt.Printf("%s: %v\n", entry.DN, entry.GetAttributeValue("cn"))
}
}

View File

@@ -1,36 +0,0 @@
package main
import (
"fmt"
"log"
"github.com/gin-gonic/gin"
"github.com/go-ldap/ldap"
)
// ExampleConnSearch ldap demo
func ExampleConnSearchGood2(c *gin.Context) {
filter := c.Query("name")
l, err := ldap.DialURL("ldap://127.0.0.1:389")
if err != nil {
log.Fatal(err)
}
defer l.Close()
searchRequest := ldap.NewSearchRequest(
"dc=example,dc=com", // The base dn to search
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
"(&(objectClass=organizationalPerson))"+ldap.EscapeFilter(filter), // The filter to apply
[]string{"dn", "cn"}, // A list attributes to retrieve
nil,
)
sr, err := l.Search(searchRequest)
if err != nil {
log.Fatal(err)
}
for _, entry := range sr.Entries {
fmt.Printf("%s: %v\n", entry.DN, entry.GetAttributeValue("cn"))
}
}