mirror of
https://github.com/github/codeql.git
synced 2026-04-30 03:05:15 +02:00
Merge pull request #8318 from geoffw0/cwe497b
C++: New query cpp/potential-system-data-exposure
This commit is contained in:
@@ -3,17 +3,17 @@
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>Exposing system data or debugging information may help an adversary to learn about the system and form an attack plan. An attacker can use error messages that reveal technologies, operating systems, and product versions to tune their attack against known vulnerabilities in these technologies.</p>
|
||||
<p>Exposing system data or debugging information may help a malicious user learn about the system and form an attack plan. An attacker can use error messages that reveal technologies, operating systems, and product versions to tune their attack against known vulnerabilities in the software.</p>
|
||||
|
||||
<p>This query finds locations where system configuration information might be revealed to a user.</p>
|
||||
<p>This query finds locations where system configuration information might be revealed to a remote user.</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>Do not expose system configuration information to users. Be wary of the difference between information that could be helpful to users, and unnecessary details that could be useful to an adversary.</p>
|
||||
<p>Do not expose system configuration information to remote users. Be wary of the difference between information that could be helpful to users, and unnecessary details that could be useful to a malicious user.</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>In this example the value of the <code>PATH</code> environment variable is revealed in full to the user when a particular error occurs. This might reveal information such as the software installed on your system to an adversary who does not have legitimate access to that information.</p>
|
||||
<p>In this example the value of the <code>PATH</code> environment variable is revealed in full to the user when a particular error occurs. This might reveal information such as the software installed on your system to a malicious user who does not have legitimate access to that information.</p>
|
||||
|
||||
<sample src="ExposedSystemDataIncorrect.cpp" />
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @name Exposure of system data to an unauthorized control sphere
|
||||
* @description Exposing system data or debugging information helps
|
||||
* an adversary learn about the system and form an
|
||||
* a malicious user learn about the system and form an
|
||||
* attack plan.
|
||||
* @kind path-problem
|
||||
* @problem.severity warning
|
||||
@@ -13,284 +13,15 @@
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.commons.Environment
|
||||
import semmle.code.cpp.ir.dataflow.TaintTracking
|
||||
import semmle.code.cpp.models.interfaces.FlowSource
|
||||
import DataFlow::PathGraph
|
||||
|
||||
/**
|
||||
* An element that should not be exposed to an adversary.
|
||||
*/
|
||||
abstract class SystemData extends Element {
|
||||
/**
|
||||
* Gets an expression that is part of this `SystemData`.
|
||||
*/
|
||||
abstract Expr getAnExpr();
|
||||
}
|
||||
|
||||
/**
|
||||
* Data originating from the environment.
|
||||
*/
|
||||
class EnvData extends SystemData {
|
||||
EnvData() {
|
||||
// identify risky looking environment variables only
|
||||
this.(EnvironmentRead)
|
||||
.getEnvironmentVariable()
|
||||
.toLowerCase()
|
||||
.regexpMatch(".*(user|host|admin|root|home|path|http|ssl|snmp|sock|port|proxy|pass|token|crypt|key).*")
|
||||
}
|
||||
|
||||
override Expr getAnExpr() { result = this }
|
||||
}
|
||||
|
||||
/**
|
||||
* Data originating from a call to `mysql_get_client_info()`.
|
||||
*/
|
||||
class SqlClientInfo extends SystemData {
|
||||
SqlClientInfo() { this.(FunctionCall).getTarget().hasName("mysql_get_client_info") }
|
||||
|
||||
override Expr getAnExpr() { result = this }
|
||||
}
|
||||
|
||||
private predicate sqlConnectInfo(FunctionCall source, VariableAccess use) {
|
||||
(
|
||||
source.getTarget().hasName("mysql_connect") or
|
||||
source.getTarget().hasName("mysql_real_connect")
|
||||
) and
|
||||
use = source.getAnArgument()
|
||||
}
|
||||
|
||||
/**
|
||||
* Data passed into an SQL connect function.
|
||||
*/
|
||||
class SqlConnectInfo extends SystemData {
|
||||
SqlConnectInfo() { sqlConnectInfo(this, _) }
|
||||
|
||||
override Expr getAnExpr() { sqlConnectInfo(this, result) }
|
||||
}
|
||||
|
||||
private predicate posixSystemInfo(FunctionCall source, Element use) {
|
||||
// size_t confstr(int name, char *buf, size_t len)
|
||||
// - various OS / system strings, such as the libc version
|
||||
// int statvfs(const char *__path, struct statvfs *__buf)
|
||||
// int fstatvfs(int __fd, struct statvfs *__buf)
|
||||
// - various filesystem parameters
|
||||
// int uname(struct utsname *buf)
|
||||
// - OS name and version
|
||||
source.getTarget().hasName(["confstr", "statvfs", "fstatvfs", "uname"]) and
|
||||
use = source.getArgument(1)
|
||||
}
|
||||
|
||||
/**
|
||||
* Data obtained from a POSIX system information call.
|
||||
*/
|
||||
class PosixSystemInfo extends SystemData {
|
||||
PosixSystemInfo() { posixSystemInfo(this, _) }
|
||||
|
||||
override Expr getAnExpr() { posixSystemInfo(this, result) }
|
||||
}
|
||||
|
||||
private predicate posixPWInfo(FunctionCall source, Element use) {
|
||||
// struct passwd *getpwnam(const char *name);
|
||||
// struct passwd *getpwuid(uid_t uid);
|
||||
// struct passwd *getpwent(void);
|
||||
// struct group *getgrnam(const char *name);
|
||||
// struct group *getgrgid(gid_t);
|
||||
// struct group *getgrent(void);
|
||||
source
|
||||
.getTarget()
|
||||
.hasName(["getpwnam", "getpwuid", "getpwent", "getgrnam", "getgrgid", "getgrent"]) and
|
||||
use = source
|
||||
or
|
||||
// int getpwnam_r(const char *name, struct passwd *pwd,
|
||||
// char *buf, size_t buflen, struct passwd **result);
|
||||
// int getpwuid_r(uid_t uid, struct passwd *pwd,
|
||||
// char *buf, size_t buflen, struct passwd **result);
|
||||
// int getgrgid_r(gid_t gid, struct group *grp,
|
||||
// char *buf, size_t buflen, struct group **result);
|
||||
// int getgrnam_r(const char *name, struct group *grp,
|
||||
// char *buf, size_t buflen, struct group **result);
|
||||
source.getTarget().hasName(["getpwnam_r", "getpwuid_r", "getgrgid_r", "getgrnam_r"]) and
|
||||
use = source.getArgument([1, 2, 4])
|
||||
or
|
||||
// int getpwent_r(struct passwd *pwd, char *buffer, size_t bufsize,
|
||||
// struct passwd **result);
|
||||
// int getgrent_r(struct group *gbuf, char *buf,
|
||||
// size_t buflen, struct group **gbufp);
|
||||
source.getTarget().hasName(["getpwent_r", "getgrent_r"]) and
|
||||
use = source.getArgument([0, 1, 3])
|
||||
}
|
||||
|
||||
/**
|
||||
* Data obtained from a POSIX user/password/group database information call.
|
||||
*/
|
||||
class PosixPWInfo extends SystemData {
|
||||
PosixPWInfo() { posixPWInfo(this, _) }
|
||||
|
||||
override Expr getAnExpr() { posixPWInfo(this, result) }
|
||||
}
|
||||
|
||||
private predicate windowsSystemInfo(FunctionCall source, Element use) {
|
||||
// DWORD WINAPI GetVersion(void);
|
||||
source.getTarget().hasGlobalName("GetVersion") and
|
||||
use = source
|
||||
or
|
||||
// BOOL WINAPI GetVersionEx(_Inout_ LPOSVERSIONINFO lpVersionInfo);
|
||||
// void WINAPI GetSystemInfo(_Out_ LPSYSTEM_INFO lpSystemInfo);
|
||||
// void WINAPI GetNativeSystemInfo(_Out_ LPSYSTEM_INFO lpSystemInfo);
|
||||
source
|
||||
.getTarget()
|
||||
.hasGlobalName([
|
||||
"GetVersionEx", "GetVersionExA", "GetVersionExW", "GetSystemInfo", "GetNativeSystemInfo"
|
||||
]) and
|
||||
use = source.getArgument(0)
|
||||
}
|
||||
|
||||
/**
|
||||
* Data obtained from a Windows system information call.
|
||||
*/
|
||||
class WindowsSystemInfo extends SystemData {
|
||||
WindowsSystemInfo() { windowsSystemInfo(this, _) }
|
||||
|
||||
override Expr getAnExpr() { windowsSystemInfo(this, result) }
|
||||
}
|
||||
|
||||
private predicate windowsFolderPath(FunctionCall source, Element use) {
|
||||
// BOOL SHGetSpecialFolderPath(
|
||||
// HWND hwndOwner,
|
||||
// _Out_ LPTSTR lpszPath,
|
||||
// _In_ int csidl,
|
||||
// _In_ BOOL fCreate
|
||||
// );
|
||||
source
|
||||
.getTarget()
|
||||
.hasGlobalName([
|
||||
"SHGetSpecialFolderPath", "SHGetSpecialFolderPathA", "SHGetSpecialFolderPathW"
|
||||
]) and
|
||||
use = source.getArgument(1)
|
||||
or
|
||||
// HRESULT SHGetKnownFolderPath(
|
||||
// _In_ REFKNOWNFOLDERID rfid,
|
||||
// _In_ DWORD dwFlags,
|
||||
// _In_opt_ HANDLE hToken,
|
||||
// _Out_ PWSTR *ppszPath
|
||||
// );
|
||||
source.getTarget().hasGlobalName("SHGetKnownFolderPath") and
|
||||
use = source.getArgument(3)
|
||||
or
|
||||
// HRESULT SHGetFolderPath(
|
||||
// _In_ HWND hwndOwner,
|
||||
// _In_ int nFolder,
|
||||
// _In_ HANDLE hToken,
|
||||
// _In_ DWORD dwFlags,
|
||||
// _Out_ LPTSTR pszPath
|
||||
// );
|
||||
source.getTarget().hasGlobalName(["SHGetFolderPath", "SHGetFolderPathA", "SHGetFolderPathW"]) and
|
||||
use = source.getArgument(4)
|
||||
or
|
||||
// HRESULT SHGetFolderPathAndSubDir(
|
||||
// _In_ HWND hwnd,
|
||||
// _In_ int csidl,
|
||||
// _In_ HANDLE hToken,
|
||||
// _In_ DWORD dwFlags,
|
||||
// _In_ LPCTSTR pszSubDir,
|
||||
// _Out_ LPTSTR pszPath
|
||||
// );
|
||||
source
|
||||
.getTarget()
|
||||
.hasGlobalName([
|
||||
"SHGetFolderPathAndSubDir", "SHGetFolderPathAndSubDirA", "SHGetFolderPathAndSubDirW"
|
||||
]) and
|
||||
use = source.getArgument(5)
|
||||
}
|
||||
|
||||
/**
|
||||
* Data obtained about Windows special paths (for example, the
|
||||
* location of `System32`).
|
||||
*/
|
||||
class WindowsFolderPath extends SystemData {
|
||||
WindowsFolderPath() { windowsFolderPath(this, _) }
|
||||
|
||||
override Expr getAnExpr() { windowsFolderPath(this, result) }
|
||||
}
|
||||
|
||||
private predicate logonUser(FunctionCall source, VariableAccess use) {
|
||||
source.getTarget().hasGlobalName(["LogonUser", "LogonUserW", "LogonUserA"]) and
|
||||
use = source.getAnArgument()
|
||||
}
|
||||
|
||||
/**
|
||||
* Data passed into a `LogonUser` (Windows) function.
|
||||
*/
|
||||
class LogonUser extends SystemData {
|
||||
LogonUser() { logonUser(this, _) }
|
||||
|
||||
override Expr getAnExpr() { logonUser(this, result) }
|
||||
}
|
||||
|
||||
private predicate regQuery(FunctionCall source, VariableAccess use) {
|
||||
// LONG WINAPI RegQueryValue(
|
||||
// _In_ HKEY hKey,
|
||||
// _In_opt_ LPCTSTR lpSubKey,
|
||||
// _Out_opt_ LPTSTR lpValue,
|
||||
// _Inout_opt_ PLONG lpcbValue
|
||||
// );
|
||||
source.getTarget().hasGlobalName(["RegQueryValue", "RegQueryValueA", "RegQueryValueW"]) and
|
||||
use = source.getArgument(2)
|
||||
or
|
||||
// LONG WINAPI RegQueryMultipleValues(
|
||||
// _In_ HKEY hKey,
|
||||
// _Out_ PVALENT val_list,
|
||||
// _In_ DWORD num_vals,
|
||||
// _Out_opt_ LPTSTR lpValueBuf,
|
||||
// _Inout_opt_ LPDWORD ldwTotsize
|
||||
// );
|
||||
source
|
||||
.getTarget()
|
||||
.hasGlobalName([
|
||||
"RegQueryMultipleValues", "RegQueryMultipleValuesA", "RegQueryMultipleValuesW"
|
||||
]) and
|
||||
use = source.getArgument(3)
|
||||
or
|
||||
// LONG WINAPI RegQueryValueEx(
|
||||
// _In_ HKEY hKey,
|
||||
// _In_opt_ LPCTSTR lpValueName,
|
||||
// _Reserved_ LPDWORD lpReserved,
|
||||
// _Out_opt_ LPDWORD lpType,
|
||||
// _Out_opt_ LPBYTE lpData,
|
||||
// _Inout_opt_ LPDWORD lpcbData
|
||||
// );
|
||||
source.getTarget().hasGlobalName(["RegQueryValueEx", "RegQueryValueExA", "RegQueryValueExW"]) and
|
||||
use = source.getArgument(4)
|
||||
or
|
||||
// LONG WINAPI RegGetValue(
|
||||
// _In_ HKEY hkey,
|
||||
// _In_opt_ LPCTSTR lpSubKey,
|
||||
// _In_opt_ LPCTSTR lpValue,
|
||||
// _In_opt_ DWORD dwFlags,
|
||||
// _Out_opt_ LPDWORD pdwType,
|
||||
// _Out_opt_ PVOID pvData,
|
||||
// _Inout_opt_ LPDWORD pcbData
|
||||
// );
|
||||
source.getTarget().hasGlobalName(["RegGetValue", "RegGetValueA", "RegGetValueW"]) and
|
||||
use = source.getArgument(5)
|
||||
}
|
||||
|
||||
/**
|
||||
* Data read from the Windows registry.
|
||||
*/
|
||||
class RegQuery extends SystemData {
|
||||
RegQuery() { regQuery(this, _) }
|
||||
|
||||
override Expr getAnExpr() { regQuery(this, result) }
|
||||
}
|
||||
import SystemData
|
||||
|
||||
class ExposedSystemDataConfiguration extends TaintTracking::Configuration {
|
||||
ExposedSystemDataConfiguration() { this = "ExposedSystemDataConfiguration" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
source.asConvertedExpr() = any(SystemData sd).getAnExpr()
|
||||
}
|
||||
override predicate isSource(DataFlow::Node source) { source = any(SystemData sd).getAnExpr() }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
exists(FunctionCall fc, FunctionInput input, int arg |
|
||||
|
||||
@@ -2,6 +2,5 @@ char* path = getenv("PATH");
|
||||
|
||||
//...
|
||||
|
||||
fprintf(stderr, "A required executable file could not be found. " \
|
||||
"Please ensure that the software has been installed " \
|
||||
"correctly or contact a system administrator.\n");
|
||||
message = "An internal error has occurred. Please try again or contact a system administrator.\n";
|
||||
send(socket, message, strlen(message), 0);
|
||||
@@ -2,4 +2,5 @@ char* path = getenv("PATH");
|
||||
|
||||
//...
|
||||
|
||||
fprintf(stderr, "cannot find exe on path %s\n", path);
|
||||
sprintf(buffer, "Cannot find exe on path: %s", path);
|
||||
send(socket, buffer, strlen(buffer), 0);
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>Exposing system data or debugging information may help a malicious user learn about the system and form an attack plan. An attacker can use error messages that reveal technologies, operating systems, and product versions to tune their attack against known vulnerabilities in the software.</p>
|
||||
|
||||
<p>This query finds locations where system configuration information that is particularly sensitive might be revealed to a user.</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>Do not expose system configuration information to users. Be wary of the difference between information that could be helpful to users, and unnecessary details that could be useful to a malicious user.</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>In this example the value of the <code>PATH</code> environment variable is revealed in full to the user when a particular error occurs. This might reveal information such as the software installed on your system to a malicious user who does not have legitimate access to that information.</p>
|
||||
|
||||
<sample src="PotentiallyExposedSystemDataIncorrect.cpp" />
|
||||
|
||||
<p>The message should be rephrased without this information, for example:</p>
|
||||
|
||||
<sample src="PotentiallyExposedSystemDataCorrect.cpp" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
</references>
|
||||
|
||||
</qhelp>
|
||||
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* @name Potential exposure of sensitive system data to an unauthorized control sphere
|
||||
* @description Exposing sensitive system data helps
|
||||
* a malicious user learn about the system and form an
|
||||
* attack plan.
|
||||
* @kind path-problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 6.5
|
||||
* @precision medium
|
||||
* @id cpp/potential-system-data-exposure
|
||||
* @tags security
|
||||
* external/cwe/cwe-497
|
||||
*/
|
||||
|
||||
/*
|
||||
* These queries are closely related:
|
||||
* - `cpp/system-data-exposure`, which flags exposure of system information
|
||||
* to a remote sink (i.e. focusses on quality of the sink).
|
||||
* - `cpp/potential-system-data-exposure`, which flags on exposure of the most
|
||||
* sensitive information to a local sink (i.e. focusses on quality of the
|
||||
* sensitive information).
|
||||
*
|
||||
* This used to be a single query with neither focus, which was too noisy and
|
||||
* gave the user less control.
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.ir.dataflow.TaintTracking
|
||||
import semmle.code.cpp.models.interfaces.FlowSource
|
||||
import semmle.code.cpp.security.OutputWrite
|
||||
import DataFlow::PathGraph
|
||||
import SystemData
|
||||
|
||||
class PotentiallyExposedSystemDataConfiguration extends TaintTracking::Configuration {
|
||||
PotentiallyExposedSystemDataConfiguration() { this = "PotentiallyExposedSystemDataConfiguration" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
source = any(SystemData sd | sd.isSensitive()).getAnExpr()
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
exists(OutputWrite ow | ow.getASource().getAChild*() = sink.asExpr())
|
||||
}
|
||||
}
|
||||
|
||||
from
|
||||
PotentiallyExposedSystemDataConfiguration config, DataFlow::PathNode source,
|
||||
DataFlow::PathNode sink
|
||||
where config.hasFlowPath(source, sink)
|
||||
select sink, source, sink, "This operation potentially exposes sensitive system data from $@.",
|
||||
source, source.getNode().toString()
|
||||
@@ -0,0 +1,5 @@
|
||||
char* key = getenv("APP_KEY");
|
||||
|
||||
//...
|
||||
|
||||
fprintf(stderr, "Application key not recognized. Please ensure the key is correct or contact a system administrator.\n", key);
|
||||
@@ -0,0 +1,5 @@
|
||||
char* key = getenv("APP_KEY");
|
||||
|
||||
//...
|
||||
|
||||
fprintf(stderr, "Key not recognized: %s\n", key);
|
||||
342
cpp/ql/src/Security/CWE/CWE-497/SystemData.qll
Normal file
342
cpp/ql/src/Security/CWE/CWE-497/SystemData.qll
Normal file
@@ -0,0 +1,342 @@
|
||||
/**
|
||||
* Classes for recognizing system data, used by the exposed system data queries.
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.commons.Environment
|
||||
import semmle.code.cpp.ir.dataflow.TaintTracking
|
||||
|
||||
/**
|
||||
* An element that should not be exposed to a malicious user.
|
||||
*/
|
||||
abstract class SystemData extends Element {
|
||||
/**
|
||||
* Gets an expression that is part of this `SystemData`.
|
||||
*/
|
||||
abstract DataFlow::Node getAnExpr();
|
||||
|
||||
/**
|
||||
* Holds if this system data is considered especially sensitive (for example
|
||||
* a password or token).
|
||||
*/
|
||||
predicate isSensitive() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Data originating from the environment.
|
||||
*/
|
||||
class EnvData extends SystemData {
|
||||
EnvData() {
|
||||
// identify risky looking environment variables only
|
||||
this.(EnvironmentRead)
|
||||
.getEnvironmentVariable()
|
||||
.toLowerCase()
|
||||
.regexpMatch(".*(user|host|admin|root|home|path|http|ssl|snmp|sock|port|proxy|pass|token|crypt|key).*")
|
||||
}
|
||||
|
||||
override DataFlow::Node getAnExpr() { result.asConvertedExpr() = this }
|
||||
|
||||
override predicate isSensitive() {
|
||||
this.(EnvironmentRead)
|
||||
.getEnvironmentVariable()
|
||||
.toLowerCase()
|
||||
.regexpMatch(".*(pass|token|key).*")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Data originating from a call to `mysql_get_client_info()`.
|
||||
*/
|
||||
class SQLClientInfo extends SystemData {
|
||||
SQLClientInfo() { this.(FunctionCall).getTarget().hasName("mysql_get_client_info") }
|
||||
|
||||
override DataFlow::Node getAnExpr() { result.asConvertedExpr() = this }
|
||||
|
||||
override predicate isSensitive() { any() }
|
||||
}
|
||||
|
||||
private predicate sqlConnectInfo(FunctionCall source, Expr use) {
|
||||
(
|
||||
source.getTarget().hasName("mysql_connect") or
|
||||
source.getTarget().hasName("mysql_real_connect")
|
||||
) and
|
||||
use = source.getAnArgument()
|
||||
}
|
||||
|
||||
/**
|
||||
* Data passed into an SQL connect function.
|
||||
*/
|
||||
class SQLConnectInfo extends SystemData {
|
||||
SQLConnectInfo() { sqlConnectInfo(this, _) }
|
||||
|
||||
override DataFlow::Node getAnExpr() { sqlConnectInfo(this, result.asConvertedExpr()) }
|
||||
|
||||
override predicate isSensitive() { any() }
|
||||
}
|
||||
|
||||
private predicate posixSystemInfo(FunctionCall source, DataFlow::Node use) {
|
||||
// size_t confstr(int name, char *buf, size_t len)
|
||||
// - various OS / system strings, such as the libc version
|
||||
// int statvfs(const char *__path, struct statvfs *__buf)
|
||||
// int fstatvfs(int __fd, struct statvfs *__buf)
|
||||
source.getTarget().hasName(["confstr", "statvfs", "fstatvfs"]) and
|
||||
use.asDefiningArgument() = source.getArgument(1)
|
||||
or
|
||||
// - various filesystem parameters
|
||||
// int uname(struct utsname *buf)
|
||||
// - OS name and version
|
||||
source.getTarget().hasName("uname") and
|
||||
use.asDefiningArgument() = source.getArgument(0)
|
||||
}
|
||||
|
||||
/**
|
||||
* Data obtained from a POSIX system information call.
|
||||
*/
|
||||
class PosixSystemInfo extends SystemData {
|
||||
PosixSystemInfo() { posixSystemInfo(this, _) }
|
||||
|
||||
override DataFlow::Node getAnExpr() { posixSystemInfo(this, result) }
|
||||
}
|
||||
|
||||
private predicate posixPWInfo(FunctionCall source, DataFlow::Node use) {
|
||||
// struct passwd *getpwnam(const char *name);
|
||||
// struct passwd *getpwuid(uid_t uid);
|
||||
// struct passwd *getpwent(void);
|
||||
// struct group *getgrnam(const char *name);
|
||||
// struct group *getgrgid(gid_t);
|
||||
// struct group *getgrent(void);
|
||||
source
|
||||
.getTarget()
|
||||
.hasName(["getpwnam", "getpwuid", "getpwent", "getgrnam", "getgrgid", "getgrent"]) and
|
||||
use.asConvertedExpr() = source
|
||||
or
|
||||
// int getpwnam_r(const char *name, struct passwd *pwd,
|
||||
// char *buf, size_t buflen, struct passwd **result);
|
||||
// int getpwuid_r(uid_t uid, struct passwd *pwd,
|
||||
// char *buf, size_t buflen, struct passwd **result);
|
||||
// int getgrgid_r(gid_t gid, struct group *grp,
|
||||
// char *buf, size_t buflen, struct group **result);
|
||||
// int getgrnam_r(const char *name, struct group *grp,
|
||||
// char *buf, size_t buflen, struct group **result);
|
||||
source.getTarget().hasName(["getpwnam_r", "getpwuid_r", "getgrgid_r", "getgrnam_r"]) and
|
||||
(
|
||||
use.asConvertedExpr() = source.getArgument([1, 2]) or
|
||||
use.asDefiningArgument() = source.getArgument(4)
|
||||
)
|
||||
or
|
||||
// int getpwent_r(struct passwd *pwd, char *buffer, size_t bufsize,
|
||||
// struct passwd **result);
|
||||
// int getgrent_r(struct group *gbuf, char *buf,
|
||||
// size_t buflen, struct group **gbufp);
|
||||
source.getTarget().hasName(["getpwent_r", "getgrent_r"]) and
|
||||
(
|
||||
use.asConvertedExpr() = source.getArgument([0, 1]) or
|
||||
use.asDefiningArgument() = source.getArgument(3)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Data obtained from a POSIX user/password/group database information call.
|
||||
*/
|
||||
class PosixPWInfo extends SystemData {
|
||||
PosixPWInfo() { posixPWInfo(this, _) }
|
||||
|
||||
override DataFlow::Node getAnExpr() { posixPWInfo(this, result) }
|
||||
|
||||
override predicate isSensitive() { any() }
|
||||
}
|
||||
|
||||
private predicate windowsSystemInfo(FunctionCall source, DataFlow::Node use) {
|
||||
// DWORD WINAPI GetVersion(void);
|
||||
source.getTarget().hasGlobalName("GetVersion") and
|
||||
use.asConvertedExpr() = source
|
||||
or
|
||||
// BOOL WINAPI GetVersionEx(_Inout_ LPOSVERSIONINFO lpVersionInfo);
|
||||
// void WINAPI GetSystemInfo(_Out_ LPSYSTEM_INFO lpSystemInfo);
|
||||
// void WINAPI GetNativeSystemInfo(_Out_ LPSYSTEM_INFO lpSystemInfo);
|
||||
source
|
||||
.getTarget()
|
||||
.hasGlobalName([
|
||||
"GetVersionEx", "GetVersionExA", "GetVersionExW", "GetSystemInfo", "GetNativeSystemInfo"
|
||||
]) and
|
||||
use.asDefiningArgument() = source.getArgument(0)
|
||||
}
|
||||
|
||||
/**
|
||||
* Data obtained from a Windows system information call.
|
||||
*/
|
||||
class WindowsSystemInfo extends SystemData {
|
||||
WindowsSystemInfo() { windowsSystemInfo(this, _) }
|
||||
|
||||
override DataFlow::Node getAnExpr() { windowsSystemInfo(this, result) }
|
||||
}
|
||||
|
||||
private predicate windowsFolderPath(FunctionCall source, Element use) {
|
||||
// BOOL SHGetSpecialFolderPath(
|
||||
// HWND hwndOwner,
|
||||
// _Out_ LPTSTR lpszPath,
|
||||
// _In_ int csidl,
|
||||
// _In_ BOOL fCreate
|
||||
// );
|
||||
source
|
||||
.getTarget()
|
||||
.hasGlobalName([
|
||||
"SHGetSpecialFolderPath", "SHGetSpecialFolderPathA", "SHGetSpecialFolderPathW"
|
||||
]) and
|
||||
use = source.getArgument(1)
|
||||
or
|
||||
// HRESULT SHGetKnownFolderPath(
|
||||
// _In_ REFKNOWNFOLDERID rfid,
|
||||
// _In_ DWORD dwFlags,
|
||||
// _In_opt_ HANDLE hToken,
|
||||
// _Out_ PWSTR *ppszPath
|
||||
// );
|
||||
source.getTarget().hasGlobalName("SHGetKnownFolderPath") and
|
||||
use = source.getArgument(3)
|
||||
or
|
||||
// HRESULT SHGetFolderPath(
|
||||
// _In_ HWND hwndOwner,
|
||||
// _In_ int nFolder,
|
||||
// _In_ HANDLE hToken,
|
||||
// _In_ DWORD dwFlags,
|
||||
// _Out_ LPTSTR pszPath
|
||||
// );
|
||||
source.getTarget().hasGlobalName(["SHGetFolderPath", "SHGetFolderPathA", "SHGetFolderPathW"]) and
|
||||
use = source.getArgument(4)
|
||||
or
|
||||
// HRESULT SHGetFolderPathAndSubDir(
|
||||
// _In_ HWND hwnd,
|
||||
// _In_ int csidl,
|
||||
// _In_ HANDLE hToken,
|
||||
// _In_ DWORD dwFlags,
|
||||
// _In_ LPCTSTR pszSubDir,
|
||||
// _Out_ LPTSTR pszPath
|
||||
// );
|
||||
source
|
||||
.getTarget()
|
||||
.hasGlobalName([
|
||||
"SHGetFolderPathAndSubDir", "SHGetFolderPathAndSubDirA", "SHGetFolderPathAndSubDirW"
|
||||
]) and
|
||||
use = source.getArgument(5)
|
||||
}
|
||||
|
||||
/**
|
||||
* Data obtained about Windows special paths (for example, the
|
||||
* location of `System32`).
|
||||
*/
|
||||
class WindowsFolderPath extends SystemData {
|
||||
WindowsFolderPath() { windowsFolderPath(this, _) }
|
||||
|
||||
override DataFlow::Node getAnExpr() { windowsFolderPath(this, result.asDefiningArgument()) }
|
||||
}
|
||||
|
||||
private predicate logonUser(FunctionCall source, VariableAccess use) {
|
||||
source.getTarget().hasGlobalName(["LogonUser", "LogonUserW", "LogonUserA"]) and
|
||||
use = source.getAnArgument()
|
||||
}
|
||||
|
||||
/**
|
||||
* Data passed into a `LogonUser` (Windows) function.
|
||||
*/
|
||||
class LogonUser extends SystemData {
|
||||
LogonUser() { logonUser(this, _) }
|
||||
|
||||
override DataFlow::Node getAnExpr() { logonUser(this, result.asConvertedExpr()) }
|
||||
|
||||
override predicate isSensitive() { any() }
|
||||
}
|
||||
|
||||
/**
|
||||
* The type of a registry query parameter, if it is of interest to us. This
|
||||
* is used to express information about registry query parameters in the
|
||||
* `regQuery` predicate concisely.
|
||||
*/
|
||||
private newtype TRegQueryParameter =
|
||||
TSubKeyName() or
|
||||
TValueName() or
|
||||
TReturnData()
|
||||
|
||||
/**
|
||||
* Registry query call (`source`) with information about parameters (`param`).
|
||||
*/
|
||||
private predicate regQuery(FunctionCall source, TRegQueryParameter paramType, Expr param) {
|
||||
// LONG WINAPI RegQueryValue(
|
||||
// _In_ HKEY hKey,
|
||||
// _In_opt_ LPCTSTR lpSubKey,
|
||||
// _Out_opt_ LPTSTR lpValue,
|
||||
// _Inout_opt_ PLONG lpcbValue
|
||||
// );
|
||||
source.getTarget().hasGlobalName(["RegQueryValue", "RegQueryValueA", "RegQueryValueW"]) and
|
||||
(
|
||||
paramType = TSubKeyName() and param = source.getArgument(1)
|
||||
or
|
||||
paramType = TReturnData() and param = source.getArgument(2)
|
||||
)
|
||||
or
|
||||
// LONG WINAPI RegQueryMultipleValues(
|
||||
// _In_ HKEY hKey,
|
||||
// _Out_ PVALENT val_list,
|
||||
// _In_ DWORD num_vals,
|
||||
// _Out_opt_ LPTSTR lpValueBuf,
|
||||
// _Inout_opt_ LPDWORD ldwTotsize
|
||||
// );
|
||||
source
|
||||
.getTarget()
|
||||
.hasGlobalName([
|
||||
"RegQueryMultipleValues", "RegQueryMultipleValuesA", "RegQueryMultipleValuesW"
|
||||
]) and
|
||||
paramType = TReturnData() and
|
||||
param = source.getArgument(3)
|
||||
or
|
||||
// LONG WINAPI RegQueryValueEx(
|
||||
// _In_ HKEY hKey,
|
||||
// _In_opt_ LPCTSTR lpValueName,
|
||||
// _Reserved_ LPDWORD lpReserved,
|
||||
// _Out_opt_ LPDWORD lpType,
|
||||
// _Out_opt_ LPBYTE lpData,
|
||||
// _Inout_opt_ LPDWORD lpcbData
|
||||
// );
|
||||
source.getTarget().hasGlobalName(["RegQueryValueEx", "RegQueryValueExA", "RegQueryValueExW"]) and
|
||||
(
|
||||
paramType = TValueName() and param = source.getArgument(1)
|
||||
or
|
||||
paramType = TReturnData() and param = source.getArgument(4)
|
||||
)
|
||||
or
|
||||
// LONG WINAPI RegGetValue(
|
||||
// _In_ HKEY hkey,
|
||||
// _In_opt_ LPCTSTR lpSubKey,
|
||||
// _In_opt_ LPCTSTR lpValue,
|
||||
// _In_opt_ DWORD dwFlags,
|
||||
// _Out_opt_ LPDWORD pdwType,
|
||||
// _Out_opt_ PVOID pvData,
|
||||
// _Inout_opt_ LPDWORD pcbData
|
||||
// );
|
||||
source.getTarget().hasGlobalName(["RegGetValue", "RegGetValueA", "RegGetValueW"]) and
|
||||
(
|
||||
paramType = TSubKeyName() and param = source.getArgument(1)
|
||||
or
|
||||
paramType = TValueName() and param = source.getArgument(2)
|
||||
or
|
||||
paramType = TReturnData() and param = source.getArgument(5)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Data read from the Windows registry.
|
||||
*/
|
||||
class RegQuery extends SystemData {
|
||||
RegQuery() { regQuery(this, _, _) }
|
||||
|
||||
override DataFlow::Node getAnExpr() { regQuery(this, TReturnData(), result.asDefiningArgument()) }
|
||||
|
||||
override predicate isSensitive() {
|
||||
exists(Expr e |
|
||||
(
|
||||
regQuery(this, TSubKeyName(), e) or
|
||||
regQuery(this, TValueName(), e)
|
||||
) and
|
||||
e.getValue().toLowerCase().regexpMatch(".*(pass|token|key).*")
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* A new query, "Potential exposure of sensitive system data to an unauthorized control sphere" (`cpp/potential-system-data-exposure`) has been added. This query is focused on exposure of information that is highly likely to be sensitive, whereas the similar query "Exposure of system data to an unauthorized control sphere" (`cpp/system-data-exposure`) is focused on exposure of information on a channel that is more likely to be intercepted by an attacker.
|
||||
@@ -0,0 +1,8 @@
|
||||
edges
|
||||
| tests.c:57:21:57:28 | password | tests.c:70:70:70:77 | array to pointer conversion |
|
||||
nodes
|
||||
| tests.c:57:21:57:28 | password | semmle.label | password |
|
||||
| tests.c:70:70:70:77 | array to pointer conversion | semmle.label | array to pointer conversion |
|
||||
subpaths
|
||||
#select
|
||||
| tests.c:70:70:70:77 | array to pointer conversion | tests.c:57:21:57:28 | password | tests.c:70:70:70:77 | array to pointer conversion | This operation potentially exposes sensitive system data from $@. | tests.c:57:21:57:28 | password | password |
|
||||
@@ -0,0 +1 @@
|
||||
Security/CWE/CWE-497/PotentiallyExposedSystemData.ql
|
||||
@@ -67,6 +67,6 @@ void CWE535_Info_Exposure_Shell_Error__w32_char_01_bad()
|
||||
printLine("Unable to login.");
|
||||
}
|
||||
/* FLAW: Write sensitive data to stderr */
|
||||
fprintf(stderr, "User attempted access with password: %s\n", password); // [NOT DETECTED]
|
||||
fprintf(stderr, "User attempted access with password: %s\n", password);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,15 +2,26 @@ edges
|
||||
| tests2.cpp:63:13:63:18 | call to getenv | tests2.cpp:63:13:63:26 | (const char *)... |
|
||||
| tests2.cpp:64:13:64:18 | call to getenv | tests2.cpp:64:13:64:26 | (const char *)... |
|
||||
| tests2.cpp:65:13:65:18 | call to getenv | tests2.cpp:65:13:65:30 | (const char *)... |
|
||||
| tests2.cpp:76:18:76:38 | call to mysql_get_client_info | tests2.cpp:79:14:79:19 | (const char *)... |
|
||||
| tests2.cpp:78:14:78:34 | call to mysql_get_client_info | tests2.cpp:78:14:78:34 | call to mysql_get_client_info |
|
||||
| tests2.cpp:78:14:78:34 | call to mysql_get_client_info | tests2.cpp:78:14:78:34 | call to mysql_get_client_info |
|
||||
| tests2.cpp:89:42:89:45 | str1 | tests2.cpp:91:14:91:17 | str1 |
|
||||
| tests2.cpp:99:8:99:15 | call to getpwuid | tests2.cpp:100:14:100:15 | pw |
|
||||
| tests2.cpp:107:3:107:4 | c1 [post update] [ptr] | tests2.cpp:109:14:109:15 | c1 [read] [ptr] |
|
||||
| tests2.cpp:107:6:107:8 | ptr [post update] | tests2.cpp:107:3:107:4 | c1 [post update] [ptr] |
|
||||
| tests2.cpp:107:12:107:17 | call to getenv | tests2.cpp:107:6:107:8 | ptr [post update] |
|
||||
| tests2.cpp:109:14:109:15 | c1 [read] [ptr] | tests2.cpp:109:14:109:19 | (const char *)... |
|
||||
| tests2.cpp:66:13:66:18 | call to getenv | tests2.cpp:66:13:66:34 | (const char *)... |
|
||||
| tests2.cpp:78:18:78:38 | call to mysql_get_client_info | tests2.cpp:81:14:81:19 | (const char *)... |
|
||||
| tests2.cpp:80:14:80:34 | call to mysql_get_client_info | tests2.cpp:80:14:80:34 | call to mysql_get_client_info |
|
||||
| tests2.cpp:80:14:80:34 | call to mysql_get_client_info | tests2.cpp:80:14:80:34 | call to mysql_get_client_info |
|
||||
| tests2.cpp:91:42:91:45 | str1 | tests2.cpp:93:14:93:17 | str1 |
|
||||
| tests2.cpp:101:8:101:15 | call to getpwuid | tests2.cpp:102:14:102:15 | pw |
|
||||
| tests2.cpp:109:3:109:4 | c1 [post update] [ptr] | tests2.cpp:111:14:111:15 | c1 [read] [ptr] |
|
||||
| tests2.cpp:109:6:109:8 | ptr [post update] | tests2.cpp:109:3:109:4 | c1 [post update] [ptr] |
|
||||
| tests2.cpp:109:12:109:17 | call to getenv | tests2.cpp:109:6:109:8 | ptr [post update] |
|
||||
| tests2.cpp:111:14:111:15 | c1 [read] [ptr] | tests2.cpp:111:14:111:19 | (const char *)... |
|
||||
| tests_sockets.cpp:26:15:26:20 | call to getenv | tests_sockets.cpp:39:19:39:22 | (const void *)... |
|
||||
| tests_sockets.cpp:26:15:26:20 | call to getenv | tests_sockets.cpp:39:19:39:22 | path |
|
||||
| tests_sockets.cpp:26:15:26:20 | call to getenv | tests_sockets.cpp:43:20:43:23 | (const void *)... |
|
||||
| tests_sockets.cpp:26:15:26:20 | call to getenv | tests_sockets.cpp:43:20:43:23 | path |
|
||||
| tests_sockets.cpp:63:15:63:20 | call to getenv | tests_sockets.cpp:76:19:76:22 | (const void *)... |
|
||||
| tests_sockets.cpp:63:15:63:20 | call to getenv | tests_sockets.cpp:76:19:76:22 | path |
|
||||
| tests_sockets.cpp:63:15:63:20 | call to getenv | tests_sockets.cpp:80:20:80:23 | (const void *)... |
|
||||
| tests_sockets.cpp:63:15:63:20 | call to getenv | tests_sockets.cpp:80:20:80:23 | path |
|
||||
| tests_sysconf.cpp:36:21:36:27 | confstr output argument | tests_sysconf.cpp:39:19:39:25 | (const void *)... |
|
||||
| tests_sysconf.cpp:36:21:36:27 | confstr output argument | tests_sysconf.cpp:39:19:39:25 | pathbuf |
|
||||
nodes
|
||||
| tests2.cpp:63:13:63:18 | call to getenv | semmle.label | call to getenv |
|
||||
| tests2.cpp:63:13:63:18 | call to getenv | semmle.label | call to getenv |
|
||||
@@ -21,27 +32,49 @@ nodes
|
||||
| tests2.cpp:65:13:65:18 | call to getenv | semmle.label | call to getenv |
|
||||
| tests2.cpp:65:13:65:18 | call to getenv | semmle.label | call to getenv |
|
||||
| tests2.cpp:65:13:65:30 | (const char *)... | semmle.label | (const char *)... |
|
||||
| tests2.cpp:76:18:76:38 | call to mysql_get_client_info | semmle.label | call to mysql_get_client_info |
|
||||
| tests2.cpp:78:14:78:34 | call to mysql_get_client_info | semmle.label | call to mysql_get_client_info |
|
||||
| tests2.cpp:78:14:78:34 | call to mysql_get_client_info | semmle.label | call to mysql_get_client_info |
|
||||
| tests2.cpp:79:14:79:19 | (const char *)... | semmle.label | (const char *)... |
|
||||
| tests2.cpp:89:42:89:45 | str1 | semmle.label | str1 |
|
||||
| tests2.cpp:91:14:91:17 | str1 | semmle.label | str1 |
|
||||
| tests2.cpp:99:8:99:15 | call to getpwuid | semmle.label | call to getpwuid |
|
||||
| tests2.cpp:100:14:100:15 | pw | semmle.label | pw |
|
||||
| tests2.cpp:107:3:107:4 | c1 [post update] [ptr] | semmle.label | c1 [post update] [ptr] |
|
||||
| tests2.cpp:107:6:107:8 | ptr [post update] | semmle.label | ptr [post update] |
|
||||
| tests2.cpp:107:12:107:17 | call to getenv | semmle.label | call to getenv |
|
||||
| tests2.cpp:109:14:109:15 | c1 [read] [ptr] | semmle.label | c1 [read] [ptr] |
|
||||
| tests2.cpp:109:14:109:19 | (const char *)... | semmle.label | (const char *)... |
|
||||
| tests2.cpp:66:13:66:18 | call to getenv | semmle.label | call to getenv |
|
||||
| tests2.cpp:66:13:66:18 | call to getenv | semmle.label | call to getenv |
|
||||
| tests2.cpp:66:13:66:34 | (const char *)... | semmle.label | (const char *)... |
|
||||
| tests2.cpp:78:18:78:38 | call to mysql_get_client_info | semmle.label | call to mysql_get_client_info |
|
||||
| tests2.cpp:80:14:80:34 | call to mysql_get_client_info | semmle.label | call to mysql_get_client_info |
|
||||
| tests2.cpp:80:14:80:34 | call to mysql_get_client_info | semmle.label | call to mysql_get_client_info |
|
||||
| tests2.cpp:81:14:81:19 | (const char *)... | semmle.label | (const char *)... |
|
||||
| tests2.cpp:91:42:91:45 | str1 | semmle.label | str1 |
|
||||
| tests2.cpp:93:14:93:17 | str1 | semmle.label | str1 |
|
||||
| tests2.cpp:101:8:101:15 | call to getpwuid | semmle.label | call to getpwuid |
|
||||
| tests2.cpp:102:14:102:15 | pw | semmle.label | pw |
|
||||
| tests2.cpp:109:3:109:4 | c1 [post update] [ptr] | semmle.label | c1 [post update] [ptr] |
|
||||
| tests2.cpp:109:6:109:8 | ptr [post update] | semmle.label | ptr [post update] |
|
||||
| tests2.cpp:109:12:109:17 | call to getenv | semmle.label | call to getenv |
|
||||
| tests2.cpp:111:14:111:15 | c1 [read] [ptr] | semmle.label | c1 [read] [ptr] |
|
||||
| tests2.cpp:111:14:111:19 | (const char *)... | semmle.label | (const char *)... |
|
||||
| tests_sockets.cpp:26:15:26:20 | call to getenv | semmle.label | call to getenv |
|
||||
| tests_sockets.cpp:39:19:39:22 | (const void *)... | semmle.label | (const void *)... |
|
||||
| tests_sockets.cpp:39:19:39:22 | path | semmle.label | path |
|
||||
| tests_sockets.cpp:43:20:43:23 | (const void *)... | semmle.label | (const void *)... |
|
||||
| tests_sockets.cpp:43:20:43:23 | path | semmle.label | path |
|
||||
| tests_sockets.cpp:63:15:63:20 | call to getenv | semmle.label | call to getenv |
|
||||
| tests_sockets.cpp:76:19:76:22 | (const void *)... | semmle.label | (const void *)... |
|
||||
| tests_sockets.cpp:76:19:76:22 | path | semmle.label | path |
|
||||
| tests_sockets.cpp:80:20:80:23 | (const void *)... | semmle.label | (const void *)... |
|
||||
| tests_sockets.cpp:80:20:80:23 | path | semmle.label | path |
|
||||
| tests_sysconf.cpp:36:21:36:27 | confstr output argument | semmle.label | confstr output argument |
|
||||
| tests_sysconf.cpp:39:19:39:25 | (const void *)... | semmle.label | (const void *)... |
|
||||
| tests_sysconf.cpp:39:19:39:25 | pathbuf | semmle.label | pathbuf |
|
||||
subpaths
|
||||
#select
|
||||
| tests2.cpp:63:13:63:18 | call to getenv | tests2.cpp:63:13:63:18 | call to getenv | tests2.cpp:63:13:63:18 | call to getenv | This operation exposes system data from $@. | tests2.cpp:63:13:63:18 | call to getenv | call to getenv |
|
||||
| tests2.cpp:64:13:64:18 | call to getenv | tests2.cpp:64:13:64:18 | call to getenv | tests2.cpp:64:13:64:18 | call to getenv | This operation exposes system data from $@. | tests2.cpp:64:13:64:18 | call to getenv | call to getenv |
|
||||
| tests2.cpp:65:13:65:18 | call to getenv | tests2.cpp:65:13:65:18 | call to getenv | tests2.cpp:65:13:65:18 | call to getenv | This operation exposes system data from $@. | tests2.cpp:65:13:65:18 | call to getenv | call to getenv |
|
||||
| tests2.cpp:78:14:78:34 | call to mysql_get_client_info | tests2.cpp:78:14:78:34 | call to mysql_get_client_info | tests2.cpp:78:14:78:34 | call to mysql_get_client_info | This operation exposes system data from $@. | tests2.cpp:78:14:78:34 | call to mysql_get_client_info | call to mysql_get_client_info |
|
||||
| tests2.cpp:78:14:78:34 | call to mysql_get_client_info | tests2.cpp:78:14:78:34 | call to mysql_get_client_info | tests2.cpp:78:14:78:34 | call to mysql_get_client_info | This operation exposes system data from $@. | tests2.cpp:78:14:78:34 | call to mysql_get_client_info | call to mysql_get_client_info |
|
||||
| tests2.cpp:79:14:79:19 | (const char *)... | tests2.cpp:76:18:76:38 | call to mysql_get_client_info | tests2.cpp:79:14:79:19 | (const char *)... | This operation exposes system data from $@. | tests2.cpp:76:18:76:38 | call to mysql_get_client_info | call to mysql_get_client_info |
|
||||
| tests2.cpp:91:14:91:17 | str1 | tests2.cpp:89:42:89:45 | str1 | tests2.cpp:91:14:91:17 | str1 | This operation exposes system data from $@. | tests2.cpp:89:42:89:45 | str1 | str1 |
|
||||
| tests2.cpp:100:14:100:15 | pw | tests2.cpp:99:8:99:15 | call to getpwuid | tests2.cpp:100:14:100:15 | pw | This operation exposes system data from $@. | tests2.cpp:99:8:99:15 | call to getpwuid | call to getpwuid |
|
||||
| tests2.cpp:109:14:109:19 | (const char *)... | tests2.cpp:107:12:107:17 | call to getenv | tests2.cpp:109:14:109:19 | (const char *)... | This operation exposes system data from $@. | tests2.cpp:107:12:107:17 | call to getenv | call to getenv |
|
||||
| tests2.cpp:66:13:66:18 | call to getenv | tests2.cpp:66:13:66:18 | call to getenv | tests2.cpp:66:13:66:18 | call to getenv | This operation exposes system data from $@. | tests2.cpp:66:13:66:18 | call to getenv | call to getenv |
|
||||
| tests2.cpp:80:14:80:34 | call to mysql_get_client_info | tests2.cpp:80:14:80:34 | call to mysql_get_client_info | tests2.cpp:80:14:80:34 | call to mysql_get_client_info | This operation exposes system data from $@. | tests2.cpp:80:14:80:34 | call to mysql_get_client_info | call to mysql_get_client_info |
|
||||
| tests2.cpp:80:14:80:34 | call to mysql_get_client_info | tests2.cpp:80:14:80:34 | call to mysql_get_client_info | tests2.cpp:80:14:80:34 | call to mysql_get_client_info | This operation exposes system data from $@. | tests2.cpp:80:14:80:34 | call to mysql_get_client_info | call to mysql_get_client_info |
|
||||
| tests2.cpp:81:14:81:19 | (const char *)... | tests2.cpp:78:18:78:38 | call to mysql_get_client_info | tests2.cpp:81:14:81:19 | (const char *)... | This operation exposes system data from $@. | tests2.cpp:78:18:78:38 | call to mysql_get_client_info | call to mysql_get_client_info |
|
||||
| tests2.cpp:93:14:93:17 | str1 | tests2.cpp:91:42:91:45 | str1 | tests2.cpp:93:14:93:17 | str1 | This operation exposes system data from $@. | tests2.cpp:91:42:91:45 | str1 | str1 |
|
||||
| tests2.cpp:102:14:102:15 | pw | tests2.cpp:101:8:101:15 | call to getpwuid | tests2.cpp:102:14:102:15 | pw | This operation exposes system data from $@. | tests2.cpp:101:8:101:15 | call to getpwuid | call to getpwuid |
|
||||
| tests2.cpp:111:14:111:19 | (const char *)... | tests2.cpp:109:12:109:17 | call to getenv | tests2.cpp:111:14:111:19 | (const char *)... | This operation exposes system data from $@. | tests2.cpp:109:12:109:17 | call to getenv | call to getenv |
|
||||
| tests_sockets.cpp:39:19:39:22 | path | tests_sockets.cpp:26:15:26:20 | call to getenv | tests_sockets.cpp:39:19:39:22 | path | This operation exposes system data from $@. | tests_sockets.cpp:26:15:26:20 | call to getenv | call to getenv |
|
||||
| tests_sockets.cpp:43:20:43:23 | path | tests_sockets.cpp:26:15:26:20 | call to getenv | tests_sockets.cpp:43:20:43:23 | path | This operation exposes system data from $@. | tests_sockets.cpp:26:15:26:20 | call to getenv | call to getenv |
|
||||
| tests_sockets.cpp:76:19:76:22 | path | tests_sockets.cpp:63:15:63:20 | call to getenv | tests_sockets.cpp:76:19:76:22 | path | This operation exposes system data from $@. | tests_sockets.cpp:63:15:63:20 | call to getenv | call to getenv |
|
||||
| tests_sockets.cpp:80:20:80:23 | path | tests_sockets.cpp:63:15:63:20 | call to getenv | tests_sockets.cpp:80:20:80:23 | path | This operation exposes system data from $@. | tests_sockets.cpp:63:15:63:20 | call to getenv | call to getenv |
|
||||
| tests_sysconf.cpp:39:19:39:25 | pathbuf | tests_sysconf.cpp:36:21:36:27 | confstr output argument | tests_sysconf.cpp:39:19:39:25 | pathbuf | This operation exposes system data from $@. | tests_sysconf.cpp:36:21:36:27 | confstr output argument | confstr output argument |
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
edges
|
||||
| tests.cpp:48:15:48:20 | call to getenv | tests.cpp:48:15:48:36 | (const char *)... |
|
||||
| tests.cpp:49:15:49:20 | call to getenv | tests.cpp:49:15:49:36 | (const char *)... |
|
||||
| tests.cpp:50:15:50:20 | call to getenv | tests.cpp:50:15:50:36 | (const char *)... |
|
||||
| tests.cpp:57:18:57:23 | call to getenv | tests.cpp:57:18:57:39 | (const char_type *)... |
|
||||
| tests.cpp:58:41:58:46 | call to getenv | tests.cpp:58:41:58:62 | (const char_type *)... |
|
||||
| tests.cpp:59:43:59:48 | call to getenv | tests.cpp:59:43:59:64 | (const char *)... |
|
||||
| tests.cpp:86:29:86:31 | *msg | tests.cpp:88:15:88:17 | msg |
|
||||
| tests.cpp:86:29:86:31 | msg | tests.cpp:88:15:88:17 | msg |
|
||||
| tests.cpp:97:13:97:18 | call to getenv | tests.cpp:97:13:97:34 | (const char *)... |
|
||||
| tests.cpp:97:13:97:18 | call to getenv | tests.cpp:97:13:97:34 | call to getenv |
|
||||
| tests.cpp:97:13:97:18 | call to getenv | tests.cpp:97:13:97:34 | call to getenv indirection |
|
||||
| tests.cpp:97:13:97:34 | call to getenv | tests.cpp:86:29:86:31 | msg |
|
||||
| tests.cpp:97:13:97:34 | call to getenv indirection | tests.cpp:86:29:86:31 | *msg |
|
||||
| tests.cpp:107:30:107:32 | *msg | tests.cpp:111:15:111:17 | tmp |
|
||||
| tests.cpp:107:30:107:32 | msg | tests.cpp:111:15:111:17 | tmp |
|
||||
| tests.cpp:114:30:114:32 | *msg | tests.cpp:119:7:119:12 | (const char *)... |
|
||||
| tests.cpp:114:30:114:32 | msg | tests.cpp:119:7:119:12 | (const char *)... |
|
||||
| tests.cpp:122:30:122:32 | *msg | tests.cpp:124:15:124:17 | msg |
|
||||
| tests.cpp:122:30:122:32 | msg | tests.cpp:124:15:124:17 | msg |
|
||||
| tests.cpp:131:14:131:19 | call to getenv | tests.cpp:131:14:131:35 | call to getenv |
|
||||
| tests.cpp:131:14:131:19 | call to getenv | tests.cpp:131:14:131:35 | call to getenv indirection |
|
||||
| tests.cpp:131:14:131:35 | call to getenv | tests.cpp:107:30:107:32 | msg |
|
||||
| tests.cpp:131:14:131:35 | call to getenv indirection | tests.cpp:107:30:107:32 | *msg |
|
||||
| tests.cpp:132:14:132:19 | call to getenv | tests.cpp:132:14:132:35 | call to getenv |
|
||||
| tests.cpp:132:14:132:19 | call to getenv | tests.cpp:132:14:132:35 | call to getenv indirection |
|
||||
| tests.cpp:132:14:132:35 | call to getenv | tests.cpp:114:30:114:32 | msg |
|
||||
| tests.cpp:132:14:132:35 | call to getenv indirection | tests.cpp:114:30:114:32 | *msg |
|
||||
| tests.cpp:133:14:133:19 | call to getenv | tests.cpp:133:14:133:35 | (const char *)... |
|
||||
| tests.cpp:133:14:133:19 | call to getenv | tests.cpp:133:14:133:35 | call to getenv |
|
||||
| tests.cpp:133:14:133:19 | call to getenv | tests.cpp:133:14:133:35 | call to getenv indirection |
|
||||
| tests.cpp:133:14:133:35 | call to getenv | tests.cpp:122:30:122:32 | msg |
|
||||
| tests.cpp:133:14:133:35 | call to getenv indirection | tests.cpp:122:30:122:32 | *msg |
|
||||
| tests_passwd.cpp:16:8:16:15 | call to getpwnam | tests_passwd.cpp:18:29:18:31 | pwd |
|
||||
| tests_passwd.cpp:16:8:16:15 | call to getpwnam | tests_passwd.cpp:19:26:19:28 | pwd |
|
||||
nodes
|
||||
| tests.cpp:48:15:48:20 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:48:15:48:20 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:48:15:48:36 | (const char *)... | semmle.label | (const char *)... |
|
||||
| tests.cpp:49:15:49:20 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:49:15:49:20 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:49:15:49:36 | (const char *)... | semmle.label | (const char *)... |
|
||||
| tests.cpp:50:15:50:20 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:50:15:50:20 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:50:15:50:36 | (const char *)... | semmle.label | (const char *)... |
|
||||
| tests.cpp:57:18:57:23 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:57:18:57:23 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:57:18:57:39 | (const char_type *)... | semmle.label | (const char_type *)... |
|
||||
| tests.cpp:58:41:58:46 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:58:41:58:46 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:58:41:58:62 | (const char_type *)... | semmle.label | (const char_type *)... |
|
||||
| tests.cpp:59:43:59:48 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:59:43:59:48 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:59:43:59:64 | (const char *)... | semmle.label | (const char *)... |
|
||||
| tests.cpp:86:29:86:31 | *msg | semmle.label | *msg |
|
||||
| tests.cpp:86:29:86:31 | msg | semmle.label | msg |
|
||||
| tests.cpp:88:15:88:17 | msg | semmle.label | msg |
|
||||
| tests.cpp:97:13:97:18 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:97:13:97:18 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:97:13:97:34 | (const char *)... | semmle.label | (const char *)... |
|
||||
| tests.cpp:97:13:97:34 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:97:13:97:34 | call to getenv indirection | semmle.label | call to getenv indirection |
|
||||
| tests.cpp:107:30:107:32 | *msg | semmle.label | *msg |
|
||||
| tests.cpp:107:30:107:32 | msg | semmle.label | msg |
|
||||
| tests.cpp:111:15:111:17 | tmp | semmle.label | tmp |
|
||||
| tests.cpp:114:30:114:32 | *msg | semmle.label | *msg |
|
||||
| tests.cpp:114:30:114:32 | msg | semmle.label | msg |
|
||||
| tests.cpp:119:7:119:12 | (const char *)... | semmle.label | (const char *)... |
|
||||
| tests.cpp:122:30:122:32 | *msg | semmle.label | *msg |
|
||||
| tests.cpp:122:30:122:32 | msg | semmle.label | msg |
|
||||
| tests.cpp:124:15:124:17 | msg | semmle.label | msg |
|
||||
| tests.cpp:131:14:131:19 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:131:14:131:35 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:131:14:131:35 | call to getenv indirection | semmle.label | call to getenv indirection |
|
||||
| tests.cpp:132:14:132:19 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:132:14:132:35 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:132:14:132:35 | call to getenv indirection | semmle.label | call to getenv indirection |
|
||||
| tests.cpp:133:14:133:19 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:133:14:133:19 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:133:14:133:35 | (const char *)... | semmle.label | (const char *)... |
|
||||
| tests.cpp:133:14:133:35 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:133:14:133:35 | call to getenv indirection | semmle.label | call to getenv indirection |
|
||||
| tests_passwd.cpp:16:8:16:15 | call to getpwnam | semmle.label | call to getpwnam |
|
||||
| tests_passwd.cpp:18:29:18:31 | pwd | semmle.label | pwd |
|
||||
| tests_passwd.cpp:19:26:19:28 | pwd | semmle.label | pwd |
|
||||
subpaths
|
||||
#select
|
||||
| tests.cpp:48:15:48:20 | call to getenv | tests.cpp:48:15:48:20 | call to getenv | tests.cpp:48:15:48:20 | call to getenv | This operation potentially exposes sensitive system data from $@. | tests.cpp:48:15:48:20 | call to getenv | call to getenv |
|
||||
| tests.cpp:48:15:48:36 | (const char *)... | tests.cpp:48:15:48:20 | call to getenv | tests.cpp:48:15:48:36 | (const char *)... | This operation potentially exposes sensitive system data from $@. | tests.cpp:48:15:48:20 | call to getenv | call to getenv |
|
||||
| tests.cpp:49:15:49:20 | call to getenv | tests.cpp:49:15:49:20 | call to getenv | tests.cpp:49:15:49:20 | call to getenv | This operation potentially exposes sensitive system data from $@. | tests.cpp:49:15:49:20 | call to getenv | call to getenv |
|
||||
| tests.cpp:49:15:49:36 | (const char *)... | tests.cpp:49:15:49:20 | call to getenv | tests.cpp:49:15:49:36 | (const char *)... | This operation potentially exposes sensitive system data from $@. | tests.cpp:49:15:49:20 | call to getenv | call to getenv |
|
||||
| tests.cpp:50:15:50:20 | call to getenv | tests.cpp:50:15:50:20 | call to getenv | tests.cpp:50:15:50:20 | call to getenv | This operation potentially exposes sensitive system data from $@. | tests.cpp:50:15:50:20 | call to getenv | call to getenv |
|
||||
| tests.cpp:50:15:50:36 | (const char *)... | tests.cpp:50:15:50:20 | call to getenv | tests.cpp:50:15:50:36 | (const char *)... | This operation potentially exposes sensitive system data from $@. | tests.cpp:50:15:50:20 | call to getenv | call to getenv |
|
||||
| tests.cpp:57:18:57:23 | call to getenv | tests.cpp:57:18:57:23 | call to getenv | tests.cpp:57:18:57:23 | call to getenv | This operation potentially exposes sensitive system data from $@. | tests.cpp:57:18:57:23 | call to getenv | call to getenv |
|
||||
| tests.cpp:57:18:57:39 | (const char_type *)... | tests.cpp:57:18:57:23 | call to getenv | tests.cpp:57:18:57:39 | (const char_type *)... | This operation potentially exposes sensitive system data from $@. | tests.cpp:57:18:57:23 | call to getenv | call to getenv |
|
||||
| tests.cpp:58:41:58:46 | call to getenv | tests.cpp:58:41:58:46 | call to getenv | tests.cpp:58:41:58:46 | call to getenv | This operation potentially exposes sensitive system data from $@. | tests.cpp:58:41:58:46 | call to getenv | call to getenv |
|
||||
| tests.cpp:58:41:58:62 | (const char_type *)... | tests.cpp:58:41:58:46 | call to getenv | tests.cpp:58:41:58:62 | (const char_type *)... | This operation potentially exposes sensitive system data from $@. | tests.cpp:58:41:58:46 | call to getenv | call to getenv |
|
||||
| tests.cpp:59:43:59:48 | call to getenv | tests.cpp:59:43:59:48 | call to getenv | tests.cpp:59:43:59:48 | call to getenv | This operation potentially exposes sensitive system data from $@. | tests.cpp:59:43:59:48 | call to getenv | call to getenv |
|
||||
| tests.cpp:59:43:59:64 | (const char *)... | tests.cpp:59:43:59:48 | call to getenv | tests.cpp:59:43:59:64 | (const char *)... | This operation potentially exposes sensitive system data from $@. | tests.cpp:59:43:59:48 | call to getenv | call to getenv |
|
||||
| tests.cpp:88:15:88:17 | msg | tests.cpp:97:13:97:18 | call to getenv | tests.cpp:88:15:88:17 | msg | This operation potentially exposes sensitive system data from $@. | tests.cpp:97:13:97:18 | call to getenv | call to getenv |
|
||||
| tests.cpp:97:13:97:18 | call to getenv | tests.cpp:97:13:97:18 | call to getenv | tests.cpp:97:13:97:18 | call to getenv | This operation potentially exposes sensitive system data from $@. | tests.cpp:97:13:97:18 | call to getenv | call to getenv |
|
||||
| tests.cpp:97:13:97:34 | (const char *)... | tests.cpp:97:13:97:18 | call to getenv | tests.cpp:97:13:97:34 | (const char *)... | This operation potentially exposes sensitive system data from $@. | tests.cpp:97:13:97:18 | call to getenv | call to getenv |
|
||||
| tests.cpp:111:15:111:17 | tmp | tests.cpp:131:14:131:19 | call to getenv | tests.cpp:111:15:111:17 | tmp | This operation potentially exposes sensitive system data from $@. | tests.cpp:131:14:131:19 | call to getenv | call to getenv |
|
||||
| tests.cpp:119:7:119:12 | (const char *)... | tests.cpp:132:14:132:19 | call to getenv | tests.cpp:119:7:119:12 | (const char *)... | This operation potentially exposes sensitive system data from $@. | tests.cpp:132:14:132:19 | call to getenv | call to getenv |
|
||||
| tests.cpp:124:15:124:17 | msg | tests.cpp:133:14:133:19 | call to getenv | tests.cpp:124:15:124:17 | msg | This operation potentially exposes sensitive system data from $@. | tests.cpp:133:14:133:19 | call to getenv | call to getenv |
|
||||
| tests.cpp:133:14:133:19 | call to getenv | tests.cpp:133:14:133:19 | call to getenv | tests.cpp:133:14:133:19 | call to getenv | This operation potentially exposes sensitive system data from $@. | tests.cpp:133:14:133:19 | call to getenv | call to getenv |
|
||||
| tests.cpp:133:14:133:35 | (const char *)... | tests.cpp:133:14:133:19 | call to getenv | tests.cpp:133:14:133:35 | (const char *)... | This operation potentially exposes sensitive system data from $@. | tests.cpp:133:14:133:19 | call to getenv | call to getenv |
|
||||
| tests_passwd.cpp:18:29:18:31 | pwd | tests_passwd.cpp:16:8:16:15 | call to getpwnam | tests_passwd.cpp:18:29:18:31 | pwd | This operation potentially exposes sensitive system data from $@. | tests_passwd.cpp:16:8:16:15 | call to getpwnam | call to getpwnam |
|
||||
| tests_passwd.cpp:19:26:19:28 | pwd | tests_passwd.cpp:16:8:16:15 | call to getpwnam | tests_passwd.cpp:19:26:19:28 | pwd | This operation potentially exposes sensitive system data from $@. | tests_passwd.cpp:16:8:16:15 | call to getpwnam | call to getpwnam |
|
||||
@@ -0,0 +1 @@
|
||||
Security/CWE/CWE-497/PotentiallyExposedSystemData.ql
|
||||
@@ -0,0 +1,134 @@
|
||||
// test cases for rule CWE-497
|
||||
|
||||
// library functions etc
|
||||
|
||||
#include "tests.h"
|
||||
|
||||
|
||||
typedef struct {} FILE;
|
||||
FILE *stdout;
|
||||
|
||||
int puts(const char *s);
|
||||
int printf(const char *format, ...);
|
||||
int sprintf(char *s, const char *format, ...);
|
||||
int snprintf(char *s, size_t n, const char *format, ...);
|
||||
size_t strlen(const char *s);
|
||||
char *getenv(const char *name);
|
||||
|
||||
extern std::ostream someotherostream;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#define NULL (0)
|
||||
|
||||
// test cases
|
||||
|
||||
void test1()
|
||||
{
|
||||
std::ostream cout_copy = std::cout;
|
||||
|
||||
std::cout << getenv("SECRET_TOKEN"); // BAD: outputs SECRET_TOKEN environment variable
|
||||
std::cerr << getenv("SECRET_TOKEN"); // BAD: outputs SECRET_TOKEN environment variable
|
||||
std::clog << getenv("SECRET_TOKEN"); // BAD: outputs SECRET_TOKEN environment variable
|
||||
someotherostream << getenv("SECRET_TOKEN"); // GOOD: not output
|
||||
cout_copy << getenv("SECRET_TOKEN"); // BAD: outputs SECRET_TOKEN environment variable [NOT DETECTED]
|
||||
|
||||
std::cout << getenv("USERPROFILE"); // BAD: outputs PATH environment variable [NOT DETECTED]
|
||||
std::cout << getenv("PATH"); // BAD: outputs PATH environment variable [NOT DETECTED]
|
||||
|
||||
std::cout.write(getenv("SECRET_TOKEN"), strlen(getenv("SECRET_TOKEN"))); // BAD: outputs SECRET_TOKEN environment variable
|
||||
(std::cout << "SECRET_TOKEN = ").write(getenv("SECRET_TOKEN"), strlen(getenv("SECRET_TOKEN"))); // BAD: outputs SECRET_TOKEN environment variable
|
||||
std::cout.write("SECRET_TOKEN = ", 7) << getenv("SECRET_TOKEN"); // BAD: outputs SECRET_TOKEN environment variable
|
||||
}
|
||||
|
||||
char *global_token = getenv("SECRET_TOKEN");
|
||||
char *global_other = "Hello, world!";
|
||||
|
||||
void test2(bool cond)
|
||||
{
|
||||
char *maybe;
|
||||
|
||||
maybe = cond ? global_token : global_other;
|
||||
|
||||
printf("token = '%s'\n", global_token); // BAD: outputs SECRET_TOKEN environment variable [NOT DETECTED]
|
||||
printf("other = '%s'\n", global_other);
|
||||
printf("maybe = '%s'\n", maybe); // BAD: may output SECRET_TOKEN environment variable [NOT DETECTED]
|
||||
}
|
||||
|
||||
void test3()
|
||||
{
|
||||
char *path_string = getenv("PATH");
|
||||
char buf[4096];
|
||||
|
||||
// ...
|
||||
snprintf(buf, 4096, "invalid path '%s'\n", path_string);
|
||||
puts(buf); // BAD: outputs PATH environment variable [NOT DETECTED]
|
||||
}
|
||||
|
||||
void myOutputFn(const char *msg)
|
||||
{
|
||||
printf("%s", msg);
|
||||
}
|
||||
|
||||
void myOtherFn(const char *msg)
|
||||
{
|
||||
}
|
||||
|
||||
void test4()
|
||||
{
|
||||
myOutputFn(getenv("SECRET_TOKEN")); // BAD: outputs the SECRET_TOKEN environment variable
|
||||
myOtherFn(getenv("SECRET_TOKEN")); // GOOD: does not output anything.
|
||||
}
|
||||
|
||||
void myOutputFn2(const char *msg)
|
||||
{
|
||||
msg = "";
|
||||
printf("%s", msg);
|
||||
}
|
||||
|
||||
void myOutputFn3(const char *msg)
|
||||
{
|
||||
const char *tmp = msg;
|
||||
|
||||
printf("%s", tmp);
|
||||
}
|
||||
|
||||
void myOutputFn4(const char *msg)
|
||||
{
|
||||
char buffer[4096];
|
||||
|
||||
sprintf(buffer, "log: %s\n", msg);
|
||||
puts(buffer);
|
||||
}
|
||||
|
||||
void myOutputFn5(const char *msg)
|
||||
{
|
||||
printf("%s", msg);
|
||||
msg = "";
|
||||
}
|
||||
|
||||
void test5()
|
||||
{
|
||||
myOutputFn2(getenv("SECRET_TOKEN")); // GOOD: myOutputFn2 doesn't actually output the parameter
|
||||
myOutputFn3(getenv("SECRET_TOKEN")); // BAD: outputs the SECRET_TOKEN environment variable
|
||||
myOutputFn4(getenv("SECRET_TOKEN")); // BAD: outputs the SECRET_TOKEN environment variable
|
||||
myOutputFn5(getenv("SECRET_TOKEN")); // BAD: outputs the SECRET_TOKEN environment variable
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
|
||||
typedef unsigned long size_t;
|
||||
|
||||
namespace std
|
||||
{
|
||||
typedef size_t streamsize;
|
||||
|
||||
template<class charT> struct char_traits;
|
||||
|
||||
template <class charT, class traits = char_traits<charT> >
|
||||
class basic_ostream /*: virtual public basic_ios<charT,traits> - not needed for this test */ {
|
||||
public:
|
||||
typedef charT char_type;
|
||||
basic_ostream<charT,traits>& write(const char_type* s, streamsize n);
|
||||
|
||||
basic_ostream<charT, traits>& operator<<(int n);
|
||||
};
|
||||
template<class charT, class traits> basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>&, const charT*);
|
||||
|
||||
typedef basic_ostream<char> ostream;
|
||||
|
||||
extern ostream cout;
|
||||
extern ostream cerr;
|
||||
extern ostream clog;
|
||||
}
|
||||
@@ -2,24 +2,24 @@
|
||||
|
||||
// library functions etc
|
||||
|
||||
#include "tests.h"
|
||||
|
||||
char *getenv(const char *name);
|
||||
char *strcpy(char *s1, const char *s2);
|
||||
|
||||
namespace std
|
||||
{
|
||||
template<class charT> struct char_traits;
|
||||
|
||||
template <class charT, class traits = char_traits<charT> >
|
||||
class basic_ostream /*: virtual public basic_ios<charT,traits> - not needed for this test */ {
|
||||
public:
|
||||
};
|
||||
|
||||
template<class charT, class traits> basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>&, const charT*);
|
||||
|
||||
typedef basic_ostream<char> ostream;
|
||||
|
||||
extern ostream cout;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int socket(int p1, int p2, int p3);
|
||||
void send(int sock, const char *buffer, int p3, int p4);
|
||||
@@ -63,10 +63,12 @@ void test1()
|
||||
send(sock, getenv("HOME"), val(), val()); // BAD
|
||||
send(sock, getenv("PATH"), val(), val()); // BAD
|
||||
send(sock, getenv("USERNAME"), val(), val()); // BAD
|
||||
send(sock, getenv("APP_PASSWORD"), val(), val()); // BAD
|
||||
send(sock, getenv("HARMLESS"), val(), val()); // GOOD: harmless information
|
||||
send(sock, "HOME", val(), val()); // GOOD: not system data
|
||||
send(sock, "PATH", val(), val()); // GOOD: not system data
|
||||
send(sock, "USERNAME", val(), val()); // GOOD: not system data
|
||||
send(sock, "APP_PASSWORD", val(), val()); // GOOD: not system data
|
||||
send(sock, "HARMLESS", val(), val()); // GOOD: not system data
|
||||
|
||||
// tests for `mysql_get_client_info`, including via a global
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
|
||||
int printf(const char *format, ...);
|
||||
|
||||
struct passwd {
|
||||
char *pw_passwd;
|
||||
char *pw_dir;
|
||||
// ...
|
||||
};
|
||||
|
||||
struct passwd *getpwnam(const char *name);
|
||||
|
||||
void test6(char *username)
|
||||
{
|
||||
passwd *pwd;
|
||||
|
||||
pwd = getpwnam(username);
|
||||
|
||||
printf("pw_passwd = %s\n", pwd->pw_passwd); // BAD
|
||||
printf("pw_dir = %s\n", pwd->pw_dir); // BAD
|
||||
printf("sizeof(passwd) = %i\n", sizeof(passwd)); // GOOD
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
|
||||
typedef unsigned long size_t;
|
||||
|
||||
size_t strlen(const char *s);
|
||||
char *getenv(const char *name);
|
||||
|
||||
#define AF_INET (2)
|
||||
#define SOCK_STREAM (1)
|
||||
|
||||
struct sockaddr {
|
||||
int sa_family;
|
||||
|
||||
// ...
|
||||
};
|
||||
|
||||
int socket(int domain, int type, int protocol);
|
||||
int connect(int socket, const struct sockaddr *address, size_t address_len);
|
||||
size_t send(int socket, const void *buffer, size_t length, int flags);
|
||||
int write(int handle, const void *buffer, size_t length);
|
||||
|
||||
void test_sockets1()
|
||||
{
|
||||
int sockfd;
|
||||
sockaddr addr_remote;
|
||||
char *msg = "Hello, world!";
|
||||
char *path = getenv("PATH");
|
||||
|
||||
// create socket
|
||||
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sockfd < 0) return;
|
||||
|
||||
// connect socket to a remote address
|
||||
addr_remote.sa_family = AF_INET;
|
||||
// ...
|
||||
if (connect(sockfd, &addr_remote, sizeof(addr_remote)) != 0) return;
|
||||
|
||||
// send something using 'send'
|
||||
if (send(sockfd, msg, strlen(msg) + 1, 0) < 0) return; // GOOD
|
||||
if (send(sockfd, path, strlen(path) + 1, 0) < 0) return; // BAD
|
||||
|
||||
// send something using 'write'
|
||||
if (write(sockfd, msg, strlen(msg) + 1) < 0) return; // GOOD
|
||||
if (write(sockfd, path, strlen(path) + 1) < 0) return; // BAD
|
||||
|
||||
// clean up
|
||||
// ...
|
||||
}
|
||||
|
||||
int mksocket()
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
void test_sockets2()
|
||||
{
|
||||
int sockfd;
|
||||
sockaddr addr_remote;
|
||||
char *msg = "Hello, world!";
|
||||
char *path = getenv("PATH");
|
||||
|
||||
// create socket
|
||||
sockfd = mksocket();
|
||||
if (sockfd < 0) return;
|
||||
|
||||
// connect socket to a remote address
|
||||
addr_remote.sa_family = AF_INET;
|
||||
// ...
|
||||
if (connect(sockfd, &addr_remote, sizeof(addr_remote)) != 0) return;
|
||||
|
||||
// send something using 'send'
|
||||
if (send(sockfd, msg, strlen(msg) + 1, 0) < 0) return; // GOOD
|
||||
if (send(sockfd, path, strlen(path) + 1, 0) < 0) return; // BAD
|
||||
|
||||
// send something using 'write'
|
||||
if (write(sockfd, msg, strlen(msg) + 1) < 0) return; // GOOD
|
||||
if (write(sockfd, path, strlen(path) + 1) < 0) return; // BAD
|
||||
|
||||
// clean up
|
||||
// ...
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
|
||||
typedef unsigned long size_t;
|
||||
typedef signed long ssize_t;
|
||||
void *malloc(size_t size);
|
||||
#define NULL (0)
|
||||
|
||||
int printf(const char *format, ...);
|
||||
size_t strlen(const char *s);
|
||||
|
||||
int get_fd();
|
||||
int write(int handle, const void *buffer, size_t length);
|
||||
|
||||
long sysconf(int name);
|
||||
#define _SC_CHILD_MAX (2)
|
||||
|
||||
size_t confstr(int name, char *buffer, size_t length);
|
||||
#define _CS_PATH (1)
|
||||
|
||||
void test_sc_1()
|
||||
{
|
||||
int value = sysconf(_SC_CHILD_MAX);
|
||||
|
||||
printf("_SC_CHILD_MAX = %i\n", _SC_CHILD_MAX); // GOOD
|
||||
printf("_SC_CHILD_MAX = %i\n", value); // BAD [NOT DETECTED]
|
||||
}
|
||||
|
||||
void test_sc_2()
|
||||
{
|
||||
char *pathbuf;
|
||||
size_t n;
|
||||
|
||||
n = confstr(_CS_PATH, NULL, (size_t)0);
|
||||
pathbuf = (char *)malloc(n);
|
||||
if (pathbuf != NULL)
|
||||
{
|
||||
confstr(_CS_PATH, pathbuf, n);
|
||||
|
||||
printf("path: %s", pathbuf); // BAD [NOT DETECTED]
|
||||
write(get_fd(), pathbuf, strlen(pathbuf)); // BAD
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user