Hello information security stack exchange!
I made a captcha application in PHP. It's certainly not a great idea to do so, but I was bored and I wanted to learn about Bézier curves and Bresenham line algorithms. Therefore let's disregard that my application is not really secure against serious cracking attempts that try to crack it with OCR methods.
To my question: My app basically writes every two hours 10 new captcha images in a directory (with a cronjob). If there are more than 1000 images in the directory, it replaces the oldest 10 images with the newly generated ones. So there is always a pool of 1000 captchas that slowly but steadily refreshes. All the captcha images have a 18 char long random filename and I have a associative array in my database that maps the filenames as keys to the captchas value.The array looks something like this:
Array
(
[captchas/6aab1bfa796ff02b48] => knfbb
[captchas/3f53d6eefb535233f0] => HnHnQ
[captchas/436e3567bdbb987b45] => HaEQS
[captchas/916ac5d684f17f1677] => aQnWE
[captchas/fb6267bfb72ff37fdb] => fHWya
[captchas/3fb748ba654b98088e] => WkSEG
[captchas/71ea9d1d88a245c1e3] => HkQXy
.
.
.
);
Whenever my captcha application hooks into a comment form or login form in order to inject a captcha image, it choses a random captcha from the pool and let's the user try to solve it.
Now you might already see the security drawback: How can I make sure that a user doesn't download all captchas and maps them manually (Decipher the captcha manually and map it to the md5-sum of the png-image) to it's corresponding string value and then spams my site with a script?
The attacker would just need to download around 20 percent of all images and then he had a average success rate of, errhh, yeah 20%, in succeeding to spam my site (The script would just refresh the form as long as it serves a captcha that it knows).
How would you defend against such attacks? (Under the condition that my app architecture doesn't change: I can't generate captchas on demand, it would be too slow).
I thought of blacklisting IP addresses (parsing apache2 access_log IP addresses) from my site that visit my site more than 100 times per 5 minutes, but this could easily be circumvented by proxies.