apache mod_security not logging certain POST data - brute-force

In Apache access log, I'm seeing far too many entries containing:
POST /wp-login.php HTTP/1.1" 302
indicating successful logins (because status is 302) - but too many too quickly to be genuine (human) logins.
I want to see what's in their POST data, so I have mod_security 2.x installed, together with OWASP 3.1.0.
But I don't see any of these entries being caught by mod_security in modsec_audit.log
I do see other POST transactions in modsec_audit.log, so I think mod_security is working.
I'm wondering if the OWASP Wordpress Exclusion Rules are suppressing it and, if so, how to change those rules in a way which will log the POST data without denying genuine logins?

Typically ModSecurity only adds an audit log for requests that it blocks. This is because those requests are usually the ones you want more info on, to understand why it was blocked. Additionally you would not want your audit log to log every request as they are large entries and the log would get quite large on even a moderately used web server.
In this case the request was not blocked by ModSecurity and passed back the 302 request so I would not expect the request to be in the audit log in typically ModSecurity setups.
As discussed in the comments your SecAuditEngine config setting was set to RelevantOnly which is the typical setting following above logic. So the other POST entries you saw must be for POST requests that were ultimately blocked by ModSecurity. Change the SecAuditEngine value to On to log all transactions and you should see what you want. As I say this will log a lot of data so you probably only want it on for a short time. Alternatively you could write a rule to only turn on the AuditEngine for these transactions to reduce
SecRule REQUEST_URI “#beginswith /wp-login.php” \
“phase:2,id:1234,nolog,ctl:auditEngine=On,pass”
It should also be noted that this will log all POST params including the password (in pwd param). This is considered pretty bad form (even system administrators should not know passwords as they should be stored as one way hashes), so you should sanitise this argument to prevent it being logged into the audit log by setting this rule first:
SecRule ARGS_NAMES "pwd" "phase:5,id:1233,nolog,pass,sanitiseMatched,t:lowercase"

Related

REST API - "GET /user" changes user in database

We have a simple User API including "GET /user" to request user information. When processing the request we store the current datetime as "lastVisit" in our database. As a result we have a GET request updating the user in our database, which seems to be bad practice.
As we don't handle the login process on ourselves, GET /user is the first request to our backend. We cannot use /login to retrieve and store "lastVisit".
Is it bad practice? How to solve the issue?
There's nothing wrong with updating your database when you receive a GET request - the uniform interface of HTTP constrains what the GET method token means, but you have a lot of freedom in how your server implements the handling of that request.
So that much is fine.
"lastVisit", however, may be a problem - which is to say, your interpretation of what it means that somebody asked for a copy of the page ignores various edge cases: a web spider following links to index the documents (think Google), or a smart browser that is trying to reduce latency by downloading a link before the user clicks on it.
You don't know, from the request, whether the fetch was triggered by the client, or by the general purpose agent acting in the client's stead. Similarly, you don't know about any requests for the resource that were intercepted and handled by a cache that had a valid copy of the resource.
It may be that using request handling time as a proxy for last visit is a good enough cost effective approximation of what you want to get by, but you should keep in mind that it is an estimate, not a truth.

In JMeter, is there a way of testing an autocomplete that cancels requests

