May be security issue?
shirshak55 opened this issue · 29 comments
Our components are available on client side
<paystack
:amount="amount"
:email="email"
:paystackkey="paystackkey"
:reference="reference"
:callback="callback"
:close="close"
:embed="false"
></paystack>
say the item is of 100 Naira and using devtools or anything i changed it to 10 Naira.
Now there are two scenario
1.
Using 10 Naira i purchased the item loss to website is 90Naira and hacker are enjoying . If large commercial site it is even worst
Server may validate that item was 100 Naira but user paid 90 Naira. Now hacker will say they were charged but didn't receive and would settle with site owner. Site owner have to give them 10 naira and would have to deal with settlement fees etc.
Both side hacker won admin loss :(
@shirshak55 Thanks for this. How do you suggest we go about this?
@iamraphson its not your fault :D
Its paystack fault :( . I emailed them but they don't give a damn. So i started using their transaction feature .
Have you checked stripe. They give option to charge via backend but paystack ...
You can keep message like its paystack end problem not this package so new user can know consequence .
@shirshak55 Paystack gives options for backend charges. you can see a lot of backend libraries here - https://developers.paystack.co/docs/libraries-and-plugins. Nevertheless, it's advisable to validate the transaction again at the back using reference cc @PaystackHQ
backend charge is not good bro . User should know who is charging them like paystack or website. It clearly some complaints. From the information i know user credit card information should never touch your server so you even remove name field from credit card form.
See, you and I am customer to some site. If there is credit card form will you fill if you know it is related to that site. We only fill if we sure know that credit card form is from paystack because we trust paystack but not that site.
Thats why stripe also made credit card form, pop up form.
So for now transaction is good but this damn paystack transaction requires me to redirect to paystack site come back to my own site and using that token send to server and validate everything .
And their webhook is not even so testable. They don't provide like sending test webhook from their site. :( Really dissatisfied with their api development :(
Hello @shirshak55,
If you are worried about vulnerabilities, you can
-
Create your own form where Paystack provides a token for charging https://developers.paystack.co/v2.0/docs/paystack-custom
-
Create the transaction via the backend by calling the initialize endpoint (https://developers.paystack.co/v2.0/reference#initialize-a-transaction). A reference is returned to you which you can then use to start the transaction using popup by passing the reference to https://developers.paystack.co/v2.0/docs/paystack-popup
@steveamaza cannot people change frontend code?
@steveamaza yes i know that test webhook but how can i fire it? There should be some provision to fire it. I know if we purchase item we can fire it but it really not the way to fire the webhook. Can you check stripe they have a dedicated part for just firing test webhook.
@steveamaza You are mistaking me by 1 no I mean this one
https://developers.paystack.co/v2.0/docs/paystack-custom
By 2 number i mean this
https://developers.paystack.co/v2.0/reference#initialize-a-transaction
1 number can be changed by customer
@iamraphson don't you think customer can change No 1?
@steveamaza yes i know that test webhook but how can i fire it? There should be some provision to fire it. I know if we purchase item we can fire it but it really not the way to fire the webhook. Can you check stripe they have a dedicated part for just firing test webhook.
Thank you for the feedback @shirshak55. We will make this update in the nearest future.
Hello @shirshak55, your best bet is the second option. However, you can do the first one as advised with minimal to no risk
@steveamaza how to do no 1 without no risk. I am using no 2 which i am unsatisfied because customer has to do more 👍
There is no security whatsoever, you need to verify payment in your backend before you give value.
@AustineA Ok but even if u verify ur user gonna get charged and they will complain. If u take user money without delivering him items/service u are regarded as fraud :)
U cannot take user's money no matter what they do and if u take u must give the value . Paystack is clearly doing nothing and I also don't care anymore :)
@iamraphson if u think this is not a security issue feel free to close.
Hello @shirshak55 , we have gone over this. There are multiple options for you to achieve what you need.
You said "Have you checked stripe. They give option to charge via backend but paystack ..." and Segun mentioned that you can charge from backend and you said that isn't good.
I have also provided two options where you can charge securely. Can you kindly explain how you want to go about this?
Also like @AustineA mentioned, you need to verify the transaction. You can issue a refund via our API if the amount does not match up
@steveamaza we are taking about this plugin and regarding that you only gave workaround not a solution.
"You said "Have you checked stripe. They give option to charge via backend but paystack ..." and Segun mentioned that you can charge from backend and you said that isn't good."
I was taking this in popup form not that one that we need to open a paystack page and redirect back to our page. That popup paystack is good buy you guys are dening the fact that this is bug in ur implementation. Even people can change from devtools and buy it com'n its not 90's and even kids can do this.
And regarding refund...
Do u give refund without causing us loss?
By the way I have don't use paystack any more so I wont complain from now but user need to be aware of this . Due to this implementation I find most of the site that use paystack popup are vulnerable to this. I tried with one site and it worked so I don't feel any safe it with anymore.
Thanks.
Yes, for popup, it is possible to have the interface and still have security. This is what I explained in the second option for #7 (comment). Though you are initializing the transaction from the backend, the customer will still be able to pay via topup. You are only intializing from the backend to get a reference which contains the amount to be paid and this cannot be changed by the customer since the details are already on our server from when you intialized
see this is what u are saying?
var submitFunction = async function(event) {
var transactionData = {
email: "",
amount: 100,
key: ""
};
var transactionResponse = await Paystack.transaction.request(transactionData);
var transaction = new Paystack.Transaction(transactionResponse);
var card = new Paystack.Card({
number: "4084084084084081",
cvv: "408",
month: "12",
year: "20"
});
console.log(card, "card");
// Payment method instances usually provide validation functions
if (card.isValid()) {
// Set the payment method on the transaction
transaction.setPaymentMethod(Transaction.PaymentMethods.CARD, card);
}
// Charge the payment method
const chargeResponse = await transaction.card.charge();
// Handle the charge responses
if (chargeResponse.status === "success") {
alert("Payment completed!");
}
// Another charge response example
if (chargeResponse.status === "auth") {
const token = 123456;
const authenticationResponse = await transaction.card.authenticate(token);
if (authenticationResponse.status === "success") {
alert("Payment completed!");
}
}
event.preventDefault();
};
var form = document.getElementById("paystack-card-form");
form.addEventListener("submit", submitFunction, true);
This is frontend code right? meaning i can change this easily
var transactionData = {
email: "",
amount: 100,
key: ""
};
And make it
var transactionData = {
email: "",
amount: 1,
key: ""
};
Create your own form where Paystack provides a token for charging developers.paystack.co/v2.0/docs/paystack-custom
Create the transaction via the backend by calling the initialize endpoint (developers.paystack.co/v2.0/reference#initialize-a-transaction). A reference is returned to you which you can then use to start the transaction using popup by passing the reference to developers.paystack.co/v2.0/docs/paystack-popup
To make long story short and what we discussed from email u already said 2nd one is good and I agree too and it is not that convenient however we can use iframe etc. And please don't deceive user by saying no 1 is properly safe and secure .Paystack charges before and think server should verify the charge and what if server couldn't verify the charge WHat do we do that unverified amount ?
No @shirshak55 , that is not what I am saying. You can either use https://developers.paystack.co/v2.0/docs/paystack-custom (which is the first option I gave).
However, since you want to use the popup, you can initialize the transaction on the server, get a reference and use it to create a transaction using https://developers.paystack.co/v1.0/reference#paystack-inline-x.
Both are perfectly safe and secure
If you need more explanation on this, please send an email so we can get on a call where I can explain in more detail or answer any questions you might have. Thank you for choosing Paystack!
@steveamaza wait can u give me any websites that uses ur first option. I would like to test couple of sites .
@steveamaza what is code for for using reference send me instead of showing that docs as it is not clear.
Is this correct code?
<script>
function payWithPaystack(){
var handler = PaystackPop.setup({
ref: ReferenceFromServer,
callback: function(response){
alert('success. transaction ref is ' + response.reference);
},
onClose: function(){
alert('window closed');
}
});
handler.openIframe();
}
</script>
ReferenceFromServer variable will contain id that we get from server.
If this works than yes it is secure. But this vue-paystack package is not safe unless we ignore :)
A very simple solution to this would be providing a method (paystack.open() should expose the payWithPaystack
method) to programmatically trigger the paystack popup. In an ideal scenario, devs should verify transaction details before giving the front end the go-ahead to raise the popup. Your library should serve a functional purpose, not presentation (and by extension, controlling when modal appears).
Aside security concerns, I might have additional validation checks to perform before permitting user to pay.
I could imitate this behavior with $(".payButton").click()
after verifying details, but it doesn't make any sense because script kiddie could as well run that from the console (WHICH IS CURRENTLY AN UNACKNOWLEDGED SECURITY SCARE). I would take off all selectors on that element, for a start. Next, I would refactor the method to be invoked by client instead of being triggered by an event i.e. by watching an raise_modal
property the client updates once verification requirements are satisfied.
Alternatively, you could use custom events.
Please notify me when/if these fixes are being implemented so I can both update the package and my implementation. Cheers
Yes, for popup, it is possible to have the interface and still have security. This is what I explained in the second option for #7 (comment). Though you are initializing the transaction from the backend, the customer will still be able to pay via topup. You are only intializing from the backend to get a reference which contains the amount to be paid and this cannot be changed by the customer since the details are already on our server from when you intialized
Really? If I still have to interface Paystack servers at my back end, what is the essence of a client side checkout? I might as well generate the reference and redirect to its checkout page in one fell swoop. Or, am I missing something?