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 | require_once($AR->dir->install."/lib/modules/mod_htmlparser.php"); |
||
3 | |||
4 | class ESI { |
||
5 | function esiExpression( $expression ) { |
||
6 | /* Regexp now matches $(HTTP_COOKIE{stuff}); |
||
7 | TODO: |
||
8 | Add matching for: |
||
9 | [v] $(HTTP_COOKIE{stuff}|default) |
||
10 | [v] $(HTTP_COOKIE{stuff}|'default blah') |
||
11 | |||
12 | Add variable replacement for: |
||
13 | [v] HTTP_ACCEPT_LANGUAGE |
||
14 | [v] HTTP_HOST |
||
15 | [v] HTTP_REFERER |
||
16 | [v] QUERY_STRING |
||
17 | |||
18 | HTTP_USER_AGENT |
||
19 | FIXME: ariadne cookies are serialized by default, which would break HTTP_COOKIE usage in other ESI processors |
||
20 | */ |
||
21 | |||
22 | $result = preg_replace_callback('!\$\(([^)|{]*)(\{(([^}]*))\})?(\|([^)]*))?\)!', function($matches) { |
||
23 | // print_r($matches); |
||
24 | |||
25 | switch ($matches[1]) { |
||
26 | case 'HTTP_COOKIE': |
||
27 | $cookie = ldGetUserCookie($matches[3]); |
||
28 | $default = preg_replace("/^'(.*?)'$/", "$1", $matches[6]); |
||
29 | return $cookie ? $cookie : $default; |
||
30 | break; |
||
31 | View Code Duplication | case 'HTTP_HOST': |
|
32 | $host = ldGetServerVar('HTTP_HOST'); |
||
33 | $default = preg_replace("/^'(.*?)'$/", "$1", $matches[6]); |
||
34 | return $host ? $host : $default; |
||
35 | break; |
||
36 | View Code Duplication | case 'HTTP_REFERER': |
|
37 | $referer = ldGetServerVar('HTTP_REFERER'); |
||
38 | $default = preg_replace("/^'(.*?)'$/", "$1", $matches[6]); |
||
39 | return $referer ? $referer : $default; |
||
40 | break; |
||
41 | case 'HTTP_ACCEPT_LANGUAGE': |
||
42 | $acceptLanguage = ldGetServerVar('HTTP_ACCEPT_LANGUAGE'); |
||
43 | $acceptLanguage = strtolower(str_replace(", ", ",", $acceptLanguage)); |
||
44 | |||
45 | $languages = explode(",", $acceptLanguage); |
||
46 | if (in_array(strtolower($matches[3]), $languages)) { |
||
47 | return 1; |
||
48 | } |
||
49 | return 0; |
||
50 | break; |
||
51 | case 'QUERY_STRING': |
||
52 | $value = ar_loader::getvar($matches[3], "GET"); |
||
53 | $default = preg_replace("/^'(.*?)'$/", "$1", $matches[6]); |
||
54 | return isset($value) ? $value : $default; |
||
55 | break; |
||
56 | } |
||
57 | }, $expression); |
||
58 | return $result; |
||
59 | } |
||
60 | |||
61 | function esiRemove($page) { |
||
62 | $regExp = '|<esi:remove>(.*)</esi:remove>|Uis'; |
||
63 | return preg_replace($regExp, "", $page); |
||
64 | } |
||
65 | |||
66 | function esiComment($page) { |
||
67 | $regExp = '|<esi:comment[^>]*>|Uis'; |
||
68 | return preg_replace($regExp, "", $page); |
||
69 | } |
||
70 | |||
71 | function esiMarker($page) { |
||
72 | $regExp = '|<!--esi(.*)-->|Uis'; |
||
73 | return preg_replace($regExp, '$1', $page); |
||
74 | } |
||
75 | |||
76 | function esiVars($page) { |
||
77 | $regExp = '|<esi:vars>(.*)</esi:vars>|Uis'; |
||
78 | $page = preg_replace_callback($regExp, function($matches){ |
||
79 | return ESI::esiExpression($matches[1]); |
||
80 | }, $page); |
||
81 | return $page; |
||
82 | } |
||
83 | |||
84 | function esiFetch($url) { |
||
0 ignored issues
–
show
esiFetch uses the super-global variable $_GET which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
![]() |
|||
85 | $scriptName = $_SERVER["SCRIPT_NAME"] ? basename($_SERVER["SCRIPT_NAME"]) : basename($_SERVER["SCRIPT_FILENAME"]); |
||
86 | if ($scriptName) { |
||
87 | $scriptName = "/" . $scriptName; |
||
0 ignored issues
–
show
$scriptName is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
88 | } |
||
89 | |||
90 | $scriptName = "/loader.php"; // FIXME: Bij een request buiten Ariadne om kan het een andere scriptname zijn waardoor de include niet werkt. |
||
91 | |||
92 | $url = ESI::esiExpression( $url ); |
||
93 | if (strstr($url, $scriptName)) { |
||
94 | // Looks like an Ariadne request, handle it! |
||
95 | $urlArr = parse_url($url); |
||
96 | parse_str($urlArr['query'], $_GET); |
||
97 | // $pathInfo = str_replace($scriptName, '', $urlArr['path']); |
||
98 | $pathInfo = substr($urlArr['path'], strpos($urlArr['path'], $scriptName)+strlen($scriptName), strlen($urlArr['path'])); |
||
99 | $pathInfo = str_replace("//", "/", $pathInfo); |
||
100 | |||
101 | ob_start(); |
||
102 | ldProcessRequest($pathInfo); |
||
103 | $replacement = ob_get_contents(); |
||
104 | ob_end_clean(); |
||
105 | // FIXME: Check of the request went ok or not; |
||
106 | |||
107 | } else { |
||
108 | // FIXME: Is it a good idea to do http requests from the server this way? |
||
109 | $client = ar('http')->client(); |
||
110 | $scheme = parse_url($url, PHP_URL_SCHEME); |
||
111 | if (!$scheme) { |
||
0 ignored issues
–
show
The expression
$scheme of type string|false is loosely compared to false ; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.
In PHP, under loose comparison (like For '' == false // true
'' == null // true
'ab' == false // false
'ab' == null // false
// It is often better to use strict comparison
'' === false // false
'' === null // false
![]() |
|||
112 | $url = 'http:'.$url; |
||
113 | } |
||
114 | $replacement = $client->get($url); |
||
115 | |||
116 | if ($client->statusCode != "200") { |
||
117 | return false; |
||
118 | } |
||
119 | } |
||
120 | |||
121 | return $replacement; |
||
122 | } |
||
123 | |||
124 | function esiTry($page) { |
||
125 | $regExp = '|<esi:try>.*?<esi:attempt>(.*)</esi:attempt>.*?<esi:except>(.*)</esi:except>.*?</esi:try>|Uis'; |
||
126 | $page = preg_replace_callback($regExp, function($matches) { |
||
127 | $result = ESI::esiProcessAll($matches[1]); |
||
128 | if ($result === false) { |
||
129 | $result = ESI::esiProcessAll($matches[2]); |
||
130 | } |
||
131 | return $result; |
||
132 | }, $page); |
||
133 | return $page; |
||
134 | } |
||
135 | |||
136 | function esiChoose($page) { |
||
137 | $regExp = '|<esi:choose>.*?(<esi:when[^>]*>.*</esi:when>)+.*?<esi:otherwise>(.*)</esi:otherwise>.*?</esi:choose>|is'; |
||
138 | |||
139 | $page = preg_replace_callback($regExp, function($matches) { |
||
140 | $regExp2 = '|<esi:when[^>]*>(.*?)</esi:when>|is'; |
||
141 | preg_match_all($regExp2, $matches[1], $whens); |
||
142 | |||
143 | foreach ($whens[0] as $key => $when) { |
||
144 | $parts = htmlparser::parse($when); |
||
145 | $test = $parts['children'][0]['attribs']['test']; |
||
146 | |||
147 | if (ESI::esiEvaluate($test)) { |
||
148 | return ESI::esiProcessAll($whens[1][$key]); |
||
149 | } |
||
150 | } |
||
151 | return ESI::esiProcessAll($matches[2]); |
||
152 | }, $page); |
||
153 | return $page; |
||
154 | } |
||
155 | |||
156 | function esiEvaluate($test) { |
||
157 | global $AR; |
||
158 | |||
159 | // print_r($test); |
||
160 | $test = preg_replace('!(\$\([^)]*\))!', '\'$1\'', $test); |
||
161 | // echo "[2[" . print_r($test, true) . "]]"; |
||
162 | |||
163 | $test = ESI::esiExpression($test); |
||
164 | // echo "[[" . print_r($test, true) . "]]"; |
||
165 | |||
166 | require_once($AR->dir->install."/lib/modules/mod_pinp.phtml"); |
||
167 | $pinp=new pinp($AR->PINP_Functions, "esilocal->", "\$AR_ESI_this->_"); |
||
168 | $pinp->allowed_functions = array(); |
||
169 | $pinp->language_types['array'] = false; |
||
170 | $pinp->language_types['object'] = false; |
||
171 | |||
172 | $compiled=$pinp->compile("<pinp>" . $test . "</pinp>"); |
||
173 | |||
174 | $compiled = preg_replace("/^<\?php(.*)\?".">$/s", '$1', $compiled); |
||
175 | |||
176 | // FIXME: Is eval after the pinp compiler save enough to run? |
||
177 | $result = eval("return (" . $compiled . ");"); |
||
0 ignored issues
–
show
It is generally not recommended to use
eval unless absolutely required.
On one hand, ![]() |
|||
178 | |||
179 | return $result; |
||
180 | } |
||
181 | |||
182 | function esiInclude($page) { |
||
183 | /* TODO: |
||
184 | [v] alt |
||
185 | [v] onerror |
||
186 | */ |
||
187 | global $ARCurrent, $AR; |
||
188 | |||
189 | // parse <esi:include src="view.html"> |
||
190 | $regExp = '|<esi:include.*?'.'>|i'; |
||
191 | |||
192 | |||
193 | preg_match_all($regExp, $page, $matches); |
||
194 | |||
195 | foreach ($matches[0] as $match) { |
||
196 | $parts = htmlparser::parse($match); |
||
197 | |||
198 | $src = $parts['children'][0]['attribs']['src']; |
||
199 | $alt = $parts['children'][0]['attribs']['alt']; |
||
200 | $onerror = $parts['children'][0]['attribs']['onerror']; |
||
201 | |||
202 | $replacement = ESI::esiFetch($src); |
||
203 | if ($replacement == false && isset($alt)) { |
||
204 | $replacement = ESI::esiFetch($alt); |
||
205 | } |
||
206 | if ( |
||
207 | $replacement == false && |
||
208 | isset($onerror) && |
||
209 | $onerror == "continue" |
||
210 | ) { |
||
211 | $replacement = ""; |
||
212 | } |
||
213 | |||
214 | if ($replacement !== false) { |
||
215 | $page = str_replace($match, $replacement, $page); |
||
216 | } else { |
||
217 | return false; |
||
218 | } |
||
219 | } |
||
220 | |||
221 | return $page; |
||
222 | } |
||
223 | |||
224 | function esiProcessAll($page) { |
||
225 | $page = ESI::esiMarker($page); |
||
226 | if ($page === false) {return false;} |
||
227 | |||
228 | $page = ESI::esiRemove($page); |
||
229 | if ($page === false) {return false;} |
||
230 | |||
231 | $page = ESI::esiComment($page); |
||
232 | if ($page === false) {return false;} |
||
233 | |||
234 | $page = ESI::esiTry($page); |
||
235 | if ($page === false) {return false;} |
||
236 | |||
237 | $page = ESI::esiChoose($page); |
||
238 | if ($page === false) {return false;} |
||
239 | |||
240 | $page = ESI::esiInclude($page); |
||
241 | if ($page === false) {return false;} |
||
242 | |||
243 | $page = ESI::esiVars($page); |
||
244 | if ($page === false) {return false;} |
||
245 | |||
246 | return $page; |
||
247 | } |
||
248 | |||
249 | function esiProcess($page) { |
||
250 | /* |
||
251 | TODO: |
||
252 | inline |
||
253 | |||
254 | [v] choose/when/otherwise |
||
255 | [v] try/attempt/except |
||
256 | [v] include |
||
257 | [v] comment |
||
258 | [v] remove |
||
259 | [v] vars |
||
260 | [v] <!-- esi --> |
||
261 | */ |
||
262 | |||
263 | $page = ESI::esiProcessAll($page); |
||
264 | if ($page === false) { |
||
265 | ldObjectNotFound("", "esiInclude failed"); |
||
266 | } |
||
267 | return $page; |
||
268 | } |
||
269 | } |
||
270 |
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: