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/create_post.php:13 (show/hide source)
1  <?php
2  
3      require('../vendor/autoload.php');
4      require('credentials.php');
5  
6      use JonathanTorres\MediumSdk\Medium;
7  
8      $credentials['redirect-url'] = 'http://localhost:8888/create_post.php';
9      $medium = new Medium($credentials);
10  
11      if (isset($_GET['code'])) {
12          session_start();
13 $code = $_GET['code'];
14 $medium->authenticate($code); 15 $_SESSION['user'] = $medium->getAuthenticatedUser();
Threat level 1

Callstack:

GuzzleHttp\Client::applyOptions /social-booster/vendor/guzzlehttp/guzzle/src/Client.php:371 (show/hide source)
351                      // Ensure that we don't have the header in different case and set the new value.
352                      $modify['set_headers'] = Psr7\_caseless_remove(['Authorization'], $modify['set_headers']);
353                      $modify['set_headers']['Authorization'] = 'Basic '
354                          . base64_encode("$value[0]:$value[1]");
355                      break;
356                  case 'digest':
357                      // @todo: Do not rely on curl
358                      $options['curl'][CURLOPT_HTTPAUTH] = CURLAUTH_DIGEST;
359                      $options['curl'][CURLOPT_USERPWD] = "$value[0]:$value[1]";
360                      break;
361                  case 'ntlm':
362                      $options['curl'][CURLOPT_HTTPAUTH] = CURLAUTH_NTLM;
363                      $options['curl'][CURLOPT_USERPWD] = "$value[0]:$value[1]";
364                      break;
365              }
366          }
367  
368          if (isset($options['query'])) {
369              $value = $options['query'];
370              if (is_array($value)) {
371 $value = http_build_query($value, null, '&', PHP_QUERY_RFC3986);
372 } 373 if (!is_string($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/create_post.php /social-booster/vendor/jonathantorres/medium-sdk/examples/create_post.php:14 (show/hide source)
1  <?php
2  
3      require('../vendor/autoload.php');
4      require('credentials.php');
5  
6      use JonathanTorres\MediumSdk\Medium;
7  
8      $credentials['redirect-url'] = 'http://localhost:8888/create_post.php';
9      $medium = new Medium($credentials);
10  
11      if (isset($_GET['code'])) {
12          session_start();
13          $code = $_GET['code'];
14 $medium->authenticate($code);
15 $_SESSION['user'] = $medium->getAuthenticatedUser(); 16 $_SESSION['code'] = $code;