Author Topic: Bypassing Payments Using Webhooks  (Read 130 times)

0 Members and 1 Guest are viewing this topic.

Offline Flavio58

Bypassing Payments Using Webhooks
« Reply #1 on: March 13, 2018, 06:30:30 PM »
Advertisement

In diving deeper to find vulnerabilities in bug bounty programs, it is necessary to search for functionality not visible to the end user. Payment webhooks are one example, used by payment providers such as Stripe or Braintree to notify websites about updates to a user's subscription details. What's important is that a user never interacts with these webhook endpoints โ€” all communication occurs directly between the payment provider and the server. This means that all too often a bug bounty hunter never even thinks to test against webhook functionality, missing out on potentially dangerous exploits.

Finding
While testing a site that offered a monthly subscription, I happened across the company's internal API documentation. One endpoint that immediately caught my eye was a PUT request to /api/webhooks/stripe. Based on my prior experience with payments providers, I wondered if I could send a fake request to this endpoint that would trick the website into thinking I paid.

Sending an empty JSON request returned an error. After looking into the format Stripe uses for webhooks, I sent the following body:

{
  "payment": {
    "status":"success",
    "provider":"stripe"
  },
  "id":"..."
}
The server responded with a success:

{
  "id":"...",
  "amount":1,
  "status":"success",
  "provider":"stripe"
}
And just like that, my account was authorized and appeared as having a paid subscription. This got me thinking: how often is such a vulnerability overlooked, and what are payment providers doing to prevent this?



Prevention by Payment Providers
Payment providers have the ability to prevent this vulnerability from ever happening, so it's surprising that endpoints do go unprotected. Braintree is an example of the right way to do things: users must parse the incoming webhook through Braintree's library, which automatically validates the request and extracts the JSON body. This way, webhook endpoints are secure by default, and cannot be spoofed by attackers.

Stripe, the payment provider used by the company, is a little less foolproof when it comes to webhook security. Although Stripe does mention verifying webhook signatures, this is only as a sidenote, and there is little overall emphasis on the importance of ensuring that webhooks originate from Stripe. The example code listed in the documentation doesn't include any signature verification, instead directly parsing the JSON request.


Not being secure by default is a tricky route. Users are likely to take the path of least resistance when creating payment integrations, meaning many will never verify incoming signatures.

Recurly, another subscription payment provider, offers HTTP Basic Authentication to share a secret between the servers. Again, one has to ask if users will actually go through the trouble of verifying a shared secret. Additionally, Recurly offers a list of IP addresses that webhook requests will originate from. However, this alone is not sufficient: what if, for instance, an attacker creates a separate Recurly account to send malicious, but valid, webhooks?

Lastly, BitPay, a service to accept bitcoin payments, states, "BitPay does not sign IPNs, so the information in the payload should not be trusted outright." Perhaps there's something to be said for being transparent about a lack of security โ€” users, after all, are much more likely to question their security after reading this.

Discovery
An immediate cue to test for payment-related webhook vulnerabilities is when a company offers a monthly subscription. Depending on the payment provider (as outlined above), the site may not have implemented sufficient protection against attacks.

Some ways to find webhook endpoints:

Search JavaScript files for "webhook" or "payment". Companies may expose internal endpoints without realizing it.
Look through the organization's GitHub repos or similar to find references to webhooks.
The format for webhook endpoints usually follows a similar form, so it's worthwhile to try visiting different API endpoints such as /api/stripe/webhook, /api/payments/webhook, /api/stripeWebhook, etc.
Conclusion
It goes without saying that verifying payment webhooks should be the default for any sensitive actions. Payment providers give their customers methods to protect against such attacks, but depending on the provider this still requires some effort from the customer.


https://docs.recurly.com/docs/webhooks

In the meantime, why not start checking to see if a payment endpoint has been left misconfigured? And this isn't just limited to payments โ€” any incoming webhook notifications for any service should be verified.



Consulente in Informatica dal 1984

Software automazione, progettazione elettronica, computer vision, intelligenza artificiale, IoT, sicurezza informatica, tecnologie di sicurezza militare, SIGINT. 

Facebook:https://www.facebook.com/flaviobernardotti58
Twitter : https://www.twitter.com/Flavio58

Cell:  +39 366 3416556

f.bernardotti@deeplearningitalia.eu

#deeplearning #computervision #embeddedboard #iot #ai

 

Related Topics

  Subject / Started by Replies Last post
0 Replies
89 Views
Last post July 01, 2018, 12:02:14 AM
by Flavio58
0 Replies
85 Views
Last post July 24, 2018, 12:20:18 PM
by Flavio58
0 Replies
44 Views
Last post August 08, 2018, 10:01:22 PM
by Flavio58
0 Replies
51 Views
Last post August 26, 2018, 08:02:50 AM
by Flavio58
0 Replies
54 Views
Last post August 31, 2018, 06:11:29 PM
by Flavio58

Sitemap 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326