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 | |||
3 | namespace TorDetect; |
||
4 | |||
5 | /** |
||
6 | * Class TorDetect to determine if Remote User is using the TOR Network |
||
7 | * |
||
8 | * @author Alexander Over <[email protected]> |
||
9 | */ |
||
10 | class TorDetect |
||
11 | { |
||
12 | /** |
||
13 | * @var object |
||
14 | */ |
||
15 | private static $instance; |
||
16 | |||
17 | /** |
||
18 | * @var string |
||
19 | */ |
||
20 | private $target = null; |
||
21 | |||
22 | /** |
||
23 | * @var string |
||
24 | */ |
||
25 | private $exithost = null; |
||
26 | |||
27 | /** |
||
28 | * @var integer |
||
29 | */ |
||
30 | private $port = 443; |
||
31 | |||
32 | /** |
||
33 | * @var array |
||
34 | */ |
||
35 | private $cache = array(); |
||
36 | |||
37 | /** |
||
38 | * Constructor |
||
39 | */ |
||
40 | private function __construct() |
||
41 | { |
||
42 | if (isset($_SERVER) && array_key_exists('REMOTE_ADDR', $_SERVER)) { |
||
43 | $this->setTarget($_SERVER['REMOTE_ADDR']); |
||
44 | } |
||
45 | |||
46 | if (isset($_SERVER) && array_key_exists('SERVER_ADDR', $_SERVER)) { |
||
47 | $this->setExithost($_SERVER["SERVER_ADDR"]); |
||
48 | $this->setPort($_SERVER["SERVER_PORT"]); |
||
49 | } |
||
50 | } |
||
51 | |||
52 | /** |
||
53 | * @param $target |
||
54 | * |
||
55 | * @return $this |
||
56 | * @throws \InvalidArgumentException |
||
57 | */ |
||
58 | public function setTarget($target) |
||
59 | { |
||
60 | if (filter_var($target, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) { |
||
61 | $this->target = implode('.', array_reverse(explode('.', $target))); |
||
62 | } else { |
||
63 | throw new \InvalidArgumentException( |
||
64 | sprintf('"%s" is not a valid value for target', $target) |
||
65 | ); |
||
66 | } |
||
67 | |||
68 | return $this; |
||
69 | } |
||
70 | |||
71 | /** |
||
72 | * @param $exithost |
||
73 | * @return $this |
||
74 | */ |
||
75 | public function setExithost($exithost) |
||
76 | { |
||
77 | $this->exithost = $this->prepareExithost($exithost); |
||
78 | |||
79 | return $this; |
||
80 | } |
||
81 | |||
82 | /** |
||
83 | * @param integer $port |
||
84 | * @return $this |
||
85 | */ |
||
86 | public function setPort($port) |
||
87 | { |
||
88 | $this->port = intval($port); |
||
89 | |||
90 | return $this; |
||
91 | } |
||
92 | |||
93 | /** |
||
94 | * @return object|TorDetect |
||
95 | */ |
||
96 | public static function getInstance() |
||
97 | { |
||
98 | if (!(self::$instance instanceof self)) { |
||
99 | self::$instance = new self; |
||
100 | } |
||
101 | |||
102 | return self::$instance; |
||
103 | } |
||
104 | |||
105 | /** |
||
106 | * @return mixed |
||
107 | */ |
||
108 | public function isTorActive() |
||
109 | { |
||
110 | if (null === $this->target) { |
||
111 | throw new \InvalidArgumentException('No target set. Use setTarget($ip) first.'); |
||
112 | } |
||
113 | |||
114 | if (!array_key_exists($this->target, $this->cache)) { |
||
115 | $this->doFreshCheck(); |
||
116 | } |
||
117 | |||
118 | return $this->cache[$this->target]; |
||
119 | } |
||
120 | |||
121 | private function doFreshCheck() |
||
122 | { |
||
123 | if (null === $this->exithost) { |
||
124 | throw new \InvalidArgumentException('No exithost set. Use setExithost($host) first.'); |
||
125 | } |
||
126 | |||
127 | $query = array( |
||
128 | $this->target, |
||
129 | $this->port, |
||
130 | $this->exithost, |
||
131 | 'ip-port.exitlist.torproject.org' |
||
132 | ); |
||
133 | |||
134 | $dns = $this->dnsGetRecord($query); |
||
135 | $isActive = $this->checkRecord($dns); |
||
136 | |||
137 | $this->cache[$this->target] = $isActive; |
||
138 | } |
||
139 | |||
140 | /** |
||
141 | * Wrapper for windows < 5.3 and, theoretically for |
||
142 | * linux without dns_get_record() function |
||
143 | * |
||
144 | * @param array $address |
||
145 | * |
||
146 | * @return array |
||
147 | */ |
||
148 | private function dnsGetRecord(array $address) |
||
149 | { |
||
150 | if (!function_exists('dns_get_record') && !function_exists('exec')) { |
||
151 | throw new \LogicException( |
||
152 | 'no suitable methods for dns fetching found' |
||
153 | ); |
||
154 | } |
||
155 | |||
156 | $address = implode('.', $address); |
||
157 | if (function_exists('dns_get_record')) { |
||
158 | return dns_get_record($address, DNS_A); |
||
159 | } |
||
160 | |||
161 | return $this->doFallbackCheck($address); |
||
162 | } |
||
163 | |||
164 | /** |
||
165 | * @param string $address |
||
166 | * @return array |
||
167 | */ |
||
168 | private function doFallbackCheck($address) |
||
169 | { |
||
170 | $output = $dns = array(); |
||
171 | $retval = false; |
||
172 | if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') { |
||
173 | @exec('nslookup -type A ' . $address, $output, $retval); |
||
0 ignored issues
–
show
|
|||
174 | if (!$retval && array_key_exists(1, $output)) { |
||
0 ignored issues
–
show
The expression
$retval of type integer|null is loosely compared to false ; this is ambiguous if the integer can be zero. You might want to explicitly use === null instead.
In PHP, under loose comparison (like For 0 == false // true
0 == null // true
123 == false // false
123 == null // false
// It is often better to use strict comparison
0 === false // false
0 === null // false
![]() |
|||
175 | $output[0] = $output[1]; |
||
176 | } |
||
177 | } else { |
||
178 | @exec('host ' . $address, $output, $retval); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
179 | } |
||
180 | |||
181 | if (!$retval && array_key_exists(0, $output)) { |
||
0 ignored issues
–
show
The expression
$retval of type integer|null is loosely compared to false ; this is ambiguous if the integer can be zero. You might want to explicitly use === null instead.
In PHP, under loose comparison (like For 0 == false // true
0 == null // true
123 == false // false
123 == null // false
// It is often better to use strict comparison
0 === false // false
0 === null // false
![]() |
|||
182 | $explode = explode(' ', $output[0]); |
||
183 | $result = $explode[count($explode) - 1]; |
||
184 | if (filter_var($result, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) { |
||
185 | $dns[0]['ip'] = $result; |
||
186 | } |
||
187 | unset($explode, $result); |
||
188 | } |
||
189 | |||
190 | return $dns; |
||
191 | } |
||
192 | |||
193 | /** |
||
194 | * @param $dns |
||
195 | * @return bool |
||
196 | */ |
||
197 | private function checkRecord($dns) |
||
198 | { |
||
199 | if (array_key_exists(0, $dns) && array_key_exists('ip', $dns[0])) { |
||
200 | return ($dns[0]['ip'] === '127.0.0.2'); |
||
201 | } |
||
202 | |||
203 | return false; |
||
204 | } |
||
205 | |||
206 | /** |
||
207 | * @param string $exithost |
||
208 | * @return string |
||
209 | */ |
||
210 | private function prepareExithost($exithost) |
||
211 | { |
||
212 | return implode('.', array_reverse(explode('.', $exithost))); |
||
213 | } |
||
214 | } |
||
215 |
If you suppress an error, we recommend checking for the error condition explicitly: