what can be used instead if captcha is insecure? - javascript

As far as I read from here, the fact that captchas are not 100% secure.what can be used instead of captcha? As a programmer what do you think? how to solve this issue?
Edit: thanks for all answers.

This is an unsolved problem, and will become more unsolved as time passes. The better the OCR tools get, the smaller the gap between humans and computers, and the harder it will be to tell them apart. Eventually, computers will be indistinguishable from humans, and then the game will be up.
If your server wants to make sure that a human is at the other end of a TCP pipe, there isn't a turing-test in existence that won't eventually be defeated (and there probably never will be one). CAPTCHA is doomed, it's just a matter of how soon.
Of course, that doesn't mean it's all over as far as human authentication is concerned. It just means that automated turing tests, as convenient as they are, won't be an effective way to achieve this for very much longer.

Captcha involving human reflexion (like calculation, really simple question, and the like).
Session tokens
randomly generated hidden input which requires to be null, on the server side generate a random identifier, keep it in a session for a while. If the input is filled and not null, then it might have been filled by a robot, do your users will fill an hidden input ?
I think it really depends on what you are trying to control over the use of captcha.

Further explanation of a suggestion made by Boris:
randomly generated hidden input which requires to be null
The idea is that your form contains several invisible inputs, their type should probably not be set to hidden, but they should be invisible to a human (e.g. set width or height to 0). The initial content of these fields should be empty. If a human fills out the form, the field will be empty, because the human cannot see the field in order to enter anything into it, but if a bot fills out the form the field will (possibly) not be empty, because bots usually just blindly enter something into every field.
Thus, you can distinguish between a bot and a human based on whether the content of this field is empty.

Although captchas can be broken, Capthca's only add to security reCapthca is very good, and a trained OCR like Tesseract is going to have very limited success in breaking it. However, there are outfits that use Human Computation to break them for pennies. But this makes attacks against your system more expensive, and thats the best you can hope for. Cryptography can be broken with brute-force. All password hashes are breakable, but we still use them because it makes it harder for the attacker.
Most of the "solutions" on this thread are "Security Though Obscurity" and you should be wary of these quick fixes to a very complex problem.

Captcha's are used to determine that an actual human being is doing the request, not a machine. Captcha's and captcha-like systems will upgrade, and so will the technology to break them.
So how do you proof that you're talking to a human and not a computer? You could for instance require users to engage in a chat session and have small conversation. There's no AI nowadays that pass the turing test.
So the answer is, no system is perfect. Don't try to solve this issue, but try to find a way to reduce the impact of this.

In the long run government could run openid servers as digital passports for their citizens.
It would be a clean way to identify human beings and prevent sockpuppeting.

At the moment on my website I opted for simple questions. Some questions I've used in the past:
What is two to the power of one?
What is 2+2? (this one was hacked though so don't use it)
What is the name of this website domain?
What is the sum of two and two?
Some other nice ones could be
type in 'stuff' to this box as a spam check
What does 1337 look like? (using only letters)
the current year is?

The best way I can think of is using something unconventional, like a special hidden field that should be null (or another specific value) that robots will mess with.
If some robot maker adjusts his robot for your site, you'll have to quickly change the captcha to something different. It will (hopefully) take a good while before another robot maker adjusts his robot for your site.
Basically, it's a security through obscurity that has to constantly change to remain obscure.
This won't work very well if someone is specifically targeting your site.

Its just an idea, id used that in my application and works well
you can create a cookie on mouse movement with javascript or jquery and in server side check if cookie exist, because only humans have mouse, cookie can be created only by them
the cookie can be a timestamp or a token that can be validate

Gets the coordinates of the mouse, determine whether the coordinates have changed, you can determine whether it is a robot.
Then encrypt the coordinate data.

Related

Secure High score ladder [duplicate]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
[I know there have been similar questions about preventing cheating on high score lists, but no answer didn't really help me for JavaScript based games, so please try to think about my question, before telling me about similar posts. I ask about best practices because the JavaScript is always visible for the user and therefore it is not possible to prevent cheating completly, I just want to make it harder.]
I'm developing a JavaScript based game that works in the browser. I want to make a high score list that contains the user name and the score of all users. To achieve that the browser sends the username and the score to my server (via AJAX).
Submitting fake scores to this list would be fairly easy: One could take a look at the AJAX requests and then make an own AJAX request with a faked score. Using something like a token that has to be send with the other data is pointless, as it will be easy to discover.
My only approach, that would prevent cheating, would be to send a description of every user action to the server and calculate the score there. But this is not really practicable as it would be too much for the server.
I accepted an answer, but in case anyone has other ideas about how to make cheating harder, please create another answer!
I like to play cheat the cheater - something like using a token to authenticate the score that changes every time the update is called... but I accept the cheat score that gets posted using a duplicate token. Then I display that cheat score to only the cheater, so it appears that it worked, but now the cheater is seeing his results in a sandbox.
You pretty much answered your own question. If you want to really make it harder for users to cheat, send game log to the server, where you'll calculate the score.
You don't have to send all the events, just ones that affect result score.
There are some techniques, though, that may help you:
include signature in your request. Something like MD5(secret_key + params). Although, "secret key" will have to be in JS source, it will effectively protect you from simple request interception (see Tamper Data and Charles)
if it's a multiplayer game, accept scores calculated by clients and compare them. Cheaters will be pretty visible (assuming that the majority of users are honest).
you can set a score cap, an "unreachable" result. Everyone who posts score higher than this is a cheater. For example, speed typing game: no one can type correct text at 1500 chars/minute, even 700 is pretty damn hard (though achievable).
On score submit:
Request some token from the server, this should be time based and only valid for about 2 seconds
Only accept submits that include a valid hash of this token, some salt and the score.
This prevents manual tampering with the request as it would timeout the score. If you want to account for high-latency give it a little more time until the timeout.
The hashing function:
Scramble the hashing function inside packed code (http://dean.edwards.name/packer/ really produces nasty to read code) if you use jQuery or some other library just drop the hashing functionality inside the library file and it gets pretty bad to find, escpecially if you use a function name like "h" :)
Handling the score-variable itself:
Well everybody with a debugging console can change the variable on runtime when doing this but if you encapsulate your whole Javascript inside a function and call it nothing is in the global namespace and it's much harder to get to the variables:
(function() {
//your js code here
})();
I have had lots of thoughts about it and, eventually, decided to only have local individual highscores, so cheating is not really beneficial for player and not harmful to others. Yet my game is just a simple minesweeper, and there were people who complained about the lack of competitive table.
Option 2, is approach taken by WebSudoku - to show your place "among the people of internet". So you will not see any other results, and people wont see your results - but you can compare yourself to crowd.
p.s: And seriously - any kid with Firebug/WebInspector can easily hack your JS game and, eventually, to be able to reach very high score.
If you are relying on the client to send the final score to the server, then there is no way (afaik) to prevent a genius from cheating. But I think you might be able to prevent stupid people (and honest people) from cheating, so that only geniuses and their friends will dominate your leaderboards.
There are two ways I can think of
1.) "security through obscurity."
Come up with an algorithm that transforms simple scores into something else (and to transform them back). Then obfuscate it. Complicate it. Write a function that multiplies it by q and divides it by ralph. Apply a bunch of functions to it, and among the 5-15 functions that do random stuff to it, include one that multiplies the number by 19 ( a prime number ). On your server, check to make sure every incoming number (or letter) is divisible by 19, and decode
You have to write a bunch of complex code that transforms simple scores into something crazy-looking. You have to write a series of functions in the least-efficient, most spaghetti-code fashion possible. Use
One thing you cold do is to have a set of disallowed values. I.e., perhaps all points awarded are even. If anyone tries to submit an odd number, they are obviously cheating (and very stupid).
2.) time
You should be able to know when the user started the game. You should have a session started and record when they requested the page. Then you should also be able to tell when they submitted their score. And you should also know what the time series is for max points. I.e. can you get 5 points per minute, 100 per minute, minute^3, etc... If user submits more points than are possible during that time, they are cheating.
You could also strike a balance between server and client processing and make the client should send progress update every x minutes by ajax. And if it fails to report, you assume it's been compromised (much like in Bond movies, when he's infiltrating the enemy's lair and he snaps some guard's neck. When the guard doesn't respond to his next 10-minutely check-in, the alarms will go off).
If you've ever played Zynga Poker, you've probably seen what happens when someone at the table has a slow internet connection.
Depending on the nature of the game, you could use other players to verify the results. In simple games this works great, on others you have to be clever and develop many aspects around this feature. E.g. sometimes is possible to replay and verify results based on logged actions. This trick works specially well for Human versus AI, as long as the model is deterministic.
Another option is redefining the score concept to be more user-centric, this is pretty easy to implement, but tends to be hard to devise, and only applies to a few categories of games.
Purely speculative approaches are also possible, it's sometimes pretty easy to know when some parameters don't fit. It would not avoid cheating, but would moderate it a lot.
The most complicated part is getting a small enough replay log, but since most data isn't random (except for player actions, which, actually aren't that random because depend on the game) it's essentially a matter of getting the design right.
Also, if gameplay is extended enough, for action games and the like you can get a lot of compression from doing some approximation, merging (e.g. motion vectors), and clipping uninteresting stuff.
Ideally you would send your entire event log to the server for checking. Perhaps you can implement a heuristic so you can easily determine if the score is within a set of bounds. For instance, if the total game time is 5 seconds you might expect a much lower score than with a much longer game time.
Alternatively, you could choose to manually check the event log for really high scores (the overall top-X, which should be fairly stable).
You will need a seeded random number generator if you're doing anything with randomness (like random events). Which might be tricky if you hadn't already thought of it.
You can find many more resources but it really just boils down to server-side checking. JavaScript is not unique in this, but likely easiest to exploit because you not only see the client-server communication but also the client-side source code!
HTML5 Multiplayer Game Security Solutions
http://lanyrd.com/2011/jsconf/sfggb/
Games like Starcraft only record the mouse clicks and key presses. The actual commands are then simulated. I expect 'Worms Armageddon' to do something similar but their random events (like the bounciness of bananas) aren't seeded properly so in the instant replay you might get a different result.
You could imagine something similar for MMORPGs. The server calculates your position based on the keypresses, the client merely tries to give a good early interpretation but you may warp around when you're lagging because the server will place you elsewhere on the map because it didn't get the keypress events timely.
If you attack something, the server will check if you're close enough and how much damage you can expect to deal with current stats and equipment.
Record key points in game, then score is submitted with these key points. When people look high scores, they can also see overview of played game, if it looks like it is impossible to play like that without cheating, then people can report these suspicious scores to admins.
I used a system using a time based request having 3 parameters
req number, curr time, score
The req number is returned from server in the response to the update score request , each time this is a new random value.
The curr time is calculated not from computer clock but from start of game and is synced with server using an ajax request.
Update score request is sent after short intervals (around 30 sec max).
Following checks are applied on the server
Time is within 10 seconds range from the server clock.
there has been not more than 40 seconds since the req number was sent.
the score change sent after 30 seconds is possible (within 2 x humanly possible range)
Score is updated only if the above checks are passed or the user gets a disconnection message :(
This is simpler than most methods and works out to eliminate all casual hackers (well, unless they read this and want to go to the trouble of updating score quickly or making a script of their own).
If not cheating is more important than the game itself, try to construct and present your game in a way that it looks like finding the solution to a math problem. So the server will give an instance of the problem to the client (example A: a chess board about to be won in 3 moves, example B: a geometry dash randomly generated level) and the user will have to solve it and post back a solution (example A: the winning moves, example b: the exact timestamps and intensity of jumps to avoid obstacles)
With this approach, it is key that the server doesn't send the same level twice, or else the cheater can plan and "design" his solution in advance. Also, the game information must be randomly generated in the server and not sent via seed, or else the cheater can fake the seed and design his solution with time.
The given time for valid submissions must be also tracked in the server so that they will only have "playing" time and no "designing" time. If the cheater is good enough to design a solution as fast as honest players can win the game, then they are talented enough to win the game honestly and deserve their points.
Back in the server, you will need to check that the submitted solution is valid for that instance.
Of course this approach requires lots of extra work: More instances of games (ideally infinite and non repeating), server side generation, server side validation of submissions, time caps, etc.
Note: I know these approach was already suggested in multiple solutions some years ago, I wanted to add my humble contribution.

Real-time password rule checker?

I am doing a bit of preliminary investigation for my school (I work for the IT department as a student). The students here have to change their passwords every 6 months, and many of them struggle with the (many) password rules that are enforced. That is, they often have to make several attempts at setting a new password.
The rules are:
Must be 8 characters or more in
length
Must contain 3 of 4 types of
characters (capital, lowercase,
number, special character)
Must not contain the user's first,
last or middle name
Must not contain the user's username
Must not match any password used
before
User must type password in twice, and
typed passwords must match exactly
I have a few questions:
Is it possible to create a web-based
password checker that provides
real-time feedback as the user types
in their new password? I am
imagining a checklist on one side of
the web-page where green checkmarks
are activated as the password meets
more criteria.
Is it possible to do perform this
checking securely and entirely
client-side?
Where would one start on such a task?
Is there a guide you can recommend?
Please keep in mind that I am not a web developer. Also, please leave any witty comments like "change the password policy" or "they're just dumb users" out of here.
Is it possible to create a web-based password checker that provides real-time feedback as the user types in their new password? I am imagining a checklist on one side of the web-page where green checkmarks are activated as the password meets more criteria.
Yes.
Is it possible to do perform this checking securely
As the lights go green, it exposes information about where in a password the requirements are met. That will leak data about the password to anyone who can see the screen.
and entirely client-side?
Yes.
Where would one start on such a task?
A list of rules in the HTML document with a FAIL image next to each one. Programatic versions of the rules in JS. Then just test each rule in turn in a loop on each keypress event on the password input and swap PASS and FAIL images depending on if the rule is followed or not.
You'll need to hit the server with an XMLHttpRequest object to check if a password has been used before. Make sure you only store hashed and salted passwords there though.
Please keep in mind that I am not a web developer.
Then I recommend you get one or become one.
Also, please leave any witty comments like "change the password policy"
Fine, leaving the wit aside and sticking to the serious issue:
If people have problems coming up with passwords that conform to the policy, then they will have problems remembering them. This will lead to an increase in people having to have them reset (more work for the IT dept) and in people writing them down (which is probably going to be less secure then a password that is easier to guess / brute force).
Most of the rules you specify can be checked in real time using javascript, more specifically using regular expressions. Checking whether the password has been used before should be done on the server side to be secure.
Is it possible to create a web-based password checker that provides real-time feedback as the user types in their new password? I am imagining a checklist on one side of the web-page where green checkmarks are activated as the password meets more criteria.
Yes, but you will need to know some javascript to do it.
Is it possible to do perform this checking securely and entirely client-side?
No, and yes, or yes and no, but not both. You can do the check entirely client-side (except for checking against previous passwords, which would need database access). But nothing, NOTHING, on the client-side is ever secure. Anything you do on the client-side should be considered a help to the user. All validation must always be made again on the server.
I don't want to be a smart-ass and tell you to change the password policy, and doing so because validation would be "hard to do" would be a bad choice, but I would like to recommend the following article to the one that has decided on the password policy: http://www.baekdal.com/tips/password-security-usability
Must not match any password used before <--that one is the only one that has to be performed server side, but can be done securely using hashes or some form or encryption, because a client side copy of said passwords would not be a good thing.
Regexp's are probably where you'd wanna start. If you're unfamiliar with regexp's in web development, I'd suggest you start here: http://www.w3schools.com/jsref/jsref_obj_regexp.asp. If you truly have no experience in web development, I'd have to ask how you got stuck with a job where you'd have to learn a new language to accomplish a relatively simple task. You'll definitely need to have an understanding of javascript to do something like this all client side. Oh, and I wouldn't recommend testing
Must not match any password used before
It's too risky to do this in a simple way client side and complicated to do it securely without bringing in help from outside libraries, etc. Hope this helps and good luck!

What is the best way to filter spam with JavaScript?

I have recently been inspired to write spam filters in JavaScript, Greasemonkey-style, for several websites I use that are prone to spam (especially in comments). When considering my options about how to go about this, I realize I have several options, each with pros/cons. My goal for this question is to expand on this list I have created, and hopefully determine the best way of client-side spam filtering with JavaScript.
As for what makes a spam filter the "best", I would say these are the criteria:
Most accurate
Least vulnerable to attacks
Fastest
Most transparent
Also, please note that I am trying to filter content that already exists on websites that aren't mine, using Greasemonkey Userscripts. In other words, I can't prevent spam; I can only filter it.
Here is my attempt, so far, to compile a list of the various methods along with their shortcomings and benefits:
Rule-based filters:
What it does: "Grades" a message by assigning a point value to different criteria (i.e. all uppercase, all non-alphanumeric, etc.) Depending on the score, the message is discarded or kept.
Benefits:
Easy to implement
Mostly transparent
Shortcomings:
Transparent- it's usually easy to reverse engineer the code to discover the rules, and thereby craft messages which won't be picked up
Hard to balance point values (false positives)
Can be slow; multiple rules have to be executed on each message, a lot of times using regular expressions
In a client-side environment, server interaction or user interaction is required to update the rules
Bayesian filtering:
What it does: Analyzes word frequency (or trigram frequency) and compares it against the data it has been trained with.
Benefits:
No need to craft rules
Fast (relatively)
Tougher to reverse engineer
Shortcomings:
Requires training to be effective
Trained data must still be accessible to JavaScript; usually in the form of human-readable JSON, XML, or flat file
Data set can get pretty large
Poorly designed filters are easy to confuse with a good helping of common words to lower the spamacity rating
Words that haven't been seen before can't be accurately classified; sometimes resulting in incorrect classification of entire message
In a client-side environment, server interaction or user interaction is required to update the rules
Bayesian filtering- server-side:
What it does: Applies Bayesian filtering server side by submitting each message to a remote server for analysis.
Benefits:
All the benefits of regular Bayesian filtering
Training data is not revealed to users/reverse engineers
Shortcomings:
Heavy traffic
Still vulnerable to uncommon words
Still vulnerable to adding common words to decrease spamacity
The service itself may be abused
To train the classifier, it may be desirable to allow users to submit spam samples for training. Attackers may abuse this service
Blacklisting:
What it does: Applies a set of criteria to a message or some attribute of it. If one or more (or a specific number of) criteria match, the message is rejected. A lot like rule-based filtering, so see its description for details.
CAPTCHAs, and the like:
Not feasible for this type of application. I am trying to apply these methods to sites that already exist. Greasemonkey will be used to do this; I can't start requiring CAPTCHAs in places that they weren't before someone installed my script.
Can anyone help me fill in the blanks? Thank you,
There is no "best" way, especially for all users or all situations.
Keep it simple:
Have the GM script initially hide all comments that contain links and maybe universally bad words (F*ck, Presbyterian, etc.). ;)
Then the script contacts your server and lets the server judge each comment by X criteria (more on that, below).
Show or hide comments based on the server response. In the event of a timeout, show or reveal based on a user preference setting ("What to do when the filter server is down? (show/hide comments with links) ).
That's it for the GM script; the rest is handled by the server.
As for the actual server/filtering criteria...
Most important is do not dare to assume that you can guess what a user will want filtered! This will vary wildly from person to person, or even mood to mood.
Setup the server to use a combination of bad words, bad link destinations (.ru and .cn domains, for example) and public spam-filtering services.
The most important thing is to offer users some way to choose and ideally adjust what is applied, for them.

javascript securty: an AJAX call to record the user's screen resolution, is it possible to prevent fake numbers?

This is a javascript security question: suppose a page finds out the screen resolution of the computer, such as 1024 x 768, and want to use an AJAX call to log this data into the DB.
Is there a way to actually prevent fake data from being entered into the DB? I think whatever the HTML or Javascript does, the user can reverse engineer the code so that some fake numbers get entered into the DB, or is there a way prevent it from happening totally? (100% secure).
Update: or in a similar situation... if i write a simple javascript game... is there a way for the user to send back the score by AJAX and lie about their score?
If you start with the assumption that the user you are communicating with is malicious, then no; there is nothing you can do to control what data they pass you. Certainly not with 100% certainty - in the worst case, they can use network tools to rewrite or replace any "correct" content with whatever they want.
If you just want to prevent casual maliciousness, you could obfuscate or encrypt your code and/or data. This will not deter a determined attacker.
If you actually trust the real user, but suspect that others might try to impersonate them, you can use other techniques like a dynamic canary: send the user a random number, and if they return that same number to you, you know that it really came from them. (Or you're being hit by a man-in-the-middle attack, but hey; that's what SSL is for.)
It's not possible to stop users from sending any numbers they like back from JavaScript.
I think the best you could do is do some sort of check on the server-side to make sure the numbers sent back look like a realistic resolution.
I'm not sure why someone would spend the time to spoof those numbers in the first place though.
Yes, you are correct. Since you're using client-side code, you have to tell the
user's computer (and thus the user) in one way or another, whatever encryption or obfuscation you're using. There's no way around it.
For the resolution, it would basically be impossible to determine if it's valid resolution. My resolution is usually sent to the server as 5120 x 1600, which seems pretty unrealistic, but it's because the 2 screens are often sent as 1. Otherwise, there is a such a huge variety of possibilities in screen resolutions and screen configurations, you'd probably remove a lot of valid ones, although they might be few.
For the game score, you could do additional checks that make it more complicated to check. Things like sending multiple notices of the score throughout the game and requiring X number to ensure that the score received is valid. (IE, must receive one between 200-300, 400-500, 700-800 and then the final score of 1000.) With the final score, you could also have some kind of encrypted value that can only be used once or that contains some data with a CRC on it. Basically, in the end, require receiving other data than just the score, especially for higher scores.
To attempt an answer by elaborating on comments made by Dok, and yourself, there is a clear distinction between manipulating an application to 'cheat' it out of something, whether it be an online business to get something cheaper or a MMPORG to get more experience, than manipulating it in such a way that it renders the interface incorrectly and diminishes the overall user experience for that particular (hacker?) user.
Your time would be better spent focusing on other aspects of your site. I don't recommend the users of my site manipulate the HTML to make it look funny on their machines, but I'm not going to go all out and obfuscate my server output to stop them from hurting themselves. In your case, range checking against pre-defined safe values, making use of the DB, to ensure the user is viewing with an 'allowed' resolution puts unnecessary burden on your application, and takes time to do.

What ideas do you think can it be applied to this GUI to make it more effective for real people usage?

I am talking about Google Text Translation User Interface, in Google Language Tools.
I like the fact that you can get translations of text for a lot of languages. However, I think is not so good always to show all options of translation. I believe is preferably to show, in first instance, only the most frequent options for text translation.
Really, it has become very annoying trying to translate from English to spanish, for example. Using the keyboard (E, Tab, then S Key repeatedly), the first three options presented are Serbian, Slovak, Slovenian, and finally Spanish...
Another example: from English to French. Using the keyboard again (F key repeatedly) shows Filipino and Finish before French!!!
What sort of ideas do you think can it be applied to this GUI to make it more effective for real people usage?
I think it's probably fine. There are only a little over 30 languages in the list, and close to half of them are pretty common languages, so I don't think it really makes sense to put the common ones first. It's not like a country list where you have to search through 180+ countries to find yours.
The only thing I would probably do is use a cookie to store your last language selection(s).
I think the best would be an autocomplete input field similar to the one used for tags on Stack Overflow and the one used for search on Facebook. Each letter you type narrows the field of results down and allows you to easily choose the right one with either the mouse or the arrow keys.
You could also keep track of the most popular ones and sort the results by most frequently used, like Stack Overflow does with their suggested tags.
I've been frustrated with this interface as well. I think it would be a good idea to (a) use cookies to give preference to the languages this user has selected in the past; and (b) to display a limited list (4-8 languages) of the most common languages, with a "more..." option that expands the list.
I really appreciate the fact that a lot of websites and software applications have started using this approach when asking you to specify your time zone. Why display "Mid-Atlantic", "Azores", etc. if you expect 95% of your users to be in (for example) the 5 U.S. time zones.
The simplest way to do what you are asking is to sort by request frequency and then by alpha/numeric. This will put languages where translation requests are most common to the top. It still won't solve your problem perfectly, but it would be an easy improvement, and one that would work better for most people.
Now, if only there were some google employees who came to this website ;-)
I'd try and detect their locale through browser/ISP meta data if I could, then default to that - but most people expect an alphabeticly-ordered list of languages. What if they're looking for Serbian, but after they hit 'S' once they get spanish, with no Serbian in sight? They might assume that there is no Serbian, since it's not where they expect it (before spanish) and leave. That'd be bad.
I would agree with most previous responses, as plain as this page is there is not much you could do upfront, languages should stay sorted alphabetically.
But there are some things that one could do in the background, store last settings or letting you bookmark translation settings.
Don't forget that some browser will let you do multiple letters for shortcuts, e.g. in Firefox you can type 'SP' to get to spanish.

Categories

Resources