Issues (63)

Security Analysis    no request data  

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

source/VKBase.php (2 issues)

Upgrade to new PHP Analysis Engine

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 FreedomCore\VK;
4
5
use FreedomCore\VK\API\VKAccount;
6
use FreedomCore\VK\API\VKUsers;
7
8
class VKBase {
9
10
    /**
11
     * Application ID
12
     * @var string
13
     */
14
    private $applicationID;
15
16
    /**
17
     * Application Secret Key
18
     * @var string
19
     */
20
    private $APISecret;
21
22
    /**
23
     * API Version. If null, uses latest available version
24
     * @var string
25
     */
26
    private $APIVersion;
27
28
    /**
29
     * Acess Token String
30
     * @var string
31
     */
32
    private $accessToken;
33
34
    /**
35
     * Authorization Status
36
     * @var bool
37
     */
38
    private $authorizationStatus = false;
39
40
    /**
41
     * CURL Object
42
     * @var Resource
43
     */
44
    private $curlObject;
45
46
    /**
47
     * Users Access Permissions
48
     * @var int
49
     */
50
    private $permissionsMask = 0;
51
52
    /**
53
     * Determine if permissions mask is set
54
     * @var bool
55
     */
56
    private $isPermissionsMaskSet = false;
57
58
    /**
59
     * URL For Authorization
60
     */
61
    const AUTHORIZATION_URL = 'https://oauth.vk.com/authorize';
62
63
    /**
64
     * URL For Access Token
65
     */
66
    const ACCESS_TOKEN_URL = 'https://oauth.vk.com/access_token';
67
68
    /**
69
     * URL For VK API
70
     */
71
    const METHOD_URL = 'https://api.vk.com/method/';
72
73
    /**
74
     * URL For OAuth Token
75
     */
76
    const TOKEN_URL = 'https://oauth.vk.com/token';
77
78
    const DEFAULT_CALLBACK = 'https://api.vk.com/blank.html';
79
80
    const PACKAGE_VERSION = '1.0.5';
81
82
    /**
83
     * VK constructor.
84
     * @param string $appID
85
     * @param string $apiSecret
86
     * @param string $accessToken
87
     * @throws VKException
88
     */
89
    public function __construct($appID, $apiSecret, $accessToken = null) {
90
        $this->applicationID = $appID;
91
        $this->APISecret = $apiSecret;
92
        $this->accessToken = $accessToken;
93
        $this->curlObject = curl_init();
94
        if (!is_null($accessToken)) {
95
            if (!$this->isPermissionsMaskSet) {
96
                $VKUser = new VKUsers($this);
97
                $VKAccount = new VKAccount($this);
98
                $CurrentUser = $VKUser->get([ '' ])[ 'response' ][ 0 ][ 'uid' ];
99
                $this->setPermissionsMask($VKAccount->getAppPermissions($CurrentUser)[ 'response' ]);
100
                $this->isPermissionsMaskSet = true;
101
                unset($VKUser);
102
                unset($VKAccount);
103
            }
104
        }
105
    }
106
107
    /**
108
     * VK destructor.
109
     */
110
    public function __destruct() {
111
        curl_close($this->curlObject);
112
    }
113
114
    /**
115
     * Set API Version Provided By User
116
     * @param int $apiVersion
117
     */
118
    public function setAPIVersion($apiVersion) {
119
        $this->APIVersion = $apiVersion;
0 ignored issues
show
Documentation Bug introduced by
The property $APIVersion was declared of type string, but $apiVersion is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
120
    }
121
122
    /**
123
     * Returns Base API URL
124
     * @param string $apiMethod
125
     * @param string $responseFormat
126
     * @return string
127
     */
128
    public function getAPIUrl($apiMethod, $responseFormat = 'json') {
129
        return self::METHOD_URL . $apiMethod.'.'.$responseFormat;
130
    }
131
132
    /**
133
     * Returns Authorization Link With Passed Parameters
134
     * @param string $apiSettings
135
     * @param string $callbackURL
136
     * @param string $responseType
137
     * @param bool $testMode
138
     * @return string
139
     */
140
    public function getAuthorizationURL($apiSettings = '', $callbackURL = self::DEFAULT_CALLBACK, $responseType = 'code', $testMode = false) {
141
        $allowedTypes = [ 'token', 'code' ];
142
        $requestParameters = [
143
            'client_id'     =>  $this->applicationID,
144
            'scope'         =>  $apiSettings,
145
            'redirect_uri'  =>  $callbackURL,
146
            'response_type' =>  (in_array($responseType, $allowedTypes)) ? $responseType : 'code'
147
        ];
148
149
        if ($testMode) {
150
            $requestParameters[ 'test_mode' ] = 1;
151
        }
152
153
        return $this->createURL(self::AUTHORIZATION_URL, $requestParameters);
154
    }
155
156
    /**
157
     * Returns Access Token From Authorization Link
158
     * @param $resultCode
159
     * @param string $callbackURL
160
     * @return mixed
161
     * @throws VKException
162
     */
163
    public function getAccessToken($resultCode, $callbackURL = self::DEFAULT_CALLBACK) {
164
        if (!is_null($this->accessToken) && $this->authorizationStatus) {
165
            throw new VKException('Already Authorized!', 1);
166
        }
167
168
        $requestParameters = [
169
            'client_id'     => $this->applicationID,
170
            'client_secret' =>  $this->APISecret,
171
            'redirect_uri'  =>  $callbackURL,
172
            'code'          =>  $resultCode
173
        ];
174
175
        $apiResponse = json_decode($this->performRequest($this->createURL(self::ACCESS_TOKEN_URL, $requestParameters)), true);
176
177
        try {
178
            if (isset($apiResponse[ 'error' ])) {
179
                throw new VKException($apiResponse[ 'error' ].(!isset($apiResponse[ 'error_description' ]) ?: ': '.$apiResponse[ 'error_description' ]), '0');
180
            } else {
181
                $this->authorizationStatus = true;
182
                $this->accessToken = $apiResponse[ 'access_token' ];
183
                return $apiResponse;
184
            }
185
        } catch (VKException $ex) {
186
            echo $ex->getMessage();
187
            return [ ];
188
        }
189
    }
190
191
    /**
192
     * Returns User Authorization Status
193
     * @return bool
194
     */
195
    public function isAuthorized() {
196
        return !is_null($this->accessToken);
197
    }
198
199
200
    /**
201
     * Execute API Method With Parameters and return Result
202
     * @param string $apiMethod
203
     * @param array $requestParameters
204
     * @param string $resultType
205
     * @param string $requestMethod
206
     * @return mixed
207
     */
208
    public function apiQuery($apiMethod, $requestParameters = [ ], $resultType = 'array', $requestMethod = 'get') {
209
        $requestParameters[ 'timestamp' ] = time();
210
        $requestParameters[ 'api_id' ]    = $this->applicationID;
211
        $requestParameters[ 'random' ]    = rand(0, 10000);
212
213
        if (!array_key_exists('access_token', $requestParameters) && !is_null($this->accessToken)) {
214
            $requestParameters[ 'access_token' ] = $this->accessToken;
215
        }
216
217
        if (!array_key_exists('v', $requestParameters) && !is_null($this->APIVersion)) {
218
            $requestParameters[ 'v' ] = $this->APIVersion;
219
        }
220
221
        ksort($requestParameters);
222
223
        $parametersSignature = '';
224
        foreach ($requestParameters as $pKey=>$pValue) {
225
            if (is_array($pValue)) {
226
                $pValue = implode(', ', $pValue);
227
            }
228
            $parametersSignature .= $pKey . '=' . $pValue;
229
        }
230
        $parametersSignature .= $this->APISecret;
231
232
        $requestParameters[ 'sig' ] = md5($parametersSignature);
233
234
        if ($apiMethod == 'execute' || $requestMethod == 'post') {
235
            $apiResponse = $this->performRequest($this->getAPIUrl($apiMethod, $resultType == 'array' ? 'json' : $resultType), "POST", $requestParameters);
236
        } else {
237
            $apiResponse = $this->performRequest($this->createURL($this->getAPIUrl($apiMethod, $resultType == 'array' ? 'json' : $resultType), $requestParameters));
238
        }
239
240
        try {
241
            $decodedJSON = json_decode($apiResponse, true);
242
            if (isset($decodedJSON[ 'error' ])) {
243
                throw new VKException($decodedJSON[ 'error' ][ 'error_msg' ], $decodedJSON[ 'error' ][ 'error_code' ], $decodedJSON[ 'error' ][ 'request_params' ]);
244
            }
245
246
            return $resultType == 'array' ? $decodedJSON : $apiResponse;
247
        } catch(VKException $ex) {
248
            echo $ex->getMessage();
249
            return [ ];
250
        }
251
    }
252
253
    /**
254
     * Set Permissions Mask
255
     * @param int $permMask
256
     */
257
    public function setPermissionsMask($permMask) {
258
        $this->permissionsMask = $permMask;
259
    }
260
261
    /**
262
     * Get Permissions Mask
263
     * @return int
264
     */
265
    public function getPermissionsMask() {
266
        return $this->permissionsMask;
267
    }
268
269
    /**
270
     * Concatenate Keys And Values Of Parameters Array And Return URL String
271
     * @param string $urlString
272
     * @param array $parametersArray
273
     * @return string
274
     */
275
    private function createURL($urlString, $parametersArray) {
276
        $urlString .= '?' . http_build_query($parametersArray);
277
        return $urlString;
278
    }
279
280
    /**
281
     * Execute Request
282
     * @param string $requestURL
283
     * @param string $requestMethod
284
     * @param array $postFields
285
     * @return string
286
     */
287
    private function performRequest($requestURL, $requestMethod = 'GET', $postFields = [ ]) {
288
        curl_setopt_array($this->curlObject, [
289
            CURLOPT_USERAGENT       =>  'FreedomCore/' . self::PACKAGE_VERSION . ' VK OAuth Client',
290
            CURLOPT_RETURNTRANSFER  => true,
291
            CURLOPT_SSL_VERIFYPEER  => false,
292
            CURLOPT_POST            => ($requestMethod == 'POST'),
293
            CURLOPT_POSTFIELDS      => $postFields,
294
            CURLOPT_URL             => $requestURL
295
        ]);
296
297
        return curl_exec($this->curlObject);
298
    }
299
300
}
301
302
/**
303
 * Class VKException
304
 * @package FreedomCore\VK
305
 */
