Dynamically block IP addresses that have reached a honeypot - java

Happy new 2020.
I have a question regarding the functionality of blocking IP addresses that have reached a honeypot system.
I have a real system A and a honeypot B.
The honeypot (B) is a completely different application from A.
Both systems (A and B) are Spring Boot applications.
However, what I want to achieve is when, let's say, a hacker reaches the honeypot B, its IP address to get dynamically blacklisted in the real application A but also the hacker should be able to keep operating with the honeypot B.
Update: After the IP address is blocked for the real system, the hacker should still be able to interact with the honeypot.
Describing the following scenario:
A hacker opens the real system and by hidden hints inside the HTML source code of the application, they navigate to the honeypot system.
The honeypot system itself contains low hanging fruits that seem open to attacks - such as fields where you can execute SQL injections.
When the hacker makes attempts to perform SQL injections - the honeypot is collecting all the information - what the intruder is doing.
And once the intruder hits the honeypot - their IP address gets blocked for the real application but remains active for the honeypot.
So the hacker doesn't know that they were blocked for the real application and they keep performing SQL injections to the honeypot.
The first solution that came up to my mind is to make an http call from the honeypot to the real system - providing the IP address of the intruder and blacklisting it with internal mechanism from the real system itself. /however, I am not sure if it is the best approach here/
Update: The internal mechanism of the real system is nothing else but an internal cache holding IP addresses that should not interact with the real system itself. When there is an incoming request the IP address of the client is checked and those requests coming from a blacklisted IPs are not served.
Another solution is to use a reverse proxy but I was not able to find a suitable way of doing it.
I would appreciate your help in finding an easy solution or providing me an idea for a different approach in this situation.
Thank you in advance.

Related

How to stop hack/DOS attack on web API

