Today i noticed my site was getting bombarded by someone doing a HTTP post. This is what i see in the log files.
2022-09-27 20:10:15 [141.98.83.249][-][sctld9l1o96eniqsb3tqr1qfpg][error][yii\web\HttpException:400] yii\web\BadRequestHttpException: Unable to verify your data submission. in /var/www/html/vendor/yiisoft/yii2/web/Controller.php:220
That’s an attack on your website / server. you should block it. Country IP, this IP or IP range level until it stops. Purpose of these attacks to load your server, inject your database or crash your website.
Hi Shaho. These are some automatic attacks trying to use some known ways how to penetrate website, like various SQL injections or bugs in widespread systems like Wordpress. I also noticed this like a Year ago.
I created to myself a custom component for automatic blocking IPs based on the request, since there is a lot of common things with these attacks. It wasn’t hard.
Of course performance wise, the best ways is to block these Ips in firewall, but then you have to manage the list yourself. Which is unrealistic for me.
So how does my component work?
There is a simple table with blocked Ips, which I can (beside the automation) administrate in my custom CMS
It contains these columns
Ip - it’s also primary key, in postgre there is a special type of column for IP
Active – if the block is “on” or “off”. Sometimes you wanna turn off the block but keep the entry for the future
Note – description what was the reason for blocking. The automatic script fill this but I can put some info there if I add some IP manually
Log – content of global variables (POST, GET, …) – important when analysing
Counter – when the IP block is created, it actually counts every attempt to access the website from this IP. Its funny, some times it goes to thousands, since the attack tries lots of variants
Some other columns like when it as created, by who etc
If it is, it shows very simply page and rises up the counter
It it is not, it checks if the request is dangerous based on some internal metrics – mostly checks a presence of prohibited words, phrases or characters
If it is dangerous request, it puts a record to the table with all the info
Some really important things:
Performance. As I said, the best solution is to have the block list in firewall. Then the request don’t even hit the PHP webserver and db. But if you can’t do it, it’s important to make the block component as light ass possible. How to do it?
Make sure it’s loaded as one of the first thing. The best would be to do some custom code in entry script. But I wanted to have it as a Yii component since I use it on more webs and want to have the option to config it. In that case, it’s required to “bootstrap” the component in your app config. For example Log component does it - Application Structure: Application Components | The Definitive Guide to Yii 2.0 | Yii PHP Framework
Cache the list of blocked ips. This is also crucial. You will safe a SQL request. Invalidate the cache only when the component actually adds new entry. Tag you cache for this purpose so you don’t have to delete whole cache, only the tagged. Easy peasy. (I’m assuming you use cache like Redis) TagDependency, yii\caching\TagDependency | API Documentation for Yii 2.0 | Yii PHP Framework
Blocked page – it must be very simple. Don’t use standard controller (which usually loads a lots of data). Have simple pure controller with simple view. No SQL, co css, no html. Just put some info about blocking IP, contact (when there is false positive case) and proper HTTP code, like 403.
So in the best scenario, when you catch the dangerous request, you block it and any other request is handled with minimal performance impact with all the benefits of have this as a component.
Your app don’t event start running, no SQL is executed, no large app css and js assets are used.
My component also has this configurable parts
If search in GET request
If search in POST request
White/allow list params – this is handy if you know you have some param (for searching for example) where can be some legit but dangerous for the component stuff.
Well, I hope I helped you a bit.
My whole component has like 260 rows across 7 methods (1 class), so you should be ok to write it by your own.
The component works pretty well, it already blocked hundreds of Ips and hundreds of thousands of requests. It’s funny to go through the blocked Ips and analyse the request and how they tried to attack you.