mirror of
https://github.com/github/codeql.git
synced 2026-04-30 19:26:02 +02:00
Merge pull request #5983 from atorralba/atorralba/promote-insecure-basic-auth
Java: Promote Insecure Basic Authentication query from experimental
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
lgtm,codescanning
|
||||
* The query "Insecure basic authentication" (`java/insecure-basic-auth`) has been promoted from experimental to the main query pack. Its results will now appear by default. This query was originally [submitted as an experimental query by @luchua-bc](https://github.com/github/codeql/pull/3976).
|
||||
@@ -52,11 +52,20 @@ class UriCreation extends Call {
|
||||
/**
|
||||
* Gets the host argument of the newly created URI. In the case where the
|
||||
* host is specified separately, this is only the host. In the case where the
|
||||
* uri is parsed from an input string, such as in
|
||||
* URI is parsed from an input string, such as in
|
||||
* `URI("http://foo.com/mypath")`, this is the entire argument passed in,
|
||||
* that is `"http://foo.com/mypath"`.
|
||||
*/
|
||||
Expr getHostArg() { none() }
|
||||
abstract Expr getHostArg();
|
||||
|
||||
/**
|
||||
* Gets the scheme argument of the newly created URI. In the case where the
|
||||
* scheme is specified separately, this is only the scheme. In the case where the
|
||||
* URI is parsed from an input string, such as in
|
||||
* `URI("http://foo.com/mypath")`, this is the entire argument passed in,
|
||||
* that is `"http://foo.com/mypath"`.
|
||||
*/
|
||||
abstract Expr getSchemeArg();
|
||||
}
|
||||
|
||||
/** A `java.net.URI` constructor call. */
|
||||
@@ -74,6 +83,8 @@ class UriConstructorCall extends ClassInstanceExpr, UriCreation {
|
||||
// String fragment)
|
||||
result = this.getArgument(2) and this.getNumArgument() = 7
|
||||
}
|
||||
|
||||
override Expr getSchemeArg() { result = this.getArgument(0) }
|
||||
}
|
||||
|
||||
/** A call to `java.net.URI::create`. */
|
||||
@@ -81,6 +92,8 @@ class UriCreate extends UriCreation {
|
||||
UriCreate() { this.getCallee().hasName("create") }
|
||||
|
||||
override Expr getHostArg() { result = this.getArgument(0) }
|
||||
|
||||
override Expr getSchemeArg() { result = this.getArgument(0) }
|
||||
}
|
||||
|
||||
/** A `java.net.URL` constructor call. */
|
||||
@@ -105,7 +118,7 @@ class UrlConstructorCall extends ClassInstanceExpr {
|
||||
}
|
||||
|
||||
/** Gets the argument that corresponds to the protocol of the URL. */
|
||||
Expr protocolArg() {
|
||||
Expr getProtocolArg() {
|
||||
// In all cases except where the first parameter is a URL, the argument
|
||||
// containing the protocol is the first one, otherwise it is the second.
|
||||
if this.getConstructor().getParameterType(0) instanceof TypeUrl
|
||||
|
||||
91
java/ql/lib/semmle/code/java/security/HttpsUrls.qll
Normal file
91
java/ql/lib/semmle/code/java/security/HttpsUrls.qll
Normal file
@@ -0,0 +1,91 @@
|
||||
/** Provides classes and predicates to reason about plaintext HTTP vulnerabilities. */
|
||||
|
||||
import java
|
||||
private import semmle.code.java.dataflow.DataFlow
|
||||
private import semmle.code.java.dataflow.ExternalFlow
|
||||
private import semmle.code.java.dataflow.TaintTracking
|
||||
private import semmle.code.java.frameworks.ApacheHttp
|
||||
private import semmle.code.java.frameworks.Networking
|
||||
|
||||
/**
|
||||
* String of HTTP URLs not in private domains.
|
||||
*/
|
||||
class HttpStringLiteral extends StringLiteral {
|
||||
HttpStringLiteral() {
|
||||
exists(string s | this.getRepresentedString() = s |
|
||||
s = "http"
|
||||
or
|
||||
s.matches("http://%") and
|
||||
not s.substring(7, s.length()) instanceof PrivateHostName and
|
||||
not TaintTracking::localExprTaint(any(StringLiteral p |
|
||||
p.getRepresentedString() instanceof PrivateHostName
|
||||
), this.getParent*())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A sink that represents a URL opening method call, such as a call to `java.net.URL.openConnection()`.
|
||||
*/
|
||||
abstract class UrlOpenSink extends DataFlow::Node { }
|
||||
|
||||
private class DefaultUrlOpenSink extends UrlOpenSink {
|
||||
DefaultUrlOpenSink() { sinkNode(this, "open-url") }
|
||||
}
|
||||
|
||||
/**
|
||||
* A unit class for adding additional taint steps.
|
||||
*
|
||||
* Extend this class to add additional taint steps that should apply
|
||||
* to configurations working with HTTP URLs.
|
||||
*/
|
||||
class HttpUrlsAdditionalTaintStep extends Unit {
|
||||
/**
|
||||
* Holds if the step from `node1` to `node2` should be considered a taint
|
||||
* step for taint tracking configurations working with HTTP URLs.
|
||||
*/
|
||||
abstract predicate step(DataFlow::Node n1, DataFlow::Node n2);
|
||||
}
|
||||
|
||||
private class DefaultHttpUrlAdditionalTaintStep extends HttpUrlsAdditionalTaintStep {
|
||||
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
|
||||
apacheHttpRequestStep(n1, n2) or
|
||||
createUriStep(n1, n2) or
|
||||
createUrlStep(n1, n2) or
|
||||
urlOpenStep(n1, n2)
|
||||
}
|
||||
}
|
||||
|
||||
/** Constructor of `ApacheHttpRequest` */
|
||||
private predicate apacheHttpRequestStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
exists(ConstructorCall cc |
|
||||
cc.getConstructedType() instanceof ApacheHttpRequest and
|
||||
node2.asExpr() = cc and
|
||||
cc.getAnArgument() = node1.asExpr()
|
||||
)
|
||||
}
|
||||
|
||||
/** `URI` methods */
|
||||
private predicate createUriStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
exists(UriConstructorCall cc |
|
||||
cc.getSchemeArg() = node1.asExpr() and
|
||||
node2.asExpr() = cc
|
||||
)
|
||||
}
|
||||
|
||||
/** Constructors of `URL` */
|
||||
private predicate createUrlStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
exists(UrlConstructorCall cc |
|
||||
cc.getProtocolArg() = node1.asExpr() and
|
||||
node2.asExpr() = cc
|
||||
)
|
||||
}
|
||||
|
||||
/** Method call of `HttpURLOpenMethod` */
|
||||
private predicate urlOpenStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
exists(MethodAccess ma |
|
||||
ma.getMethod() instanceof UrlOpenConnectionMethod and
|
||||
node1.asExpr() = ma.getQualifier() and
|
||||
ma = node2.asExpr()
|
||||
)
|
||||
}
|
||||
25
java/ql/lib/semmle/code/java/security/HttpsUrlsQuery.qll
Normal file
25
java/ql/lib/semmle/code/java/security/HttpsUrlsQuery.qll
Normal file
@@ -0,0 +1,25 @@
|
||||
/** Provides taint tracking configurations to be used in HTTPS URLs queries. */
|
||||
|
||||
import java
|
||||
import semmle.code.java.dataflow.TaintTracking
|
||||
import semmle.code.java.frameworks.Networking
|
||||
import semmle.code.java.security.HttpsUrls
|
||||
|
||||
/**
|
||||
* A taint tracking configuration for HTTP connections.
|
||||
*/
|
||||
class HttpStringToUrlOpenMethodFlowConfig extends TaintTracking::Configuration {
|
||||
HttpStringToUrlOpenMethodFlowConfig() { this = "HttpStringToUrlOpenMethodFlowConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof HttpStringLiteral }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { sink instanceof UrlOpenSink }
|
||||
|
||||
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
any(HttpUrlsAdditionalTaintStep c).step(node1, node2)
|
||||
}
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node node) {
|
||||
node.getType() instanceof PrimitiveType or node.getType() instanceof BoxedType
|
||||
}
|
||||
}
|
||||
45
java/ql/lib/semmle/code/java/security/InsecureBasicAuth.qll
Normal file
45
java/ql/lib/semmle/code/java/security/InsecureBasicAuth.qll
Normal file
@@ -0,0 +1,45 @@
|
||||
/** Provides classes and predicates to reason about Insecure Basic Authentication vulnerabilities. */
|
||||
|
||||
import java
|
||||
import semmle.code.java.dataflow.DataFlow
|
||||
import semmle.code.java.dataflow.TaintTracking
|
||||
import semmle.code.java.security.HttpsUrls
|
||||
|
||||
/**
|
||||
* A source that represents HTTP URLs.
|
||||
* Extend this class to add your own Insecure Basic Authentication sources.
|
||||
*/
|
||||
abstract class InsecureBasicAuthSource extends DataFlow::Node { }
|
||||
|
||||
/** A default source representing HTTP strings, URLs or URIs. */
|
||||
private class DefaultInsecureBasicAuthSource extends InsecureBasicAuthSource {
|
||||
DefaultInsecureBasicAuthSource() { this.asExpr() instanceof HttpStringLiteral }
|
||||
}
|
||||
|
||||
/**
|
||||
* A sink that represents a method that sets Basic Authentication.
|
||||
* Extend this class to add your own Insecure Basic Authentication sinks.
|
||||
*/
|
||||
abstract class InsecureBasicAuthSink extends DataFlow::Node { }
|
||||
|
||||
/** A default sink representing methods that set an Authorization header. */
|
||||
private class DefaultInsecureBasicAuthSink extends InsecureBasicAuthSink {
|
||||
DefaultInsecureBasicAuthSink() {
|
||||
exists(MethodAccess ma |
|
||||
ma.getMethod().hasName("addHeader") or
|
||||
ma.getMethod().hasName("setHeader") or
|
||||
ma.getMethod().hasName("setRequestProperty")
|
||||
|
|
||||
this.asExpr() = ma.getQualifier() and
|
||||
ma.getArgument(0).(CompileTimeConstantExpr).getStringValue() = "Authorization" and
|
||||
TaintTracking::localExprTaint(any(BasicAuthString b), ma.getArgument(1))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* String pattern of basic authentication.
|
||||
*/
|
||||
private class BasicAuthString extends StringLiteral {
|
||||
BasicAuthString() { exists(string s | this.getRepresentedString() = s | s.matches("Basic %")) }
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/** Provides taint tracking configurations to be used in Insecure Basic Authentication queries. */
|
||||
|
||||
import java
|
||||
import semmle.code.java.security.HttpsUrls
|
||||
import semmle.code.java.security.InsecureBasicAuth
|
||||
import semmle.code.java.dataflow.TaintTracking
|
||||
|
||||
/**
|
||||
* A taint tracking configuration for the Basic authentication scheme
|
||||
* being used in HTTP connections.
|
||||
*/
|
||||
class BasicAuthFlowConfig extends TaintTracking::Configuration {
|
||||
BasicAuthFlowConfig() { this = "InsecureBasicAuth::BasicAuthFlowConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node src) { src instanceof InsecureBasicAuthSource }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { sink instanceof InsecureBasicAuthSink }
|
||||
|
||||
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
any(HttpUrlsAdditionalTaintStep c).step(node1, node2)
|
||||
}
|
||||
}
|
||||
@@ -11,54 +11,10 @@
|
||||
*/
|
||||
|
||||
import java
|
||||
import semmle.code.java.dataflow.TaintTracking
|
||||
import semmle.code.java.frameworks.Networking
|
||||
import semmle.code.java.security.HttpsUrlsQuery
|
||||
import DataFlow::PathGraph
|
||||
private import semmle.code.java.dataflow.ExternalFlow
|
||||
|
||||
class HttpString extends StringLiteral {
|
||||
HttpString() {
|
||||
// Avoid matching "https" here.
|
||||
exists(string s | this.getRepresentedString() = s |
|
||||
(
|
||||
// Either the literal "http", ...
|
||||
s = "http"
|
||||
or
|
||||
// ... or the beginning of a http URL.
|
||||
s.matches("http://%")
|
||||
) and
|
||||
not s.matches("%/localhost%")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class HttpStringToUrlOpenMethodFlowConfig extends TaintTracking::Configuration {
|
||||
HttpStringToUrlOpenMethodFlowConfig() { this = "HttpsUrls::HttpStringToUrlOpenMethodFlowConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof HttpString }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { sink instanceof UrlOpenSink }
|
||||
|
||||
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
exists(UrlConstructorCall u |
|
||||
node1.asExpr() = u.protocolArg() and
|
||||
node2.asExpr() = u
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node node) {
|
||||
node.getType() instanceof PrimitiveType or node.getType() instanceof BoxedType
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A sink that represents a URL opening method call, such as a call to `java.net.URL.openConnection()`.
|
||||
*/
|
||||
private class UrlOpenSink extends DataFlow::Node {
|
||||
UrlOpenSink() { sinkNode(this, "open-url") }
|
||||
}
|
||||
|
||||
from DataFlow::PathNode source, DataFlow::PathNode sink, MethodAccess m, HttpString s
|
||||
from DataFlow::PathNode source, DataFlow::PathNode sink, MethodAccess m, HttpStringLiteral s
|
||||
where
|
||||
source.getNode().asExpr() = s and
|
||||
sink.getNode().asExpr() = m.getQualifier() and
|
||||
|
||||
@@ -1,22 +1,19 @@
|
||||
public class InsecureBasicAuth {
|
||||
/**
|
||||
* Test basic authentication with Apache HTTP request.
|
||||
*/
|
||||
*/
|
||||
public void testApacheHttpRequest(String username, String password) {
|
||||
{
|
||||
|
||||
// BAD: basic authentication over HTTP
|
||||
String url = "http://www.example.com/rest/getuser.do?uid=abcdx";
|
||||
}
|
||||
|
||||
{
|
||||
// GOOD: basic authentication over HTTPS
|
||||
String url = "https://www.example.com/rest/getuser.do?uid=abcdx";
|
||||
}
|
||||
url = "https://www.example.com/rest/getuser.do?uid=abcdx";
|
||||
|
||||
HttpPost post = new HttpPost(url);
|
||||
post.setHeader("Accept", "application/json");
|
||||
post.setHeader("Content-type", "application/json");
|
||||
|
||||
|
||||
String authString = username + ":" + password;
|
||||
byte[] authEncBytes = Base64.getEncoder().encode(authString.getBytes());
|
||||
String authStringEnc = new String(authEncBytes);
|
||||
@@ -28,15 +25,12 @@ public class InsecureBasicAuth {
|
||||
* Test basic authentication with Java HTTP URL connection.
|
||||
*/
|
||||
public void testHttpUrlConnection(String username, String password) {
|
||||
{
|
||||
|
||||
// BAD: basic authentication over HTTP
|
||||
String urlStr = "http://www.example.com/rest/getuser.do?uid=abcdx";
|
||||
}
|
||||
|
||||
{
|
||||
// GOOD: basic authentication over HTTPS
|
||||
String urlStr = "https://www.example.com/rest/getuser.do?uid=abcdx";
|
||||
}
|
||||
urlStr = "https://www.example.com/rest/getuser.do?uid=abcdx";
|
||||
|
||||
String authString = username + ":" + password;
|
||||
String encoding = Base64.getEncoder().encodeToString(authString.getBytes("UTF-8"));
|
||||
@@ -2,7 +2,7 @@
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>Basic authentication only obfuscates username/password in Base64 encoding, which can be easily recognized and reversed, thus it must not be transmitted over the cleartext HTTP channel. Transmission of sensitive information not in HTTPS is vulnerable to packet sniffing.</p>
|
||||
<p>Basic authentication only obfuscates usernames and passwords in Base64 encoding, which can be easily recognized and reversed, thus it must not be transmitted over the cleartext HTTP channel. Transmitting sensitive information without using HTTPS makes the data vulnerable to packet sniffing.</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
@@ -15,16 +15,13 @@
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>
|
||||
<a href="https://cwe.mitre.org/data/definitions/522">CWE-522</a>
|
||||
</li>
|
||||
<li>
|
||||
SonarSource rule:
|
||||
<a href="https://rules.sonarsource.com/java/tag/owasp/RSPEC-2647">Basic authentication should not be used</a>
|
||||
<a href="https://rules.sonarsource.com/java/tag/owasp/RSPEC-2647">Basic authentication should not be used</a>.
|
||||
</li>
|
||||
<li>
|
||||
Acunetix:
|
||||
<a href="https://www.acunetix.com/vulnerabilities/web/basic-authentication-over-http/">WEB VULNERABILITIES INDEX - Basic authentication over HTTP</a>
|
||||
<a href="https://www.acunetix.com/vulnerabilities/web/basic-authentication-over-http/">WEB VULNERABILITIES INDEX - Basic authentication over HTTP</a>.
|
||||
</li>
|
||||
</references>
|
||||
</qhelp>
|
||||
23
java/ql/src/Security/CWE/CWE-522/InsecureBasicAuth.ql
Normal file
23
java/ql/src/Security/CWE/CWE-522/InsecureBasicAuth.ql
Normal file
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* @name Insecure basic authentication
|
||||
* @description Basic authentication only obfuscates username/password in
|
||||
* Base64 encoding, which can be easily recognized and reversed.
|
||||
* Transmitting sensitive information without using HTTPS makes
|
||||
* the data vulnerable to packet sniffing.
|
||||
* @kind path-problem
|
||||
* @problem.severity warning
|
||||
* @precision medium
|
||||
* @id java/insecure-basic-auth
|
||||
* @tags security
|
||||
* external/cwe/cwe-522
|
||||
* external/cwe/cwe-319
|
||||
*/
|
||||
|
||||
import java
|
||||
import semmle.code.java.security.InsecureBasicAuthQuery
|
||||
import DataFlow::PathGraph
|
||||
|
||||
from DataFlow::PathNode source, DataFlow::PathNode sink, BasicAuthFlowConfig config
|
||||
where config.hasFlowPath(source, sink)
|
||||
select sink.getNode(), source, sink, "Insecure basic authentication from $@.", source.getNode(),
|
||||
"HTTP URL"
|
||||
@@ -1,238 +0,0 @@
|
||||
/**
|
||||
* @name Insecure basic authentication
|
||||
* @description Basic authentication only obfuscates username/password in
|
||||
* Base64 encoding, which can be easily recognized and reversed.
|
||||
* Transmission of sensitive information not over HTTPS is
|
||||
* vulnerable to packet sniffing.
|
||||
* @kind path-problem
|
||||
* @problem.severity warning
|
||||
* @precision medium
|
||||
* @id java/insecure-basic-auth
|
||||
* @tags security
|
||||
* external/cwe/cwe-522
|
||||
* external/cwe/cwe-319
|
||||
*/
|
||||
|
||||
import java
|
||||
import semmle.code.java.frameworks.Networking
|
||||
import semmle.code.java.frameworks.ApacheHttp
|
||||
import semmle.code.java.dataflow.TaintTracking
|
||||
import DataFlow::PathGraph
|
||||
|
||||
/**
|
||||
* Class of Java URL constructor.
|
||||
*/
|
||||
class URLConstructor extends ClassInstanceExpr {
|
||||
URLConstructor() { this.getConstructor().getDeclaringType() instanceof TypeUrl }
|
||||
|
||||
predicate hasHttpStringArg() {
|
||||
this.getConstructor().getParameter(0).getType() instanceof TypeString and
|
||||
(
|
||||
// URLs constructed with any of the three string constructors below:
|
||||
// `URL(String protocol, String host, int port, String file)`,
|
||||
// `URL(String protocol, String host, int port, String file, URLStreamHandler handler)`,
|
||||
// `URL(String protocol, String host, String file)`
|
||||
this.getConstructor().getNumberOfParameters() > 1 and
|
||||
concatHttpString(getArgument(0), this.getArgument(1)) // First argument contains the protocol part and the second argument contains the host part.
|
||||
or
|
||||
// URLs constructed with the string constructor `URL(String spec)`
|
||||
this.getConstructor().getNumberOfParameters() = 1 and
|
||||
this.getArgument(0) instanceof HttpString // First argument contains the whole spec.
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class of Java URI constructor.
|
||||
*/
|
||||
class URIConstructor extends ClassInstanceExpr {
|
||||
URIConstructor() { this.getConstructor().getDeclaringType() instanceof TypeUri }
|
||||
|
||||
predicate hasHttpStringArg() {
|
||||
(
|
||||
this.getNumArgument() = 1 and
|
||||
this.getArgument(0) instanceof HttpString // `URI(String str)`
|
||||
or
|
||||
this.getNumArgument() = 4 and
|
||||
concatHttpString(this.getArgument(0), this.getArgument(1)) // `URI(String scheme, String host, String path, String fragment)`
|
||||
or
|
||||
this.getNumArgument() = 5 and
|
||||
concatHttpString(this.getArgument(0), this.getArgument(1)) // `URI(String scheme, String authority, String path, String query, String fragment)` without user-info in authority
|
||||
or
|
||||
this.getNumArgument() = 7 and
|
||||
concatHttpString(this.getArgument(0), this.getArgument(2)) // `URI(String scheme, String userInfo, String host, int port, String path, String query, String fragment)`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* String of HTTP URLs not in private domains.
|
||||
*/
|
||||
class HttpStringLiteral extends StringLiteral {
|
||||
HttpStringLiteral() {
|
||||
// Match URLs with the HTTP protocol and without private IP addresses to reduce false positives.
|
||||
exists(string s | this.getRepresentedString() = s |
|
||||
s.regexpMatch("(?i)http://[\\[a-zA-Z0-9].*") and
|
||||
not s.substring(7, s.length()) instanceof PrivateHostName
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks both parts of protocol and host.
|
||||
*/
|
||||
predicate concatHttpString(Expr protocol, Expr host) {
|
||||
(
|
||||
protocol.(CompileTimeConstantExpr).getStringValue().regexpMatch("(?i)http(://)?") or
|
||||
protocol
|
||||
.(VarAccess)
|
||||
.getVariable()
|
||||
.getAnAssignedValue()
|
||||
.(CompileTimeConstantExpr)
|
||||
.getStringValue()
|
||||
.regexpMatch("(?i)http(://)?")
|
||||
) and
|
||||
not exists(string hostString |
|
||||
hostString = host.(CompileTimeConstantExpr).getStringValue() or
|
||||
hostString =
|
||||
host.(VarAccess).getVariable().getAnAssignedValue().(CompileTimeConstantExpr).getStringValue()
|
||||
|
|
||||
hostString.length() = 0 or // Empty host is loopback address
|
||||
hostString instanceof PrivateHostName
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the leftmost operand in a concatenated string */
|
||||
Expr getLeftmostConcatOperand(Expr expr) {
|
||||
if expr instanceof AddExpr
|
||||
then result = getLeftmostConcatOperand(expr.(AddExpr).getLeftOperand())
|
||||
else result = expr
|
||||
}
|
||||
|
||||
/**
|
||||
* String concatenated with `HttpStringLiteral`.
|
||||
*/
|
||||
class HttpString extends Expr {
|
||||
HttpString() {
|
||||
this instanceof HttpStringLiteral
|
||||
or
|
||||
concatHttpString(this.(AddExpr).getLeftOperand(),
|
||||
getLeftmostConcatOperand(this.(AddExpr).getRightOperand()))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* String pattern of basic authentication.
|
||||
*/
|
||||
class BasicAuthString extends StringLiteral {
|
||||
BasicAuthString() { exists(string s | this.getRepresentedString() = s | s.matches("Basic %")) }
|
||||
}
|
||||
|
||||
/**
|
||||
* String concatenated with `BasicAuthString`.
|
||||
*/
|
||||
predicate builtFromBasicAuthStringConcat(Expr expr) {
|
||||
expr instanceof BasicAuthString
|
||||
or
|
||||
builtFromBasicAuthStringConcat(expr.(AddExpr).getLeftOperand())
|
||||
or
|
||||
exists(Expr other | builtFromBasicAuthStringConcat(other) |
|
||||
exists(Variable var | var.getAnAssignedValue() = other and var.getAnAccess() = expr)
|
||||
)
|
||||
}
|
||||
|
||||
/** The `openConnection` method of Java URL. Not to include `openStream` since it won't be used in this query. */
|
||||
class HttpURLOpenMethod extends Method {
|
||||
HttpURLOpenMethod() {
|
||||
this.getDeclaringType() instanceof TypeUrl and
|
||||
this.getName() = "openConnection"
|
||||
}
|
||||
}
|
||||
|
||||
/** Constructor of `ApacheHttpRequest` */
|
||||
predicate apacheHttpRequest(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
exists(ConstructorCall cc |
|
||||
cc.getConstructedType() instanceof ApacheHttpRequest and
|
||||
node2.asExpr() = cc and
|
||||
cc.getAnArgument() = node1.asExpr()
|
||||
)
|
||||
}
|
||||
|
||||
/** `URI` methods */
|
||||
predicate createURI(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
exists(
|
||||
URIConstructor cc // new URI
|
||||
|
|
||||
node2.asExpr() = cc and
|
||||
cc.getArgument(0) = node1.asExpr()
|
||||
)
|
||||
or
|
||||
exists(
|
||||
StaticMethodAccess ma // URI.create
|
||||
|
|
||||
ma.getMethod().getDeclaringType() instanceof TypeUri and
|
||||
ma.getMethod().hasName("create") and
|
||||
node1.asExpr() = ma.getArgument(0) and
|
||||
node2.asExpr() = ma
|
||||
)
|
||||
}
|
||||
|
||||
/** Constructors of `URL` */
|
||||
predicate createURL(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
exists(URLConstructor cc |
|
||||
node2.asExpr() = cc and
|
||||
cc.getArgument(0) = node1.asExpr()
|
||||
)
|
||||
}
|
||||
|
||||
/** Method call of `HttpURLOpenMethod` */
|
||||
predicate urlOpen(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
exists(MethodAccess ma |
|
||||
ma.getMethod() instanceof HttpURLOpenMethod and
|
||||
node1.asExpr() = ma.getQualifier() and
|
||||
ma = node2.asExpr()
|
||||
)
|
||||
}
|
||||
|
||||
class BasicAuthFlowConfig extends TaintTracking::Configuration {
|
||||
BasicAuthFlowConfig() { this = "InsecureBasicAuth::BasicAuthFlowConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node src) {
|
||||
src.asExpr() instanceof HttpString
|
||||
or
|
||||
exists(URLConstructor uc |
|
||||
uc.hasHttpStringArg() and
|
||||
src.asExpr() = uc.getArgument(0)
|
||||
)
|
||||
or
|
||||
exists(URIConstructor uc |
|
||||
uc.hasHttpStringArg() and
|
||||
src.asExpr() = uc.getArgument(0)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
exists(MethodAccess ma |
|
||||
sink.asExpr() = ma.getQualifier() and
|
||||
(
|
||||
ma.getMethod().hasName("addHeader") or
|
||||
ma.getMethod().hasName("setHeader") or
|
||||
ma.getMethod().hasName("setRequestProperty")
|
||||
) and
|
||||
ma.getArgument(0).(CompileTimeConstantExpr).getStringValue() = "Authorization" and
|
||||
builtFromBasicAuthStringConcat(ma.getArgument(1))
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
apacheHttpRequest(node1, node2) or
|
||||
createURI(node1, node2) or
|
||||
createURL(node1, node2) or
|
||||
urlOpen(node1, node2)
|
||||
}
|
||||
}
|
||||
|
||||
from DataFlow::PathNode source, DataFlow::PathNode sink, BasicAuthFlowConfig config
|
||||
where config.hasFlowPath(source, sink)
|
||||
select sink.getNode(), source, sink, "Insecure basic authentication from $@.", source.getNode(),
|
||||
"HTTP url"
|
||||
@@ -1,63 +0,0 @@
|
||||
edges
|
||||
| InsecureBasicAuth.java:20:39:20:52 | ... + ... : String | InsecureBasicAuth.java:28:3:28:6 | post |
|
||||
| InsecureBasicAuth.java:35:19:35:64 | "http://www.example.com:8000/payment/retrieve" : String | InsecureBasicAuth.java:38:3:38:5 | get |
|
||||
| InsecureBasicAuth.java:45:19:45:68 | "http://www.example.com/rest/getuser.do?uid=abcdx" : String | InsecureBasicAuth.java:46:50:46:55 | uriStr : String |
|
||||
| InsecureBasicAuth.java:45:19:45:68 | "http://www.example.com/rest/getuser.do?uid=abcdx" : String | InsecureBasicAuth.java:54:3:54:6 | post |
|
||||
| InsecureBasicAuth.java:46:39:46:56 | create(...) : URI | InsecureBasicAuth.java:54:3:54:6 | post |
|
||||
| InsecureBasicAuth.java:46:50:46:55 | uriStr : String | InsecureBasicAuth.java:46:39:46:56 | create(...) : URI |
|
||||
| InsecureBasicAuth.java:61:19:61:68 | "http://www.example.com/rest/getuser.do?uid=abcdx" : String | InsecureBasicAuth.java:62:21:62:26 | uriStr : String |
|
||||
| InsecureBasicAuth.java:61:19:61:68 | "http://www.example.com/rest/getuser.do?uid=abcdx" : String | InsecureBasicAuth.java:71:3:71:6 | post |
|
||||
| InsecureBasicAuth.java:62:13:62:27 | new URI(...) : URI | InsecureBasicAuth.java:71:3:71:6 | post |
|
||||
| InsecureBasicAuth.java:62:21:62:26 | uriStr : String | InsecureBasicAuth.java:62:13:62:27 | new URI(...) : URI |
|
||||
| InsecureBasicAuth.java:78:47:78:52 | "http" : String | InsecureBasicAuth.java:86:3:86:6 | post |
|
||||
| InsecureBasicAuth.java:93:19:93:68 | "http://www.example.com/rest/getuser.do?uid=abcdx" : String | InsecureBasicAuth.java:102:3:102:6 | post |
|
||||
| InsecureBasicAuth.java:109:19:109:68 | "http://www.example.com/rest/getuser.do?uid=abcdx" : String | InsecureBasicAuth.java:110:58:110:63 | uriStr : String |
|
||||
| InsecureBasicAuth.java:110:29:110:70 | new BasicRequestLine(...) : BasicRequestLine | InsecureBasicAuth.java:119:3:119:6 | post |
|
||||
| InsecureBasicAuth.java:110:58:110:63 | uriStr : String | InsecureBasicAuth.java:110:29:110:70 | new BasicRequestLine(...) : BasicRequestLine |
|
||||
| InsecureBasicAuth.java:126:19:126:68 | "http://www.example.com/rest/getuser.do?uid=abcdx" : String | InsecureBasicAuth.java:129:21:129:26 | urlStr : String |
|
||||
| InsecureBasicAuth.java:126:19:126:68 | "http://www.example.com/rest/getuser.do?uid=abcdx" : String | InsecureBasicAuth.java:130:28:130:67 | (...)... : URLConnection |
|
||||
| InsecureBasicAuth.java:129:13:129:27 | new URL(...) : URL | InsecureBasicAuth.java:130:28:130:67 | (...)... : URLConnection |
|
||||
| InsecureBasicAuth.java:129:21:129:26 | urlStr : String | InsecureBasicAuth.java:129:13:129:27 | new URL(...) : URL |
|
||||
| InsecureBasicAuth.java:130:28:130:67 | (...)... : URLConnection | InsecureBasicAuth.java:133:3:133:6 | conn |
|
||||
| InsecureBasicAuth.java:145:21:145:28 | protocol : String | InsecureBasicAuth.java:146:28:146:67 | (...)... : URLConnection |
|
||||
| InsecureBasicAuth.java:146:28:146:67 | (...)... : URLConnection | InsecureBasicAuth.java:149:3:149:6 | conn |
|
||||
nodes
|
||||
| InsecureBasicAuth.java:20:39:20:52 | ... + ... : String | semmle.label | ... + ... : String |
|
||||
| InsecureBasicAuth.java:28:3:28:6 | post | semmle.label | post |
|
||||
| InsecureBasicAuth.java:35:19:35:64 | "http://www.example.com:8000/payment/retrieve" : String | semmle.label | "http://www.example.com:8000/payment/retrieve" : String |
|
||||
| InsecureBasicAuth.java:38:3:38:5 | get | semmle.label | get |
|
||||
| InsecureBasicAuth.java:45:19:45:68 | "http://www.example.com/rest/getuser.do?uid=abcdx" : String | semmle.label | "http://www.example.com/rest/getuser.do?uid=abcdx" : String |
|
||||
| InsecureBasicAuth.java:46:39:46:56 | create(...) : URI | semmle.label | create(...) : URI |
|
||||
| InsecureBasicAuth.java:46:50:46:55 | uriStr : String | semmle.label | uriStr : String |
|
||||
| InsecureBasicAuth.java:54:3:54:6 | post | semmle.label | post |
|
||||
| InsecureBasicAuth.java:61:19:61:68 | "http://www.example.com/rest/getuser.do?uid=abcdx" : String | semmle.label | "http://www.example.com/rest/getuser.do?uid=abcdx" : String |
|
||||
| InsecureBasicAuth.java:62:13:62:27 | new URI(...) : URI | semmle.label | new URI(...) : URI |
|
||||
| InsecureBasicAuth.java:62:21:62:26 | uriStr : String | semmle.label | uriStr : String |
|
||||
| InsecureBasicAuth.java:71:3:71:6 | post | semmle.label | post |
|
||||
| InsecureBasicAuth.java:78:47:78:52 | "http" : String | semmle.label | "http" : String |
|
||||
| InsecureBasicAuth.java:86:3:86:6 | post | semmle.label | post |
|
||||
| InsecureBasicAuth.java:93:19:93:68 | "http://www.example.com/rest/getuser.do?uid=abcdx" : String | semmle.label | "http://www.example.com/rest/getuser.do?uid=abcdx" : String |
|
||||
| InsecureBasicAuth.java:102:3:102:6 | post | semmle.label | post |
|
||||
| InsecureBasicAuth.java:109:19:109:68 | "http://www.example.com/rest/getuser.do?uid=abcdx" : String | semmle.label | "http://www.example.com/rest/getuser.do?uid=abcdx" : String |
|
||||
| InsecureBasicAuth.java:110:29:110:70 | new BasicRequestLine(...) : BasicRequestLine | semmle.label | new BasicRequestLine(...) : BasicRequestLine |
|
||||
| InsecureBasicAuth.java:110:58:110:63 | uriStr : String | semmle.label | uriStr : String |
|
||||
| InsecureBasicAuth.java:119:3:119:6 | post | semmle.label | post |
|
||||
| InsecureBasicAuth.java:126:19:126:68 | "http://www.example.com/rest/getuser.do?uid=abcdx" : String | semmle.label | "http://www.example.com/rest/getuser.do?uid=abcdx" : String |
|
||||
| InsecureBasicAuth.java:129:13:129:27 | new URL(...) : URL | semmle.label | new URL(...) : URL |
|
||||
| InsecureBasicAuth.java:129:21:129:26 | urlStr : String | semmle.label | urlStr : String |
|
||||
| InsecureBasicAuth.java:130:28:130:67 | (...)... : URLConnection | semmle.label | (...)... : URLConnection |
|
||||
| InsecureBasicAuth.java:133:3:133:6 | conn | semmle.label | conn |
|
||||
| InsecureBasicAuth.java:145:21:145:28 | protocol : String | semmle.label | protocol : String |
|
||||
| InsecureBasicAuth.java:146:28:146:67 | (...)... : URLConnection | semmle.label | (...)... : URLConnection |
|
||||
| InsecureBasicAuth.java:149:3:149:6 | conn | semmle.label | conn |
|
||||
subpaths
|
||||
#select
|
||||
| InsecureBasicAuth.java:28:3:28:6 | post | InsecureBasicAuth.java:20:39:20:52 | ... + ... : String | InsecureBasicAuth.java:28:3:28:6 | post | Insecure basic authentication from $@. | InsecureBasicAuth.java:20:39:20:52 | ... + ... | HTTP url |
|
||||
| InsecureBasicAuth.java:38:3:38:5 | get | InsecureBasicAuth.java:35:19:35:64 | "http://www.example.com:8000/payment/retrieve" : String | InsecureBasicAuth.java:38:3:38:5 | get | Insecure basic authentication from $@. | InsecureBasicAuth.java:35:19:35:64 | "http://www.example.com:8000/payment/retrieve" | HTTP url |
|
||||
| InsecureBasicAuth.java:54:3:54:6 | post | InsecureBasicAuth.java:45:19:45:68 | "http://www.example.com/rest/getuser.do?uid=abcdx" : String | InsecureBasicAuth.java:54:3:54:6 | post | Insecure basic authentication from $@. | InsecureBasicAuth.java:45:19:45:68 | "http://www.example.com/rest/getuser.do?uid=abcdx" | HTTP url |
|
||||
| InsecureBasicAuth.java:71:3:71:6 | post | InsecureBasicAuth.java:61:19:61:68 | "http://www.example.com/rest/getuser.do?uid=abcdx" : String | InsecureBasicAuth.java:71:3:71:6 | post | Insecure basic authentication from $@. | InsecureBasicAuth.java:61:19:61:68 | "http://www.example.com/rest/getuser.do?uid=abcdx" | HTTP url |
|
||||
| InsecureBasicAuth.java:86:3:86:6 | post | InsecureBasicAuth.java:78:47:78:52 | "http" : String | InsecureBasicAuth.java:86:3:86:6 | post | Insecure basic authentication from $@. | InsecureBasicAuth.java:78:47:78:52 | "http" | HTTP url |
|
||||
| InsecureBasicAuth.java:102:3:102:6 | post | InsecureBasicAuth.java:93:19:93:68 | "http://www.example.com/rest/getuser.do?uid=abcdx" : String | InsecureBasicAuth.java:102:3:102:6 | post | Insecure basic authentication from $@. | InsecureBasicAuth.java:93:19:93:68 | "http://www.example.com/rest/getuser.do?uid=abcdx" | HTTP url |
|
||||
| InsecureBasicAuth.java:119:3:119:6 | post | InsecureBasicAuth.java:109:19:109:68 | "http://www.example.com/rest/getuser.do?uid=abcdx" : String | InsecureBasicAuth.java:119:3:119:6 | post | Insecure basic authentication from $@. | InsecureBasicAuth.java:109:19:109:68 | "http://www.example.com/rest/getuser.do?uid=abcdx" | HTTP url |
|
||||
| InsecureBasicAuth.java:133:3:133:6 | conn | InsecureBasicAuth.java:126:19:126:68 | "http://www.example.com/rest/getuser.do?uid=abcdx" : String | InsecureBasicAuth.java:133:3:133:6 | conn | Insecure basic authentication from $@. | InsecureBasicAuth.java:126:19:126:68 | "http://www.example.com/rest/getuser.do?uid=abcdx" | HTTP url |
|
||||
| InsecureBasicAuth.java:149:3:149:6 | conn | InsecureBasicAuth.java:145:21:145:28 | protocol : String | InsecureBasicAuth.java:149:3:149:6 | conn | Insecure basic authentication from $@. | InsecureBasicAuth.java:145:21:145:28 | protocol | HTTP url |
|
||||
@@ -1,164 +0,0 @@
|
||||
import org.apache.http.RequestLine;
|
||||
import org.apache.http.client.methods.HttpRequestBase;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.message.BasicHttpRequest;
|
||||
import org.apache.http.message.BasicRequestLine;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URLConnection;
|
||||
import java.util.Base64;
|
||||
|
||||
public class InsecureBasicAuth {
|
||||
/**
|
||||
* Test basic authentication with Apache HTTP POST request using string constructor.
|
||||
*/
|
||||
public void testApacheHttpRequest(String username, String password) {
|
||||
String host = "www.example.com";
|
||||
HttpRequestBase post = new HttpPost("http://"+host+"/rest/getuser.do?uid=abcdx");
|
||||
post.setHeader("Accept", "application/json");
|
||||
post.setHeader("Content-type", "application/json");
|
||||
|
||||
String authString = username + ":" + password;
|
||||
byte[] authEncBytes = Base64.getEncoder().encode(authString.getBytes());
|
||||
String authStringEnc = new String(authEncBytes);
|
||||
|
||||
post.addHeader("Authorization", "Basic " + authStringEnc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test basic authentication with Apache HTTP GET request.
|
||||
*/
|
||||
public void testApacheHttpRequest2(String url) throws java.io.IOException {
|
||||
String urlStr = "http://www.example.com:8000/payment/retrieve";
|
||||
HttpGet get = new HttpGet(urlStr);
|
||||
get.setHeader("Accept", "application/json");
|
||||
get.setHeader("Authorization", "Basic " + new String(Base64.getEncoder().encode("admin:test".getBytes())));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test basic authentication with Apache HTTP POST request using URI create method.
|
||||
*/
|
||||
public void testApacheHttpRequest3(String username, String password) {
|
||||
String uriStr = "http://www.example.com/rest/getuser.do?uid=abcdx";
|
||||
HttpRequestBase post = new HttpPost(URI.create(uriStr));
|
||||
post.setHeader("Accept", "application/json");
|
||||
post.setHeader("Content-type", "application/json");
|
||||
|
||||
String authString = username + ":" + password;
|
||||
byte[] authEncBytes = Base64.getEncoder().encode(authString.getBytes());
|
||||
String authStringEnc = new String(authEncBytes);
|
||||
|
||||
post.addHeader("Authorization", "Basic " + authStringEnc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test basic authentication with Apache HTTP POST request using the URI constructor with one argument.
|
||||
*/
|
||||
public void testApacheHttpRequest4(String username, String password) throws Exception {
|
||||
String uriStr = "http://www.example.com/rest/getuser.do?uid=abcdx";
|
||||
URI uri = new URI(uriStr);
|
||||
HttpRequestBase post = new HttpPost(uri);
|
||||
post.setHeader("Accept", "application/json");
|
||||
post.setHeader("Content-type", "application/json");
|
||||
|
||||
String authString = username + ":" + password;
|
||||
byte[] authEncBytes = Base64.getEncoder().encode(authString.getBytes());
|
||||
String authStringEnc = new String(authEncBytes);
|
||||
|
||||
post.addHeader("Authorization", "Basic " + authStringEnc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test basic authentication with Apache HTTP POST request using a URI constructor with multiple arguments.
|
||||
*/
|
||||
public void testApacheHttpRequest5(String username, String password) throws Exception {
|
||||
HttpRequestBase post = new HttpPost(new URI("http", "www.example.com", "/test", "abc=123", null));
|
||||
post.setHeader("Accept", "application/json");
|
||||
post.setHeader("Content-type", "application/json");
|
||||
|
||||
String authString = username + ":" + password;
|
||||
byte[] authEncBytes = Base64.getEncoder().encode(authString.getBytes());
|
||||
String authStringEnc = new String(authEncBytes);
|
||||
|
||||
post.addHeader("Authorization", "Basic " + authStringEnc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test basic authentication with Apache HTTP `BasicHttpRequest` using string constructor.
|
||||
*/
|
||||
public void testApacheHttpRequest6(String username, String password) {
|
||||
String uriStr = "http://www.example.com/rest/getuser.do?uid=abcdx";
|
||||
BasicHttpRequest post = new BasicHttpRequest("POST", uriStr);
|
||||
post.setHeader("Accept", "application/json");
|
||||
post.setHeader("Content-type", "application/json");
|
||||
|
||||
String authString = username + ":" + password;
|
||||
byte[] authEncBytes = Base64.getEncoder().encode(authString.getBytes());
|
||||
String authStringEnc = new String(authEncBytes);
|
||||
|
||||
post.addHeader("Authorization", "Basic " + authStringEnc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test basic authentication with Apache HTTP `BasicHttpRequest` using `RequestLine`.
|
||||
*/
|
||||
public void testApacheHttpRequest7(String username, String password) {
|
||||
String uriStr = "http://www.example.com/rest/getuser.do?uid=abcdx";
|
||||
RequestLine requestLine = new BasicRequestLine("POST", uriStr, null);
|
||||
BasicHttpRequest post = new BasicHttpRequest(requestLine);
|
||||
post.setHeader("Accept", "application/json");
|
||||
post.setHeader("Content-type", "application/json");
|
||||
|
||||
String authString = username + ":" + password;
|
||||
byte[] authEncBytes = Base64.getEncoder().encode(authString.getBytes());
|
||||
String authStringEnc = new String(authEncBytes);
|
||||
|
||||
post.addHeader("Authorization", "Basic " + authStringEnc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test basic authentication with Java HTTP URL connection using the `URL(String spec)` constructor.
|
||||
*/
|
||||
public void testHttpUrlConnection(String username, String password) throws Exception {
|
||||
String urlStr = "http://www.example.com/rest/getuser.do?uid=abcdx";
|
||||
String authString = username + ":" + password;
|
||||
String encoding = Base64.getEncoder().encodeToString(authString.getBytes("UTF-8"));
|
||||
URL url = new URL(urlStr);
|
||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setRequestMethod("POST");
|
||||
conn.setDoOutput(true);
|
||||
conn.setRequestProperty("Authorization", "Basic " + encoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test basic authentication with Java HTTP URL connection using the `URL(String protocol, String host, String file)` constructor.
|
||||
*/
|
||||
public void testHttpUrlConnection2(String username, String password) throws Exception {
|
||||
String host = "www.example.com";
|
||||
String path = "/rest/getuser.do?uid=abcdx";
|
||||
String protocol = "http";
|
||||
String authString = username + ":" + password;
|
||||
String encoding = Base64.getEncoder().encodeToString(authString.getBytes("UTF-8"));
|
||||
URL url = new URL(protocol, host, path);
|
||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setRequestMethod("POST");
|
||||
conn.setDoOutput(true);
|
||||
conn.setRequestProperty("Authorization", "Basic " + encoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test basic authentication with Java HTTP URL connection using a constructor with private URL.
|
||||
*/
|
||||
public void testHttpUrlConnection3(String username, String password) throws Exception {
|
||||
String host = "LOCALHOST";
|
||||
String authString = username + ":" + password;
|
||||
String encoding = Base64.getEncoder().encodeToString(authString.getBytes("UTF-8"));
|
||||
HttpURLConnection conn = (HttpURLConnection) new URL("http://"+(((host+"/rest/getuser.do")+"?uid=abcdx"))).openConnection();
|
||||
conn.setRequestMethod("POST");
|
||||
conn.setDoOutput(true);
|
||||
conn.setRequestProperty("Authorization", "Basic " + encoding);
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
experimental/Security/CWE/CWE-522/InsecureBasicAuth.ql
|
||||
@@ -0,0 +1,253 @@
|
||||
import org.apache.http.RequestLine;
|
||||
import org.apache.http.client.methods.HttpRequestBase;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.message.BasicHttpRequest;
|
||||
import org.apache.http.message.BasicRequestLine;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URLConnection;
|
||||
import java.util.Base64;
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
|
||||
public class InsecureBasicAuthTest {
|
||||
/**
|
||||
* Test basic authentication with Apache HTTP POST request using string constructor.
|
||||
*/
|
||||
public void testApacheHttpRequest(String username, String password) {
|
||||
String host = "www.example.com";
|
||||
String authString = username + ":" + password;
|
||||
byte[] authEncBytes = Base64.getEncoder().encode(authString.getBytes());
|
||||
String authStringEnc = new String(authEncBytes);
|
||||
{
|
||||
HttpRequestBase post = new HttpPost("http://" + host + "/rest/getuser.do?uid=abcdx");
|
||||
post.setHeader("Accept", "application/json");
|
||||
post.setHeader("Content-type", "application/json");
|
||||
post.addHeader("Authorization", "Basic " + authStringEnc); // $hasInsecureBasicAuth
|
||||
}
|
||||
{
|
||||
HttpRequestBase post = new HttpPost("https://" + host + "/rest/getuser.do?uid=abcdx");
|
||||
post.setHeader("Accept", "application/json");
|
||||
post.setHeader("Content-type", "application/json");
|
||||
post.addHeader("Authorization", "Basic " + authStringEnc); // Safe
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test basic authentication with Apache HTTP GET request.
|
||||
*/
|
||||
public void testApacheHttpRequest2(String url) throws java.io.IOException {
|
||||
{
|
||||
String urlStr = "http://www.example.com:8000/payment/retrieve";
|
||||
HttpGet get = new HttpGet(urlStr);
|
||||
get.setHeader("Accept", "application/json");
|
||||
get.setHeader("Authorization", // $hasInsecureBasicAuth
|
||||
"Basic " + new String(Base64.getEncoder().encode("admin:test".getBytes())));
|
||||
}
|
||||
{
|
||||
String urlStr = "https://www.example.com:8000/payment/retrieve";
|
||||
HttpGet get = new HttpGet(urlStr);
|
||||
get.setHeader("Accept", "application/json");
|
||||
get.setHeader("Authorization", // Safe
|
||||
"Basic " + new String(Base64.getEncoder().encode("admin:test".getBytes())));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test basic authentication with Apache HTTP POST request using URI create method.
|
||||
*/
|
||||
public void testApacheHttpRequest3(String username, String password) {
|
||||
String authString = username + ":" + password;
|
||||
byte[] authEncBytes = Base64.getEncoder().encode(authString.getBytes());
|
||||
String authStringEnc = new String(authEncBytes);
|
||||
{
|
||||
String uriStr = "http://www.example.com/rest/getuser.do?uid=abcdx";
|
||||
HttpRequestBase post = new HttpPost(URI.create(uriStr));
|
||||
post.setHeader("Accept", "application/json");
|
||||
post.setHeader("Content-type", "application/json");
|
||||
post.addHeader("Authorization", "Basic " + authStringEnc); // $hasInsecureBasicAuth
|
||||
}
|
||||
{
|
||||
String uriStr = "https://www.example.com/rest/getuser.do?uid=abcdx";
|
||||
HttpRequestBase post = new HttpPost(URI.create(uriStr));
|
||||
post.setHeader("Accept", "application/json");
|
||||
post.setHeader("Content-type", "application/json");
|
||||
post.addHeader("Authorization", "Basic " + authStringEnc); // Safe
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test basic authentication with Apache HTTP POST request using the URI constructor with one
|
||||
* argument.
|
||||
*/
|
||||
public void testApacheHttpRequest4(String username, String password) throws Exception {
|
||||
String authString = username + ":" + password;
|
||||
byte[] authEncBytes = Base64.getEncoder().encode(authString.getBytes());
|
||||
String authStringEnc = new String(authEncBytes);
|
||||
{
|
||||
String uriStr = "http://www.example.com/rest/getuser.do?uid=abcdx";
|
||||
URI uri = new URI(uriStr);
|
||||
HttpRequestBase post = new HttpPost(uri);
|
||||
post.setHeader("Accept", "application/json");
|
||||
post.setHeader("Content-type", "application/json");
|
||||
post.addHeader("Authorization", "Basic " + authStringEnc); // $hasInsecureBasicAuth
|
||||
}
|
||||
{
|
||||
String uriStr = "https://www.example.com/rest/getuser.do?uid=abcdx";
|
||||
URI uri = new URI(uriStr);
|
||||
HttpRequestBase post = new HttpPost(uri);
|
||||
post.setHeader("Accept", "application/json");
|
||||
post.setHeader("Content-type", "application/json");
|
||||
post.addHeader("Authorization", "Basic " + authStringEnc); // Safe
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test basic authentication with Apache HTTP POST request using a URI constructor with multiple
|
||||
* arguments.
|
||||
*/
|
||||
public void testApacheHttpRequest5(String username, String password) throws Exception {
|
||||
String authString = username + ":" + password;
|
||||
byte[] authEncBytes = Base64.getEncoder().encode(authString.getBytes());
|
||||
String authStringEnc = new String(authEncBytes);
|
||||
{
|
||||
HttpRequestBase post =
|
||||
new HttpPost(new URI("http", "www.example.com", "/test", "abc=123", null));
|
||||
post.setHeader("Accept", "application/json");
|
||||
post.setHeader("Content-type", "application/json");
|
||||
post.addHeader("Authorization", "Basic " + authStringEnc); // $hasInsecureBasicAuth
|
||||
}
|
||||
{
|
||||
HttpRequestBase post =
|
||||
new HttpPost(new URI("https", "www.example.com", "/test", "abc=123", null));
|
||||
post.setHeader("Accept", "application/json");
|
||||
post.setHeader("Content-type", "application/json");
|
||||
post.addHeader("Authorization", "Basic " + authStringEnc); // Safe
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test basic authentication with Apache HTTP `BasicHttpRequest` using string constructor.
|
||||
*/
|
||||
public void testApacheHttpRequest6(String username, String password) {
|
||||
String authString = username + ":" + password;
|
||||
byte[] authEncBytes = Base64.getEncoder().encode(authString.getBytes());
|
||||
String authStringEnc = new String(authEncBytes);
|
||||
{
|
||||
String uriStr = "http://www.example.com/rest/getuser.do?uid=abcdx";
|
||||
BasicHttpRequest post = new BasicHttpRequest("POST", uriStr);
|
||||
post.setHeader("Accept", "application/json");
|
||||
post.setHeader("Content-type", "application/json");
|
||||
post.addHeader("Authorization", "Basic " + authStringEnc); // $hasInsecureBasicAuth
|
||||
}
|
||||
{
|
||||
String uriStr = "https://www.example.com/rest/getuser.do?uid=abcdx";
|
||||
BasicHttpRequest post = new BasicHttpRequest("POST", uriStr);
|
||||
post.setHeader("Accept", "application/json");
|
||||
post.setHeader("Content-type", "application/json");
|
||||
post.addHeader("Authorization", "Basic " + authStringEnc); // Safe
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test basic authentication with Apache HTTP `BasicHttpRequest` using `RequestLine`.
|
||||
*/
|
||||
public void testApacheHttpRequest7(String username, String password) {
|
||||
String authString = username + ":" + password;
|
||||
byte[] authEncBytes = Base64.getEncoder().encode(authString.getBytes());
|
||||
String authStringEnc = new String(authEncBytes);
|
||||
{
|
||||
String uriStr = "http://www.example.com/rest/getuser.do?uid=abcdx";
|
||||
RequestLine requestLine = new BasicRequestLine("POST", uriStr, null);
|
||||
BasicHttpRequest post = new BasicHttpRequest(requestLine);
|
||||
post.setHeader("Accept", "application/json");
|
||||
post.setHeader("Content-type", "application/json");
|
||||
post.addHeader("Authorization", "Basic " + authStringEnc); // $hasInsecureBasicAuth
|
||||
}
|
||||
{
|
||||
String uriStr = "https://www.example.com/rest/getuser.do?uid=abcdx";
|
||||
RequestLine requestLine = new BasicRequestLine("POST", uriStr, null);
|
||||
BasicHttpRequest post = new BasicHttpRequest(requestLine);
|
||||
post.setHeader("Accept", "application/json");
|
||||
post.setHeader("Content-type", "application/json");
|
||||
post.addHeader("Authorization", "Basic " + authStringEnc); // Safe
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test basic authentication with Java HTTP URL connection using the `URL(String spec)`
|
||||
* constructor.
|
||||
*/
|
||||
public void testHttpUrlConnection(String username, String password) throws Exception {
|
||||
String authString = username + ":" + password;
|
||||
String encoding = Base64.getEncoder().encodeToString(authString.getBytes("UTF-8"));
|
||||
{
|
||||
String urlStr = "http://www.example.com/rest/getuser.do?uid=abcdx";
|
||||
URL url = new URL(urlStr);
|
||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setRequestMethod("POST");
|
||||
conn.setDoOutput(true);
|
||||
conn.setRequestProperty("Authorization", "Basic " + encoding); // $hasInsecureBasicAuth
|
||||
}
|
||||
{
|
||||
String urlStr = "https://www.example.com/rest/getuser.do?uid=abcdx";
|
||||
URL url = new URL(urlStr);
|
||||
HttpURLConnection conn = (HttpsURLConnection) url.openConnection();
|
||||
conn.setRequestMethod("POST");
|
||||
conn.setDoOutput(true);
|
||||
conn.setRequestProperty("Authorization", "Basic " + encoding); // Safe
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test basic authentication with Java HTTP URL connection using the `URL(String protocol,
|
||||
* String host, String file)` constructor.
|
||||
*/
|
||||
public void testHttpUrlConnection2(String username, String password) throws Exception {
|
||||
String authString = username + ":" + password;
|
||||
String encoding = Base64.getEncoder().encodeToString(authString.getBytes("UTF-8"));
|
||||
String host = "www.example.com";
|
||||
String path = "/rest/getuser.do?uid=abcdx";
|
||||
{
|
||||
String protocol = "http";
|
||||
URL url = new URL(protocol, host, path);
|
||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setRequestMethod("POST");
|
||||
conn.setDoOutput(true);
|
||||
conn.setRequestProperty("Authorization", "Basic " + encoding); // $hasInsecureBasicAuth
|
||||
}
|
||||
{
|
||||
String protocol = "https";
|
||||
URL url = new URL(protocol, host, path);
|
||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setRequestMethod("POST");
|
||||
conn.setDoOutput(true);
|
||||
conn.setRequestProperty("Authorization", "Basic " + encoding); // Safe
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test basic authentication with Java HTTP URL connection using a constructor with private URL.
|
||||
*/
|
||||
public void testHttpUrlConnection3(String username, String password) throws Exception {
|
||||
String host = "LOCALHOST";
|
||||
String authString = username + ":" + password;
|
||||
String encoding = Base64.getEncoder().encodeToString(authString.getBytes("UTF-8"));
|
||||
{
|
||||
HttpURLConnection conn = (HttpURLConnection) new URL(
|
||||
"http://" + (((host + "/rest/getuser.do") + "?uid=abcdx"))).openConnection();
|
||||
conn.setRequestMethod("POST");
|
||||
conn.setDoOutput(true);
|
||||
conn.setRequestProperty("Authorization", "Basic " + encoding); // Safe
|
||||
}
|
||||
{
|
||||
HttpURLConnection conn = (HttpURLConnection) new URL(
|
||||
"https://" + (((host + "/rest/getuser.do") + "?uid=abcdx"))).openConnection();
|
||||
conn.setRequestMethod("POST");
|
||||
conn.setDoOutput(true);
|
||||
conn.setRequestProperty("Authorization", "Basic " + encoding); // Safe
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import java
|
||||
import semmle.code.java.security.InsecureBasicAuthQuery
|
||||
import TestUtilities.InlineExpectationsTest
|
||||
|
||||
class HasInsecureBasicAuthTest extends InlineExpectationsTest {
|
||||
HasInsecureBasicAuthTest() { this = "HasInsecureBasicAuthTest" }
|
||||
|
||||
override string getARelevantTag() { result = "hasInsecureBasicAuth" }
|
||||
|
||||
override predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
tag = "hasInsecureBasicAuth" and
|
||||
exists(DataFlow::Node src, DataFlow::Node sink, BasicAuthFlowConfig conf |
|
||||
conf.hasFlow(src, sink)
|
||||
|
|
||||
sink.getLocation() = location and
|
||||
element = sink.toString() and
|
||||
value = ""
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
// semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/apache-http-4.4.13
|
||||
// semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/apache-http-4.4.13
|
||||
Reference in New Issue
Block a user