I'll start this question with 'this is not the same as the previous one'. I can see straightaway that an almost identical question has been asked but the answer is not what I'm after. I will explain...
I need to test an autocomplete search box in a web page. Normally I'd just do a series of requests with the HTML containing one extra letter each time (which is the answer to the other question similar to this). Problem is, that's not how the page behaves. It does submit a new request each time I type a letter, but it's cancelling the previous one instead of letting it continue. Therefore the only one that actually gets to a HTTP 200 response is the very last one.
This blog contains an example of what I'm seeing;
Autocomplete and request cancellation
But about halfway down it shows our test condition;
Client cancellation must also be supported by the search backend. Backend that doesn’t support cancellation continues processing request even after client disconnects.
I need to write a jmeter script that replicates a series of cancelled requests, followed by a single successful request, such that when I look on the backend I either see multiple running queries (bad) or just the last one (good).
Edit: I've also hit a follow up issue, how to identify canceled requests in web server logs. It looks like I'm only seeing single requests if they are allowed to complete (IE if I pause between letters). If the requests are cancelled, they don't get logged in the log. So, how do I verify that they happened at all? If we import the logs into a visualization tool, are we going to be missing the 'canceled' requests.
"Request cancellation" is nothing more than closing the connection from the client side
The easiest way of implementing it in JMeter is setting the response timeout, the setting lives under "Advanced" tab of the HTTP Request sampler or even better HTTP Request Defaults)
Just set this timeout to be lower than the threshold configured in your frontend and JMeter will close the connection making the backend "think" that the autocomplete request has been aborted because the user is still typing.
Demo:

Sending passwords over HTTPS: GET vs POST

I'm creating a headless API that's going to drive an Angular front end. I'm having a bit of trouble figuring out how I should handle user authentication though.
Obviously the API should run over SSL, but the question that's coming up is how should I send the request that contains the user's password: over GET or POST. It's a RESTFUL API, so what I'm doing is retrieving information meaning it should get a GET request. But sending the password over get means it's part of the URI, right? I know even a GET request is encrypted over HTTPS, but is that still the correct way? Or is this a case to break from RESTFUL and have the data in the body or something (can a GET request have data in the body?).
If you pass the credentials in a request header, you will be fine with either a GET or POST request. You have the option of using the established Authorization header with your choice of authentication scheme, or you can create custom headers that are specific to your API.
When using header fields as a means of communicating credentials, you do not need to fear the credentials being written to the access log as headers are not included in that log. Using header fields also conforms to REST standards, and should actually be utilized to communicate any meta-data relevant to the resource request/response. Such meta-data can include, but is not limited to, information like: collection size, pagination details, or locations of related resources.
In summary, always use header fields as a means of authentication/authorization.
mostly GET request will bind data in URL itself... so it is more redable than POST..
so if it is GET, there is a possibility to alive HISTORY LOG
Using ?user=myUsername&pass=MyPasswort is exactly like using a GET based form and, while the Referer issue can be contained, the problems regarding logs and history remain.
Sending any kind of sensitive data over GET is dangerous, even if it is HTTPS. These data might end up in log files at the server and will be included in the Referer header in links to or includes from other sides. They will also be saved in the history of the browser so an attacker might try to guess and verify the original contents of the link with an attack against the history.
You could send a data body with a get request too but this isn't supported by all libraries I guess.
Better to use POST or request headers. Look at other APIs and how they are handling it.
But you could still use GET with basic authentication like here: http://restcookbook.com/Basics/loggingin/

How can we detect which users have performed which operations in GCS (Google Cloud Storage)?

Using access logging, as detailed here: https://cloud.google.com/storage/docs/access-logs, we can download and analyze usage patterns for our data. However, looking at the actual data, I noticed that there is no data relating which user (or service-account) performed the operation. The closest seeming attribute in the usage logs as described here: https://cloud.google.com/storage/docs/access-logs#format is the cs_user_agent attribute. However, this attribute seems to describe more about the tool performing the access (i.e., gsutil or gcloud) rather than the user.
Is it possible to obtain information that relates the activity to a user/service-account? Perhaps using the s_request_id attribute?
Is there a technical reason this is missing? Or is it intended as a privacy-preserving mechanism?
You can read about the access log schema in our docs. cs_user_agent tells you what kind of program made the request, while s_request_id is a unique id for the request. The closest thing to what you need would be c_ip, which is the IP address of the machine making the request. You could possibly tie those to users. If this doesn't suffice, you could have your clients make requests only through some code you yourself have written which will log - in parallel to sending the request - the URL, method, any headers / metadata desired, and the user / account making the request.

