One place for hosting & domains

      Prevention

      What is SQL Injection? Attack Examples & Prevention Tips


      Security is an important issue for all web applications and databases, especially those using the Structured Query Language (SQL). Although criminals most frequently focus on high-value targets, even small online applications can be victimized. When important information is stolen or an application is compromised, the financial, logistical, and reputation costs can be severe. Criminals and hackers frequently use a technique named SQL Injection (SQLi) to gain unauthorized entry to a remote database. This guide describes a SQL injection attack and explains how it is used. It also discusses how to detect SQLi vulnerabilities and how to defend against them.

      What is a SQL Injection Attack?

      A SQL injection attack is an incursion that alters SQL Queries with the objective of tampering with a SQL database. It is most often used to attack web applications, but can be used on other systems that host a database. This attack uses a code injection strategy to send malicious SQL queries to the database. Often, these commands are based on legitimate information from the website. SQLi attacks are usually launched to achieve the following:

      • View private or restricted information contained in a database, including sensitive personal or financial information.
      • Add, delete, or edit information stored in a database. This could include either application data or metadata including the schema or table definitions.
      • Gain administrative access to a database, possibly creating a back door for long-term future use.
      • Compromise the server by using the database as an access point.
      • Launch a denial-of-service attack or incapacitate the database’s underlying infrastructure.

      Some SQL injection attacks are designed to remain undetected for a long period of time. In this case, the objective is usually to maintain ongoing access and eavesdrop on the database in the future. In some other cases, the hackers want to immediately extract as much information as they can, such as credit card numbers. Their intention is to resell the information or use it for criminal purposes. While the intruders would prefer to go undetected, they do not expect to access the system again. Finally, other attackers only want to inflict damage and take the application offline. They have no need for secrecy.

      No matter the purpose of the attack, it can inflict tremendous consequences upon the victimized organization. A SQL injection attack can cause several of the following negative consequences:

      • Lead to the loss of corporate secrets, confidential information, and other sensitive data.
      • Expose sensitive customer information, including credit/financial information, personal details, or private correspondence.
      • Incur direct financial loss due to theft and claims for compensation from users or third parties.
      • Generate negative publicity and a public relations crisis.
      • Take a web application or other component of a site offline or render it inoperable.
      • Hurt customer confidence and make it difficult for the organization to attract new clients and retain existing ones.

      Any organization can be targeted, even personal websites and small forums. According to the
      Wikipedia SQL Injection page
      , the average web application is attacked around four times per month. New exploits are always being developed, and it is difficult to design a truly bulletproof site. However, many hackers target sites indiscriminately using brute force. A database that has been secured through a few basic techniques is much more secure and difficult to compromise.

      Note

      This guide is intended as an introduction to SQL injections and does not cover every possible type of attack.
      Web security
      is a very complex field, and many possible attacks demand careful consideration. You should consult with web security professionals before launching any application that stores private personal or financial information.

      What is a SQL Query?

      SQL is a simple domain-specific programming language used to communicate with a Relational DataBase Management System (RDBMS). Database developers use SQL commands to send queries from database clients to the RDBMS. These queries contain commands to insert, update, delete, or read data. Queries are also used to administer the database and update the schema, including table definitions.

      During normal operations, web applications incorporate user data into SQL queries and forward them to the RDBMS. For instance, a query might add a new forum user or retrieve information about a category of products. Unfortunately, bad actors can manipulate these queries and cause the application to behave in an unintended or insecure manner.

      Types of SQL Injection Attacks

      Most SQL injection attacks fall into one of three categories. They vary in how direct they are and how difficult they are to execute. The three main categories are:

      • Classic (In-Band)
      • Blind
      • Out-of-Band

      Classic SQL Injection

      The classic method attack, also known as an in-band attack, sends altered commands to the database using the regular communication channel. It uses information learned from the response to gain information about the structure or contents of the database. This type of attack is easy to execute and can quickly yield results. It requires less skill, imagination, and programming ability than the other attack types. Many attackers use these techniques in an automated fashion on random sites, trying to find poorly-designed web applications.

      For this injection attack, the user adds information to the URL or the fields on a web form in an attempt to trick the database. The assailant hopes the database might transmit sensitive information or provide clues about its internal structure. For example, they might try to trick the database into displaying not only the public entries, but every row in the table.

      There are several variations on this method. Error-based SQLi attacks are designed to get the database to transmit error messages that reveal information about its internal schema. Union-based attacks use the SQL UNION command to append an additional query to the command. This can cause a database to display extra data. The information gained through a SQL injection attack is frequently used to craft subsequent attacks. A classic attack often takes an iterative approach. The attacking queries are refined until the database is fully compromised.

      Classic SQL injection attacks are often more successful with older applications that are built with PHP or ASP. This is due to security gaps and the lack of more advanced programming tools.

      Blind SQL Injection

      This approach is often used when classic attack methods do not work. In a blind attack, the attacker sends a manipulated query to the database and analyzes the response. The attack is considered “blind” because the attacker does not receive any direct information from the server. The attacker can analyze details, such as how long it takes the server to reply, to learn more about the database.

      The two most common types of blind SQL injection attacks are the Boolean Attack and the Time-based Attack. In a Boolean attack, the attacker expects a different response if the query is True than if it is False. For example, the results might get updated if the query is valid, but stay the same otherwise. The attacker might also be able to deduce some information based on whether they receive an error page or not.

      A time-based attack extracts information from the database based on how long it takes the server to respond. The attacker can selectively add delays to the query and calculate the response time. They can also construct commands that take longer to process in some situations compared to others. For example, a time-based attack might initiate a complex calculation for each column in a table. Tables that have more columns take longer to process the query. However, if the processing time exceeds the connection timeout value, the response becomes useless.

      Although this type of attack takes more time, forethought, and consideration, it can eventually uncover plenty of information about the database. Therefore, it can be as damaging as a classic attack, even though it is less common.

      Out-of-Band Injection

      Out-of-band attacks are the most complicated and the most difficult to construct. They are less common than the other two types. They do not rely on the behavior of the database. Instead, they receive information through a different channel other than the original web application. For example, they can trigger the database to transmit DNS or HTTP requests to a server under the attacker’s control. This is often referred to as a compounded SQL attack.

      Some out-of-band attacks might only work if certain features are enabled on the database. For example, the UTL_HTTP package must be configured on an Oracle database before it can forward any HTTP requests.

      SQL Injection Attack Examples

      Many SQL injection attacks take advantage of SQL keywords and syntax. The object is to use valid queries to get the database to operate in an undesirable manner. The particular details of these dangerous commands vary between the various RDBMS applications. However, most attacks use a few basic methods. The following SQL injection examples demonstrate some commonly used approaches.

      Note

      Although the core SQL syntax is standardized, the implementation varies between RDBMS applications. The different database applications also offer unique enhancements and features. These might be more or less secure. Some of the following attacks might work on some databases and not others. Consult the database documentation for more details.

      In SQL, the -- symbol means the rest of the command is a comment. If a user adds a comment indicator to a field it might be incorporated into a dynamic command. This could cause other fields to be ignored.

      In the following SQL injection example, a web form might have a field for the username and another for the user password. The backend of the application validates the login using the following command:

      SELECT * FROM forumusers WHERE username="username" AND password = 'password'
      

      If an unprotected dynamic query, a hostile agent could enter the name of another user followed by the sequence '--. The quotation mark closes the field while the -- characters convert the rest of the command into a comment. As a result, the web application sends the following command to the database.

      SELECT * FROM forumusers WHERE username="otheruser"--' AND password = 'password'
      

      When the comment is stripped out, the command evaluates to the following.

      SELECT * FROM forumusers WHERE username="otheruser"
      

      If no other validation or safeguards are in place, the application might permit the attacker to log in as the other user.

      Using the UNION Command

      The UNION command is very powerful. It retrieves the intersection of two distinct queries. This can be used to extract additional results from the database, combining an “innocent” query with one requesting sensitive information.

      As an example, the original command might be constructed in the following manner.

      SELECT name, price, description FROM products where category ='categoryname'
      

      The attacker might then add the phrase 'UNION ALL SELECT username, password FROM forumusers -- to the end of a product name. This results in the following query.

      SELECT name, price, description FROM products where category ='categoryname' UNION ALL SELECT username, password FROM forumusers
      

      This might result in the login details of all the forum users being dumped onto the attacker’s screen along with the product information.

      Using Stacked Queries

      In SQL, the ; symbol is used to separate two queries, which are executed together in the same transaction. This is known as a stacked query. This is often a useful feature, but it can cause problems for web applications. If an attacker adds a ' character to terminate the original field, they can then add ;, followed by a malevolent command.

      For example, the application logic constructs the following command from a user-specified category.

      SELECT name, price, description FROM products where category ='categoryname'
      

      Then the user might end their product selection with '; DROP TABLE forumusers --. This causes the command to execute the following commands:

      SELECT name, price, description FROM products where category ='categoryname' ; DROP TABLE forumusers
      

      If not detected elsewhere in the application, this command would delete all the user accounts, rendering the forum nearly worthless.

      Using the OR Keyword

      Attackers can also use the SQL OR keyword to extract additional information. The phrase +OR+1=1 always evaluates to True, so an attacker can use it to access the entire table. It could also be used on the forum login page, which ordinarily generates the following query.

      SELECT * FROM forumusers WHERE username="username" AND password = 'password'
      

      The phrase +OR+1=1 could be inserted, radically altering the command.

      SELECT * FROM forumusers WHERE username="username" OR 1=1 --' AND password = 'password'
      

      The expression 1=1 evaluates to True. So does username="username" OR True. This results in an unqualified SELECT * statement without any conditionals, which displays the login information for every user.

      SELECT * FROM forumusers
      

      Other Techniques

      Attackers typically iterate through several techniques until they find something that works. They can potentially use a long list of keywords along with numerical and string manipulators. For instance, they can use the SQL CONCAT keyword. They can also use the CHAR keyword to transmit individual characters as their hexadecimal equivalents. This could bypass validation techniques that are scanning for certain invalid characters. Some commands provide information about the database and its schema, although they differ between the various RDBMS applications.

      Several websites provide detailed “cheat sheets” about the most common attacks. One example is
      Netsparker’s SQL Injection Cheat Sheet
      . It compares and contrasts the various RDBMS systems, so it can be used as a MySQL injection cheat sheet, for example. The Open Web Application Security Project (OWASP) also provides a very detailed and useful
      SQL Injection Prevention Cheat Sheet
      .

      How to Detect a SQL Injection Vulnerability

      To ensure a web application is not vulnerable to common web attacks, consider security issues at every stage of the development process.

      • During the design specification process, document how to handle security threats.
      • At the implementation stage, build common classes or functions to sanitize input and detect suspicious data. Every client should call these routines to ensure every case is covered.
      • Develop a strategy for input validation, also known as sanitization, to detect malicious input. All user-provided data should be verified to ensure it is legitimate. At the same time, valid input must still be allowed. See the section on
        Preventing a SQL Injection Attack
        for more information.
      • Use established quality assurance techniques and tools to ensure common SQLi attacks are blocked. Build automated test and regression scripts to validate fixes and ensure security holes are not introduced.
      • Stay informed about new security issues and emerging threats. Keep the web server and RDBMS updated to the most recent release using the latest security updates.

      Applications handling financial information are at an even higher risk of attack, and should consider some additional measures. This increases the development and operational costs but provides an extra level of protection.

      • Consider hiring a security firm or consultant. An expert can review the design documents beforehand and run a security audit on the final product. Some firms provide commercial web vulnerability scanners. These scanners can be run anytime during the development process.
      • Employ a web application firewall (WAF) to detect threats. These applications continually update their list of attack signatures and filter input coming IP addresses with bad reputations. Because these applications are continually updated, they provide a reliable level of ongoing security.

      The OWASP has a good
      security code review guide
      which covers SQL injection attacks along with other web security issues.

      Preventing a SQL Injection Attack

      Several basic coding principles can greatly enhance database security. Most attackers are hoping to find easy targets. If their standard playbook does not work, they are likely to move on to another site. Many of the most obvious safeguards can be used together for increased effectiveness. To reduce the chances of a SQL injection attack, follow the steps below.

      • Use parameterized queries: This technique uses prepared SQL statements to construct the query beforehand. Variables initially take the place of the actual parameters. The actual user-supplied values replace the placeholders later on. This draws a distinction between code and data, and renders many attack techniques much less useful. For example, an attacker cannot comment out the remainder of the query using the -- sequence. The double dash would be included as part of the username field. The database would attempt to locate a user field ending with '-- and would not find it.
      • Validate all data: Before accepting any data, verify it is actually valid. This includes rejecting any input using certain characters or certain keywords. Table and column names can be mapped to their actual internal names, which should not be exposed to the customers. Choice control can be used to limit certain selections. For example, a form’s design can force a user to select their birth year from a drop-down list. This means any input in this field is guaranteed to be valid.
      • Use stored procedures: This is an alternative to parameterized queries with the same goal. Stored procedures are saved inside the database, allowing the application to use them at any time. Typically, the procedures automatically parameterize the code. As an added precaution, only a user who has execute privileges can run these procedures. Unfortunately, there might be cases where this technique is not completely foolproof. Consult the user documentation for the RDBMS for more information.
      • Use non-standard names for tables and columns: Many attackers look for standard tables such as customers or fields including username and password. Adding a prefix or suffix to each string or column provides additional protection at the cost of a bit of extra complexity and longer strings for each name.
      • Escape the input fields: This technique is not considered effective on its own, but provides another layer of protection as part of a total security strategy. Every RDBMS has a method of escaping user-supplied data. This involves recalculating the input so it is treated as pure text, rather than keywords or application-specific symbols. Some applications convert the input characters into their hex equivalents. The PHP programming language, which is often used in conjunction with SQL, also provides tools for escaping SQL queries.
      • Restrict the access privileges of the database user: Determine the level of access every account requires and configure the user roles accordingly. This limits the damage any individual user can inflict. A similar optimization is to limit the system privileges of the database owner. Even if a user gains access to an administrative account, they cannot use it to gain further access to the server. SQL views can also be used to further limit access. Our guide
        SQL Database Security: User Management
        discusses how to develop an access management strategy for an RDBMS.

      Conclusion

      A SQL injection attack is a type of security threat where attackers manipulate the data in web forms or in URLs. The main purpose of this attack is to get the database to behave in an undesirable or insecure manner. This might result in the database displaying confidential data or allowing an unauthorized user to modify, add, or delete data. An injection attack can cause a severe loss of reputation and operational or logistical consequences for the victimized business.

      The three main types of SQL injection attacks are classic, blind, and out-of-band. The classic method is the most common. The attacker directly assaults the database, submitting malevolent data as part of a query. For example, adding the -- sequence causes many RDBMS applications to treat the rest of the command as a comment. This might cause important parts of the query to be dropped and allow the attacker to log in as an administrator or another user.

      Database operators can protect themselves by considering security at every stage of the development process, hiring a security auditor, or deploying a web application firewall. Several coding defenses including parameterized queries, input validation, and stored procedures can thwart most common attacks. If you are considering deploying a web application that uses a database, consult OWASP’s
      cheat sheet
      and
      security code review guide
      .

      More Information

      You may wish to consult the following resources for additional information
      on this topic. While these are provided in the hope that they will be
      useful, please note that we cannot vouch for the accuracy or timeliness of
      externally hosted materials.



      Source link

      How To Configure Suricata as an Intrusion Prevention System (IPS) on Rocky Linux 8


      Not using Rocky Linux 8?


      Choose a different version or distribution.

      Introduction

      In this tutorial you will learn how to configure Suricata’s built-in Intrusion Prevention System (IPS) mode on Rocky Linux 8. By default Suricata is configured to run as an Intrusion Detection System (IDS), which only generates alerts and logs suspicious traffic. When you enable IPS mode, Suricata can actively drop suspicious network traffic in addition to generating alerts for further analysis.

      Before enabling IPS mode, it is important to check which signatures you have enabled, and their default actions. An incorrectly configured signature, or a signature that is overly broad may result in dropping legitimate traffic to your network, or even block you from accessing your servers over SSH and other management protocols.

      In the first part of this tutorial you will check the signatures that you have installed and enabled. You will also learn how to include your own signatures. Once you know which signatures you would like to use in IPS mode, you’ll convert their default action to drop or reject traffic. With your signatures in place, you’ll learn how to send network traffic through Suricata using the netfilter NFQUEUE iptables target, and then generate some invalid network traffic to ensure that Suricata drops it as expected.

      Prerequisites

      If you have been following this tutorial series then you should already have Suricata running on a Rocky Linux 8 server.

      • If you still need to install Suricata then you can follow How To Install Suricata on Rocky Linux 8

      • You should also have the ET Open Ruleset downloaded using the suricata-update command, and included in your Suricata signatures.

      • The jq command line JSON processing tool. If you do not have it installed from a previous tutorial, you can do so using the dnf command:

      You may also have custom signatures that you would like to use from the previous Understanding Suricata Signatures tutorial.

      Step 1 — Including Custom Signatures

      The previous tutorials in this series explored how to install and configure Suricata, as well as how to understand signatures. If you would like to create and include your own rules then you need to edit Suricata’s /etc/suricata/suricata.yaml file to include a custom path to your signatures.

      First, let’s find your server’s public IPs so that you can use them in your custom signatures. To find your IPs you can use the ip command:

      You should receive output like the following:

      Output

      lo UNKNOWN 127.0.0.1/8 ::1/128 eth0 UP 203.0.113.0.5/20 10.20.0.5/16 2001:DB8::1/32 fe80::94ad:d4ff:fef9:cee0/64 eth1 UP 10.137.0.2/16 fe80::44a2:ebff:fe91:5187/64

      Your public IP address(es) will be similar to the highlighted 203.0.113.0.5 and 2001:DB8::1/32 IPs in the output.

      Now let’s create the following custom signature to scan for SSH traffic to non-SSH ports and include it in a file called /var/lib/suricata/rules/local.rules. Open the file with nano or your preferred editor:

      • sudo vi /var/lib/suricata/rules/local.rules

      Copy and paste the following signature:

      Invalid SSH Traffic Signature

      alert ssh any any -> 203.0.113.0.5 !22 (msg:"SSH TRAFFIC on non-SSH port"; flow:to_client, not_established; classtype: misc-attack; target: dest_ip; sid:1000000;)
      alert ssh any any -> 2001:DB8::1/32 !22 (msg:"SSH TRAFFIC on non-SSH port"; flow:to_client, not_established; classtype: misc-attack; target: dest_ip; sid:1000001;)
      

      Substitute your server’s public IP address in place of the 203.0.113.5 and 2001:DB8::1/32 addresses in the rule. If you are not using IPv6 then you can skip adding that signature in this and the following rules.

      You can continue adding custom signatures to this local.rules file depending on your network and applications. For example, if you wanted to alert about HTTP traffic to non-standard ports, you could use the following signatures:

      HTTP traffic on non-standard port signature

      alert http any any -> 203.0.113.0.5 !80 (msg:"HTTP REQUEST on non-HTTP port"; flow:to_client, not_established; classtype:misc-activity; sid:1000002;)
      alert http any any -> 2001:DB8::1/32 !80 (msg:"HTTP REQUEST on non-HTTP port"; flow:to_client, not_established; classtype:misc-activity; sid:1000003;)
      

      To add a signature that checks for TLS traffic to ports other than the default 443 for web servers, add the following:

      TLS traffic on non-standard port signature

      alert tls any any -> 203.0.113.0.5 !443 (msg:"TLS TRAFFIC on non-TLS HTTP port"; flow:to_client, not_established; classtype:misc-activity; sid:1000004;)
      alert tls any any -> 2001:DB8::1/32 !443 (msg:"TLS TRAFFIC on non-TLS HTTP port"; flow:to_client, not_established; classtype:misc-activity; sid:1000005;)
      

      When you are done adding signatures, save and close the file. If you are using vi, press ESC and then :x then ENTER to save and exit.

      Now that you have some custom signatures defined, edit Suricata’s /etc/suricata/suricata.yaml configuration file using nano or your preferred editor to include them:

      • sudo vi /etc/suricata/suricata.yaml

      Find the rule-files: portion of the configuration. If you are using vi enter 1879gg to go to the line. The exact location in your file may be different, but you should be in the correct general region of the file.

      Edit the section and add the following highlighted - local.rules line:

      /etc/suricata/suricata.yaml

      . . .
      rule-files:
        - suricata.rules
        - local.rules
      . . .
      

      Save and exit the file. Be sure to validate Suricata’s configuration after adding your rules. To do so run the following command:

      • sudo suricata -T -c /etc/suricata/suricata.yaml -v

      The test can take some time depending on how many rules you have loaded in the default suricata.rules file. If you find the test takes too long, you can comment out the - suricata.rules line in the configuration by adding a # to the beginning of the line and then run your configuration test again. Be sure to remove the # comment if you plan to use the suricata.rules signature in your final running configuration.

      Once you are satisfied with the signatures that you have created or included using the suricata-update tool, you can proceed to the next step, where you’ll switch the default action for your signatures from alert or log to actively dropping traffic.

      Step 2 — Configuring Signature Actions

      Now that you have your custom signatures tested and working with Suricata, you can change the action to drop or reject. When Suricata is operating in IPS mode, these actions will actively block invalid traffic for any matching signature.

      These two actions are described in the previous tutorial in this series, Understanding Suricata Signatures. The choice of which action to use is up to you. A drop action will immediately discard a packet and any subsequent packets that belong to the network flow. A reject action will send both the client and server a reset packet if the traffic is TCP-based, and an ICMP error packet for any other protocol.

      Let’s use the custom rules from the previous section and convert them to use the drop action, since the traffic that they match is likely to be a network scan, or some other invalid connection.

      Open your /var/lib/suricata/rules/local.rules file using nano or your preferred editor and change the alert action at the beginning of each line in the file to drop:

      • sudo vi /var/lib/suricata/rules/local.rules

      /var/lib/suricata/rules/local.rules

      drop ssh any any -> 203.0.113.0.5 !22 (msg:"SSH TRAFFIC on non-SSH port"; classtype: misc-attack; target: dest_ip; sid:1000000;)
      drop ssh any any -> 2001:DB8::1/32 !22 (msg:"SSH TRAFFIC on non-SSH port"; classtype: misc-attack; target: dest_ip; sid:1000001;)
      . . .
      

      Repeat the step above for any signatures in /var/lib/suricata/rules/suricata.rules that you would like to convert to drop or reject mode.

      Note: If you ran suricata-update in the prerequisite tutorial, you may have more than 30,000 signatures included in your suricata.rules file.

      If you convert every signature to drop or reject you risk blocking legitimate access to your network or servers. Instead, leave the rules in suricata.rules for the time being, and add your custom signatures to local.rules. Suricata will continue to generate alerts for suspicious traffic that is described by the signatures in suricata.rules while it is running in IPS mode.

      After you have a few days or weeks of alerts collected, you can analyze them and choose the relevant signatures to convert to drop or reject based on their sid.

      Once you have all the signatures configured with the action that you would like them to take, the next step is to reconfigure and then restart Suricata in IPS mode.

      Step 3 — Enabling nfqueue Mode

      Suricata runs in IDS mode by default, which means it will not actively block network traffic. To switch to IPS mode, you’ll need to edit Suricata’s /etc/sysconfig/suricata configuration file.

      Open the file in nano or your preferred editor:

      • sudo vi /etc/sysconfig/suricata

      Find the OPTIONS="-i eth0 --user suricata" line and comment it out by adding a # to the beginning of the line. Then add a new line OPTIONS="-q 0 -vvv --user suricata" line that tells Suricata to run in IPS mode.

      Your file should have the following highlighted lines in it when you are done editing:

      /etc/sysconfig/suricata

      . . .
      # OPTIONS="-i eth0 --user suricata"
      OPTIONS="-q 0 -vvv --user suricata"
      . . .
      

      Save and close the file. Now you can restart Suricata using systemctl:

      • sudo systemctl restart suricata.service

      Check Suricata’s status using systemctl:

      • sudo systemctl status suricata.service

      You should receive output like the following:

      Output

      ● suricata.service - Suricata Intrusion Detection Service Loaded: loaded (/usr/lib/systemd/system/suricata.service; disabled; vendor preset: disabled) Active: active (running) since Tue 2021-12-14 16:52:07 UTC; 6s ago Docs: man:suricata(1) Process: 44256 ExecStartPre=/bin/rm -f /var/run/suricata.pid (code=exited, status=0/SUCCESS) Main PID: 44258 (Suricata-Main) Tasks: 10 (limit: 11188) Memory: 52.8M CGroup: /system.slice/suricata.service └─44258 /sbin/suricata -c /etc/suricata/suricata.yaml --pidfile /var/run/suricata.pid -q 0 -vvv --user suricata . . . Dec 14 16:52:07 suricata suricata[44258]: 14/12/2021 -- 16:52:07 - <Notice> - all 4 packet processing threads, 4 management threads initialized, engine started.

      Note the highlighted active (running) line that indicates Suricata restarted successfully.

      With this change you are now ready to send traffic to Suricata using Firewalld in the next step.

      Step 4 — Configuring Firewalld To Send Traffic to Suricata

      Now that you have configured Suricata to process traffic in IPS mode, the next step is to direct incoming packets to Suricata. If you followed the prerequisite tutorials for this series and are using a Rocky Linux 8 system, you should have Firewalld installed and enabled.

      To add the required rules for Suricata to Firewalld, you will need to run the following commands:

      • sudo firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 0 -p tcp --dport 22 -j NFQUEUE --queue-bypass
      • sudo firewall-cmd --permanent --direct --add-rule ipv4 filter OUTPUT 0 -p tcp --sport 22 -j NFQUEUE --queue-bypass

      These two rules ensure that SSH traffic on IPv4 interfaces will bypass Suricata so that you can connect to your server using SSH, even when Suricata is not running. Without these rules, an incorrect or overly broad signature could block your SSH access. Additionally, if Suricata is stopped, all traffic will be sent to the NFQUEUE target and then dropped since Suricata is not running.

      Add the same rules for IPv6 using the following commands:

      • sudo firewall-cmd --permanent --direct --add-rule ipv6 filter INPUT 0 -p tcp --dport 22 -j NFQUEUE --queue-bypass
      • sudo firewall-cmd --permanent --direct --add-rule ipv6 filter OUTPUT 0 -p tcp --sport 22 -j NFQUEUE --queue-bypass

      Next, add FORWARD rules to ensure that if your server is acting as a gateway for other systems, all that traffic will also go to Suricata for processing.

      • sudo firewall-cmd --permanent --direct --add-rule ipv4 filter FORWARD 0 -j NFQUEUE
      • sudo firewall-cmd --permanent --direct --add-rule ipv6 filter FORWARD 0 -j NFQUEUE

      The final two INPUT and OUTPUT rules send all remaining traffic that is not SSH traffic to Suricata for processing.

      • sudo firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 1 -j NFQUEUE
      • sudo firewall-cmd --permanent --direct --add-rule ipv4 filter OUTPUT 1 -j NFQUEUE

      Repeat the commands for IPv6 traffic:

      • sudo firewall-cmd --permanent --direct --add-rule ipv6 filter INPUT 1 -j NFQUEUE
      • sudo firewall-cmd --permanent --direct --add-rule ipv6 filter OUTPUT 1 -j NFQUEUE

      Now reload Firewalld to make the rules persistent:

      • sudo firewall-cmd --reload

      Note: If you are using another firewall like iptables you will need to modify these rules to match the format your firewall expects.

      At this point in the tutorial you have Suricata configured to run in IPS mode, and your network traffic is being sent to Suricata by default. You will be able to restart your server at any time and your Suricata and firewall rules will be persistent.

      The last step in this tutorial is to verify Suricata is dropping traffic correctly.

      Step 5 — Testing Invalid Traffic

      Now that you have Suricata and your firewall configured to process network traffic, you can test whether Suricata will drop packets that match your custom and other included signatures.

      Recall signature sid:2100498 from the previous tutorial, which is modified in this example to drop matching packets:

      sid:2100498

      drop ip any any -> any any (msg:"GPL ATTACK_RESPONSE id check returned root"; content:"uid=0|28|root|29|"; classtype:bad-unknown; sid:2100498; rev:7; metadata:created_at 2010_09_23, updated_at 2010_09_23;)
      

      Find and edit the rule in your /var/lib/suricata/rules/suricata.rules file to use the drop action if you have the signature included there. Otherwise, add the rule to your /var/lib/suricata/rules/local.rules file.

      Send Suricata the SIGUSR2 signal to get it to reload its signatures:

      • sudo kill -usr2 $(pidof suricata)

      Now test the rule using curl:

      • curl --max-time 5 http://testmynids.org/uid/index.html

      You should receive an error stating that the request timed out, which indicates Suricata blocked the HTTP response:

      Output

      curl: (28) Operation timed out after 5000 milliseconds with 0 out of 39 bytes received

      You can confirm that Suricata dropped the HTTP response using jq to examine the eve.log file:

      • sudo jq 'select(.alert .signature_id==2100498)' /var/log/suricata/eve.json

      You should receive output like the following:

      Output

      { . . . "community_id": "1:SbOgFh2T3DZvwsoyMH4xfxOoVas=", "alert": { "action": "blocked", "gid": 1, "signature_id": 2100498, "rev": 7, "signature": "GPL ATTACK_RESPONSE id check returned root", "category": "Potentially Bad Traffic", "severity": 2, "metadata": { "created_at": [ "2010_09_23" ], "updated_at": [ "2010_09_23" ] } }, "http": { "hostname": "testmynids.org", "url": "/uid/index.html", "http_user_agent": "curl/7.61.1", "http_content_type": "text/html", "http_method": "GET", "protocol": "HTTP/1.1", "status": 200, "length": 39 }, . . .

      The highlighted "action": "blocked" line confirms that the signature matched, and Suricata dropped or rejected the test HTTP request.

      Conclusion

      In this tutorial you configured Suricata to block suspicious network traffic using its built-in IPS mode on Rocky Linux 8. You also added custom signatures to examine and block SSH, HTTP, and TLS traffic on non-standard ports. To tie everything together, you also added firewall rules to direct traffic through Suricata for processing.

      Now that you have Suricata installed and configured in IPS mode, and can write your own signatures that either alert on or drop suspicious traffic, you can continue monitoring your servers and networks, and refining your signatures.

      Once you are satisfied with your Suricata signatures and configuration, you can continue with the last tutorial in this series, which will guide you through sending logs from Suricata to a Security and Information Event Management (SIEM) system built using the Elastic Stack.



      Source link

      How To Configure Suricata as an Intrusion Prevention System (IPS) on Debian 11


      Not using Debian 11?


      Choose a different version or distribution.

      Introduction

      In this tutorial you will learn how to configure Suricata’s built-in Intrusion Prevention System (IPS) mode on Debian 11. By default Suricata is configured to run as an Intrusion Detection System (IDS), which only generates alerts and logs suspicious traffic. When you enable IPS mode, Suricata can actively drop suspicious network traffic in addition to generating alerts for further analysis.

      Before enabling IPS mode, it is important to check which signatures you have enabled, and their default actions. An incorrectly configured signature, or a signature that is overly broad may result in dropping legitimate traffic to your network, or even block you from accessing your servers over SSH and other management protocols.

      In the first part of this tutorial you will check the signatures that you have installed and enabled. You will also learn how to include your own signatures. Once you know which signatures you would like to use in IPS mode, you’ll convert their default action to drop or reject traffic. With your signatures in place, you’ll learn how to send network traffic through Suricata using the netfilter NFQUEUE iptables target, and then generate some invalid network traffic to ensure that Suricata drops it as expected.

      Prerequisites

      If you have been following this tutorial series then you should already have Suricata running on a server. If you still need to install Suricata then you can follow one of these tutorials depending on your server’s operating system:

      • How To Install Suricata on Debian 11

      • You should also have the ET Open Ruleset downloaded using the suricata-update command, and included in your Suricata signatures.

      • The jq command line JSON processing tool. If you do not have it installed from a previous tutorial, you can do so using the apt command:

        • sudo apt update
        • sudo apt install jq

      You may also have custom signatures that you would like to use from the previous Understanding Suricata Signatures tutorial.

      Step 1 — Including Custom Signatures

      The previous tutorials in this series explored how to install and configure Suricata, as well as how to understand signatures. If you would like to create and include your own signatures then you need to edit Suricata’s /etc/suricata/suricata.yaml file to add them.

      First, let’s find your server’s public IPs so that you can use them in your custom signatures. To find your IPs you can use the ip command:

      You should receive output like the following:

      Output

      lo UNKNOWN 127.0.0.1/8 ::1/128 eth0 UP 203.0.113.0.5/20 10.20.0.5/16 2604:a880:cad:d0::dc8:4001/64 fe80::94ad:d4ff:fef9:cee0/64 eth1 UP 10.137.0.2/16 fe80::44a2:ebff:fe91:5187/64

      Your public IP address(es) will be similar to the highlighted 203.0.113.0.5 and 2604:a880:cad:d0::dc8:4001/64 IPs in the output.

      Now let’s create the following custom signature to scan for SSH traffic to non-SSH ports and include it in a file called /etc/suricata/rules/local.rules. Open the file with nano or your preferred editor:

      • sudo nano /etc/suricata/rules/local.rules

      Copy and paste the following signature:

      Invalid SSH Traffic Signature

      alert ssh any any -> 203.0.113.0.5 !22 (msg:"SSH TRAFFIC on non-SSH port"; flow:to_client, not_established; classtype: misc-attack; target: dest_ip; sid:1000000;)
      alert ssh any any -> 2604:a880:cad:d0::dc8:4001/64 !22 (msg:"SSH TRAFFIC on non-SSH port"; flow:to_client, not_established; classtype: misc-attack; target: dest_ip; sid:1000001;)
      

      Substitute in your server’s public IP address in place of the 203.0.113.5 and 2604:a880:cad:d0::dc8:4001/64 addresses in the rule. If you are not using IPv6 then you can skip adding that signature in this and the following rules.

      You can continue adding custom signatures to this local.rules file depending on your network and applications. For example, if you wanted to alert about HTTP traffic to non-standard ports, you could use the following signatures:

      HTTP traffic on non-standard port signature

      alert http any any -> 203.0.113.0.5 !80 (msg:"HTTP REQUEST on non-HTTP port"; flow:to_client, not_established; classtype:misc-activity; sid:1000002;)
      alert http any any -> 2604:a880:cad:d0::dc8:4001/64 !80 (msg:"HTTP REQUEST on non-HTTP port"; flow:to_client, not_established; classtype:misc-activity; sid:1000003;)
      

      To add a signature that checks for TLS traffic to ports other than the default 443 for web servers, add the following:

      TLS traffic on non-standard port signature

      alert tls any any -> 203.0.113.0.5 !443 (msg:"TLS TRAFFIC on non-TLS HTTP port"; flow:to_client, not_established; classtype:misc-activity; sid:1000004;)
      alert tls any any -> 2604:a880:cad:d0::dc8:4001/64 !443 (msg:"TLS TRAFFIC on non-TLS HTTP port"; flow:to_client, not_established; classtype:misc-activity; sid:1000005;)
      

      When you are done adding signatures, save and close the file. If you are using nano, you can do so with CTRL+X, then Y and ENTER to confirm. If you are using vi, press ESC and then :x then ENTER to save and exit.

      Now that you have some custom signatures defined, edit Suricata’s /etc/suricata/suricata.yaml configuration file using nano or your preferred editor to include them:

      • sudo nano /etc/suricata/suricata.yaml

      Find the rule-files: portion of the configuration. If you are using nano use CTRL+_ and then enter the line number 1879. If you are using vi enter 1879gg to go to the line.

      Edit the section and add the following highlighted - local.rules line:

      /etc/suricata/suricata.yaml

      . . .
      rule-files:
        - suricata.rules
        - local.rules
      . . .
      

      Save and exit the file. Be sure to validate Suricata’s configuration after adding your rules. To do so run the following command:

      • sudo suricata -T -c /etc/suricata/suricata.yaml -v

      The test can take some time depending on how many rules you have loaded in the default suricata.rules file. If you find the test takes too long, you can comment out the - suricata.rules line in the configuration by adding a # to the beginning of the line and then run your configuration test again.

      Once you are satisfied with the signatures that you have created or included using the suricata-update tool, you can proceed to the next step, where you’ll switch the default action for your signatures from alert or log to actively dropping traffic.

      Step 2 — Configuring Signature Actions

      Now that you have your custom signatures tested and working with Suricata, you can change the action to drop or reject. When Suricata is operating in IPS mode, these actions will actively block invalid traffic for any matching signature.

      These two actions are described in the previous tutorial in this series, Understanding Suricata Signatures. The choice of which action to use is up to you. A drop action will immediately discard a packet and any subsequent packets that belong to the network flow. A reject action will send both the client and server a reset packet if the traffic is TCP-based, and an ICMP error packet for any other protocol.

      Let’s use the custom rules from the previous section and convert them to use the drop action, since the traffic that they match is likely to be a network scan, or some other invalid connection.

      Open your /etc/suricata/rules/local.rules file using nano or your preferred editor and change the alert action at the beginning of each line in the file to drop:

      /etc/suricata/rules/local.rules

      drop ssh any any -> 203.0.113.0.5 !22 (msg:"SSH TRAFFIC on non-SSH port"; classtype: misc-attack; target: dest_ip; sid:1000000;)
      drop ssh any any -> 2604:a880:cad:d0::dc8:4001/64 !22 (msg:"SSH TRAFFIC on non-SSH port"; classtype: misc-attack; target: dest_ip; sid:1000001;)
      . . .
      

      Repeat the step above for any signatures in /etc/suricata/rules/suricata.rules that you would like to convert to drop or reject mode.

      Note: If you ran suricata-update in the prerequisite tutorial, you may have more than 30,000 signatures included in your suricata.rules file.

      If you convert every signature to drop or reject you risk blocking legitimate access to your network or servers. Instead, leave the rules in suricata.rules for the time being, and add your custom signatures to local.rules. Suricata will continue to generate alerts for suspicious traffic that is described by the signatures in suricata.rules while it is running in IPS mode.

      After you have a few days or weeks of alerts collected, you can analyze them and choose the relevant signatures to convert to drop or reject based on their sid.

      Once you have all the signatures configured with the action that you would like them to take, the next step is to reconfigure and then restart Suricata in IPS mode.

      Step 3 — Enabling nfqueue Mode

      Suricata runs in IDS mode by default, which means it will not actively block network traffic. To switch to IPS mode, you’ll need to modify Suricata’s default settings.

      Use the systemctl edit command to create a new systemd override file:

      • sudo systemctl edit suricata.service

      Add the following highlighted lines at the start of the file, in between the comments:

      systemctl edit suricata.service

      ### Editing /etc/systemd/system/suricata.service.d/override.conf
      ### Anything between here and the comment below will become the new contents of the file
      
      [Service]
      ExecStart=
      ExecStart=/usr/bin/suricata -c /etc/suricata/suricata.yaml --pidfile /run/suricata.pid -q 0 -vvv
      Type=simple
      
      ### Lines below this comment will be discarded
      . . .
      
      • The ExecStart= line clears the default systemd command that starts a service. The next line defines the new ExecStart command to use.
      • The Type=simple line ensures that systemd can manage the Suricata process when it is running in IPS mode.

      Save and close the file. If you are using nano, you can do so with CTRL+X, then Y and ENTER to confirm. If you are using vi, press ESC and then :x then ENTER to save and exit.

      Now reload systemd so that it detects the new Suricata settings:

      • sudo systemctl daemon-reload

      Now you can restart Suricata using systemctl:

      • sudo systemctl restart suricata.service

      Check Suricata’s status using systemctl:

      • sudo systemctl status suricata.service

      You should receive output like the following:

      Output

      ● suricata.service - Suricata IDS/IDP daemon Loaded: loaded (/lib/systemd/system/suricata.service; enabled; vendor preset: enabled) Drop-In: /etc/systemd/system/suricata.service.d └─override.conf Active: active (running) since Wed 2021-12-15 14:35:21 UTC; 38s ago Docs: man:suricata(8) man:suricatasc(8) https://suricata-ids.org/docs/ Main PID: 29890 (Suricata-Main) Tasks: 10 (limit: 2340) Memory: 54.9M CPU: 3.957s CGroup: /system.slice/suricata.service └─29890 /usr/bin/suricata -c /etc/suricata/suricata.yaml --pidfile /run/suricata.pid -q 0 -vvv . . . Dec 15 14:35:21 suricata suricata[29890]: 15/12/2021 -- 14:35:21 - <Notice> - all 4 packet processing threads, 4 management threads initialized, engine started

      Note the highlighted active (running) line that indicates Suricata restarted successfully.

      With this change you are now ready to send traffic to Suricata using the UFW firewall in the next step.

      Step 4 — Configuring UFW To Send Traffic to Suricata

      Now that you have configured Suricata to process traffic in IPS mode, the next step is to direct incoming packets to Suricata. If you followed the prerequisite tutorials for this series and are using an Ubuntu 20.04 system, you should have the Uncomplicated Firewall (UFW) installed and enabled by default.

      To add the required rules for Suricata to UFW, you will need to edit the firewall files in the /etc/ufw/before.rules and /etc/ufw/before6.rules directly.

      Open the first file using nano or your preferred editor:

      • sudo nano /etc/ufw/before.rules

      Near the beginning of the file, insert the following highlighted lines:

      /etc/ufw/before.rules

      . . .
      # Don't delete these required lines, otherwise there will be errors
      *filter
      :ufw-before-input - [0:0]
      :ufw-before-output - [0:0]
      :ufw-before-forward - [0:0]
      :ufw-not-local - [0:0]
      # End required lines
      
      ## Start Suricata NFQUEUE rules
      -I INPUT 1 -p tcp --dport 22 -j NFQUEUE --queue-bypass
      -I OUTPUT 1 -p tcp --sport 22 -j NFQUEUE --queue-bypass
      -I FORWARD -j NFQUEUE
      -I INPUT 2 -j NFQUEUE
      -I OUTPUT 2 -j NFQUEUE
      ## End Suricata NFQUEUE rules
      
      # allow all on loopback
      -A ufw-before-input -i lo -j ACCEPT
      -A ufw-before-output -o lo -j ACCEPT
      . . .
      

      Save and exit the file when you are done editing it. Now add the same lines to the same section in the /etc/ufw/before6.rules file.

      The first two INPUT and OUTPUT rules are used to bypass Suricata so that you can connect to your server using SSH, even when Suricata is not running. Without these rules, an incorrect or overly broad signature could block your SSH access. Additionally, if Suricata is stopped, all traffic will be sent to the NFQUEUE target and then dropped since Suricata is not running.

      The next FORWARD rule ensures that if your server is acting as a gateway for other systems, all that traffic will also go to Suricata for processing.

      The final two INPUT and OUTPUT rules send all remaining traffic that is not SSH traffic to Suricata for processing.

      Restart UFW to load the new rules:

      • sudo systemctl restart ufw.service

      Note: If you are using another firewall you will need to modify these rules to match the format your firewall expects.

      If you are using iptables, then you can insert these rules directly using the iptables and ip6tables commands. However, you will need to ensure that the rules are persistent across reboots with a tool like iptables-persistent.

      If you are using firewalld, then the following rules will direct traffic to Suricata:

      • sudo firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 0 -p tcp --dport 22 -j NFQUEUE --queue-bypass
      • sudo firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 1 -j NFQUEUE
      • sudo firewall-cmd --permanent --direct --add-rule ipv6 filter INPUT 0 -p tcp --dport 22 -j NFQUEUE --queue-bypass
      • sudo firewall-cmd --permanent --direct --add-rule ipv6 filter INPUT 1 -j NFQUEUE
      • sudo firewall-cmd --permanent --direct --add-rule ipv4 filter FORWARD 0 -j NFQUEUE
      • sudo firewall-cmd --permanent --direct --add-rule ipv6 filter FORWARD 0 -j NFQUEUE
      • sudo firewall-cmd --permanent --direct --add-rule ipv4 filter OUTPUT 0 -p tcp --sport 22 -j NFQUEUE --queue-bypass
      • sudo firewall-cmd --permanent --direct --add-rule ipv4 filter OUTPUT 1 -j NFQUEUE
      • sudo firewall-cmd --permanent --direct --add-rule ipv6 filter OUTPUT 0 -p tcp --sport 22 -j NFQUEUE --queue-bypass
      • sudo firewall-cmd --permanent --direct --add-rule ipv6 filter OUTPUT 1 -j NFQUEUE
      • sudo firewall-cmd --reload

      At this point in the tutorial you have Suricata configured to run in IPS mode, and your network traffic is being sent to Suricata by default. You will be able to restart your server at any time and your Suricata and firewall rules will be persistent.

      The last step in this tutorial is to verify Suricata is dropping traffic correctly.

      Step 5 — Testing Invalid Traffic

      Now that you have Suricata and your firewall configured to process network traffic, you can test whether Suricata will drop packets that match your custom and other included signatures.

      Recall signature sid:2100498 from the previous tutorial, which is modified in this example to drop matching packets:

      sid:2100498

      drop ip any any -> any any (msg:"GPL ATTACK_RESPONSE id check returned root"; content:"uid=0|28|root|29|"; classtype:bad-unknown; sid:2100498; rev:7; metadata:created_at 2010_09_23, updated_at 2010_09_23;)
      

      Find and edit the rule in your /etc/suricata/rules/suricata.rules file to use the drop action if you have the signature included there. Otherwise, add the rule to your /etc/suricata/rules/local.rules file.

      Send Suricata the SIGUSR2 signal to get it to reload its signatures:

      • sudo kill -usr2 $(pidof suricata)

      Now test the rule using curl:

      • curl --max-time 5 http://testmynids.org/uid/index.html

      You should receive an error stating that the request timed out, which indicates Suricata blocked the HTTP response:

      Output

      curl: (28) Operation timed out after 5000 milliseconds with 0 out of 39 bytes received

      You can confirm that Suricata dropped the HTTP response using jq to examine the eve.log file:

      • jq 'select(.alert .signature_id==2100498)' /var/log/suricata/eve.json

      You should receive output like the following:

      Output

      { . . . "community_id": "1:Z+RcUB32putNzIZ38V/kEzZbWmQ=", "alert": { "action": "blocked", "gid": 1, "signature_id": 2100498, "rev": 7, "signature": "GPL ATTACK_RESPONSE id check returned root", "category": "Potentially Bad Traffic", "severity": 2, "metadata": { "created_at": [ "2010_09_23" ], "updated_at": [ "2010_09_23" ] } }, "http": { "hostname": "testmynids.org", "url": "/uid/index.html", "http_user_agent": "curl/7.68.0", "http_content_type": "text/html", "http_method": "GET", "protocol": "HTTP/1.1", "status": 200, "length": 39 }, . . .

      The highlighted "action": "blocked" line confirms that the signature matched, and Suricata dropped or rejected the test HTTP request.

      Conclusion

      In this tutorial you configured Suricata to block suspicious network traffic using its built-in IPS mode. You also added custom signatures to examine and block SSH, HTTP, and TLS traffic on non-standard ports. To tie everything together, you also added firewall rules that direct traffic through Suricata for processing.

      Now that you have Suricata installed and configured in IPS mode, and can write your own signatures that either alert on or drop suspicious traffic, you can continue monitoring your servers and networks, and refining your signatures.

      Once you are satisfied with your Suricata signatures and configuration, you can continue with the last tutorial in this series, which will guide you through sending logs from Suricata to a Security and Information Event Management (SIEM) system built using the Elastic Stack.



      Source link