My website has been experiencing a denial of service/hack attack for the last week. The attack is hitting our web API with randomly generated invalid API keys in a loop.
I'm not sure if they are trying to guess a key (mathematically impossible as 64bit keys) or trying to DOS attack the server. The attack is distributed, so I cannot ban all of the IP address, as it occurs from hundreds of clients.
My guess is that it is an Android app by the IPs, so someone has some malware in an Android app, and use all the installs to attack my server.
Server is Tomcat/Java, currently the web API just responds 400 to invalid keys, and caches IPs that have made several invalid key attempts, but still needs to do some processing for each bad request.
Any suggestions how to stop the attack? Is there any way to identify the Android app making the request from the HTTP header?
Preventing Brute-Force Attacks:
There is a vast array of tools and strategies available to help you do this, and which to use depends entirely on your server implementation and requirements.
Without using a firewall, IDS, or other network-control tools, you can't really stop a DDOS from, well, denying service to your application. You can, however, modify your application to make a brute-force attack significantly more difficult.
The standard way to do this is by implementing a lockout or a progressive delay. A lockout prevents an IP from making a login request for X minutes if they fail to log in N times. A progressive delay adds a longer and longer delay to processing each bad login request.
If you're using Tomcat's authentication system (i.e. you have a <login-constraint> element in your webapp configuration), you should use the Tomcat LockoutRealm, which lets you easily put IP addresses on a lockout once they make a number of bad requests.
If you are not using Tomcat's authentication system, then you would have to post more information about what you are using to get more specific information.
Finally, you could simply increase the length of your API keys. 64 bits seems like an insurmountably huge keyspace to search, but its underweight by modern standards. A number of factors could contribute to making it far less secure than you expect:
A botnet (or other large network) could make tens of thousands of attempts per second, if you have no protections in place.
Depending on how you're generating your keys and gathering entropy,
your de facto keyspace might be much smaller.
As your number of valid keys increases, the number of keys that need
to be attempted to find a valid one (at least in theory) drops
sharply.
Upping the API key length to 128 (or 256, or 512) won't cost much, and you'll tremendously increase the search space (and thus, the difficulty) of any brute force attack.
Mitigating DDOS attacks:
To mitigate DDOS attacks, however, you need to do a bit more legwork. DDOS attacks are hard to defend against, and its especially hard if you don't control the network your server is on.
That being said, there are a few server-side things you can do:
Installing and configuring a web-application firewall, like mod_security, to reject incoming connections that violate rules that you define.
Setting up an IDS system, like Snort, to detect when a DDOS attack is occurring and take the first steps to mitigate it
See #Martin Muller's post for another excellent option, fail2ban
Creating your own Tomcat Valve, as described here, to reject incoming requests by their User-Agents (or any other criterion) as a last line of defense.
In the end, however, there is only so much you can do to stop a DDOS attack for free. A server has only so much memory, so many CPU cycles, and so much network bandwidth; with enough incoming connections, even the most efficient firewall won't keep you from going down. You'll be better able to weather DDOS attacks if you invest in a higher-bandwidth internet connection and more servers, or if you deploy your application on Amazon Web Services, or if you bought one of many consumer and enterprise DDOS mitigation products (#SDude has some excellent recommendations in his post). None of those options are cheap, quick, or easy, but they're what's available.
Bottom Line:
If you rely on your application code to mitigate a DDOS, you've already lost
If it's big enough you just can't stop it alone. You can do all the optimisation you want at the app level, but you'll still go down. In addition to app-level security for prevention (as in FSQ's answer) you should use proven solutions leaving the heavy lifting to professionals (if you are serious about your business). My advise is:
Sign-up for CloudFlare or Incapsula. This is day to day for them.
Consider using AWS API gateway as the second stage for your API requests. You'll enjoy filtering, throttling, security,auto-scaling and HA for your API at Amazon scale. Then you can forward the valid requests to your machines (in or outside amazon)
Internet --> CloudFlare/Incapsula --> AWS API Gateway --> Your API Server
0,02
PS: I think this question belongs to Sec
Here are a couple ideas. There are a number of strategies in addition, but this should get you started. Also realize that amazon gets ddos'd on a frequent basis and their systems tend to have a few heuristics that harden them (and therefore you) from these attacks, particularly if you are using Elastic load balancing, which you should be using anyway.
Use a CDN -- they often have ways of detecting and defending against ddos. Akamai, mastery, or amazons own cloud front.
Use iptables to blacklist offensive ips. The more tooling you have around this, the faster you can blok/unblock
Use throttling mechanisms to prevent large numbers of requests
Automatically deny requests that are very large (say greater than 1-2mb; unless you have a photo uploading service or similar) before they get to your application
Prevent cascading failures by placing a limit on the total number of connections to other components in your system; for example, dont let your database server become overloaded by opening a thousand connections to it.
The best way is to prevent the access to your services entirely for those IP addresses who have failed let's say 3 times. This will take most of the load from your server as the attacker gets blocked before Tomcat even has to start a thread for this user.
One of the best tools to achieve this is called fail2ban (http://www.fail2ban.org). It is provided as a package in all major linux distributions.
What you have to do is basically log the failed attempts into a file and create a custom filter for fail2ban. Darryn van Tonder has a nice example on how to write your own filter on his blog: https://darrynvt.wordpress.com/tag/custom-fail2ban-filters/
If D-DOS is attack is severe, application level checks does not work at all. Entire bandwidth will be consumed by D-DOS clients and your application level checks won't be triggered. Practically your web service does not run at all.
If you have to keep your application safe from severe D-DOS attacks, you do not have any other option except relying on third party tools by paying money. One of the Clean pipe provider ( who sends only good traffic) tools I can bank on from my past experience : Neustar
If D-DOS attack is mild in your website, you can implement application level checks. For example, below configuration will restrict maximum number of connections from single IP as quoted in Restrict calls from single IP
<Directory /home/*/public_html> -- You can change this location
MaxConnPerIP 1
OnlyIPLimit audio/mpeg video
</Directory>
For more insight into D-DOS attack, visit Wiki link. It provides list of preventive & responsive tools which includes : Firewalls, Switches, Routers, IPs Based Prevention, D-DOS based defences
and finally
Clean pipes (All traffic is passed through a "cleaning center" or a "scrubbing center" via various methods such as proxies, tunnels or even direct circuits, which separates "bad" traffic (DDoS and also other common internet attacks) and only sends good traffic beyond to the server)
You can find 12 distributors of Clean pipes.
For a targeted and highly distributed DOS attack the only practical solution (other than providing the capacity to soak it up) is to profile the attack, identify the 'tells' and route that traffic to a low resource handler.
Your question has some tells - that the request is invalid, but presumably there is too much cost in determining that. That the requests originate from a specific group of networks and that presumably they occur in bursts.
In your comments you've told us at least one other tell - the user agent is null.
Without adding any additional components, you could start by tarpitting the connection - if a request matching the profile comes in, go ahead and validate the key, but then have your code sleep for a second or two. This will reduce the rate of requests from these clients at a small cost.
Another solution would be to use log failures matching the tell and use fail2ban to reconfigure your firewall in real time to drop all packets from the source address for a while.
No, its unlikely you will be able to identify the app without getting hold of an affected device.

Making multiple HTTP requests from Java Code using Amazon Spot Instances(or otherwise)

I need to making multiple(more than 100) HTTP requests to Google Scholar, from a Java code to collect data. However, the site prevents this after around 20 requests or so, and produces a captcha. I have heard of 'Amazon Spot Instances' letting the IP address of requesting system change periodically and thus avoid the occurence of captcha, by ensuring that the requests do not come from a single IP. Can anyone help me through this, with further details?(an alternate method other than Amazon EC2 spot instances is also fine)
Changing IP addresses periodically aren't a unique feature of Spot Instances within the Amazon Environment (it's also available on the On demand and Reserved Instances), the Amazon CLI will allow you to assign, attach, deattach and release IP addresses as well.
Amazon's SDK will allow you to call the creation of a Spot Instance and attach an IP address, for the latter http://docs.aws.amazon.com/AWSEC2/latest/APIReference/ApiReference-query-RunInstances.html is a good starting point. It's well supported across a wide range of languages.
For Java I would look at http://aws.amazon.com/sdkforjava/ and get your feet wet, it's a powerful API!
Depending on how much experience you have with the AWS environment there is a bit of extra stuff to keep in mind, especially with Spot Instances. Spots can terminate at any time (literally mid-query) so you should build your app to be stateless, a good solution is to send the results into an S3 bucket. It has the added benefit of being able to deploy multiple instances at one time and have a single endpoint of data collection.

How do I distinguish if two IPs belong to the same computer?

We have a master program and agents (both) on the customer side on different computers. The network configuration can be any type (we don't know). The agents connect to the master program and currently we only can get the IP and computer name as information. How do I distinguish if two IPs belong to the same computer?
Computers may have more than one ethernet cards.
Thanks.
There is no way to tell just by looking at the IP addresses.
Some computers have unique identifiers, but you would need JNI to access them and your code would be very platform-specific. It might be a better idea to generate a GUID and write it to a file in a temp folder on the machine. Then, all instances of the software that run on that machine would read the same GUID and can provide this data to the server when a connection is made.
You can modify the agents to send the MAC(s) of the machines in question. Beyond that, you can't really determine if they are the same.
You say you're getting the computer name - can't you de-duplicate based on that value?
From across a network, and given only an IP address, you can't tell. The way NAT works, and the fact that today's laptops and wireless devices often hop from network to network throughout the day, all you see is the public-facing IP address of that machine, which is very likely shared across a group, or entire organization of machines.
Unless you modify the agent application to also include a unique identifier (such as MAC address - which even then only tells you it's a unique NIC, not necessarily a unique machine if machines have multiple NICs), you're out of luck. You can't determine uniqueness from the IP address alone.
Not sure what your use case is, but if it's for banning/tracing actions within the application, then it's better to require some kind of unique identifier for the machine to access the system (such as a username) so you know that you can ban/trace a single instance of the app, or a single user logged into any instance of the app, rather than trying to solve that kind of a problem through IP addresses.
You could create a service in its machine that will expose a unique identifier. You could then call this service using different IPs as the host name and compare the values.

How do I speed up Java Google App Engine deployment?

I'm developing a test app with GWT+Java-AppEngine and the deploys are so heavy and slow.
I read about minimize permutations or parallel compilation of GWT, but my internet connection is not so good and I think that I'm uploading heavy files to App Engine Server.
How can I optimize this? Can I check where is the bottleneck?
The reason that I need several deployments is because I'm using Google API's through OAuth and I can't set localhost as a callback (I do?).
I am not entirely sure about your scenario, so I will try to guess your intentions.
For development purposes, you really should be working on the local server, it comes with all the API's and stubs for things like user login and what not. That is instantaneous. Once you are happy with your local app and it is time to upload, then if AppEngine overlord decides to take time due to AppSize/Slow Connection/Service outage/random act of diety, there is little one can do.
Considering that one doesn't deploy every hour, I think your time would be better spent on the app, instead of tuning the upload time.
I am assuming you are already following http://code.google.com/appengine/docs/java/gettingstarted/uploading.html
I personally have dabbled with appengine but the python version, and it may take a few mins but once upload is complete, you are good to go.
maybe you could get your local machine a dyndns hostname and make it accessible from the internet ? –
I think what Bastian meant was as follows (assuming Dev server can actually serve domains - i am not sure about that)
Have your domain host (example.com) maintain an 'A' record pointing to your development machine IP address [hence when you do example.com, your dev machine responds as the server]
This means if you setup DNS records to point to ghs.google.com or whatever, you will have to change them (DNS records take a while to propagate depending on host)
Once you are happy, and you want to test on google, you still have to 'upload' before you can try it on appspot.com and ofcourse change DNS entries again so example.com works off google servers.
Too much work in my opinion. Better to use dev server in local machine.
Have a break while you are uploading. Have a KitKat to kill time :)

System call to get serial number of machine in Linux

I know this is a long shot but is there any way of getting the serial number or a uniquely identifying piece of information on Linux?
If so, how can this be programmed into a Java program?
In context, I need to build a license validator that locks down to one machine. If you have any other suggestions they are welcome.
Here is an excerpt of a blog post by Lennart Poettering about IDs in general. It is about unique IDs, not necessarily about unique IDs in relation with security:
/sys/class/dmi/id/product_uuid: The main board product UUID, as set by the
board manufacturer and encoded in the
BIOS DMI information. It may be used
to identify a mainboard and only the
mainboard. It changes when the user
replaces the main board. Also, often
enough BIOS manufacturers write bogus
serials into it. In addition, it is
x86-specific. Access for unprivileged
users is forbidden. Hence it is of
little general use.
CPUID/EAX=3 CPU serial number: A CPU UUID, as set by the CPU manufacturer
and encoded on the CPU chip. It may be
used to identify a CPU and only a CPU.
It changes when the user replaces the
CPU. Also, most modern CPUs don't
implement this feature anymore, and
older computers tend to disable this
option by default, controllable via a
BIOS Setup option. In addition, it is
x86-specific. Hence this too is of
little general use.
So /sys/class/dmi/id/product_uuid seems like a good candidate for your validation daemon but means that your validation code needs to be run as a privileged user. The full blog post is really a valuable read!
Unless you can actually get a hardware dongle to the users machine, you cannot devise a copy protection setting that cannot be circumvented.
If you just want to tell the user that "hey, you are already running this license on another machine on your network, get another license", then a good way is to do network broadcasts so they can find one another. The simplest way to do reliably is probably using Zeroconf with the jmdns library.
If you want to be certain that the program is only being run at one place with a given serial number, the only way to do so with generic PC's is to have the program call a central mothership over the internet while being run and register where it is being used. The mothership then returns a snippet containing important code needing it to be run. You could most likely implement this using Java WebStart.
I use the MAC-Adress as an unique id.
InetAddress address = InetAddress.getByName("192.168.1.1");
NetworkInterface ni = NetworkInterface.getByInetAddress(address);
byte[] mac = ni.getHardwareAddress();
Mac address can be changed. Check this. Also, Mac-Address is tied to an interface (Ethernet/Wireless/HPNA etc). So a smart user can easily tweak this up. There is a similar problem discussed on stackoverflow. Check this.
The MAC address is not a good choice, as it can be changed on some systems. If you want to stay in native Java then logical system parameters such as the machine ID and user log-in account are your only options. For some cases machine name is adequately secure as there can't be two machines on the one network with the same name.

Categories

Resources