00001 //--------------------------------------------------------------------------
00002 // Copyright (C) 2014-2017 Cisco and/or its affiliates. All rights reserved.
00003 // Copyright (C) 2005-2013 Sourcefire, Inc.
00004 // Copyright (C) 1998-2005 Martin Roesch <roesch@sourcefire.com>
00005 //
00006 // This program is free software; you can redistribute it and/or modify it
00007 // under the terms of the GNU General Public License Version 2 as published
00008 // by the Free Software Foundation. You may not use, modify or distribute
00009 // this program under any other version of the GNU General Public License.
00010 //
00011 // This program is distributed in the hope that it will be useful, but
00012 // WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00014 // General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU General Public License along
00017 // with this program; if not, write to the Free Software Foundation, Inc.,
00018 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019 //--------------------------------------------------------------------------
00020
00021 /* bo
00022 *
00023 * Purpose: Detects Back Orifice traffic by brute forcing the weak encryption
00024 * of the program's network protocol and detects the magic cookie
00025 * that it's servers and clients require to communicate with each
00026 * other.
00027 *
00028 * Effect: Analyzes UDP traffic for the BO magic cookie, reports if it finds
00029 * traffic matching the profile.
00030 *
00031 */
00032
00033 /*
00034 * The following text describes a couple of ways in which the Back Orifice
00035 * signature is calculated. The snort runtime generated an array of 65K
00036 * possible signatures, of which two are described here. Refer back to
00037 * this simplified algorithm when evaluating the snort code below.
00038 *
00039 * Back Orifice magic cookie is "*!*QWTY?", which is located in the first
00040 * eight bytes of the packet. But it is encrypted using an XOR. Here we'll
00041 * generate a sequence of eight bytes which will decrypt (XOR) into the
00042 * magic cookie. This test uses the NON-DEFAULT KEY to initialize (seed) the
00043 * "random" number generator. The default seed results in the following
00044 * sequence of bytes: E4 42 FB 83 41 B3 4A F0. When XOR'd against the
00045 * magic cookie, we have our packet data which looks like a Back Orifice
00046 * signature:
00047 *
00048 * Cookie: 2A 21 2A 51 57 54 59 3F
00049 * Random: E4 42 FB 83 41 B3 4A F0
00050 * ------- -- -- -- -- -- -- -- --
00051 * Result: CE 63 D1 D2 16 E7 13 CF (XOR'd result)
00052 *
00053 * For demonstration purposes:
00054 *
00055 * static long holdrand = 1L;
00056 * static int LocalBoRand()
00057 * {
00058 * return(((holdrand = holdrand * 214013L + 2531011L) >> 16) & 0x7fff);
00059 * }
00060 * ...
00061 *
00062 * int BoRandValues_NonDefaultKey[8];
00063 * holdrand = BO_DEFAULT_KEY; (seed value)
00064 * BoRandValues_NonDefaultKey[0] = LocalBoRand() % 256; --> 228 (0xe4)
00065 * BoRandValues_NonDefaultKey[1] = LocalBoRand() % 256; --> 66 (0x42)
00066 * BoRandValues_NonDefaultKey[2] = LocalBoRand() % 256; --> 251 (0xfb)
00067 * BoRandValues_NonDefaultKey[3] = LocalBoRand() % 256; --> 131 (0x83)
00068 * BoRandValues_NonDefaultKey[4] = LocalBoRand() % 256; --> 65 (0x41)
00069 * BoRandValues_NonDefaultKey[5] = LocalBoRand() % 256; --> 179 (0xb3)
00070 * BoRandValues_NonDefaultKey[6] = LocalBoRand() % 256; --> 74 (0x4a)
00071 * BoRandValues_NonDefaultKey[7] = LocalBoRand() % 256; --> 240 (0xf0)
00072 *
00073 *
00074 * The following test uses the DEFAULT KEY to initialize (seed) the
00075 * "random" number generator. The default seed results in the following
00076 * sequence of bytes: 26 27 F6 85 97 15 AD 1D. When XOR'd against the
00077 * magic cookie, we have our packet data which looks like a Back Orifice
00078 * signature:
00079 *
00080 * Cookie: 2A 21 2A 51 57 54 59 3F
00081 * Random: 26 27 F6 85 97 15 AD 1D
00082 * ------- -- -- -- -- -- -- -- --
00083 * Result: 0C 06 DC D4 C0 41 F4 22 (XOR'd result)
00084 *
00085 * For demonstration purposes:
00086 *
00087 * int BoRandValues_DefaultKey[8];
00088 * holdrand = 0; (seed value)
00089 * BoRandValues_DefaultKey[0] = LocalBoRand() % 256; --> 38 (0x26)
00090 * BoRandValues_DefaultKey[1] = LocalBoRand() % 256; --> 39 (0x27)
00091 * BoRandValues_DefaultKey[2] = LocalBoRand() % 256; --> 246 (0xf6)
00092 * BoRandValues_DefaultKey[3] = LocalBoRand() % 256; --> 133 (0x85)
00093 * BoRandValues_DefaultKey[4] = LocalBoRand() % 256; --> 151 (0x97)
00094 * BoRandValues_DefaultKey[5] = LocalBoRand() % 256; --> 21 (0x15)
00095 * BoRandValues_DefaultKey[6] = LocalBoRand() % 256; --> 173 (0xad)
00096 * BoRandValues_DefaultKey[7] = LocalBoRand() % 256; --> 29 (0x1d)
00097 *
00098 * Notes:
00099 *
00100 * 10/13/2005 marc norton - This has a lot of changes to the runtime
00101 * decoding and testing. The '% 256' op was removed,
00102 * the xor op is bit wise so modulo is not needed,
00103 * the char casting truncates to one byte,
00104 * and len testing has been modified as was the xor decode copy and
00105 * final PONG test.
00106 */
00107
00108 #ifdef HAVE_CONFIG_H
00109 #include "config.h"
00110 #endif
00111
00112 #include "detection/detection_engine.h"
00113 #include "events/event_queue.h"
00114 #include "framework/inspector.h"
00115 #include "framework/module.h"
00116 #include "log/messages.h"
00117 #include "profiler/profiler.h"
00118 #include "protocols/packet.h"
00119
00120 #include "main/snort_debug.h"
00121
00122 #define BO_DEFAULT_KEY 31337
00123 #define BO_MAGIC_SIZE 8
00124 #define BO_MIN_SIZE 18
00125 #define BO_DEFAULT_PORT 31337
00126
00127 #define BO_TYPE_PING 1
00128 #define BO_FROM_UNKNOWN 0
00129 #define BO_FROM_CLIENT 1
00130 #define BO_FROM_SERVER 2
00131
00132 #define BO_BUF_SIZE 8
00133 #define BO_BUF_ATTACK_SIZE 1024
00134
00135 #define s_name "back_orifice"
00136
00137 #define s_help \
00138 "back orifice detection"
00139
00140 /* global keyvalue for the BoRand() function */
00141 static THREAD_LOCAL uint64_t holdrand = 1;
00142
00143 // these are const during runtime
00144 static uint16_t lookup1[65536][3];
00145 static uint16_t lookup2[65536];
00146
00147 static THREAD_LOCAL ProfileStats boPerfStats;
00148 static THREAD_LOCAL SimpleStats bostats;
00149
00150 //-------------------------------------------------------------------------
00151 // bo module
00152 //-------------------------------------------------------------------------
00153
00154 #define GID_BO 105
00155
00156 #define BO_TRAFFIC_DETECT 1
00157 #define BO_CLIENT_TRAFFIC_DETECT 2
00158 #define BO_SERVER_TRAFFIC_DETECT 3
00159 #define BO_SNORT_BUFFER_ATTACK 4
00160
00161 #define BO_TRAFFIC_DETECT_STR \
00162 "BO traffic detected"
00163 #define BO_CLIENT_TRAFFIC_DETECT_STR \
00164 "BO client traffic detected"
00165 #define BO_SERVER_TRAFFIC_DETECT_STR \
00166 "BO server traffic detected"
00167 #define BO_SNORT_BUFFER_ATTACK_STR \
00168 "BO Snort buffer attack"
00169
00170 static const RuleMap bo_rules[] =
00171 {
00172 { BO_TRAFFIC_DETECT, BO_TRAFFIC_DETECT_STR },
00173 { BO_CLIENT_TRAFFIC_DETECT, BO_CLIENT_TRAFFIC_DETECT_STR },
00174 { BO_SERVER_TRAFFIC_DETECT, BO_SERVER_TRAFFIC_DETECT_STR },
00175 { BO_SNORT_BUFFER_ATTACK, BO_SNORT_BUFFER_ATTACK_STR },
00176
00177 { 0, nullptr }
00178 };
00179
00180 class BoModule : public Module
00181 {
00182 public:
00183 BoModule() : Module(s_name, s_help)
00184 { }
00185
00186 const RuleMap* get_rules() const override
00187 { return bo_rules; }
00188
00189 unsigned get_gid() const override
00190 { return GID_BO; }
00191
00192 const PegInfo* get_pegs() const override;
00193 PegCount* get_counts() const override;
00194 ProfileStats* get_profile() const override;
00195
00196 Usage get_usage() const override
00197 { return INSPECT; }
00198 };
00199
00200 const PegInfo* BoModule::get_pegs() const
00201 { return simple_pegs; }
00202
00203 PegCount* BoModule::get_counts() const
00204 { return (PegCount*)&bostats; }
00205
00206 ProfileStats* BoModule::get_profile() const
00207 { return &boPerfStats; }
00208
00209 //-------------------------------------------------------------------------
00210 // bo implementation
00211 //-------------------------------------------------------------------------
00212
00213 /*
00214 * Function: BoRand()
00215 *
00216 * Purpose: Back Orifice "encryption" algorithm
00217 *
00218 * Arguments: None.
00219 *
00220 * Returns: key to XOR with current char to be "encrypted"
00221 */
00222 static char BoRand()
00223 {
00224 holdrand = holdrand * 214013 + 2531011;
00225 return (char)((holdrand >> 16) & 0xFF);
00226 }
00227
00228 /*
00229 * Precalculate the known cyphertext into a prefix and suffix lookup table
00230 * to recover the key. Using this in the bo_eval() function below is much
00231 * faster than the old brute force method
00232 */
00233 static void PrecalcPrefix()
00234 {
00235 uint8_t cookie_cyphertext[BO_MAGIC_SIZE];
00236 const char* cookie_plaintext = "*!*QWTY?";
00237 int key;
00238 int cookie_index;
00239 const char* cp_ptr; /* cookie plaintext indexing pointer */
00240 uint16_t cyphertext_referent;
00241
00242 memset(lookup1, 0, sizeof(lookup1));
00243 memset(lookup2, 0, sizeof(lookup2));
00244
00245 for (key=0; key<65536; key++)
00246 {
00247 /* setup to generate cyphertext for this key */
00248 holdrand = key;
00249 cp_ptr = cookie_plaintext;
00250
00251 /* convert the plaintext cookie to cyphertext for this key */
00252 for (cookie_index=0; cookie_index<BO_MAGIC_SIZE; cookie_index++)
00253 {
00254 cookie_cyphertext[cookie_index] =(uint8_t)(*cp_ptr^(BoRand()));
00255 cp_ptr++;
00256 }
00257
00258 /*
00259 * generate the key lookup mechanism from the first 2 characters of
00260 * the cyphertext
00261 */
00262 cyphertext_referent = (uint16_t)(cookie_cyphertext[0] << 8) & 0xFF00;
00263 cyphertext_referent |= (uint16_t)(cookie_cyphertext[1]) & 0x00FF;
00264
00265 /* if there are any keyspace collisions that's going to suck */
00266 if (lookup1[cyphertext_referent][0] != 0)
00267 {
00268 if (lookup1[cyphertext_referent][1] != 0)
00269 {
00270 lookup1[cyphertext_referent][2] = (uint16_t)key;
00271 }
00272 else
00273 {
00274 lookup1[cyphertext_referent][1] = (uint16_t)key;
00275 }
00276 }
00277 else
00278 {
00279 lookup1[cyphertext_referent][0] = (uint16_t)key;
00280 }
00281
00282 /*
00283 * generate the second lookup from the last two characters of
00284 * the cyphertext
00285 */
00286 cyphertext_referent = (uint16_t)(cookie_cyphertext[6] << 8) & 0xFF00;
00287 cyphertext_referent |= (uint16_t)(cookie_cyphertext[7]) & 0x00FF;
00288
00289 /*
00290 * set the second lookup with the current key
00291 */
00292 lookup2[key] = cyphertext_referent;
00293 }
00294 }
00295
00296 /*
00297 * Purpose: Attempt to guess the direction this packet is going in.
00298 *
00299 * Arguments: p => pointer to the current packet data struct
00300 * pkt_data => pointer to data after magic cookie
00301 *
00302 * Returns: BO_FROM_UNKNOWN if direction unknown
00303 * BO_FROM_CLIENT if direction from client to server
00304 * BO_FROM_SERVER if direction from server to client
00305 *
00306 * Reference: http://www.magnux.org/~flaviovs/boproto.html
00307 * BO header structure:
00308 * Mnemonic Size in bytes
00309 * -------------------------
00310 * MAGIC 8
00311 * LEN 4
00312 * ID 4
00313 * T 1
00314 * DATA variable
00315 * CRC 1
00316 *
00317 */
00318 static int BoGetDirection(Packet* p, const char* pkt_data)
00319 {
00320 uint32_t len = 0;
00321 uint32_t id = 0;
00322 uint32_t l, i;
00323 char type;
00324 char plaintext;
00325
00326 /* Check for the default port on either side */
00327 if ( p->ptrs.dp == BO_DEFAULT_PORT )
00328 {
00329 return BO_FROM_CLIENT;
00330 }
00331 else if ( p->ptrs.sp == BO_DEFAULT_PORT )
00332 {
00333 return BO_FROM_SERVER;
00334 }
00335
00336 /* Didn't find default port, so look for ping packet */
00337
00338 /* Get length from BO header - 32 bit int */
00339 for ( i = 0; i < 4; i++ )
00340 {
00341 plaintext = (char)(*pkt_data ^ BoRand());
00342 l = (uint32_t)plaintext;
00343 len += l << (8*i);
00344 pkt_data++;
00345 }
00346
00347 /* Get ID from BO header - 32 bit int */
00348 for ( i = 0; i < 4; i++ )
00349 {
00350 plaintext = (char)(*pkt_data ^ BoRand() );
00351 l = ((uint32_t)plaintext) & 0x000000FF;
00352 id += l << (8*i);
00353 pkt_data++;
00354 }
00355
00356 DebugFormat(DEBUG_INSPECTOR, "Data length = %u\n", len);
00357 DebugFormat(DEBUG_INSPECTOR, "ID = %u\n", id);
00358
00359 /* Do more len checking */
00360
00361 if ( len >= BO_BUF_ATTACK_SIZE )
00362 {
00363 DetectionEngine::queue_event(GID_BO, BO_SNORT_BUFFER_ATTACK);
00364 return BO_FROM_UNKNOWN;
00365 }
00366
00367 /* Adjust for BO packet header length */
00368 if (len <= BO_MIN_SIZE)
00369 {
00370 /* Need some data, or we can't figure out client or server */
00371 return BO_FROM_UNKNOWN;
00372 }
00373 else
00374 {
00375 len -= BO_MIN_SIZE;
00376 }
00377
00378 if ( len > 7 )
00379 {
00380 len = 7; /* we need no more than 7 variable chars */
00381 }
00382
00383 /* Continue parsing BO header */
00384 type = (char)(*pkt_data ^ BoRand());
00385 pkt_data++;
00386
00387 /* check to make sure we don't run off end of packet */
00388 if ((uint32_t)(p->dsize - ((const uint8_t*)pkt_data - p->data)) < len)
00389 {
00390 /* We don't have enough data to inspect */
00391 return BO_FROM_UNKNOWN;
00392 }
00393
00394 if ( type & 0x80 )
00395 {
00396 DebugMessage(DEBUG_INSPECTOR, "Partial packet\n");
00397 }
00398 if ( type & 0x40 )
00399 {
00400 DebugMessage(DEBUG_INSPECTOR, "Continued packet\n");
00401 }
00402
00403 /* Extract type of BO packet */
00404 type = type & 0x3F;
00405
00406 DebugFormat(DEBUG_INSPECTOR, "Type = 0x%x\n", type);
00407
00408 /* Only examine data if this is a ping request or response */
00409 if ( type == BO_TYPE_PING )
00410 {
00411 if ( len < 7 )
00412 {
00413 return BO_FROM_CLIENT;
00414 }
00415 char buf1[BO_BUF_SIZE];
00416
00417 for (i=0; i<len; i++ ) /* start at 0 to advance the BoRand() function properly */
00418 {
00419 buf1[i] = (char)(pkt_data[i] ^ BoRand());
00420
00421 if ( buf1[i] == 0 )
00422 return BO_FROM_UNKNOWN;
00423 }
00424
00425 if ( ( buf1[3] == 'P' || buf1[3] == 'p' ) &&
00426 ( buf1[4] == 'O' || buf1[4] == 'o' ) &&
00427 ( buf1[5] == 'N' || buf1[5] == 'n' ) &&
00428 ( buf1[6] == 'G' || buf1[6] == 'g' ) )
00429 {
00430 return BO_FROM_SERVER;
00431 }
00432 else
00433 {
00434 return BO_FROM_CLIENT;
00435 }
00436 }
00437
00438 return BO_FROM_UNKNOWN;
00439 }
00440
00441 //-------------------------------------------------------------------------
00442 // class stuff
00443 //-------------------------------------------------------------------------
00444
00445 class BackOrifice : public Inspector
00446 {
00447 public:
00448 BackOrifice() = default;
00449
00450 void show(SnortConfig*) override;
00451 void eval(Packet*) override;
00452 };
00453
00454 void BackOrifice::show(SnortConfig*)
00455 {
00456 LogMessage("%s\n", s_name);
00457 }
00458
00459 void BackOrifice::eval(Packet* p)
00460 {
00461 Profile profile(boPerfStats);
00462
00463 new_invoked_inspector(9, p, 0);
00464
00465 const char* const magic_cookie = "*!*QWTY?";
00466
00467 // preconditions - what we registered for
00468 assert(p->is_udp());
00469
00470 // make sure it's at least 19 bytes long
00471 if (p->dsize < BO_MIN_SIZE)
00472 return;
00473
00474 ++bostats.total_packets;
00475
00476 // take the first two characters of the packet and generate the
00477 // first reference that gives us a reference key
00478 uint16_t cyphertext_referent = (uint16_t)(p->data[0] << 8) & 0xFF00;
00479 cyphertext_referent |= (uint16_t)(p->data[1]) & 0x00FF;
00480
00481 // generate the second referent from the last two characters
00482 // of the cyphertext
00483 uint16_t cyphertext_suffix = (uint16_t)(p->data[6] << 8) & 0xFF00;
00484 cyphertext_suffix |= (uint16_t)(p->data[7]) & 0x00FF;
00485
00486 for ( int i = 0; i < 3; ++i )
00487 {
00488 // get the key from the cyphertext
00489 uint16_t key = lookup1[cyphertext_referent][i];
00490
00491 // if the lookup from the proposed key matches the cyphertext reference
00492 // then we've probably go the right key and can proceed to full
00493 // decryption using the key
00494 // moral of the story: don't use a lame keyspace
00495 if ( lookup2[key] == cyphertext_suffix )
00496 {
00497 auto pkt_data = reinterpret_cast<const char*>(p->data);
00498 auto end = pkt_data + BO_MAGIC_SIZE;
00499 const char* magic_data = magic_cookie;
00500
00501 holdrand = key;
00502
00503 while ( pkt_data < end )
00504 {
00505 char plaintext = *pkt_data ^ BoRand();
00506
00507 if ( *magic_data != plaintext )
00508 {
00509 DebugFormat(DEBUG_INSPECTOR,
00510 "Failed check one on 0x%X : 0x%X\n",
00511 *magic_data, plaintext);
00512
00513 return;
00514 }
00515
00516 ++magic_data;
00517 ++pkt_data;
00518 }
00519
00520 // if we fall thru there's a detect
00521 DebugMessage(DEBUG_INSPECTOR,
00522 "Detected Back Orifice Data!\n");
00523 DebugFormat(DEBUG_INSPECTOR, "hash value: %d\n", key);
00524
00525 int bo_direction = BoGetDirection(p, pkt_data);
00526
00527 if ( bo_direction == BO_FROM_CLIENT )
00528 {
00529 DetectionEngine::queue_event(GID_BO, BO_CLIENT_TRAFFIC_DETECT);
00530 DebugMessage(DEBUG_INSPECTOR, "Client packet\n");
00531 }
00532
00533 else if ( bo_direction == BO_FROM_SERVER )
00534 {
00535 DetectionEngine::queue_event(GID_BO, BO_SERVER_TRAFFIC_DETECT);
00536 DebugMessage(DEBUG_INSPECTOR, "Server packet\n");
00537 }
00538
00539 else
00540 DetectionEngine::queue_event(GID_BO, BO_TRAFFIC_DETECT);
00541 }
00542 }
00543 }
00544
00545 //-------------------------------------------------------------------------
00546 // api stuff
00547 //-------------------------------------------------------------------------
00548
00549 static Module* mod_ctor()
00550 { return new BoModule; }
00551
00552 static void mod_dtor(Module* m)
00553 { delete m; }
00554
00555 static void bo_init()
00556 {
00557 PrecalcPrefix();
00558 }
00559
00560 static Inspector* bo_ctor(Module*)
00561 {
00562 return new BackOrifice;
00563 }
00564
00565 static void bo_dtor(Inspector* p)
00566 {
00567 delete p;
00568 }
00569
00570 static const InspectApi bo_api =
00571 {
00572 {
00573 PT_INSPECTOR,
00574 sizeof(InspectApi),
00575 INSAPI_VERSION,
00576 0,
00577 API_RESERVED,
00578 API_OPTIONS,
00579 s_name,
00580 s_help,
00581 mod_ctor,
00582 mod_dtor
00583 },
00584 IT_NETWORK,
00585 (uint16_t)PktType::UDP,
00586 nullptr, // buffers
00587 nullptr, // service
00588 bo_init,
00589 nullptr, // pterm
00590 nullptr, // tinit
00591 nullptr, // tterm
00592 bo_ctor,
00593 bo_dtor,
00594 nullptr, // ssn
00595 nullptr // reset
00596 };
00597
00598 #ifdef BUILDING_SO
00599 SO_PUBLIC const BaseApi* snort_plugins[] =
00600 {
00601 &bo_api.base,
00602 nullptr
00603 };
00604 #else
00605 const BaseApi* sin_bo = &bo_api.base;
00606 #endif
00607
END OF CODE