Warning

There are many false positives, or unexploitable vulnerabilities. Please create working "PoC" exploit before reporting anything to vendor!

Details:

Sink Standard::http_build_query
Risk _GET
/social-booster/vendor/jonathantorres/medium-sdk/examples/callback.php:9 (show/hide source)
1  <?php
2  
3      require('../vendor/autoload.php');
4      require('credentials.php');
5  
6      use JonathanTorres\MediumSdk\Medium;
7  
8      $medium = new Medium($credentials);
9 $medium->authenticate($_GET['code']);
10 11 $authenticatedUser = $medium->getAuthenticatedUser();
Threat level 1

Callstack:

GuzzleHttp\Client::applyOptions /social-booster/vendor/guzzlehttp/guzzle/src/Client.php:310 (show/hide source)
290       */
291      private function applyOptions(RequestInterface $request, array &$options)
292      {
293          $modify = [
294              'set_headers' => [],
295          ];
296  
297          if (isset($options['headers'])) {
298              $modify['set_headers'] = $options['headers'];
299              unset($options['headers']);
300          }
301  
302          if (isset($options['form_params'])) {
303              if (isset($options['multipart'])) {
304                  throw new \InvalidArgumentException('You cannot use '
305                      . 'form_params and multipart at the same time. Use the '
306                      . 'form_params option if you want to send application/'
307                      . 'x-www-form-urlencoded requests, and the multipart '
308                      . 'option to send multipart/form-data requests.');
309              }
310 $options['body'] = http_build_query($options['form_params'], '', '&');
311 unset($options['form_params']); 312 // Ensure that we don't have the header in different case and set the new value.
GuzzleHttp\Client::transfer /social-booster/vendor/guzzlehttp/guzzle/src/Client.php:273 (show/hide source)
253       *
254       * @param RequestInterface $request
255       * @param array            $options
256       *
257       * @return Promise\PromiseInterface
258       */
259      private function transfer(RequestInterface $request, array $options)
260      {
261          // save_to -> sink
262          if (isset($options['save_to'])) {
263              $options['sink'] = $options['save_to'];
264              unset($options['save_to']);
265          }
266  
267          // exceptions -> http_errors
268          if (isset($options['exceptions'])) {
269              $options['http_errors'] = $options['exceptions'];
270              unset($options['exceptions']);
271          }
272  
273 $request = $this->applyOptions($request, $options);
274 $handler = $options['handler']; 275
GuzzleHttp\Client::requestAsync /social-booster/vendor/guzzlehttp/guzzle/src/Client.php:125 (show/hide source)
105          $options[RequestOptions::SYNCHRONOUS] = true;
106          return $this->sendAsync($request, $options)->wait();
107      }
108  
109      public function requestAsync($method, $uri = '', array $options = [])
110      {
111          $options = $this->prepareDefaults($options);
112          // Remove request modifying parameter because it can be done up-front.
113          $headers = isset($options['headers']) ? $options['headers'] : [];
114          $body = isset($options['body']) ? $options['body'] : null;
115          $version = isset($options['version']) ? $options['version'] : '1.1';
116          // Merge the URI into the base URI.
117          $uri = $this->buildUri($uri, $options);
118          if (is_array($body)) {
119              $this->invalidBody();
120          }
121          $request = new Psr7\Request($method, $uri, $headers, $body, $version);
122          // Remove the option so that they are not doubly-applied.
123          unset($options['headers'], $options['body'], $options['version']);
124  
125 return $this->transfer($request, $options);
126 } 127
GuzzleHttp\Client::request /social-booster/vendor/guzzlehttp/guzzle/src/Client.php:131 (show/hide source)
111          $options = $this->prepareDefaults($options);
112          // Remove request modifying parameter because it can be done up-front.
113          $headers = isset($options['headers']) ? $options['headers'] : [];
114          $body = isset($options['body']) ? $options['body'] : null;
115          $version = isset($options['version']) ? $options['version'] : '1.1';
116          // Merge the URI into the base URI.
117          $uri = $this->buildUri($uri, $options);
118          if (is_array($body)) {
119              $this->invalidBody();
120          }
121          $request = new Psr7\Request($method, $uri, $headers, $body, $version);
122          // Remove the option so that they are not doubly-applied.
123          unset($options['headers'], $options['body'], $options['version']);
124  
125          return $this->transfer($request, $options);
126      }
127  
128      public function request($method, $uri = '', array $options = [])
129      {
130          $options[RequestOptions::SYNCHRONOUS] = true;
131 return $this->requestAsync($method, $uri, $options)->wait();
132 } 133
JonathanTorres\MediumSdk\Client::requestTokens /social-booster/vendor/jonathantorres/medium-sdk/src/Client.php:59 (show/hide source)
39          $data = [
40              'form_params' => [
41                  'code' => $authorizationCode,
42                  'client_id' => $clientId,
43                  'client_secret' => $clientSecret,
44                  'grant_type' => 'authorization_code',
45                  'redirect_uri' => $redirectUrl,
46              ],
47          ];
48  
49          $client = new GuzzleClient([
50              'base_uri' => $this->url,
51              'exceptions' => false,
52              'headers' => [
53                  'Content-Type' => 'application/json',
54                  'Accept' => 'application/json',
55                  'Accept-Charset' => 'utf-8',
56              ],
57          ]);
58  
59 $response = $client->request('POST', 'tokens', $data);
60 61 return json_decode((string) $response->getBody());
JonathanTorres\MediumSdk\Medium::authenticate /social-booster/vendor/jonathantorres/medium-sdk/src/Medium.php:132 (show/hide source)
112              'redirect_uri' => $this->redirectUrl,
113          ];
114  
115          return 'https://medium.com/m/oauth/authorize?' . http_build_query($params);
116      }
117  
118      /**
119       * Get both the access and refresh token (authenticate) from the user
120       * to make requests to medium's api using the authorization code.
121       *
122       * @param string $authorizationCode
123       *
124       * @return void
125       */
126      public function authenticate($authorizationCode)
127      {
128          $tokens = $this->client->requestTokens(
129              $authorizationCode,
130              $this->clientId,
131              $this->clientSecret,
132 $this->redirectUrl
133 ); 134
@INLINE::/social-booster/vendor/jonathantorres/medium-sdk/examples/callback.php /social-booster/vendor/jonathantorres/medium-sdk/examples/callback.php:9 (show/hide source)
1  <?php
2  
3      require('../vendor/autoload.php');
4      require('credentials.php');
5  
6      use JonathanTorres\MediumSdk\Medium;
7  
8      $medium = new Medium($credentials);
9 $medium->authenticate($_GET['code']);
10 11 $authenticatedUser = $medium->getAuthenticatedUser();