mirror of
https://github.com/github/codeql.git
synced 2026-01-30 14:52:57 +01:00
Copyedit examples
Fragments suffice for illustration, and the two bad and good examples can be easily combined
This commit is contained in:
@@ -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>
|
||||
|
||||
13
ql/src/experimental/CWE-090/example/example_bad.go
Normal file
13
ql/src/experimental/CWE-090/example/example_bad.go
Normal 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,
|
||||
)
|
||||
// ...
|
||||
}
|
||||
@@ -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"))
|
||||
}
|
||||
}
|
||||
@@ -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"))
|
||||
}
|
||||
}
|
||||
15
ql/src/experimental/CWE-090/example/example_good.go
Normal file
15
ql/src/experimental/CWE-090/example/example_good.go
Normal 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,
|
||||
)
|
||||
// ...
|
||||
}
|
||||
@@ -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"))
|
||||
}
|
||||
}
|
||||
@@ -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"))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user