|
1 | 1 | /**
|
2 | 2 | * @name Exposure of system data to an unauthorized control sphere
|
3 | 3 | * @description Exposing system data or debugging information helps
|
4 |
| - * an adversary learn about the system and form an |
| 4 | + * a malicious user learn about the system and form an |
5 | 5 | * attack plan.
|
6 | 6 | * @kind path-problem
|
7 | 7 | * @problem.severity warning
|
|
13 | 13 | */
|
14 | 14 |
|
15 | 15 | import cpp
|
16 |
| -import semmle.code.cpp.commons.Environment |
17 | 16 | import semmle.code.cpp.ir.dataflow.TaintTracking
|
18 | 17 | import semmle.code.cpp.models.interfaces.FlowSource
|
19 | 18 | import DataFlow::PathGraph
|
20 |
| - |
21 |
| -/** |
22 |
| - * An element that should not be exposed to an adversary. |
23 |
| - */ |
24 |
| -abstract class SystemData extends Element { |
25 |
| - /** |
26 |
| - * Gets an expression that is part of this `SystemData`. |
27 |
| - */ |
28 |
| - abstract Expr getAnExpr(); |
29 |
| -} |
30 |
| - |
31 |
| -/** |
32 |
| - * Data originating from the environment. |
33 |
| - */ |
34 |
| -class EnvData extends SystemData { |
35 |
| - EnvData() { |
36 |
| - // identify risky looking environment variables only |
37 |
| - this.(EnvironmentRead) |
38 |
| - .getEnvironmentVariable() |
39 |
| - .toLowerCase() |
40 |
| - .regexpMatch(".*(user|host|admin|root|home|path|http|ssl|snmp|sock|port|proxy|pass|token|crypt|key).*") |
41 |
| - } |
42 |
| - |
43 |
| - override Expr getAnExpr() { result = this } |
44 |
| -} |
45 |
| - |
46 |
| -/** |
47 |
| - * Data originating from a call to `mysql_get_client_info()`. |
48 |
| - */ |
49 |
| -class SqlClientInfo extends SystemData { |
50 |
| - SqlClientInfo() { this.(FunctionCall).getTarget().hasName("mysql_get_client_info") } |
51 |
| - |
52 |
| - override Expr getAnExpr() { result = this } |
53 |
| -} |
54 |
| - |
55 |
| -private predicate sqlConnectInfo(FunctionCall source, VariableAccess use) { |
56 |
| - ( |
57 |
| - source.getTarget().hasName("mysql_connect") or |
58 |
| - source.getTarget().hasName("mysql_real_connect") |
59 |
| - ) and |
60 |
| - use = source.getAnArgument() |
61 |
| -} |
62 |
| - |
63 |
| -/** |
64 |
| - * Data passed into an SQL connect function. |
65 |
| - */ |
66 |
| -class SqlConnectInfo extends SystemData { |
67 |
| - SqlConnectInfo() { sqlConnectInfo(this, _) } |
68 |
| - |
69 |
| - override Expr getAnExpr() { sqlConnectInfo(this, result) } |
70 |
| -} |
71 |
| - |
72 |
| -private predicate posixSystemInfo(FunctionCall source, Element use) { |
73 |
| - // size_t confstr(int name, char *buf, size_t len) |
74 |
| - // - various OS / system strings, such as the libc version |
75 |
| - // int statvfs(const char *__path, struct statvfs *__buf) |
76 |
| - // int fstatvfs(int __fd, struct statvfs *__buf) |
77 |
| - // - various filesystem parameters |
78 |
| - // int uname(struct utsname *buf) |
79 |
| - // - OS name and version |
80 |
| - source.getTarget().hasName(["confstr", "statvfs", "fstatvfs", "uname"]) and |
81 |
| - use = source.getArgument(1) |
82 |
| -} |
83 |
| - |
84 |
| -/** |
85 |
| - * Data obtained from a POSIX system information call. |
86 |
| - */ |
87 |
| -class PosixSystemInfo extends SystemData { |
88 |
| - PosixSystemInfo() { posixSystemInfo(this, _) } |
89 |
| - |
90 |
| - override Expr getAnExpr() { posixSystemInfo(this, result) } |
91 |
| -} |
92 |
| - |
93 |
| -private predicate posixPWInfo(FunctionCall source, Element use) { |
94 |
| - // struct passwd *getpwnam(const char *name); |
95 |
| - // struct passwd *getpwuid(uid_t uid); |
96 |
| - // struct passwd *getpwent(void); |
97 |
| - // struct group *getgrnam(const char *name); |
98 |
| - // struct group *getgrgid(gid_t); |
99 |
| - // struct group *getgrent(void); |
100 |
| - source |
101 |
| - .getTarget() |
102 |
| - .hasName(["getpwnam", "getpwuid", "getpwent", "getgrnam", "getgrgid", "getgrent"]) and |
103 |
| - use = source |
104 |
| - or |
105 |
| - // int getpwnam_r(const char *name, struct passwd *pwd, |
106 |
| - // char *buf, size_t buflen, struct passwd **result); |
107 |
| - // int getpwuid_r(uid_t uid, struct passwd *pwd, |
108 |
| - // char *buf, size_t buflen, struct passwd **result); |
109 |
| - // int getgrgid_r(gid_t gid, struct group *grp, |
110 |
| - // char *buf, size_t buflen, struct group **result); |
111 |
| - // int getgrnam_r(const char *name, struct group *grp, |
112 |
| - // char *buf, size_t buflen, struct group **result); |
113 |
| - source.getTarget().hasName(["getpwnam_r", "getpwuid_r", "getgrgid_r", "getgrnam_r"]) and |
114 |
| - use = source.getArgument([1, 2, 4]) |
115 |
| - or |
116 |
| - // int getpwent_r(struct passwd *pwd, char *buffer, size_t bufsize, |
117 |
| - // struct passwd **result); |
118 |
| - // int getgrent_r(struct group *gbuf, char *buf, |
119 |
| - // size_t buflen, struct group **gbufp); |
120 |
| - source.getTarget().hasName(["getpwent_r", "getgrent_r"]) and |
121 |
| - use = source.getArgument([0, 1, 3]) |
122 |
| -} |
123 |
| - |
124 |
| -/** |
125 |
| - * Data obtained from a POSIX user/password/group database information call. |
126 |
| - */ |
127 |
| -class PosixPWInfo extends SystemData { |
128 |
| - PosixPWInfo() { posixPWInfo(this, _) } |
129 |
| - |
130 |
| - override Expr getAnExpr() { posixPWInfo(this, result) } |
131 |
| -} |
132 |
| - |
133 |
| -private predicate windowsSystemInfo(FunctionCall source, Element use) { |
134 |
| - // DWORD WINAPI GetVersion(void); |
135 |
| - source.getTarget().hasGlobalName("GetVersion") and |
136 |
| - use = source |
137 |
| - or |
138 |
| - // BOOL WINAPI GetVersionEx(_Inout_ LPOSVERSIONINFO lpVersionInfo); |
139 |
| - // void WINAPI GetSystemInfo(_Out_ LPSYSTEM_INFO lpSystemInfo); |
140 |
| - // void WINAPI GetNativeSystemInfo(_Out_ LPSYSTEM_INFO lpSystemInfo); |
141 |
| - source |
142 |
| - .getTarget() |
143 |
| - .hasGlobalName([ |
144 |
| - "GetVersionEx", "GetVersionExA", "GetVersionExW", "GetSystemInfo", "GetNativeSystemInfo" |
145 |
| - ]) and |
146 |
| - use = source.getArgument(0) |
147 |
| -} |
148 |
| - |
149 |
| -/** |
150 |
| - * Data obtained from a Windows system information call. |
151 |
| - */ |
152 |
| -class WindowsSystemInfo extends SystemData { |
153 |
| - WindowsSystemInfo() { windowsSystemInfo(this, _) } |
154 |
| - |
155 |
| - override Expr getAnExpr() { windowsSystemInfo(this, result) } |
156 |
| -} |
157 |
| - |
158 |
| -private predicate windowsFolderPath(FunctionCall source, Element use) { |
159 |
| - // BOOL SHGetSpecialFolderPath( |
160 |
| - // HWND hwndOwner, |
161 |
| - // _Out_ LPTSTR lpszPath, |
162 |
| - // _In_ int csidl, |
163 |
| - // _In_ BOOL fCreate |
164 |
| - // ); |
165 |
| - source |
166 |
| - .getTarget() |
167 |
| - .hasGlobalName([ |
168 |
| - "SHGetSpecialFolderPath", "SHGetSpecialFolderPathA", "SHGetSpecialFolderPathW" |
169 |
| - ]) and |
170 |
| - use = source.getArgument(1) |
171 |
| - or |
172 |
| - // HRESULT SHGetKnownFolderPath( |
173 |
| - // _In_ REFKNOWNFOLDERID rfid, |
174 |
| - // _In_ DWORD dwFlags, |
175 |
| - // _In_opt_ HANDLE hToken, |
176 |
| - // _Out_ PWSTR *ppszPath |
177 |
| - // ); |
178 |
| - source.getTarget().hasGlobalName("SHGetKnownFolderPath") and |
179 |
| - use = source.getArgument(3) |
180 |
| - or |
181 |
| - // HRESULT SHGetFolderPath( |
182 |
| - // _In_ HWND hwndOwner, |
183 |
| - // _In_ int nFolder, |
184 |
| - // _In_ HANDLE hToken, |
185 |
| - // _In_ DWORD dwFlags, |
186 |
| - // _Out_ LPTSTR pszPath |
187 |
| - // ); |
188 |
| - source.getTarget().hasGlobalName(["SHGetFolderPath", "SHGetFolderPathA", "SHGetFolderPathW"]) and |
189 |
| - use = source.getArgument(4) |
190 |
| - or |
191 |
| - // HRESULT SHGetFolderPathAndSubDir( |
192 |
| - // _In_ HWND hwnd, |
193 |
| - // _In_ int csidl, |
194 |
| - // _In_ HANDLE hToken, |
195 |
| - // _In_ DWORD dwFlags, |
196 |
| - // _In_ LPCTSTR pszSubDir, |
197 |
| - // _Out_ LPTSTR pszPath |
198 |
| - // ); |
199 |
| - source |
200 |
| - .getTarget() |
201 |
| - .hasGlobalName([ |
202 |
| - "SHGetFolderPathAndSubDir", "SHGetFolderPathAndSubDirA", "SHGetFolderPathAndSubDirW" |
203 |
| - ]) and |
204 |
| - use = source.getArgument(5) |
205 |
| -} |
206 |
| - |
207 |
| -/** |
208 |
| - * Data obtained about Windows special paths (for example, the |
209 |
| - * location of `System32`). |
210 |
| - */ |
211 |
| -class WindowsFolderPath extends SystemData { |
212 |
| - WindowsFolderPath() { windowsFolderPath(this, _) } |
213 |
| - |
214 |
| - override Expr getAnExpr() { windowsFolderPath(this, result) } |
215 |
| -} |
216 |
| - |
217 |
| -private predicate logonUser(FunctionCall source, VariableAccess use) { |
218 |
| - source.getTarget().hasGlobalName(["LogonUser", "LogonUserW", "LogonUserA"]) and |
219 |
| - use = source.getAnArgument() |
220 |
| -} |
221 |
| - |
222 |
| -/** |
223 |
| - * Data passed into a `LogonUser` (Windows) function. |
224 |
| - */ |
225 |
| -class LogonUser extends SystemData { |
226 |
| - LogonUser() { logonUser(this, _) } |
227 |
| - |
228 |
| - override Expr getAnExpr() { logonUser(this, result) } |
229 |
| -} |
230 |
| - |
231 |
| -private predicate regQuery(FunctionCall source, VariableAccess use) { |
232 |
| - // LONG WINAPI RegQueryValue( |
233 |
| - // _In_ HKEY hKey, |
234 |
| - // _In_opt_ LPCTSTR lpSubKey, |
235 |
| - // _Out_opt_ LPTSTR lpValue, |
236 |
| - // _Inout_opt_ PLONG lpcbValue |
237 |
| - // ); |
238 |
| - source.getTarget().hasGlobalName(["RegQueryValue", "RegQueryValueA", "RegQueryValueW"]) and |
239 |
| - use = source.getArgument(2) |
240 |
| - or |
241 |
| - // LONG WINAPI RegQueryMultipleValues( |
242 |
| - // _In_ HKEY hKey, |
243 |
| - // _Out_ PVALENT val_list, |
244 |
| - // _In_ DWORD num_vals, |
245 |
| - // _Out_opt_ LPTSTR lpValueBuf, |
246 |
| - // _Inout_opt_ LPDWORD ldwTotsize |
247 |
| - // ); |
248 |
| - source |
249 |
| - .getTarget() |
250 |
| - .hasGlobalName([ |
251 |
| - "RegQueryMultipleValues", "RegQueryMultipleValuesA", "RegQueryMultipleValuesW" |
252 |
| - ]) and |
253 |
| - use = source.getArgument(3) |
254 |
| - or |
255 |
| - // LONG WINAPI RegQueryValueEx( |
256 |
| - // _In_ HKEY hKey, |
257 |
| - // _In_opt_ LPCTSTR lpValueName, |
258 |
| - // _Reserved_ LPDWORD lpReserved, |
259 |
| - // _Out_opt_ LPDWORD lpType, |
260 |
| - // _Out_opt_ LPBYTE lpData, |
261 |
| - // _Inout_opt_ LPDWORD lpcbData |
262 |
| - // ); |
263 |
| - source.getTarget().hasGlobalName(["RegQueryValueEx", "RegQueryValueExA", "RegQueryValueExW"]) and |
264 |
| - use = source.getArgument(4) |
265 |
| - or |
266 |
| - // LONG WINAPI RegGetValue( |
267 |
| - // _In_ HKEY hkey, |
268 |
| - // _In_opt_ LPCTSTR lpSubKey, |
269 |
| - // _In_opt_ LPCTSTR lpValue, |
270 |
| - // _In_opt_ DWORD dwFlags, |
271 |
| - // _Out_opt_ LPDWORD pdwType, |
272 |
| - // _Out_opt_ PVOID pvData, |
273 |
| - // _Inout_opt_ LPDWORD pcbData |
274 |
| - // ); |
275 |
| - source.getTarget().hasGlobalName(["RegGetValue", "RegGetValueA", "RegGetValueW"]) and |
276 |
| - use = source.getArgument(5) |
277 |
| -} |
278 |
| - |
279 |
| -/** |
280 |
| - * Data read from the Windows registry. |
281 |
| - */ |
282 |
| -class RegQuery extends SystemData { |
283 |
| - RegQuery() { regQuery(this, _) } |
284 |
| - |
285 |
| - override Expr getAnExpr() { regQuery(this, result) } |
286 |
| -} |
| 19 | +import SystemData |
287 | 20 |
|
288 | 21 | class ExposedSystemDataConfiguration extends TaintTracking::Configuration {
|
289 | 22 | ExposedSystemDataConfiguration() { this = "ExposedSystemDataConfiguration" }
|
290 | 23 |
|
291 |
| - override predicate isSource(DataFlow::Node source) { |
292 |
| - source.asConvertedExpr() = any(SystemData sd).getAnExpr() |
293 |
| - } |
| 24 | + override predicate isSource(DataFlow::Node source) { source = any(SystemData sd).getAnExpr() } |
294 | 25 |
|
295 | 26 | override predicate isSink(DataFlow::Node sink) {
|
296 | 27 | exists(FunctionCall fc, FunctionInput input, int arg |
|
|
0 commit comments