📜 ⬆️ ⬇️

Demonstration of vulnerabilities in Liqpay

Since Privatbank did not respond to messages describing the vulnerabilities of its Liqpay payment system, I, having waited several months, will back up the theses of my previous article with real examples. In addition, I believe that the kick will be useful - I will advise the PB below to somewhat extinguish bugs. These vulnerabilities may already be exploited, and their nature is such that end users suffer. Forcing the PB to act, we will rescue them (users).

As I noted, errors are most often made in the logic of generating a signature for key data. The problem is that these errors are conceptual, not in implementation.

Vulnerability number 1


The bottom line: when paying for a merchandise store, an attacker can change these forms sent by his browser to api Liqpay, and pay for a different item than was chosen in the store.

The problem in the formation of the signature: the signed data is "glued together" without a separator, in particular the order_id parameter and type. Suppose order_id = '1234', and type = 'buy'. The attacker changes order_id = '123' and type = '4buy', sends it to the liqpay server. In this case, the signature validation will be successful. the string for its formation has not changed. You can easily repeat these actions in Chrome or Firefox browser by editing the form on the page - remove the last character from the order and set the first one in the type parameter.
')
Just in case, I will chew a little bit what happened, because not all of my comrades understood the result of the vulnerability:

When buying, the store creates a unique order number (order_id), forms the form, signs it and sends the customer with this data to Liqpay. When Liqpay successfully collects money from the buyer, he informs the store that such an order_id has been paid. The problem is that Liqpay will report a payment for a completely different order, which has a different amount to pay. It is enough for an attacker to create unpaid orders until one order_id has a fragment of another order_id. Since order_id is often not randomly formed, this is possible to some extent or another.

A quick solution for Privatbank: just validate the type parameter, which is not happening now. As I noted, this is a special case that does not solve the problem conceptually.

Vulnerability number 2


The bottom line: a payment form signed by the store can be manually sent to the url callback, and it will be accepted by the store because the signature is formed according to all the rules. It is only necessary to make small manipulations:

rename result_url to transaction_id
rename server_url field to sender_phone
add status field with empty value

This package will be accepted by the store!

Here is how the signature in the Liqpay package is considered:

private_key . amount . currency . public_key . order_id . type . description . result_url . server_url 


And here is how the signature in the OT Liqpay package is considered:

 private_key . amount . currency . public_key . order_id . type . description . status . transaction_id . sender_phone 


It is seen that the packets differ only in the last three parameters. We simply changed the field names and fooled the store, making it think that this package from Liqpay, since the signature will match.

In order for the store to think that this is a successful payment, you need a little more action and one condition:

in the description of the goods must be a fragment of "success".


Surely, in stores that use Liqpay, there is a product with this fragment. Well, for example, think up the name of the book “My successful story”. In the form created for payment, we change:



As a result: the signature does not change! The store accepts the package. Field status = “success” - payment is successful. In the transaction_id field - the left text is accepted, because the store does not have to know how id transactions are formed in Liqpay (99% ignore it), sender_phone is the left text (it’s unlikely that the package will be logged in if something is wrong, the phone is logged in).

Bottom line: you can “buy in” any product for free as long as you wish if only the word “success” was in the description. Url kolbeka is available in the form in an explicit form, so there will be no problem finding out where to send the package.

If you do not understand the meaning of manipulations, then briefly: let's say there are parameters A = AAA, B = BBB, C = BBB. Software store protocol Liqpay concatenates all the parameters in a certain order in one line AAABBBVVV and gets the signature XXX. We can change the names and values ​​of the parameters, let's say: G = AA, B = ABBV, C = BB. As a result, the concatenated string is the same (AAABBBVV), and the parameters and their values ​​are completely different.

A quick solution for Privatbank: block the processing of purchases with the “success” fragment in the description. Again, this does not solve the problem conceptually.

I ask you not to kick the PB much, because there are even more bugs in other payment systems, but so far I don’t care for them.

Source: https://habr.com/ru/post/239549/


All Articles