306
class VKException extends \Exception {
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
307
308
    /**
309
     * VKException constructor.
310
     * @param string $message
311
     * @param int $code
312
     * @param null $parameters
313
     */
314
    public function __construct($message, $code, $parameters = null) {
315
        $Message = '<h1>API Request Error!</h1>';
316
        $Message .= '<table width="100%">';
317
318
        $Message .= '<tr><td width="10%"><strong>Error Code:</strong></td> <td>'.$code.'</td></tr>';
319
        $APIError = $this->codeToErrorText($code);
320
        $Message .= '<tr><td width="10%"><strong>API Message:</strong></td> <td>'.$APIError[ 'title' ].' <span style="color: gray;">('.$APIError[ 'description' ].')</span></td></tr>';
321
        $Message .= '<tr><td width="10%"><strong>Error Message:</strong></td> <td>'.$message.'</td></tr>';
322
        if ($parameters != null && is_array($parameters)) {
323
            $Message .= '<tr><td width="10%"><strong>Request Parameters:</strong></td> <td>';
324
325
            $Message .= '<table width="15%">';
326
            foreach ($parameters as $parameter) {
327
                $Message .= "<tr><td><strong>".$parameter[ 'key' ]."</strong></td><td width='15%'>=></td><td>".$parameter[ 'value' ]."</td></tr>";
328
            }
329
            $Message .= '</table>';
330
            $Message .= '</td></tr>';
331
        }
332
333
        $Message .= '</table>';
334
        parent::__construct($Message, $code);
335
    }
336
337
    /**
338
     * Convert INT Code To Full Description
339
     * @param int $Code
340
     * @return mixed
341
     */
342
    private function codeToErrorText($Code) {
343
        $errorsData = [
344
            1       =>  [ 'title' => 'Unknown error occurred',  'description' => 'Try again later.' ],
345
            2       =>  [ 'title' => 'Application is disabled. Enable your application or use test mode ',  'description' => 'You need to switch on the app in Settings (https://vk.com/editapp?id={Your API_ID} or use the test mode (test_mode=1).' ],
346
            3       =>  [ 'title' => 'Unknown method passed ',  'description' => 'Check the method name: <a href="http://vk.com/dev/methods" target="_blank">http://vk.com/dev/methods</a> ' ],
347
            4       =>  [ 'title' => 'Incorrect signature ',  'description' => 'Check if the signature has been formed correctly: <a href="https://vk.com/dev/api_nohttps" target="_blank"></a>' ],
348
            5       =>  [ 'title' => 'User authorization failed ',  'description' => 'Make sure that you use a correct authorization type. To work with the methods without a secureprefix you need to authorize a user with one of these ways:  http://vk.com/dev/auth_sites, http://vk.com/dev/auth_mobile.' ],
349
            6       =>  [ 'title' => 'Too many requests per second ',  'description' => 'Decrease the request frequency or use the execute method. More details on frequency limits here: <a href="http://vk.com/dev/api_requests" target="_blank">http://vk.com/dev/api_requests</a>' ],
350
            7       =>  [ 'title' => 'Permission to perform this action is denied ',  'description' => 'Make sure that your have received required permissions during the authorization. You can do it with the account.getAppPermissions method.' ],
351
            8       =>  [ 'title' => 'Invalid request ',  'description' => 'Check the request syntax and used parameters list (it can be found on a method description page) ' ],
352
            9       =>  [ 'title' => 'Flood control ',  'description' => 'You need to decrease the count of identical requests. For more efficient work you may use execute or JSONP.' ],
353
            10      =>  [ 'title' => 'Internal server error',  'description' => 'Try again later.' ],
354
            11      =>  [ 'title' => 'In test mode application should be disabled or user should be authorized',  'description' => 'Switch the app off in Settings: https://vk.com/editapp?id={Your API_ID}.' ],
355
            14      =>  [ 'title' => 'Captcha needed ',  'description' => 'Work with this error is explained in detail on the <a href="https://vk.com/dev/need_confirmation" target="_blank">separate page</a>' ],
356
            15      =>  [ 'title' => 'Access denied ',  'description' => 'Make sure that you use correct identifiers and the content is available for the user in the full version of the site.' ],
357
            16      =>  [ 'title' => 'HTTP authorization failed',  'description' => 'To avoid this error check if a user has the \'Use secure connection\' option enabled with the account.getInfo method.' ],
358
            17      =>  [ 'title' => 'Validation required ',  'description' => 'Make sure that you don\'t use a token received with http://vk.com/dev/auth_mobile for a request from the server. It\'s restricted. The validation process is described on the <a href="https://vk.com/dev/need_confirmation" target="_blank">separate page</a>.' ],
359
            20      =>  [ 'title' => 'Permission to perform this action is denied for non-standalone applications ',  'description' => 'If you see this error despite your app has the Standalone type, make sure that you use redirect_uri=https://oauth.vk.com/blank.html. Details here: http://vk.com/dev/auth_mobile.' ],
360
            21      =>  [ 'title' => 'Permission to perform this action is allowed only for Standalone and OpenAPI applications',  'description' => '' ],
361
            23      =>  [ 'title' => 'This method was disabled ',  'description' => 'All the methods available now are listed here: <a href="http://vk.com/dev/methods" target="_blank">http://vk.com/dev/methods</a>' ],
362
            24      =>  [ 'title' => 'Confirmation required ',  'description' => 'Confirmation process is described on the <a href="https://vk.com/dev/need_confirmation" target="_blank">separate page</a>' ],
363
            100     =>  [ 'title' => 'One of the parameters specified was missing or invalid ',  'description' => 'Check the required parameters list and their format on a method description page.' ],
364
            101     =>  [ 'title' => 'Invalid application API ID ',  'description' => 'Find the app in the administrated list in settings: <a href="http://vk.com/apps?act=settings" target="_blank">http://vk.com/apps?act=settings</a> And set the correct API_ID in the request.' ],
365
            103     =>  [ 'title' => 'Out of limits', 'description' => 'Out of limits' ],
366
            104     =>  [ 'title' => 'Not found', 'description' => 'Not found' ],
367
            113     =>  [ 'title' => 'Invalid user id ',  'description' => 'Make sure that you use a correct id. You can get an id using a screen name with the utils.resolveScreenName method' ],
368
            150     =>  [ 'title' => 'Invalid timestamp ',  'description' => 'You may get a correct value with the utils.getServerTime method.' ],
369
            200     =>  [ 'title' => 'Access to album denied ',  'description' => 'Make sure you use correct ids (owner_id is always positive for users, negative for communities) and the current user has access to the requested content in the full version of the site.' ],
370
            201     =>  [ 'title' => 'Access to audio denied ',  'description' => 'Make sure you use correct ids (owner_id is always positive for users, negative for communities) and the current user has access to the requested content in the full version of the site.' ],
371
            203     =>  [ 'title' => 'Access to group denied ',  'description' => 'Make sure that the current user is a member or admin of the community (for closed and private groups and events).' ],
372
            300     =>  [ 'title' => 'This album is full ',  'description' => 'You need to delete the odd objects from the album or use another album.' ],
373
            500     =>  [ 'title' => 'Permission denied. You must enable votes processing in application settings',  'description' => 'Check the app settings: http://vk.com/editapp?id={Your API_ID}&section=payments' ],
374
            600     =>  [ 'title' => 'Permission denied. You have no access to operations specified with given object(s)',  'description' => '' ],
375
            603     =>  [ 'title' => 'Some ads error occurred',  'description' => '' ],
376
            1260    =>  [ 'title' => 'Invalid screen name',  'description' => 'This screen name is already in use or invalid' ],
377
        ];
378
379
        return (!array_key_exists($Code, $errorsData)) ? $errorsData[1] : $errorsData[$Code];
380
    }
381
382
}