{"id":27691,"date":"2015-10-08T13:46:06","date_gmt":"2015-10-08T08:16:06","guid":{"rendered":"http:\/\/www.tothenew.com\/blog\/?p=27691"},"modified":"2015-10-13T13:13:33","modified_gmt":"2015-10-13T07:43:33","slug":"protect-wordpress-login-using-aws-waf-web-application-firewall","status":"publish","type":"post","link":"https:\/\/www.tothenew.com\/blog\/protect-wordpress-login-using-aws-waf-web-application-firewall\/","title":{"rendered":"Protect WordPress login using AWS WAF &#8211; Web Application Firewall"},"content":{"rendered":"<p>AWS re:Invent has already begun and keeping in mind security of your applications in the cloud, AWS has launched a new service called AWS Web Application Firewall. This service is intended to secure what you share on the world wide web via AWS CloudFront. Making the experience for the user better with more security is what AWS has always aimed for.<\/p>\n<p>AWS\u00a0WAF allows you to create your own set of rules to block most common attacks on Web Applications such as SQL\u00a0injection or cross-site scripting etc. You need to specify the rules and just associate the set of rules to your AWS CloudFront Distribution. The set of rules are also called web ACL. AWS WAF\u00a0also gives you a deeper monitoring of the traffic.<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"wp-image-27955 aligncenter\" src=\"\/blog\/wp-ttn-blog\/uploads\/2015\/10\/AWS-Re-Invent.png\" alt=\"AWS-Re-Invent\" width=\"486\" height=\"265\" \/><\/p>\n<h3>Use-case<\/h3>\n<p>I have a PHP application running on EC2 \u00a0in a load balanced environment. For better content delivery globally, I have also used AWS CloudFront. Recently there were hits from a lot of unknown IPs on the wp-login.php page of my website. I was trying to figure out what to do\u00a0and how\u00a0to prevent unwanted logins to wp-admin of my PHP blog website. The URI is actually wp-login.php which opens up wp-admin page. I decided to use AWS WAF &#8211; Web Application Firewall and give it a try and so far it seems good. I have setup a basic WordPress website for demo purposes of this blog and will try to allow only few IPs to be able to access wp-login.php.<\/p>\n<h3>Workflow of AWS WAF<\/h3>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-27780 aligncenter\" src=\"\/blog\/wp-ttn-blog\/uploads\/2015\/10\/Screenshot-from-2015-10-08-133650.png\" alt=\"Screenshot from 2015-10-08 13:36:50\" width=\"382\" height=\"486\" \/><\/p>\n<h3>Steps<\/h3>\n<p>What we will be doing is creating conditions as per requirement, adding them to rules and then finally adding these rules to web ACL in the AWS WAF service. After this we would need to associate this ACL with the CloudFront Distribution we want it to work for.<\/p>\n<p>1. Open the AWS WAF console and go to Create new ACL:<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-27742\" src=\"\/blog\/wp-ttn-blog\/uploads\/2015\/10\/Screenshot-from-2015-10-07-224146.png\" alt=\"Screenshot from 2015-10-07 22:41:46\" width=\"1329\" height=\"435\" \/><\/p>\n<p>Just enter a name for your new web ACL. I have used demo for this demo. Just click on next and go to the Create conditions step.<\/p>\n<p>2. In this step, we will create 2 conditions. One for IP and the other for the URl string matching. So, firstly click on Create IP match condition.<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-27743\" src=\"\/blog\/wp-ttn-blog\/uploads\/2015\/10\/Screenshot-from-2015-10-07-224229.png\" alt=\"Screenshot from 2015-10-07 22:42:29\" width=\"568\" height=\"80\" \/><\/p>\n<p>After this a window will pop out as below:<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-27744\" src=\"\/blog\/wp-ttn-blog\/uploads\/2015\/10\/Screenshot-from-2015-10-07-225114.png\" alt=\"Screenshot from 2015-10-07 22:51:14\" width=\"819\" height=\"599\" \/><\/p>\n<p>Give a name to this condition. \u00a0I have named it as WordPress. Also, enter the IP addresses or IP address range \u00a0for which you want to allow access to the wp-login.php\u00a0page. Click on Create. It will return a message on the console like:<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-27745\" src=\"\/blog\/wp-ttn-blog\/uploads\/2015\/10\/Screenshot-from-2015-10-07-225151.png\" alt=\"Screenshot from 2015-10-07 22:51:51\" width=\"582\" height=\"88\" \/><\/p>\n<p>Now, Lets go ahead and create a URI string match condition and we will check for the <strong>wp-login<\/strong>\u00a0string. Click on <strong>Create string match condition.\u00a0<\/strong><\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-27746\" src=\"\/blog\/wp-ttn-blog\/uploads\/2015\/10\/Screenshot-from-2015-10-07-225208.png\" alt=\"Screenshot from 2015-10-07 22:52:08\" width=\"592\" height=\"78\" \/><\/p>\n<p>After clicking it will pop out something like:<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-27759\" src=\"\/blog\/wp-ttn-blog\/uploads\/2015\/10\/Screenshot-from-2015-10-08-002639.png\" alt=\"Screenshot from 2015-10-08 00:26:39\" width=\"793\" height=\"632\" \/><\/p>\n<p>Give the condition a name. Select the options as above and in the<strong> Value to match<\/strong> text enter <strong>wp-login.\u00a0<\/strong>Just click on Create. It will again show a message on the console like:<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-27748\" src=\"\/blog\/wp-ttn-blog\/uploads\/2015\/10\/Screenshot-from-2015-10-07-225352.png\" alt=\"Screenshot from 2015-10-07 22:53:52\" width=\"594\" height=\"88\" \/><\/p>\n<p>Click on Next on the the right bottom corner. Now, that your conditions have been created lets apply them to rules.<\/p>\n<p>3. Time to create rules. We will create 2 rules. One &#8211; whom to allow access to wp-login.php\u00a0and Two &#8211; whom to deny access or block. Click on Create rule.<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-27749\" src=\"\/blog\/wp-ttn-blog\/uploads\/2015\/10\/Screenshot-from-2015-10-07-225502.png\" alt=\"Screenshot from 2015-10-07 22:55:02\" width=\"1349\" height=\"617\" \/><\/p>\n<p>You will get the following windows. Here, name the rule as\u00a0<strong>wordpress-rule-allow<\/strong> to make things clearer and add the following conditions to it for IP as we don&#8217;t want to block any requests from this IP. Also, it will create a CloudWatch metric with the same name. We can also do without the allow rule as by default all IPs will be allowed to access wp-login.php. Just filtering the IPs not in the IP condition in step 2 will also do our job.<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-27750\" src=\"\/blog\/wp-ttn-blog\/uploads\/2015\/10\/Screenshot-from-2015-10-07-225557.png\" alt=\"Screenshot from 2015-10-07 22:55:57\" width=\"792\" height=\"306\" \/><\/p>\n<p>Click on Create. Now, it will redirect you back to the console. We will select allow this rule as below:<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-27752\" src=\"\/blog\/wp-ttn-blog\/uploads\/2015\/10\/Screenshot-from-2015-10-07-225913.png\" alt=\"Screenshot from 2015-10-07 22:59:13\" width=\"654\" height=\"299\" \/><\/p>\n<p>Now, comes the block rule. Click on Create rule again. Name the rule as <strong>wordpress-rule-block-all.\u00a0<\/strong>Now, you need to add the following two conditions:<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-27768\" src=\"\/blog\/wp-ttn-blog\/uploads\/2015\/10\/Screenshot-from-2015-10-08-004548.png\" alt=\"Screenshot from 2015-10-08 00:45:48\" width=\"761\" height=\"304\" \/><\/p>\n<p>and<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-27753\" src=\"\/blog\/wp-ttn-blog\/uploads\/2015\/10\/Screenshot-from-2015-10-07-225945.png\" alt=\"Screenshot from 2015-10-07 22:59:45\" width=\"789\" height=\"349\" \/><\/p>\n<p>Just click on <strong>Create<\/strong>. What the second rule will do is that it will check for the client IP address who is making the request matching string &#8220;<strong>wp-login<\/strong>&#8220;. If the IP is not the one specified in the IP address condition we created in step 2, requests to the URI will be blocked for that client. Below is what the rules for this web ACL will look like:<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-27755\" src=\"\/blog\/wp-ttn-blog\/uploads\/2015\/10\/Screenshot-from-2015-10-07-230040.png\" alt=\"Screenshot from 2015-10-07 23:00:40\" width=\"659\" height=\"486\" \/><\/p>\n<p>Default action is &#8220;Allow all requests that don&#8217;t match any rules&#8221; else it will block all requests from any client IP. It seems quite obvious.<\/p>\n<p>4. Now, is the Review and create step. Review the config and select <strong>confirm and Create<\/strong>:<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-27756\" src=\"\/blog\/wp-ttn-blog\/uploads\/2015\/10\/Screenshot-from-2015-10-07-230106.png\" alt=\"Screenshot from 2015-10-07 23:01:06\" width=\"1351\" height=\"613\" \/><\/p>\n<p>5. The web ACL will be created and listed as below:<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-27760\" src=\"\/blog\/wp-ttn-blog\/uploads\/2015\/10\/Screenshot-from-2015-10-08-002819.png\" alt=\"Screenshot from 2015-10-08 00:28:19\" width=\"1355\" height=\"433\" \/><\/p>\n<p>You can see the details of requests in the requests tab later when traffic starts flowing. You can edit the web ACL with the &#8220;Edit web ACL&#8221; as well.\u00a0<strong>REMEMBER<\/strong>: to change the order &#8211; make block rule as rule number 1. Now,\u00a0you need to add this ACL to CloudFront and test. In the Requests tab you can see the traffic and allowed\/blocked IPs. Also, there will be a link which will take you to the CloudWatch metric.<\/p>\n<p>6. Go to AWS CloudFront and select the Distribution settings for the Distribution you want to apply the ACL for. In my case I will select the WordPress \u00a0one and then click on Edit inside Distribution Settings.<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-27761\" src=\"\/blog\/wp-ttn-blog\/uploads\/2015\/10\/Screenshot-from-2015-10-07-233635.png\" alt=\"Screenshot from 2015-10-07 23:36:35\" width=\"1150\" height=\"305\" \/><\/p>\n<p>Select the ACL you just created. For me its demo. Then click <strong>Yes, edit<\/strong> on the bottom right corner of the screen.<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-27762\" src=\"\/blog\/wp-ttn-blog\/uploads\/2015\/10\/Screenshot-from-2015-10-07-233703.png\" alt=\"Screenshot from 2015-10-07 23:37:03\" width=\"1343\" height=\"263\" \/><\/p>\n<p>Your CloudFront Distribution will show &#8220;In Progress&#8221; under Status. Once it is Deployed we can go ahead and test.<\/p>\n<p>7. So, lets test. I have changed my IP by connecting to a different network.\u00a0Now, opened the wp-login page while connected to this network and got the following error:<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone  wp-image-27776\" src=\"\/blog\/wp-ttn-blog\/uploads\/2015\/10\/Screenshot-from-2015-10-08-122244.png\" alt=\"Screenshot from 2015-10-08 12:22:44\" width=\"635\" height=\"257\" \/><\/p>\n<p>Lets connect to the network I allowed the login page for:<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-27765\" src=\"\/blog\/wp-ttn-blog\/uploads\/2015\/10\/Screenshot-from-2015-10-08-010155.png\" alt=\"Screenshot from 2015-10-08 01:01:55\" width=\"236\" height=\"96\" \/><\/p>\n<p>The login page opened:<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-27766\" src=\"\/blog\/wp-ttn-blog\/uploads\/2015\/10\/Screenshot-from-2015-10-08-010258.png\" alt=\"Screenshot from 2015-10-08 01:02:58\" width=\"1365\" height=\"572\" \/><\/p>\n<p>So, yes, it worked. I am thrilled to use this service. I have already put it to use on UAT and will be proceeding to put it to use on production soon. You can use any string or IP as per requirement. This service indeed looks promising. In my next blog on AWS WAF we will discuss some more use-cases.\u00a0Be tuned in to my blogs and follow me on twitter @ranvijay<\/p>\n","protected":false},"excerpt":{"rendered":"<p>AWS re:Invent has already begun and keeping in mind security of your applications in the cloud, AWS has launched a new service called AWS Web Application Firewall. This service is intended to secure what you share on the world wide web via AWS CloudFront. Making the experience for the user better with more security is [&hellip;]<\/p>\n","protected":false},"author":174,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":80},"categories":[1174,2348,1],"tags":[2270,248,2534,1216,2531,2539,2533,2535,2503,1877],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/27691"}],"collection":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/users\/174"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/comments?post=27691"}],"version-history":[{"count":0,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/27691\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/media?parent=27691"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/categories?post=27691"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/tags?post=27691"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}