What is a better practice for protecting my app against malicious sign ups - Captcha or confirming user email? - ruby-on-rails

I am using Authlogic for a Ruby on Rails (2.3.9) app that I built where users can track workouts. As it grows in popularity I am worried about false/malicious sign-ups. What is the best practice here or advantages and disadvantages to each approach.
Should I simply require that the user confirm their email before successfully accessing my app? Should I only require the user fill out a successful Captcha? Are these two things mutually exclusive or should they be used together?
Just looking for some general discussion around this so I better understand.

Any botnet can set up their own mail server to spam you...
Several can get past captchas too...
Use email confirmation, captchas, and gotchas (Hidden field humans wouldn't fill in)
There are bound to be many others (Bocking all russian and chinese IPs is one of the more extreme ones) but those are the most used currently...

It's been my experience that some spam bots are actually not bots at all but rather humans from 3-world countries paid to sit there and fill out all kinds forms for whatever reason. This means that while email confirmation and captchas help, you're still bound to get some spam.
There's a few other things you could consider:
If the site is social, implement a flagging system which causes the community to become the moderator.
Have all users disabled by default, then require an admin to approve or delete them.
Require a credit card to sign up.
Some of these may or may not work depending on your case. I've found that #3 pretty much eliminates spam all together, but it may also discourage real potential customers.

Good security has more than one layer. I would at least use both and also add in functionality for auto-blocking and auto-admin alerts when attempts to escalate privileges/access blocked pages occurs. Write code to make it easy for you to permanently block certain IPs, etc… if you want as well (I like to be able to block from a secure link, because then it can be called by other services with a secure API call).
You should obfuscate email as well anywhere that it appears on a page (in my opinion, as this will help a little; not as much as it used to, though):
def obfuscate_email(email)
return nil if email.nil? #Don't bother if the parameter is nil.
lower = ('a'..'z').to_a
upper = ('A'..'Z').to_a
email.split('').map { |char|
output = lower.index(char) + 97 if lower.include?(char)
output = upper.index(char) + 65 if upper.include?(char)
output ? "&##{output};" : (char == '#' ? '#' : char)
}.join
end

Related

Detecting use of iOS's "Hide my Email" on website signup

Apple's latest changes which allow users to hide their IP, hide their email, etc. are creating problems for my web-based app (non-native) which relies upon these things to build a sense of who a person is.
In most situations, I can see why these are great "features" to have, however in my use case I have a voting platform that utilizes things like email address and IP to do a decent job at detecting duplicate votes or fraudulent vote (i.e, logins from other countries, etc.).
Now, before anyone says "These aren't foolproof ways of identifying a person" and derail my actual question: I know. I'm not looking for perfection, but these methodologies shed light on the 95%+ of people who might be trying to circumvent our voting system.
Apple placing the ability to circumvent these measures by being right up in front of the user as a first-class feature shoots major holes in my existing strategy.
Is there a way to detect if a user is utilizing these methods to where I could prompt them that they need to sign-up without using these features?
I think it would be easily justifiable to explain that, due to the nature of the application being a voting website, the ability to create multiple aliases would directly undermine the purpose of the site.
Perhaps there is an email address pattern to look for (I know in my test cases, I was getting email addresses #icloud.com).
If there is no reasonable way, I need to rethink the entire process of identifying individuals and preventing aliases (phone / text confirmation, etc).

Rails/Devise - preventing spam signups?

We have been noticing a large number (~3400) of fake signups over the last year and have not been able to determine where they are coming from. Common parameters:
They often come from weird, yet validly formatted, email address (many in the .ru TLD or from thefmail.com)
Some use cyrillic or arabic characters in their name (we are basically focused only on US English speakers by our content)
They do NOT trigger the Intercom.io javascript for account signup notifications
They somehow defeat reCaptcha 3
They sometimes use URLs for their username
They don't confirm (devise_confirmable)
We've been handling these by disabling the accounts, and there's obviously a few items above we could use to identify these before they even get created, but I was wondering if someone's cracked this nut already or if there's some simple best practices (pwned db check?) that might cut this down to a dull roar or out entirely.
The two big "I don't get its" are bypassing the JS and defeating recaptcha. Is this just mechanical-turking?
Do you know whether these users have been created by the same IP address? (probably not). Are the accounts sporadically created or are they created in batches? The gem rack-attack could be used to mitigate this issue, especially if at least one of these conditions is satisfied. It also comes with some sort of fail2ban filter which could be helpful, as it is designed to detect suspicious requests from 'misbehaving' clients.
I also can't understand how they possibly bypassed recaptcha.

How do I hide my API calls / routes from users of my Rails app?

I'm writing an app that make some calls to my API that have restrictions. If users were to figure out what these url routes were and the proper parameters and how to specify them, then they could exploit it right?
For example if casting a vote on something and I only want users to be able to cast one vote, a user knowing the route:
get '/castvote/' => 'votemanager#castvote'
could be problematic, could it not? Is it easy to figure out these API routes?
Does anyone know any ways to remove the possibility of this happening?
There is no way to hide AJAX calls - if nothing else, one just needs to open Developer Tools - Network panel, and simply see what was sent. Everything on clientside is an open book, if you just know how to read it.
Instead, do validation on serverside: in your example, record the votes and users that cast them; if a vote was already recorded by that user, don't let them do it again.
Your API should have authorization built into it. Only authorized users having specific access scopes should be allowed to consume your API. Checkout Doorkeeper and cancancan gems provided by the rails community.
As others have said, adding access_tokens/username/password authorisation is a good place to start. Also, if your application should only allow one vote per user, then this should be validated by your application logic on the server
This is a broader problem. There's no way to stop users from figuring out how voting works and trying to game it but there are different techniques used to make it harder. I list some solutions from least to most effective here:
Using a nonce or proof of work, in case of Rails this is implemented through authenticity token for non-GET requests. This will require user to at least load the page before voting, therefore limiting scripted replay attacks
Recording IP address or other identifiable information (i.e. browser fingerprinting). This will limit number of votes from a single device
Requiring signup. This is what other answers suggest
Requiring third-party login (i.e. Facebook, Twitter)
Require payment to cast a vote (like in tv talent shows)
None of those methods is perfect and you can quickly come up with ways to trick any of them.
The real question is what your threat model and how hard you want it to make for users to cast fake votes. From my practical experience requiring third-party login will ensure most votes are valid in typical use cases.

Handling user abuse in rails

I've been working on a web app that could be prone to user abuse, especially spam comments/accounts. I know that RECAPTCHA will take care of bots as far as fake users are concerned, but it won't do anything for those users who create an account and somehow put their spam comments on autopilot (like I've seen on twitter countless times).
The solution that I've thought up is to enable any user to flag another user and then have a list of flagged users (boolean attribute) come up on a users index action only accessible by the admin. Then the users that have been flagged can become candidates for banning(another boolean attribute) or unflagging. Banned users will still be able to access the site but will have greatly reduced privileges. For certain reasons, I don't want to delete users entirely.
However, when I thought of it, I realized that going through a list of flagged users to decide which ones should be banned or unflagged could be potentially very time consuming for an admin. Short of hiring someone to do the unflagging/banning of users, is there a more automated and elegant way to go about this?
I would create a table named abuses, containing both the reported user and the one that filed the report. Instead of the flagged boolean field, I suggest having a counter cache column such as "abuse_count". When this column reaches a predefined value, you could automatically "ban" the users.
Before "Web 2.0", web sites were moderated by administrators. Now, the goal is to get communities to moderate themselves. StackOverflow itself is a fantastic case study. The reputation system enables users to take on more "administrative" tasks as they prove themselves trustworthy. If you're allowing users to flag each other, you're already on this path. As for the details of the system (who can flag, unflag, and ban), I'd say you should look at various successful online communities (like StackOverflow) to see how they work, and how successful they are. In the end it will probably take some trial and error, since all communities differ.
If you want to write some code, you might create a script that looks for usage patterns typical of spammers (eg, same comment posted on multiple pages), though I think the goal should be to grow a community that does this for you. This may be more about planning than programming.
Some sophisticated spammers are happy to spend their time breaking your captcha if they feel that the reward is high enough. You should also consider looking at a spam server such as akismet for which there's a great rails plugin (https://github.com/joshfrench/rakismet).
There are other alternatives such as defensio (https://github.com/thewebfellas/defensio-ruby) as well as a gem that I found once which worked pretty well at detecting common blog spam, but I can't for the life of me find it any more.

Is it worth using "pretty URLs" if you don't care about SEO/SEM

I'm designing a hosted software-as-a-service application that's like a highly specialized version of 37Signal's Highrise product. In that context, where SEO is a non-issue, is it worth implementing "pretty URLs" instead of going with numeric IDs (e.g. customers/john-smith instead of customers/1234)? I notice that a lot of web applications don't bother with them unless they provide a real value (e.g. e-commerce apps, blogs - things that need SEO to be found via search engines)
Depends on how often URLs are transmitted verbally by its users. People tend to find it relatively difficult to pronounce something like
http://www.domain.com/?id=4535&f=234&r=s%39fu__
and like
http://www.domain.com/john-doe
much better ;)
In addition to readability, another thing to keep in mind is that by exposing an auto-incrementing numeric key you also allow someone to guess the URLs for other resources and could give away certain details about your data. For instance, if someone signs up for your app and sees that their account is at /customer/12, it may effect their confidence in your application knowing that you only have 11 other customers. This wouldn't be an issue if they had a url of /customer/some-company.
It's always worth it if you just have the time to do it right.
Friendly-urls look a lot nicer and they give a better idea where the link will lead. This is useful if the link is shared eg. via instant message.
If you're searching for a specific page from browser history, human readable url helps.
Friendly url is a lot easier to remember (useful in some cases).
Like said earlier, it is also a lot easier to communicate verbally (needed more often than you'd think).
It hides unnecessary technical details from the user. In one case where user id was visible in the url, several users asked why their user id is higher than total amount of users. No damage done, but why have a confused user if you can avoid it.
I sure am a lot more likely to click on a link when I mouseover it, and it has http://www.example.com/something-i-am-interested-in.html.
Rather than seeing http://www.example.com/23847ozjo8uflidsa.asp.
It's quite annoying clicking links on MSDN because I never know what to expect I will get.
When I create applications I try my best to hide its structure from prying eyes - while it's subjective on how much "SEO" you get out of it - Pretty URLs tend to help people navigate and understand where they are while protecting your code from possible injections.
I notice you're using Rails app - so you probably wouldn't have a huge query string like in ASP, PHP, or those other languages - but in my opinion the added cleanliness and overall appearance is a plus for customer interaction. When sharing links it's nicer for customers to be able to copy the url: customer/john_doe than have to hunt for a "link me" or a random /customer/
Marco
I typically go with a combination -- keeping the ease of using Rails RESTful routing while still providing some extended information in URLs.
My app URLs look something like this:
http://example.com/discussions/123-is-it-worth-using-pretty-urls/
http://example.com/discussions/123-is-it-worth-using-pretty-urls/comments
http://example.com/discussions/123-is-it-worth-using-pretty-urls/comments/34567
You don't have to add ANY custom routes to pull this off, you just need to add the following method to your model:
def to_param
[ id, permalink ].join("-")
end
And ensure any find calling params[:id] in your controller is converted to an integer by setting params[:id].to_i.
Just a note, you'll need to set a permalink attribute when your record is saved...
If your application is restful, the URLs that rails gives you are SEO-friendly by default.
In your example, customers/1234 will probably return something like
<h1>Customer</h1>
<p><strong>Name:</strong> John Smith</p>
etc etc
Any current SEO spider will be smart enough to parse the destination page and extract that "John Smith" from there anyway.
So, in that sense, customers/1234 is already a "nice" URL (as opposed to other systems, in which you would have something like resource/123123/1234 for customer 1234 resource/23232/321 for client 321).
Now, if you want your users to be regularly using urls (like in delicious, etc) you might want to start using logins and readable fields instead of ids.
But for SEO, ids are just fine.

Resources