CA BD NY
  • Categories

  • Recent Posts

  • RSS MySQL Hacker

  • RSS Apache Hacker

  • RSS MiniCTO

  • Meta

  • Keeping the find command in current directory only

    Published January 6th, 2009 by kabir

    Problem Statement

    When using the find command, it has the ability to find whatever you are looking for in sub-directories. For example, find . -type f -name "*2008*.txt" -ls will find all files with 2008 and .txt in the name in the current directory or any of its sub-directories. This is good but if you are trying to move such files into a sub-directory that already has files with this pattern, you are going to find it difficult to use find. Here is a short tick that you can use to hack this.

    Limiting nosy find’s interest to current directory only

    To limit find to your current directory, just use the -maxdepth 1 in the command-line. For example:

    $ find . -maxdepth 1 -name "*2008*.txt"

    This command will tell find to look for files with 2008 and .txt in the name but limit the scope to only one level of depth, which is equal to the current directory.

    In our real-world scenario, we wanted to move these files to a sub-folder which is also called 2008 so here is what we ran:

    $ find . -maxdepth 1 -name "*2008*.txt" -exec mv {} 2008 \;

    Worked like charm!

    Working around shell command-line wildcard limitations

    Published January 5th, 2009 by kabir

    Problem Statement

    The most commonly used shell in CentOS is /bin/bash and like other shells such as /bin/sh, /bin/tcsh, it has command line limitations. One such limitation is the wildcard expansion size. For example, say you have a directory with thousands of files or subdirectories and want to run the rm command to remove only files with .php extension using rm -f *.php, you will run into the wildcard limitation of the shell. Here we will show you a simple work around.

    Trying to delete a lot of files in a directory with thousands of files using rm -f *

    Say you are trying to delete all PHP files using rm -f *.php in a directory with thousands of PHP cache files generated by the Smarty template engine, in such a case you will see an error message from shell such as the following:

    /bin/rm: Argument list too long
    

    What happened is that shell tried to expand the wildcard *.php and placed the file list in rm’s command-line argument list. Since each command-line argument list is really an array and there is a limit to how many arguments can be stored in a process’s memory space, it fails.

    Using a workaround for wildcard expansion problem for commands like rm

    The easiest solution is to run the find command and execute rm one by one for each matching file. For example, to delete all PHP scripts in a directory, you can run:

    $ find . -type f -name "*.php" -exec rm -f {} \;
    

    This tells the find command to find all files matching the given wildcard (*.php) and execute the rm -f command on each of the matching file. Thus, this command can avoid the wildcard expansion issue as the rm -f command sees only one argument at a time.

    Creating a Chroot Jail Enabled FTP Service

    Published December 10th, 2008 by kabir

    Problem Statement

    We really dislike plain-old FTP service for its lack of security. Unfortunately, there are still brain-dead (windows) programs out there that will not work with Secure FTP (SFTP) via SSH. When your users just cannot live without such brain-dead programs and you are tired of chasing down the vendors for a reasonable explanation for not using SFTP, you are forced to enable FTP service. Here we will discuss how you can make this ungodly act of enabling FTP service a bit more secure.

    Time Estimate (10 ~ 15 min)
    We estimate that the entire process to create a chrooted jail using vsftpd daemon might take anywhere from ten to fifteen minutes.

    Step 1: Discourage users from using FTP service all together

    Yes, try to talk the users out of using the FTP service all together! Show them the following flash video that our User Interface team put together up in a zippy to let (thick) people see the difference between SFTP and plain-old FTP.

    Step 2: (Reluctantly) Use vsFTPD FTP Server

    If you fail in step 1, install VSFTPD using yum -y install vsftpd. Once installed you will need to add the following line in your /etc/modprove.conf file:

    alias ip_conntrack ip_conntract_ftp ip_nat_ftp

    Now load the ip_conntrack module by running the following command as root:

    modprobe ip_conntrack

    Next update your /etc/sysconfig/iptables-config and modify the IPTABLES_MODULES line to include
    “ip_nat_ftp” as shown below:

    IPTABLES_MODULES ="ip_nat_ftp"

    Restart iptables using service iptables restart.

    Consider one or more of the security options:

    • Use chroot jail concept so that each user who uses FTP can only see her home directory. You can always point her home directory to the directory where she likes to work
    • Use IP based access control using iptables so that FTP is not available from anywhere in the world.

    We will discuss both techniques here.

    Step 3: Lock’em Up in Chroot Jail

    The chroot jail concept is simple — user connects to your FTP server and gets locked into the home directory and cannot go outside the home directory as the home directory becomes the root (/) for the session. This forbids nosy users from browsing files and directories that have nothing to do with their work.

    To enable chroot jail for vsftp daemon, do the following:

    • Edit the /etc/vsftpd/vsftpd.conf file and add or uncomment the following line:
      chroot_local_user=YES
    • Now restart vsftpd daemon using service vsftpd restart

    Now test your setup by FTPing into the server using an user account and see if you can browse files and directories outside the home directory or not. If your setup is correctly configured, you won’t be able to get outside the home directory, which appears as / (root).

    Step 4: Use FTP only accounts

    When creating FTP service on a CentOS server, consider making FTP-only users by setting the user’s shell to /sbin/nologin.

    Step 5: Restrict incoming FTP access only to known IP addresses

    If you know that your users access the FTP service from a known IP address list, you should consider locking up the FTP service to only work for those IP addresses. You can restrict this by creating iptable rules.

    For example, to restrict FTP access to an IP address — 1.2.3.4 — you can change your FTP rule in the /etc/sysconfig/iptables file as follows:

    -A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp -s 1.2.3.4 --dport ftp -j ACCEPT

    After restarting iptables using service iptables restart you should be able to test if FTP connection is restricted to the named IP address or not by making an FTP request from that IP and also from an IP that is not listed in the iptables rules file for FTP.

    Avoid Tracking Memcached Using Ip_conntrack in CentOS Kernel

    Published December 10th, 2008 by kabir

    Problem Statement

    We recently enabled Ip_conntrack for supporting FTP service using vsftpd daemon on a CentOS server that also runs memcached. A bit later we noticed that /proc/net/ip_conntrack shows a lot of entries for memcached. Since kernel level tracking of connections require memory and CPU resources, we wanted to not track memcached connections on a busy server. Here you will find out what we had to do to overcome this problem.

    First Choice: stop using ip_conntrack kernel module on memcached server

    This is the best option as tracking connections in kernel is really a memory/CPU resource concern.
    Because, conntrac mechanism of the Linux kernal eats up memory and cpu time and may be disabling it can improve overall performance of memcached.

    Second Choice: increase the max connection tracking size for the kernel

    If you must use ip_conntrack, consider setting the maximum entry size (CONNTRACK_MAX) of the connection tracking table in the kernel to a large number.

    Take a look at /proc/sys/net/ipv4/netfilter/ip_conntrack_max
    and if it set to a low number. For systems with more than 1GB of RAM, default value is limited to 65536. To calculate what size you can set this to, use the following information:

    On i386 architecture:

    CONNTRACK_MAX = RAMSIZE (in bytes) / 16384 = RAMSIZE (in MegaBytes) * 64.
    

    So for example, a 32 bits PC with 512MB of RAM can handle 512*1024^2/16384 = 512*64 = 32768 simultaneous connections by default.

    But the real formula is:

    CONNTRACK_MAX = RAMSIZE (in bytes) / 16384 / (x / 32)
    

    where x is the number of bits in a pointer (for example, 32 or 64 bits). To set a new value run:

    echo "new value" > /proc/sys/net/ipv4/netfilter/ip_conntrack_max
    

    For example:

    echo 1234567  > /proc/sys/net/ipv4/netfilter/ip_conntrack_max
    

    To make this setting permanent, add this line in your /etc/rc.local file so that when you reboot your CentOS server, it also sets the connection tracking size to the desired value.

    Third Choice: use iptables to stop tracking memcached connections

    To minimize the resource use (memory/CPU) for connection tracking, you can consider disabling connection tracking of your memcached daemon. For example, if you run memcached on the default 11211 port, you can run the following iptables rules on the memcached CentOS server:

    iptables -t raw -I PREROUTING -p tcp --dport 11211 -j NOTRACK
    iptables -t raw -I OUTPUT -p tcp --dport 11211 -j NOTRACK
    

    The first iptables rule tells CentOS kernel to not to track incoming traffic from your memcached clients. The second one tells CentOS kernel to not to track outgoing traffic from your memcached daemon.

    Quickly Getting Memcached Stats from the Command-line (CLI)

    Published December 10th, 2008 by kabir

    Problem Statement

    Once you have memcached installed, you want to know how well it is working out for you. Here we will show you how you can get stats on memcached from the command-line in a hurry.

    Getting memcached stats from the command-line

    From your terminal app such as putty, do the following:

    1. Telnet to your memcached server using the memcached port. For example, if you are running memcached on your localhost on the default port 11211, you can run:
      telnet localhost 11211
      
    2. Once connected, enter stats and you will see the current memcached stats as shown in the sample below:
      [root@cassini ~]# telnet localhost 11211
      Trying 127.0.0.1...
      Connected to localhost.localdomain (127.0.0.1).
      Escape character is '^]'.
      stats
      STAT pid 16781
      STAT uptime 2891159
      STAT time 1228931142
      STAT version 1.2.6
      STAT pointer_size 32
      STAT rusage_user 0.071989
      STAT rusage_system 0.380942
      STAT curr_items 69
      STAT total_items 249
      STAT bytes 3871
      STAT curr_connections 2
      STAT total_connections 1965
      STAT connection_structures 6
      STAT cmd_get 3270
      STAT cmd_set 249
      STAT get_hits 403
      STAT get_misses 2867
      STAT evictions 0
      STAT bytes_read 62361
      STAT bytes_written 27026
      STAT limit_maxbytes 268435456
      STAT threads 1
      END
      

    Stopping ICMP timestamp-request/response for CentOS Server

    Published December 4th, 2008 by kabir

    Problem Statement

    If you have PCI DSS compliance requirements for your Web server doing ecommerce, you probably have a third-party scanner that checks your security compliance, in such case you might already be aware of the fact that ICMP timestamp-request and timestamp-response is not good to have turned on. These type of ICMP packets allows a potential intruder to calculate your server’s local time and possibly also do a fingerprint of your operating system. It is a good idea to disable these packets. Here we will show you how.

    Disabling ICMP timestamp-request and timestamp-response requests

    To disable these ICMP packet types, you can add a iptables firewall rule in your /etc/sysconfig/iptables file as follows:

    -A RH-Firewall-1-INPUT -p ICMP --icmp-type timestamp-request -j DROP
    -A RH-Firewall-1-INPUT -p ICMP --icmp-type timestamp-reply -j DROP
    

    Then restart the iptables service using service iptables restart and check the iptables using: iptables -L -n you should see two lines as shown below:

    
    DROP       icmp --  0.0.0.0/0            0.0.0.0/0           icmp type 13
    DROP       icmp --  0.0.0.0/0            0.0.0.0/0           icmp type 14
    

    These rules tells centos to drop the ICMP timestamp packets.

    Disabling ICMP echo requests

    If you would much rather have your server not reply to typical ping (ICMP echo) requests, you can disable it by adding the following line in your /etc/rc.local script.

    echo  1 > /proc/sys/net/ipv4/icmp_echo_ignore_all
    

    You should also run the above command immediately to disable ping right away.

    Scanning Ports on Your CentOS Server

    Published November 27th, 2008 by kabir

    Problem Statement

    It is always a good idea to routinely scan your server for open ports so that you know exactly what is open and available on the Internet. In this article, we will show you how to use too popular utility programs to do just that.

    Using nc to scan for ports on your CentOS server

    First make sure you have nc installed on your system. If you simply enter the nc at the root shell prompt and do not get the syntax information, you need to install it. Installing nc is very simple. Just run: yum -y install nc to have yum install it for you.

    Once installed, you can use nc to scan for open ports on any server that you manage. Please note that it is not polite and possibly not legal in your country to scan someone else’s system without receiving appropriate permissions apriori.

    To scan a host using nc for open ports between 1 to 9999, run:

    $ nc -w 2  -z [hostname or IP address]  [port range]

    For example:

    $ nc -w 2  -z www.example.com 1-9999

    Here the host named www.example.com will be scanned for all ports in 1-9999 range.

    A sample output of such a command is shown below:

    Connection to www.example.com 80 port [tcp/http] succeeded!
    Connection to www.example.com 110 port [tcp/pop3] succeeded!
    Connection to www.example.com 143 port [tcp/imap] succeeded!
    

    Here nc reports that the www.example.com server has port 80 (HTTP), 110 (POP3), and 143 (IMAP) open.

    Using nmap to scan for ports on your CentOS server

    Like nc, the nmap utility program is also a great tool for scanning your server ports. If you do not have it already installed just run: yum -y install nmap and let yum install it for you.

    Once installed, you can run various types of scans that you can do with nmap, the one that we found most interesting is as follows:

     $  nmap -A -T4 [hostname] 

    A sample output is shown below:

    Starting Nmap 4.11 ( http://www.insecure.org/nmap/ ) at 2008-11-27 12:37 PST
    Stats: 0:00:01 elapsed; 0 hosts completed (1 up), 1 undergoing SYN Stealth Scan
    SYN Stealth Scan Timing: About 2.17% done; ETC: 12:38 (0:00:49 remaining)
    Interesting ports on demo.evoknow.com (75.142.210.121):
    Not shown: 1018 filtered ports, 658 closed ports
    PORT     STATE SERVICE VERSION
    21/tcp   open  ftp     vsftpd 2.0.5
    80/tcp   open  http    Apache httpd
    443/tcp  open  http    Apache httpd
    3306/tcp open  mysql   MySQL (unauthorized)
    MAC Address: 00:11:25:2A:11:00 (IBM)
    Device type: general purpose
    Running: Linux 2.6.X
    OS details: Linux 2.6.5 - 2.6.11
    Uptime 42.268 days (since Thu Oct 16 07:11:35 2008)
    Service Info: OS: Unix
    
    Nmap finished: 1 IP address (1 host up) scanned in 13.303 seconds
    

    The -A option enables OS detection and Version detection, Script scanning and Traceroute and the -T4 tells nmap to be aggressive with timing.

    Restricting SSH Access Attempts Using DenyHosts

    Published November 25th, 2008 by kabir

    Problem Statement

    The real problem in the world is that there are too many people with too much free time. These wanna-be hackers often download scripts and ready-made-software to scan servers all around the globe and see if there is one that is poorly maintained to get in and deface Web pages or steal information. SSH is a great improvement over telnet based remote access but it is also setup typically using username/password based authentication. So if your password is weak, SSH has no benefit. Having weak password in combination with a default SSH server is like inviting trouble by going out of your way. Here in this article we will show you how you can secure SSH and automatically ban access attempts from people who have either forgotten their password or those who should have never connected to your SSH server.

    Time Estimate (30 ~ 60 min)
    We estimate that the entire process to get DenyHosts installed, and tested might take half an hour to an hour.

    Securing SSH by Running on a Non-Standard Port

    We covered this topic in another article called <a href=”http://centoshacker.com/admin/ssh/running-ssh-on-a-non-standard-port.html”>Running SSH on a Non-standard Port</a>. Read and implement as recommended so that your SSH server is not on the default 22.

    Deny the Idiot Users and/or Wanna-be Hackers and Script Kiddies

    DenyHosts is a Python script that runs as a daemon and monitors SSH attempts (by watching /var/log/secure) on your server. After n number of invalid attempts using non-existent user accounts are made by a potential intruder, it locks up the IP address by placing it in /etc/hosts.deny which the SSH server checks every time a connection attempt is made. This means that after n number of invalid attempts to access non-existent user accounts, the intruder has to change the IP address to resume attack your server, this is a bit of annoyance at the least and most likely a good enough deterrent that the idiot moves on and looks for another potential victim server.

    Download the source distribution from:
    http://www.denyhosts.net/

    Step 1: Installing DenyHosts

    Once you have downloaded the source and extracted the  source in /usr/local/src, do the following from the newly created DenyHosts-<version> directory:

    • Run: python setup.py install
    • to install the package

    • Change directory to /usr/share/denyhosts
    • Run: cp denyhosts.cfg-dist denyhosts.cfg to copy the sample configuration into a new configuration file that you can edit
    • The sample configuration has comments that you can follow to make any applicable changes if needed. Here is the list of options (shown without the comments) that you can configure:

      SECURE_LOG = /var/log/secure
      HOSTS_DENY = /etc/hosts.deny
      PURGE_DENY =
      BLOCK_SERVICE  = sshd
      DENY_THRESHOLD_INVALID = 5
      DENY_THRESHOLD_VALID = 10
      DENY_THRESHOLD_ROOT = 1
      DENY_THRESHOLD_RESTRICTED = 1
      WORK_DIR = /usr/share/denyhosts/data
      SUSPICIOUS_LOGIN_REPORT_ALLOWED_HOSTS=YES
      HOSTNAME_LOOKUP=YES
      LOCK_FILE = /var/lock/subsys/denyhosts
      ADMIN_EMAIL =
      SMTP_HOST = localhost
      SMTP_PORT = 25
      SMTP_FROM = DenyHosts
      SMTP_SUBJECT = DenyHosts Report
      AGE_RESET_VALID=5d
      AGE_RESET_ROOT=25d
      AGE_RESET_RESTRICTED=25d
      AGE_RESET_INVALID=10d
      DAEMON_LOG = /var/log/denyhosts
      DAEMON_SLEEP = 30s
      DAEMON_PURGE = 1h
    • By default,  DenyHosts will block access to ssh service by placing an entry sshd: <bad ip address> in the /etc/hosts.deny file. However, if you like to block all the xinetd services that check /etc/hosts.deny than set BLOCK_SERVICE = ALL
    • By default, DENY_THRESHOLD_INVALID is set to 5, which means that after five invalid attempts using wrong password, the intruder will be locked by because DenyHosts will add the intruder’s IP address in the /etc/hosts.deny file
    • By default, DENY_THRESHOLD_ROOT is set to 1, which means, that after one invalid attempt to login as root user, DenyHosts will disable the IP address. However, we highly recommend that you completely disable root login via SSH. See Stop root Login via SSH Immediately!
    • To receive email from DenyHosts, set the ADMIN_EMAIL field to your email address. You will also have to set SMTP_HOST and SMTP_PORT to approrpiate values unless the defaults — assumes that you are running a SMTP mail server on local host — works for you. If your SMTP server requires username and password, you will also have to uncomment and set SMTP_USERNAME and SMTP_PASSWORD to appropriate values. You should also review SMTP_FROM to make sure that the email address used as the From header in the email sent by DenyHost is OK. You might have to white list this email address in your anti-spam program/appliance, etc.  Similarly, review the SMTP_SUBJECT field’s default value to meet your needs
    • Now copy the sample daemon control file in /usr/share/denyhosts using cp daemon-control-dist daemon-control. You can review the daemon-control file but most likely it will work as-is
    • To start DenyHosts automatically at server startup/reboot, create a symbolic link as follows:
      ln -s /usr/share/denyhosts/daemon-control /etc/init.d/denyhosts
    • Now add the denyhosts service to your current runlevel using chkconfig --add denyhosts

    Step 2: Starting DenyHosts for the First Time

    To start DenyHosts, run service denyhosts start and you should see something similar to the following:

    starting DenyHosts:
    /usr/bin/env python /usr/bin/denyhosts.py --daemon \
                                              --config=/usr/share/denyhosts/denyhosts.cfg

    To ensure that it is running, run ps x | grep denyhosts and you should see something similar to the following:

    28788 ? S 0:00 python /usr/bin/denyhosts.py --daemon --config=/usr/share/denyhosts/denyhosts.cfg

    If you see a running denyhosts script that has been started using python you are all set!

    Step 3: Excluding Known IP Addresses from Getting Denied

    If you have users who forget their SSH username a lot and they access your SSH server from known static IP addresses, you can exclude these IP addresses from DenyHost’s radar. Here is how:

    • Create a text file called /usr/share/denyhosts/data/allowed-hosts where each line represents a full IP address or a network address or a range of IP addresses. For example:
      # Your static IP
      130.86.1.1
      
      # Your other servers on the LAN that connects to your SSH server
      192.168.1.[1-254]
    • Once you have created this file, restart DenyHosts using service denyhosts restart

    Now if any of the users using the IP addresses listed in the allowed-hosts files ever misspell their username multiple times, they won’t call you. Because, denyhosts will forgive them for good. This might not be a good practice since you want your users to really know what they are doing and perhaps you DO want them to get locked out when they forget their username. How much can you take? Never mind.

    Step 4: Testing Your DenyHosts Setup

    To test your denyhosts setup, do the following:

    • From a host that is NOT included in your /usr/share/denyhosts/data/allowed-hosts file, attempt to make a SSH connection to your SSH server using an invalid username
    • You should be able to retry DENY_THRESHOLD_INVALID (5) times by default
    • Simultaneously, you want to setup a tail -f /var/log/denyhosts session to observe how denyhosts is behaving after the maximum threshold has been reached. You will see that denyhosts has created a log entry such as:
      2008-11-25 14:56:08,705 - denyhosts   : INFO     new denied hosts: ['100.200.1.2']
    • This shows that denyhosts has blocked this IP from accessing the server via SSH. You can also verify that this IP is now listed in /etc/hosts.deny file

    To test if an allowed IP address can make username mistakes, just add the IP address in the /usr/share/denyhosts/data/allowed-hosts file and try to access the SSH server using invalid username and/or password. You will be allowed to try as much as you like.

    Step 5: Using Centralized DenyHosts Knowledge base

    The denyhosts.net provides a free global synchronization of attack data. The benefits are:

    • You receive IP addresses that have been already considered bad by other hosts elsewhere in the world. This way, you get to ban the bad IP addresses before they attack your server
    • Your bad IP addresses are contributed to the global pool of bad IP addresses so that someone else’s server can ban the IP before any attempt is made to access such a server

    To enable this service, edit the /usr/share/denyhosts/denyhosts.cfg file as follows:

    • Uncomment SYNC_SERVER = http://xmlrpc.denyhosts.net:9911 to allow DenyHosts to send and receive synchronization data from the denyhosts.net service
    • Uncomment SYNC_INTERVAL = 1h so that your DenyHosts deamon can contact the denyhosts.net every hour
    • If you wish to upload your bad IP list, uncomment and set SYNC_UPLOAD = yes
    • If you wish to download bad IP list from denyhosts.net, uncomment and set SYNC_DOWNLOAD = yes

    Stop root Login via SSH Immediately!

    Published November 25th, 2008 by kabir

    Problem Statement

    If you are still allowing root login via SSH, you love living on the edge, don’t ya? I didn’t think so. Here in this short article you will find out how to disable root login and still gain root access in a manner that is safer than direct root login via SSH.

    Disabling root user login via SSH

    Edit the /etc/ssh/sshd_config file and see if you have PermitRootLogin directive set to yes. Change this directive to be:

    PermitRootLogin no
    

    Save the changes and restart SSH daemon using service sshd restart. Now try to login to your SSH server from a remote system using the root account. For example:

    $ ssh -l root your.server -p [ssh port]
    

    If you are not able to login via root, great!. Use a standard user account to ssh to your server and then use su - to switch to root user. Using su is much better than direct login as root because:

    • Bad guys cannot keep on trying to guess your root password
    • Root user account should be only used occasionally and switching from a regular user to root makes more sense as your normal privilege is limited and thus less damage in case someone guesses your password.

    Securing WordPress Blog Upload Directory

    Published November 10th, 2008 by kabir

    Problem Statement:

    We recently uploaded a few sample PHP script on as available downloads for an article in this blog and one of our lead engineers realized that WordPress is allowing PHP execution on the upload directory by default! This is BAD! Here is how to fix this simple but potentially high risk problem with WordPress upload directory on a Apache Web server.

    Step 1: Edit your Virtual Host Configuration for the Blog

    In your virtual host configuration for the blog, add the following directives:

       <DirectoryMatch "/uploads/">
          AddType text/plain .php
       </DirectoryMatch>
    

    This will make sure that any request for a file ending with .php in /uploads/ results in displaying the contents of the file instead of executing it on your server.

    Step 2: Restart Apache and test your new settings

    Now restart Apache Web server and upload a file with .php extension in one of your blog posts using WordPress. Once file is uploaded and you have added the file link in your blog post, save the post.

    You can post a simple script has follows:

    Visit the post and click on the file link and see if it runs the script or shows the source code. If you see PHP source code, you are done!