Back to success stories

Sample of Defect

Project Name CID Checker Category Developer Description
freetds2 90703 FORWARD_NULL Null pointer dereferences This bug was quite hard to spot! This could allow the server to make the client crash due to the NULL pointer dereference.
File: /src/tds/challenge.c
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
        prefix->response_type = 0x01;
        prefix->max_response_type = 0x01;
        prefix->reserved1 = 0x0000;
        prefix->reserved2 = 0x00000000;
#ifdef WORDS_BIGENDIAN
        tds_swap_bytes(&nttime, 8);
#endif
        prefix->timestamp = nttime;
        tds_random_buffer(prefix->challenge, sizeof(prefix->challenge));

        prefix->unknown = 0x00000000;
}

static TDSRET
tds_ntlm_handle_next(TDSSOCKET * tds, struct tds_authentication * auth, size_t len)
{
        const int length = (int)len;
        unsigned char nonce[8];
        TDS_UINT flags;
        int where;

        int data_block_offset;

        int names_blob_len = 0;
 << 1. Assigning: "names_blob" = "NULL".
600
601
602
603
604
        unsigned char *names_blob = NULL;

        TDSRET rc;

        /* at least 32 bytes (till context) */
 < 2. Condition "len < 32", taking false branch
605
606
607
608
        if (len < 32)
                return TDS_FAIL;

        tds_get_n(tds, nonce, 8);        /* NTLMSSP\0 */
 < 3. Condition "memcmp(nonce, ntlm_id, 8) != 0", taking false branch
609
610
        if (memcmp(nonce, ntlm_id, 8) != 0)
                return TDS_FAIL;
 < 4. Condition "(TDS_INT)tds_get_uint(tds) != 2", taking false branch
611
612
613
614
615
616
617
        if (tds_get_int(tds) != 2)        /* sequence -> 2 */
                return TDS_FAIL;
        tds_get_smallint(tds);        /* domain len */
        tds_get_smallint(tds);        /* domain len */
        data_block_offset = tds_get_int(tds);        /* domain offset */
        flags = tds_get_int(tds);        /* flags */
        tds_get_n(tds, nonce, 8);
 < 5. Condition "!!tds_write_dump", taking true branch
 < 6. Condition "!!tds_write_dump", taking true branch
618
619
620
621
622
        tdsdump_dump_buf(TDS_DBG_INFO1, "TDS_AUTH_TOKEN nonce", nonce, 8);
        where = 32;

        /*data_block_offset == 32 */
        /* Version 1 -- The Context, Target Information, and OS Version structure are all omitted */
 < 7. Condition "data_block_offset >= 48", taking true branch
 < 8. Condition "where + 16 <= length", taking true branch
624
625
626
627
628
629
630
631
632
633
634
        if (data_block_offset >= 48 && where + 16 <= length) {
                int target_info_len, target_info_offset;

                /* Version 2 -- The Context and Target Information fields are present, but the OS Version structure is not. */
                tds_get_n(tds, NULL, 8);        /* Context (two consecutive longs) */

                target_info_len = tds_get_smallint(tds);        /* Target Information len */
                target_info_len = tds_get_smallint(tds);        /* Target Information len */
                target_info_offset = tds_get_int(tds);        /* Target Information offset */

                where += 16;
 < 9. Condition "data_block_offset >= 56", taking true branch
 < 10. Condition "where + 8 <= length", taking true branch
636
637
638
639
640
641
642
643
644
645
646
647
                if (data_block_offset >= 56 && where + 8 <= length) {
                        /* Version 3 -- The Context, Target Information, and OS Version structure are all present. */
                        tds_get_n(tds, NULL, 8);        /* OS Version Structure */
#if 0
                        /* if we have a version server handle NTLMv2 */
                        if (target_info_len > 0)
                                flags &= ~0x80000;
#endif
                        where += 8;
                }

                /* read Target Info if possible */
 < 11. Condition "target_info_len > 0", taking true branch
 < 12. Condition "target_info_offset >= where", taking true branch
 < 13. Condition "target_info_offset + target_info_len <= length", taking false branch
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
                if (target_info_len > 0 && target_info_offset >= where && target_info_offset + target_info_len <= length) {
                        tds_get_n(tds, NULL, target_info_offset - where);
                        where = target_info_offset;

                        /*
                         * the + 4 came from blob structure, after Target Info 4
                         * additional reserved bytes must be present
                         * Search "davenport port"
                         * (currently http://davenport.sourceforge.net/ntlm.html)
                         */
                        names_blob_len = TDS_OFFSET(names_blob_prefix_t, target_info) + target_info_len + 4;

                        /* read Target Info */
                        names_blob = (unsigned char *) calloc(names_blob_len, 1);
                        if (!names_blob)
                                return TDS_FAIL;

                        fill_names_blob_prefix((names_blob_prefix_t *) names_blob);
                        tds_get_n(tds, names_blob + TDS_OFFSET(names_blob_prefix_t, target_info), target_info_len);
                        where += target_info_len;
                }
        }
        /* discard anything left */
        tds_get_n(tds, NULL, length - where);
 < 14. Condition "!!tds_write_dump", taking true branch
 < 15. Condition "!!tds_write_dump", taking true branch
672
        tdsdump_log(TDS_DBG_INFO1, "Draining %d bytes\n", (int) (len - where));
 <<< CID 90703: Null pointer dereferences FORWARD_NULL
 <<< 16. Passing null pointer "names_blob" to "tds7_send_auth", which dereferences it.
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
        rc = tds7_send_auth(tds, nonce, flags, names_blob, names_blob_len);

        free(names_blob);

        return rc;
}

/**
 * Build a NTLMSPP packet to send to server
 * @param tds     A pointer to the TDSSOCKET structure managing a client/server operation.
 * @return authentication info
 */
TDSAUTHENTICATION * 
tds_ntlm_get_auth(TDSSOCKET * tds)
{
        const char *domain;
        const char *user_name;
        const char *p;
        TDS_UCHAR *packet;
        int host_name_len;
        int domain_len;
        int auth_len;
        struct tds_ntlm_auth *auth;

        if (!tds->login)
                return NULL;
Events:
1. assign_zero challenge.c:600
16. var_deref_model challenge.c:674