30
Sep
14

More useless crap with proc

Im currently on a Security course and one of the tasks we got set today was to create a a small script that would close a port only once a TCP connection had fully established. There was another lab on using nessus which i was suppose to do first but lets be honest nessus isn’t exactly rocket science and this seemed much more fun. It didn’t take long before i hacked something together and came up with the following script

#!/bin/sh
while :
do
  netstat -ant | awk '$6=="ESTABLISHED" {print $4,$5}' | while read IN
  do
    SRC=${IN% *}
    DST=${IN#* }
    if [ "${SRC#*:}" -eq "5555" ]
    then
      echo "Kill: ${DST%:*}"
      iptables -I INPUT -s ${DST%:*} -p tcp --dport ${SRC#*:} -j REJECT --reject-with icmp-host-prohibited
    fi
  done
  sleep 1
  iptables -F
done

However i didn’t really like this because it left the old connection hanging around in the CLOSE_WAIT state. After my previous fairway in to the proc system I wondered if i could improve on the above script by closing the file handle directly. So the first thing to do is fetch the inode associated with the listening port. Previously i used `netstat -tnpo` for this but we shouldn’t need to call a binary to get this information so i decided to just parse the dev system which gave me the following script

#!/bin/bash
PORT=5555
H_PORT=$(echo "obase=16; ${PORT}" | bc)
while :
do
  awk '{print $2,$10}' /proc/net/tcp | while read IN
  do
    SRC=${IN% *}
    INODE=${IN#* }
    print "Port: ${SRC#*:}, Inode: ${INODE}
  done
done

Adding this with the hackary from the previous post we can get the associate pid and file handle, we could probably simplify the below as i suspect we could find out the pid in a better manner as we will likely already know the listening PID. Anyway i had the code from before so i may as well use it, this gives us

while :
do
  awk '{print $2,$10}' /proc/net/tcp | while read IN
  do
    SRC=${IN% *}
    INODE=${IN#* }
    if [ "${SRC#*:}" == "${H_PORT}" -a ${SRC%:*} != '00000000' ]
    then
      for FD in /proc/*/fd/* ; do
        SOCKET_INODE=$(stat -c  %N ${FD} 2>/dev/null | awk -F\: '/socket:\[[0-9]+\]/ {gsub(/[\[\]]/, "", $NF);print $NF}')
        if [ "${INODE}" == "${SOCKET_INODE%?}" ]
        then
          echo "Kill: ${FD}" 
        fi
      done
    fi
  done
  sleep 1
done

So now all we need to do is kill this file descriptor. A quick google showed this should be pretty simple to do with gdb, however every-time i tried this i kept getting the following error

GNU gdb Fedora (6.8-24.fc9)
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i386-redhat-linux-gnu".
Attaching to process 16157
Reading symbols from /usr/local/bin/nc...(no debugging symbols found)...done.
(no debugging symbols found)
0x0805c008 in ?? ()
(gdb) p close(4)
No symbol table is loaded.  Use the "file" command.
(gdb) quit
The program is running.  Quit anyway (and detach it)? (y or n) y
Detaching from program: /usr/local/bin/nc, process 16157

Now im a long way from being a gdb expert but it seemed that nc had not been compiled with the right options, i would have still expected it to be able to preform this function but alas i couldn’t kick it in the right place to make it listen to me. So i thought i would give ncat a go, nc is pretty obsolete anyway and its likely that ncat was compiled with symbols. A quick test and it looked like it worked.

 gdb -p 6592
GNU gdb Fedora (6.8-24.fc9)
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i386-redhat-linux-gnu".
Attaching to process 6592
Reading symbols from /usr/bin/ncat...(no debugging symbols found)...done.
Reading symbols from /lib/libdl.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib/libdl.so.2
Reading symbols from /lib/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/ld-linux.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib/ld-linux.so.2

(no debugging symbols found)
0x00892416 in __kernel_vsyscall ()
Missing separate debuginfos, use: debuginfo-install nmap.i386
(gdb) p close (4)
$1 = 0
(gdb) quit
The program is running.  Quit anyway (and detach it)? (y or n) y
Detaching from program: /usr/bin/ncat, process 6592

Awesome now we are in business just a matter of putting it all together and we get the following

#!/bin/bash
PORT=5555
H_PORT=$(echo "obase=16; ${PORT}" | bc)
while :
do
  awk '{print $2,$10}' /proc/net/tcp | while read IN
  do
    SRC=${IN% *}
    INODE=${IN#* }
    if [ "${SRC#*:}" == "${H_PORT}" -a ${SRC%:*} != '00000000' ]
    then
      for FD in /proc/*/fd/* ; do
        SOCKET_INODE=$(stat -c  %N ${FD} 2>/dev/null | awk -F\: '/socket:\[[0-9]+\]/ {gsub(/[\[\]]/, "", $NF);print $NF}')
        if [ "${INODE}" == "${SOCKET_INODE%?}" ]
        then
          PROC=(${FD//\// })
          gdb -p ${PROC[1]} <<< "p close(${PROC[3]})"
        fi
      done
    fi
  done
  sleep 1
done

Unfortunately there is a small problem with this. it seems that been so heavy handed and forcing the file handle to close causes ncat to get into a strange state. new connections seem to be assigned inode 0 and i can’t find a file handle associated with them so it doesn’t really fit the initial use case and means it is pretty useless, although, i think you will agree, it is elegant is its uselessness :). Its worth mentioning that the socket is still open and i can send data through it so its possible this trick may open other avenues we can exploit.

[root@linux ~]# netstat -tnpe
Proto Recv-Q Send-Q Local Address               Foreign Address             State       User       Inode      PID/Program name
tcp        0      0 10.10.75.5:5555             10.10.75.3:57851            ESTABLISHED 0          0          -
tcp        0      0 10.10.75.5:5555             10.10.75.3:57859            ESTABLISHED 0          0          -
[root@linux ~]# tcpdump -nnvvi eth0 port 5555
23:05:04.160869 IP (tos 0x10, ttl 64, id 14484, offset 0, flags [DF], proto TCP (6), length 59)
    10.10.75.3.57851 > 10.10.75.5.5555: Flags [P.], cksum 0x61e0 (correct), seq 111:118, ack 1, win 8235, options [nop,nop,TS val 31297540 ecr 5667926], length 7
23:05:04.160890 IP (tos 0x0, ttl 64, id 7215, offset 0, flags [DF], proto TCP (6), length 52)
    10.10.75.5.5555 > 10.10.75.3.57851: Flags [.], cksum 0xae42 (correct), seq 1, ack 118, win 181, options [nop,nop,TS val 5668951 ecr 31297540], length 0
23:06:59.551591 IP (tos 0x10, ttl 64, id 27876, offset 0, flags [DF], proto TCP (6), length 59)
    10.10.75.3.57859 > 10.10.75.5.5555: Flags [P.], cksum 0xba4f (correct), seq 2737832488:2737832495, ack 2038745254, win 8235, options [nop,nop,TS val 31408622 ecr 5085920], length 7
23:06:59.551611 IP (tos 0x0, ttl 64, id 21062, offset 0, flags [DF], proto TCP (6), length 52)
    10.10.75.5.5555 > 10.10.75.3.57859: Flags [.], cksum 0x6570 (correct), seq 1, ack 7, win 181, options [nop,nop,TS val 5784341 ecr 31408622], length 0
Advertisements

0 Responses to “More useless crap with proc”



  1. Leave a Comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s


%d bloggers like this: