So, like any reasonably competent web development shop, we wear cotton gloves when we touch credit cards, and we use Braintree SecureVault to store them so we are clear of PCI Compliance issues.
However now we want to offer a free trial for our service, which pretty much relies on being able to guarantee that a given credit card is only used once for a free trial. Ideally we would be able to hash the credit card number itself to guarantee uniqueness. The problem there is that set of valid credit card numbers is small, so it's going to be easy to brute force the credit card numbers. Salting tactics are useless as far as I can see, because if someone has access to the database of hashes, they will most likely have the code as well, and thus the salting algorithm.
The best two ideas so far are:
A) Keeping the hashes isolated in a set, with no relation to their billing information. Therefore if the hashes are brute-forced, all they have is a list of credit card numbers that were used at some point in time, with no personal information or knowledge of whether it's even still valid. The main weakness here is that we do have record of the last-4 which could potentially be used to match them up to some extent.
B) Hash without the full number and deal with the false positives and negatives. Hashing on name, last-4 and expiration ought to be fairly unique. False positive is like winning the lottery, we can deal with it at customer support. False negative could be induced by modifying the name, we are not clear on what assurances we have about the precision of name matching (potentially affected both by the gateway and merchant account is my understanding), so this could open a loophole.
Thoughts? Suggestions? Battle-tested Wisdom?
High-level: Use Existing Payment Systems
I think that this approach -- using credit card numbers to determine if a user already has taken advantage of a free trial and should be ineligible for a subsequent free trial -- is misguided. Firstly, you will drive away potential customers by requiring a credit card upfront (which many users don't give out unless they are actually ready to buy), instead of requiring it only after the trial period has ended.
Secondly, you are reinventing the wheel. There are a plethora of "app stores" (the Chrome webstore, the Android marketplace, the iTunes app store, etc.) which provide builtin mechanisms for payment and trial periods. Using these systems will give your product increased visiblity to consumers, will offer your potential customers multiple different payment methods (making them more inclined to buy), and will also save you the hassle of implementing this mechanism yourself. Plus, users generally prefer to give out their credit card to the least number of companies possible; not only would you have to implement this complex mechanism yourself, but you would also have to get users to trust you enough to use it.
Lower-level: Implementation Details
Any hash mechanism can have collisions, hence you would still need to deal with this problem. You should obviously use full disk encryption and other best security practices with your servers. The risk of having both the database and the salting algorithm compromised at the same time can be reduced by hosting the backend database service on a separate machine from the one that hosts this code. The main vulnerability of hashing is brute force attacks. And the best way to deal with them is to just make brute forcing expensive enough that it isn't worth the attacker's while. Using a separate salt for each entry (e.g. the customer's name, the customer's zip code, etc. as part of the salt) will make using rainbow tables ineffective. Of course making the data, itself, less valuable to attackers (e.g. not including the full credit card number) is also a good way to discourage these kinds of attacks. In any case, I again advise you to take advantage of the many app stores instead of implementing this yourself.
Forgive me if I missed something, but why can't you just have a table of "UsedCreditCards" that just has a single column, which is a SHA512 hash of the credit card number and maybe the expiration date. This could not be reversed, and by keeping it in another table and not storing any other data about the code, you could easily check to see if a credit card number has been used before.
I am not sure if this would violate PCI or anything (I don't think so, but I could be wrong)
Related
Context
I'm working on my first Game working with a Smart contract and I have some question.
On my game I have characters and cards, and both player will duel each other using one character and 10 card each.
For that, no issue: All players and cards metadata are stored into an IPFS buckets, and some extra metadata (like experiences) are stored into the smart-contract to be updated by the game.
The problem
Now I want to be able to create a duel function into my smart-contract. But I don't know how I can access to players and cards metadatas to be able to know you'll win.
"Solutions" I have in mind
#1: I never saw any IPFS fetcher to get the metadata, nor JSON parser.. So it's probably not the good way to do it.
#2: Do I have to implement a mapping(uint => Players) private playersMetadata; into my contract and load all metadata on it to be able to use it on the duel function ??
But #2.1: It'll enlarge the storage needed a lot !
And #2.2: How can I even load it ? By creating a function setPlayer(uint idx, Players playerMetadata) and mint 10k+ times this function ? It'll cost me so much !
#3: Do not implement this function on the smart-contract and do it on my web-server.. But I don't like that because I want the user to be able to read the smart-contract code and trust it (but don't trust me). So if I do it on my server side, they'll not be able to trust the function.
Thank you for helping me ! Have all a good day
There's no synchronous and straightforward way to access off-chain data (including IPFS, since it's on a different chain) from a smart contract.
You could use the oracle pattern to request the specified IPFS data from an offchain app that sends it back to the contract asynchronously (in a later block). But since one of your concerns is users' trust in the code, and this pattern introduces an element that the users can't control (the offchain app can theoretically pass to your contract a different value from what is actually stored on the IPFS), I won't go deeper into this approach.
Another option is to move the metadata required for the fight logic to the contract. You can shift the transaction fees to the users, so each time they want to perform an action (e.g. create a card, update a character, fight other player), their wallet will pop up asking them to pay the transaction fees.
Usually onchain games require a significant amount of data to be transferred. Some game authors make use of sidechains (e.g. Axie Infinity and their Ronin chain, which is a layer 2 chain connected to Ethereum), where the overall fees can be significantly lower (but a chain without fees would attract spam transactions flooding the network). This is also one of the approaches worth taking a look at.
Or possibly, smart contract just might not be a good tool for your use case. You could also create the game in a web technology, opensource the code, make getter endpoints publicly available, so that anyone can verify that the code that runs on your server really does what you claim it does.
Over the past few months random email addresses, some of which are on known spam lists, have been added at the rate of 2 or 3 a day to my website.
I know they aren't real humans - for a start the website is in a very narrow geographical area, and many of these emails are clearly from a different country, others are info# addresses that appear to have been harvested from a website, rather than something a human would use to sign up to a site.
What I can't work out is, what are reasons for somebody doing this? I can't see any benefit to an external party beyond being vaguely destructive. (I don't want to link to the site here, it's just a textbox where you enter email and press join).
These emails are never verified - my question isn't about how to prevent this, but what are some valid reasons why somebody might do this. I think it's important to understand why malicious users do what they do.
This is probably a list bombing attack, which is definitely not valid. The only valid use I can think of is for security research, and that's a corner case.
List bomb
I suspect this is part of a list bombing attack, which is when somebody uses a tool or service to maliciously sign up a victim for as much junk email as possible. I work in anti-spam and have seen victims' perspectives on this: it's nearly all opt-in verifications, meaning the damage is only one per service. It sounds like you're in the Confirmed Opt-In (COI) camp, so congratulations, it could be worse.
We don't have good solutions for list bombing. There are too many problems to entertain a global database of hashed emails that have recently opted into lists (so list maintainers could look up an address, conclude it's being bombed, and refuse to invite). A global database of hashed emails opting out of bulk mail (like the US Do Not Call list or the now-defunct Blue Frog's Do Not Intrude registry but without the controversial DDoS-the-spammers portion) could theoretically work in this capacity, though there'd still be a lot of hurdles to clear.
At the moment, the best thing you can do is to rate-limit (which this attacker is savvy enough to avoid) and use captchas. You can measure your success based on the click rate of the links in your COI emails; if it's still low, you still have a problem.
In your particular case, asking the user to identify a region via drop-down, with no default, may give you an easy way to reject subscriptions or trigger more complex captchas.
If you're interested in a more research-driven approach, you could try to fingerprint the subscription requests and see if you can identify the tool (if it's client-run, and I believe most are) or the service (if it's cloud-run, in which case you can hopefully just blacklist a few CIDR ranges instead). Pay attention to requesters' HTTP headers, especially the referer. Browser fingerprinting it its own arms race; take a gander at the EFF's Panopticlick or Brian Kreb's piece on AntiDetect.
Security research
The only valid case I can consider, whose validity is debatable, is that of security research (which is my field). When I'm given a possible phishing link, I'm going to anonymize it. This means I'll enter fake data rather than reveal my source. I'd never intentionally go after a subscription mechanism (at least with an email I don't control), but I suppose automation could accidentally stumble into such a thing.
You can avoid that by requiring POST requests to subscribe. No (well-designed) subscription mechanism should accept GET requests or action links without parameters (though there are plenty that do). No (well-designed) web crawler, for search or archiving or security, should generate POST requests, at least without several controls to ensure it's acceptable (such as already concluding that it's a bad actor's site). I'm going to be generous and not call out any security vendors that I know do this.
I'm in the process of building an online credit system which takes my customers' real money and convert them to credits, which would be stored in the database. I thought of storing them as Number, which is plain and simple. But I worry that this is not safe if someone were to hack into the database as the hacker could just change the remaining credit number to whatever number he wants.
So I went for an aes encryption with a per-user salt for each user's remaining credit field. I wonder if this is necessary as encryption and decryption might slow down the overall server performance. Also, this prevents me from using $gte comparison when updating the value because the values are encrypted. This might cause racing condition under certain circumstances. Is it better if I just store it as it is?
it is best to use encrypt and decrypt the number to make it secure but it will definetly slow down the process but i read a doc which contain some security measures to prevent data from outsiders you should check out the doc this is the link this is an official doc of mongodb in which they define various security measures to prevent your data from hacker. i hope it will help you to protect you database
Say I have several accounts with Generic Bank. One account is the Master account and all the others are specific budgetary purpose accounts - like one for eating out or for gas. For any given time period theres a certain amount of money I have budgeted for each purpose - say $7 a day for eating out and $20 every three days for gas. After the given time period expires, I want the account refilled from whatever value it currently sits at, back up to the specified amount.
The idea is to passively manage my spending by limiting access and to keep me from thinking that I have more money to spend on a given purpose than I really have. For an example of the last case, say I put the whole months allotment into the gas account all at once. Anytime I checked that account's balance it would return a much larger number than what my actual time-period based allotment would be. Because of the association with the larger number and my inability to keep track of purchases or math in my head, it's very likely that I'd err on the side of making the purchase when in actuality I'm spending the money too fast.
Are there any services, software, or other utilities that can do bank transfers like this natively? Failing that, are there any money moving services, like Paypal or Google Wallet, that can accept add-on programs built to do this? I took a cursory look at the Paypal and Wallet APIs but, in addition to reminding of how out of my depth I was (I've never done anything involving APIs or banking), everything I saw was about person to person payments and not necessarily about account to account transfers. But then again, I'm not sure what the practical difference between the two is.
There are several banks who provide these types of services. I, personally, would advise against doing it with Tasker unless your bank specifically supports it, since it opens you up to glitches and security risks.
I'm involved in building a donation form for non-profits. We recently got hit by a fast round of low dollar submissions. Many were invalid cards, but a few went through. Obviously someone wrote a script to check a bunch of card numbers for validity, possibly so they can sell them later.
Any ideas on how to prevent or limit the impact of this in the future?
We have control over all aspects of the system (code, webserver, etc). Yes the form runs over https.
When a flood of invalid transactions from a single IP address or small range of addresses is detected, block that address / network.
If a botnet is in use, this will not help. You can still detect floods of low dollar amount submissions and so deduce when you are under attack; during these times, stall low dollar amount submissions to make them take longer; introduce CAPTCHAs for low dollar amount donations; consult your bank's fraud prevention department in case they can make use of your server logs to catch the perpetrators.
Force donors to create accounts in order to make donations; protect account creation with a CAPTCHA, and rate limit donations from any one account.
Raise the minimum permissible donation to a point where it no longer makes financial sense for the scammers to use you in this way.
Instead of CAPTCHAs, which will annoy users, you might want to take advantage of the fact that most people have javascript enabled while bots don't. Simply create a small piece of javascript that when run inserts a particular value in a hidden field.
For those that have Javascript disabled you can show the CAPTCHA (use the <noscript> tag), and you can then accept a submission only if either of these measures check out.
For maximum annoyance to evildoers you could make the difference between the succeed message and the failure message computationally hard to distinguish (say everything is the same, except for one picture that displays the message) but easy to understand for humans.
limit submissions from the same IP address to one per minute, or whatever reasonable period of time it would take for a real person to fill out the form
Raising the minimum donation to a point where it no longer makes financial sense for the scammers to use you in this way will help in general.
This. How many legitimate donations do you get for under 5 bucks, anyway?