When should I use GET or POST method? What's the difference between them?

What's the difference when using GET or POST method? Which one is more secure? What are (dis)advantages of each of them?
(similar question)
It's not a matter of security. The HTTP protocol defines GET-type requests as being idempotent, while POSTs may have side effects. In plain English, that means that GET is used for viewing something, without changing it, while POST is used for changing something. For example, a search page should use GET, while a form that changes your password should use POST.
Also, note that PHP confuses the concepts a bit. A POST request gets input from the query string and through the request body. A GET request just gets input from the query string. So a POST request is a superset of a GET request; you can use $_GET in a POST request, and it may even make sense to have parameters with the same name in $_POST and $_GET that mean different things.
For example, let's say you have a form for editing an article. The article-id may be in the query string (and, so, available through $_GET['id']), but let's say that you want to change the article-id. The new id may then be present in the request body ($_POST['id']). OK, perhaps that's not the best example, but I hope it illustrates the difference between the two.
When the user enters information in a form and clicks Submit , there are two ways the information can be sent from the browser to the server: in the URL, or within the body of the HTTP request.
The GET method, which was used in the example earlier, appends name/value pairs to the URL. Unfortunately, the length of a URL is limited, so this method only works if there are only a few parameters. The URL could be truncated if the form uses a large number of parameters, or if the parameters contain large amounts of data. Also, parameters passed on the URL are visible in the address field of the browser not the best place for a password to be displayed.
The alternative to the GET method is the POST method. This method packages the name/value pairs inside the body of the HTTP request, which makes for a cleaner URL and imposes no size limitations on the forms output. It is also more secure.
The best answer was the first one.
You are using:
GET when you want to retrieve data (GET DATA).
POST when you want to send data (POST DATA).
There are two common "security" implications to using GET. Since data appears in the URL string its possible someone looking over your shoulder at Address Bar/URL may be able to view something they should not be privy to such as a session cookie that could potentially be used to hijack your session. Keep in mind everyone has camera phones.
The other security implication of GET has to do with GET variables being logged to most web servers access log as part of the requesting URL. Depending on the situation, regulatory climate and general sensitivity of the data this can potentially raise concerns.
Some clients/firewalls/IDS systems may frown upon GET requests containing an excessive amount of data and may therefore provide unreliable results.
POST supports advanced functionality such as support for multi-part binary input used for file uploads to web servers.
POST requires a content-length header which may increase the complexity of an application specific client implementation as the size of data submitted must be known in advance preventing a client request from being formed in an exclusively single-pass incremental mode. Perhaps a minor issue for those choosing to abuse HTTP by using it as an RPC (Remote Procedure Call) transport.
Others have already done a good job in covering the semantic differences and the "when" part of this question.
I use GET when I'm retrieving information from a URL and POST when I'm sending information to a URL.
You should use POST if there is a lot of data, or sort-of sensitive information (really sensitive stuff needs a secure connection as well).
Use GET if you want people to be able to bookmark your page, because all the data is included with the bookmark.
Just be careful of people hitting REFRESH with the GET method, because the data will be sent again every time without warning the user (POST sometimes warns the user about resending data).
This W3C document explains the use of HTTP GET and POST.
I think it is an authoritative source.
The summary is (section 1.3 of the document):
Use GET if the interaction is more like a question (i.e., it is a safe operation such as a query, read operation, or lookup).
Use POST if:
The interaction is more like an order, or
The interaction changes the state of the resource in a way that the
user would perceive (e.g., a subscription to a service), or
The user be held accountable for the results of the interaction.
Get and Post methods have nothing to do with the server technology you are using, it works the same in php, asp.net or ruby. GET and POST are part of HTTP protocol.
As mark noted, POST is more secure. POST forms are also not cached by the browser.
POST is also used to transfer large quantities of data.
The reason for using POST when making changes to data:
A web accelerator like Google Web Accelerator will click all (GET) links on a page and cache them. This is very bad if the links make changes to things.
A browser caches GET requests so even if the user clicks the link it may not send a request to the server to execute the change.
To protect your site/application against CSRF you must use POST. To completely secure your app you must then also generate a unique identifier on the server and send that along in the request.
Also, don't put sensitive information in the query string (only option with GET) because it shows up in the address bar, bookmarks and server logs.
Hopefully this explains why people say POST is 'secure'. If you are transmitting sensitive data you must use SSL.
GET and POST are HTTP methods which can achieve similar goals
GET is basically for just getting (retrieving) data, A GET should not have a body, so aside from cookies, the only place to pass info is in the URL and URLs are limited in length , GET is less secure compared to POST because data sent is part of the URL
Never use GET when sending passwords, credit card or other sensitive information!, Data is visible to everyone in the URL, Can be cached data .
GET is harmless when we are reloading or calling back button, it will be book marked, parameters remain in browser history, only ASCII characters allowed.
POST may involve anything, like storing or updating data, or ordering a product, or sending e-mail. POST method has a body.
POST method is secured for passing sensitive and confidential information to server it will not visible in query parameters in URL and parameters are not saved in browser history. There are no restrictions on data length. When we are reloading the browser should alert the user that the data are about to be re-submitted. POST method cannot be bookmarked
All or perhaps most of the answers in this question and in other questions on SO relating to GET and POST are misguided. They are technically correct and they explain the standards correctly, but in practice it's completely different. Let me explain:
GET is considered to be idempotent, but it doesn't have to be. You can pass parameters in a GET to a server script that makes permanent changes to data. Conversely, POST is considered not idempotent, but you can POST to a script that makes no changes to the server. So this is a false dichotomy and irrelevant in practice.
Further, it is a mistake to say that GET cannot harm anything if reloaded - of course it can if the script it calls and the parameters it passes are making a permanent change (like deleting data for example). And so can POST!
Now, we know that POST is (by far) more secure because it doesn't expose the parameters being passed, and it is not cached. Plus you can pass more data with POST and it also gives you a clean, non-confusing URL. And it does everything that GET can do. So it is simply better. At least in production.
So in practice, when should you use GET vs. POST? I use GET during development so I can see and tweak the parameters I am passing. I use it to quickly try different values (to test conditions for example) or even different parameters. I can do that without having to build a form and having to modify it if I need a different set of parameters. I simply edit the URL in my browser as needed.
Once development is done, or at least stable, I switch everything to POST.
If you can think of any technical reason that this is incorrect, I would be very happy to learn.
GET method is use to send the less sensitive data whereas POST method is use to send the sensitive data.
Using the POST method you can send large amount of data compared to GET method.
Data sent by GET method is visible in browser header bar whereas data send by POST method is invisible.
Use GET method if you want to retrieve the resources from URL. You could always see the last page if you hit the back button of your browser, and it could be bookmarked, so it is not as secure as POST method.
Use POST method if you want to 'submit' something to the URL. For example you want to create a google account and you may need to fill in all the detailed information, then you hit 'submit' button (POST method is called here), once you submit successfully, and try to hit back button of your browser, you will get error or a new blank form, instead of last page with filled form.
I find this list pretty helpful
GET
GET requests can be cached
GET requests remain in the browser history
GET requests can be bookmarked
GET requests should (almost) never be used when dealing with sensitive data
GET requests have length restrictions
GET requests should be used only to retrieve data
POST
POST requests are not cached
POST requests do not remain in the browser history
POST requests cannot be bookmarked
POST requests have no restrictions on data length
The GET method:
It is used only for sending 256 character date
When using this method, the information can be seen on the browser
It is the default method used by forms
It is not so secured.
The POST method:
It is used for sending unlimited data.
With this method, the information cannot be seen on the browser
You can explicitly mention the POST method
It is more secured than the GET method
It provides more advanced features