Formcha. Antibot with a human face?
Background
Once I tried to register on one developer forum. I tried for a long time, I used almost all of my supply of curses to the admin, who overdid it very much with the captcha settings. It was registered only from the eleventh time and spent a lot of good time fighting someone's paranoia.
After this incident, I sharply wanted to come up with some kind of antibot system that would not cause attacks of aggression when solving it, but would cause attacks of aggression in those people who would write a hacking system.
Research problem
To begin with, let us return (once again) to the problem of captcha. The complexity of captcha is achieved by adding noise and distortion. But this is a double-edged sword, because the more you add noise and distortion, the more difficult it is for a person to guess the characters. If you made a mistake with the input - start all over again. Often, he simply has to update the image several times in order to at least somehow simplify his guessing task.
If we approach the solution of problems only within the framework of the current implementation, then apart from the next clone, nothing can be done. And this clone will have all the hereditary problems of the “parents”. One of my rules sounds something like this: "If you can’t solve the problem in a simple way, then you need to change the condition of the task so that it is solved in a simple way."
Why do you need captcha? To weed out the automatic sending of data to the server. With what does the user do it? Using the form. But what if you make the form the same captcha?
A form is a collection of named fields. Just replacing the field names with abracadabra will not do anything, since you can safely calculate the position of an element in the node tree, map fields, send data to the server according to mapping. The problem does not solve, but we develop the thought further. Let the fields come in random order with coded names. Before filling out the form, the user first restores the correct order of the fields, and only then fills out the form and submits it. The mystery of this captcha will be to get the correct field order. How to find out that the order is correct? You can mark the names of the fields and the input fields themselves with images, colors, figures, whatever, and then set the task to put the puzzle together using some algorithm.
Algorithm
To begin with, we create an array of normal field names in the reference order. I will use an abstract language to describe.
formData = [ { name: "first_name" }, { name: "last_name" }, { name: "nick" } ]
Add hashes to the structure that are made based on the name, plus an index that comes in handy later. Now create three fraudulent arrays with incorrect positions. I will simplify this to indexes. And add to the middle a normal array with the correct positions. It is important that this is not in the first place, so that the person understands that he needs to do something before sending. Yes, and false positives can be reduced.
formData = [
{
name: "first_name",
hash: "0947fh27",
index: 0
},
{
name: "last_name",
hash: "82jj2n4lE2",
index: 1
},
{
name: "nick",
hash: "jf12sjfjI9",
index: 2
}
]
fake = [ [ 2, 1, 0 ], [ 2, 0, 1 ], [ 1, 0, 2 ] ]
fake = [ [ 2, 1, 0 ], [ 2, 0, 1 ], [ 0, 1, 2 ], [ 1, 0, 2 ] ]
This is all good, but now how to make a puzzle? For demonstration, I chose a simple puzzle with geometric figures of different colors. You need to collect their halves. To the normal data, I added one half of some random figure, I placed pairs according to indices to the first false array. We save these structures into the session and begin to form the HTML part. To draw graphics, I used css classes, which I specified as a background link to pictures by index, and not by hash, so that there was no clue for the cracker about the true order. It turned out something like this: The script reads the data from the session and outputs the image names for the text description of the fields (type = l) from the normal array, and for the fields themselves (type = r) from the blended array.
formData = [
{
name: "first_name",
hash: "0947fh27",
index: 0,
picture: "red_circle_left"
},
{
name: "last_name",
hash: "82jj2n4lE2",
index: 1,
picture: "yellow_triangle_left"
},
{
name: "nick",
hash: "jf12sjfjI9",
index: 2,
picture: "green_circle_left"
}
]
fake[0] = [
{
hash: "jf12sjfjI9",
index: 2,
picture: "green_circle_right"
}
{
hash: "82jj2n4lE2",
index: 1,
picture: "yellow_triangle_right"
},
{
hash: "0947fh27",
index: 0,
picture: "red_circle_right"
}
]
.lp0 { background: url( /img/get/?type=l&pos=0) ... }
.lp1 { background: url( /img/get/?type=l&pos=1) ... }
.lp2 { background: url( /img/get/?type=l&pos=2) ... }
.rp0 { background: url( /img/get/?type=r&pos=0) ... }
.rp1 { background: url( /img/get/?type=r&pos=1) ... }
.rp2 { background: url( /img/get/?type=r&pos=2) ... }
We draw the left part with the text description of the fields in the normal order, and the fields themselves in the fake array, while the classes of nodes are arranged in the normal order for both the left and the right parts. Field names will be taken from hash.
Everything further comes into play JS. I used StateController as an example, which did an excellent job of cyclic permutation of fields and, in the future, the task of collecting data.
After the user “assembled” the form, he can fill it out.
But we need to ensure that the fields leave in the correct order. For this, json is the best fit. We collect the data in the structure we need, maintaining the position of each field, and send it to the server with an AJAX request.
The server receives data in a single json field, picks up its "old" records from the session about the correct data structure, and begins to compare two arrays using hashes. If all is well, then the values and names of the elements are mapped, and then this information is sent for processing to subsequent functions. If everything is bad, then we inform the user about inappropriate behavior, and if there is a desire to protect ourselves from enumerating options, we apply administrative measures with an increase in the lag between receiving information from this IP and the like.
Voila! View demo of functionality
Problems
Where without them. I will list the most important:
- The complexity of the implementation is slightly higher than with conventional captcha. Integration will be difficult for beginners.
- Data cannot be sent in the usual POST or GET requests, only JSON, in order to guarantee the position of the data.
- I can not imagine how to send data in the usual way, and not using AJAX.
- Autocomplete will not work as encrypted field names.
- The minimum number of form elements is three. Then you have to get out by introducing empty blende fields
Security Enhancement Methods
They can be invented for a long time, and the main direction, as I see it, is in creating a variety of jigsaw puzzles. You can sort through different riddles, different figures, different principles of combination. To quickly not parse the riddle text, you can make the question text in the form of a picture. But that's another story…