This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /* zKillboard |
||
3 | * Copyright (C) 2012-2015 EVE-KILL Team and EVSCO. |
||
4 | * |
||
5 | * This program is free software: you can redistribute it and/or modify |
||
6 | * it under the terms of the GNU Affero General Public License as published by |
||
7 | * the Free Software Foundation, either version 3 of the License, or |
||
8 | * (at your option) any later version. |
||
9 | * |
||
10 | * This program is distributed in the hope that it will be useful, |
||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
13 | * GNU Affero General Public License for more details. |
||
14 | * |
||
15 | * You should have received a copy of the GNU Affero General Public License |
||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
||
17 | */ |
||
18 | |||
19 | // Load globals |
||
20 | global $apiWhiteList, $maxRequestsPerHour, $debug, $fullAddr; |
||
21 | |||
22 | // Endpoints |
||
23 | $endpoints = endPoints(); |
||
24 | |||
25 | // Endpoint |
||
26 | $endpoint = isset($flags[0]) ? $flags[0] : NULL; |
||
27 | |||
28 | // Parameters |
||
29 | $parameters = Util::convertUriToParameters(); |
||
30 | |||
31 | // client IP |
||
32 | $ip = IP::get(); |
||
33 | |||
34 | if($ip == "73.169.15.22" || $ip == "104.236.126.43") |
||
35 | die(); |
||
36 | |||
37 | // init $data |
||
38 | $data = array(); |
||
39 | |||
40 | if(in_array($endpoint, $endpoints)) |
||
41 | { |
||
42 | try |
||
43 | { |
||
44 | $fileName = __DIR__ . "/api/$endpoint.php"; |
||
45 | if(!file_exists($fileName)) |
||
46 | throw new Exception(); |
||
47 | |||
48 | require_once $fileName; |
||
49 | $className = "api_$endpoint"; |
||
50 | $class = new $className(); |
||
51 | |||
52 | if(!is_a($class, "apiEndpoint")) |
||
53 | { |
||
54 | $data = array( |
||
55 | "type" => "error", |
||
56 | "message" => "Endpoint does not implement apiEndpoint" |
||
57 | ); |
||
58 | } |
||
59 | |||
60 | $data = $class->execute($parameters); |
||
61 | } |
||
62 | catch (Exception $e) |
||
63 | { |
||
64 | $data = array( |
||
65 | "type" => "error", |
||
66 | "message" => "$endpoint ended with error: " . $e->getMessage() |
||
67 | ); |
||
68 | } |
||
69 | } |
||
70 | else |
||
71 | { |
||
72 | $data = array( |
||
73 | "type" => "error", |
||
74 | "message" => "No endpoint selected.", |
||
75 | "endpoints" => array( |
||
76 | "/api/list/", |
||
77 | "/api/help/<endPoint>/", |
||
78 | "/api/parameters/<endPoint>/" |
||
79 | ) |
||
80 | ); |
||
81 | } |
||
82 | |||
83 | // If the endpoint is docs, we'll just render the html page instead, since the same data is available under /list/ and /parameters/ ! :) |
||
84 | if($endpoint == "docs") |
||
85 | return $app->render("apidocs.html", array("data" => $data)); |
||
86 | |||
87 | // Scrape Checker If type isn't set, scrapecheck, otherwise don't.. |
||
88 | $type = isset($data["type"]) ? "error" : NULL; |
||
89 | if($type == NULL) |
||
90 | if(!in_array($ip, $apiWhiteList)) |
||
91 | scrapeCheck(); |
||
92 | |||
93 | // Output the data |
||
94 | header("Access-Control-Allow-Origin: *"); |
||
95 | header("Access-Control-Allow-Methods: GET"); |
||
96 | $uri = substr($_SERVER["REQUEST_URI"], 0, 256); |
||
97 | $ip = substr(IP::get(), 0, 64); |
||
98 | $count = Db::queryField("SELECT count(*) AS count FROM zz_scrape_prevention WHERE ip = :ip AND dttm >= date_sub(now(), interval 1 hour)", "count", array(":ip" => $ip), 0); |
||
99 | header("X-Bin-Request-Count: ". $count); |
||
100 | header("X-Bin-Max-Requests: ". $maxRequestsPerHour); |
||
101 | $app->etag(md5(serialize($data))); |
||
102 | $app->expires("+1 hour"); |
||
103 | $userAgent = @$_SERVER["HTTP_USER_AGENT"]; |
||
104 | if($debug) |
||
105 | Log::log("API Fetch: " . $fullAddr . $_SERVER["REQUEST_URI"] . " (" . $ip . " / " . $userAgent . ")"); |
||
106 | |||
107 | if(isset($_GET["callback"]) && isValidCallback($_GET["callback"])) |
||
108 | { |
||
109 | $app->contentType("application/javascript; charset=utf-8"); |
||
110 | header("X-JSONP: true"); |
||
111 | echo $_GET["callback"] . "(" . json_encode($data) . ")"; |
||
112 | } |
||
113 | else |
||
114 | { |
||
115 | $app->contentType("application/json; charset=utf-8"); |
||
116 | echo json_encode($data, JSON_PRETTY_PRINT | JSON_NUMERIC_CHECK | JSON_UNESCAPED_SLASHES); |
||
117 | } |
||
118 | |||
119 | interface apiEndpoint |
||
120 | { |
||
121 | public function getDescription(); |
||
122 | public function getAcceptedParameters(); |
||
123 | public function execute($parameters); |
||
124 | } |
||
125 | |||
126 | function endPoints() |
||
127 | { |
||
128 | $endPoints = array(); |
||
129 | $dir = __DIR__ . "/api/"; |
||
130 | $data = scandir($dir); |
||
131 | |||
132 | foreach($data as $e) |
||
133 | if(!in_array($e, array(".", ".."))) |
||
134 | $endPoints[] = str_replace(".php", "", $e); |
||
135 | |||
136 | return $endPoints; |
||
137 | } |
||
138 | |||
139 | function scrapeCheck() |
||
140 | { |
||
141 | global $apiWhiteList, $maxRequestsPerHour; |
||
142 | $maxRequestsPerHour = isset($maxRequestsPerHour) ? $maxRequestsPerHour : 360; |
||
143 | |||
144 | $uri = $_SERVER["REQUEST_URI"]; |
||
145 | $uri = explode("?", $uri); |
||
146 | $uri = substr($uri[0], 0, 256); |
||
147 | $ip = substr(IP::get(), 0, 64); |
||
148 | StatsD::increment("zkb_api"); |
||
149 | |||
150 | if(!in_array($ip, $apiWhiteList)) |
||
151 | { |
||
152 | $count = Db::queryField("SELECT count(*) AS count FROM zz_scrape_prevention WHERE ip = :ip AND dttm >= date_sub(now(), interval 1 hour)", "count", array(":ip" => $ip), 0); |
||
153 | if($count > $maxRequestsPerHour) |
||
154 | { |
||
155 | $date = date("Y-m-d H:i:s"); |
||
0 ignored issues
–
show
|
|||
156 | $cachedUntil = date("Y-m-d H:i:s", time() + 3600); |
||
157 | header("Content-type: application/json; charset=utf-8"); |
||
158 | header("Retry-After: " . $cachedUntil . " GMT"); |
||
159 | header("HTTP/1.1 429 Too Many Requests"); |
||
160 | header("Etag: ".(md5(serialize($data)))); |
||
161 | $data = json_encode( |
||
162 | array( |
||
163 | "Error" => "You have too many API requests in the last hour. You are allowed a maximum of $maxRequestsPerHour requests.", |
||
164 | "cachedUntil" => $cachedUntil |
||
165 | ) |
||
166 | ); |
||
167 | echo $data; |
||
168 | die(); |
||
169 | } |
||
170 | } |
||
171 | Db::execute("INSERT INTO zz_scrape_prevention (ip, uri, dttm) VALUES (:ip, :uri, now())", array(":ip" => $ip, ":uri" => $uri)); |
||
172 | } |
||
173 | |||
174 | function isValidCallback($subject) |
||
175 | { |
||
176 | $identifier_syntax = '/^[$_\p{L}][$_\p{L}\p{Mn}\p{Mc}\p{Nd}\p{Pc}\x{200C}\x{200D}]*+$/u'; |
||
177 | |||
178 | $reserved_words = array('break', 'do', 'instanceof', 'typeof', 'case', |
||
179 | 'else', 'new', 'var', 'catch', 'finally', 'return', 'void', 'continue', |
||
180 | 'for', 'switch', 'while', 'debugger', 'function', 'this', 'with', |
||
181 | 'default', 'if', 'throw', 'delete', 'in', 'try', 'class', 'enum', |
||
182 | 'extends', 'super', 'const', 'export', 'import', 'implements', 'let', |
||
183 | 'private', 'public', 'yield', 'interface', 'package', 'protected', |
||
184 | 'static', 'null', 'true', 'false' |
||
185 | ); |
||
186 | |||
187 | return preg_match($identifier_syntax, $subject) && ! in_array(mb_strtolower($subject, 'UTF-8'), $reserved_words); |
||
188 | } |
||
189 |
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.
Both the
$myVar
assignment in line 1 and the$higher
assignment in line 2 are dead. The first because$myVar
is never used and the second because$higher
is always overwritten for every possible time line.