On 29 Jan 2014, at 09:45, Konrad Rosenbaum <[email protected]> wrote:
>  
> 1) create a fresh TCP connection for each Websocket, this way it is not 
> possible to combine a previous HTTP request and a socket in an attack; 
> consequently: if the handshake fails: terminate the TCP connection!
This is already happening in the implementation.
>  
> 2) when faced with an explicitly configured proxy: ALWAYS use the CONNECT 
> method before sending the actual socket request - proxies do not care about 
> the socket content after a CONNECT is through - additionally there are 
> probably close to zero deployed proxies that even understand the semantics of 
> Upgrade: websocket.
>  
> Unfortunately 2) does not help with broken transparent proxies, since by 
> their nature you cannot detect them easily and it is not a good strategy to 
> send a CONNECT just in case…
The implementation uses the QNetworkProxy implementation.
>  
> 3) implement masking properly.
>  
> The latter can be done in stages, I'd propose this plan:
>  
> First: implement websockets, get them into Qt. For the mask generation create 
> a virtual protected method "QByteArray getNextMaskValue(int numbytes)const" 
> and implement it using qrand()&0xff for each byte - please note that you have 
> to initialize with qsrand in each thread.


If I use std::random as Thiago proposed (see 
http://en.cppreference.com/w/cpp/numeric/random), like:

    //one time initialisation
    Q_CONST_EXPR std::size_t numSeeds = 13;     //arbitrary number
    quint32 seeds[numSeeds] = { 0 };
    bool success = false;

    try {
        std::random_device seeder;              //supported since MSVS 2008, 
since GCC 4.5
        if (seeder.entropy() >= 0.5) {
            std::generate_n(seeds, numSeeds, seeder);
            success = true;
        }
    } catch (const std::exception &) {
        //fall through
    }
#ifdef Q_OS_WIN  //the MinGW implementation of GCC 4.8 has a known bug in 
std::random_device
    if (!success) {
        HCRYPTPROV hp = 0;
        BYTE rb[4];
        if ((success = CryptAcquireContext(&hp, 0, 0, PROV_RSA_FULL, 
CRYPT_VERIFYCONTEXT)) == TRUE)
            for (std::size_t i = 0; i < numSeeds; ++i) {
                if ((success = CryptGenRandom(hp, sizeof(quint32), seeds + i) 
!= TRUE)
                    break;
        }
        CryptReleaseContext(hp, 0);
    }
#endif
    if (!success) {
        qsrand(static_cast<uint>(QDateTime::currentMSecsSinceEpoch()));
        for (std::size_t i = 0; i < numSeeds; ++i) {
            const qreal multiplier = qreal(std::numeric_limits<quint8>::max()) 
/ qreal(RAND_MAX);
            const quint32 byte1 = quint32(qrand() * multiplier) & 0xFF;
            const quint32 byte2 = quint32(qrand() * multiplier) & 0xFF;
            const quint32 byte3 = quint32(qrand() * multiplier) & 0xFF;
            const quint32 byte4 = quint32(qrand() * multiplier) & 0xFF;
            seeds[i] = byte1 | byte2 << 8 | byte3 << 16 | byte4 << 24;
        }
    }

    std::seek_seq seedSequence(seeds, seeds + numSeeds);
    std::mt19937 randomiser(seedSequence);
    //std::uniform_int_distribution<std::uint32_t> dist;        //range from 0 
to UINT_MAX


    //somewhere else
    return randomiser();        //no need to use a distribution function as 
mt19937 outputs 2^32


Would this already be more acceptable?
Of course, this implementation requires C++11 support.
An interesting presentation about std::random can be found here: 
http://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful

If the above implementation suffices, then a virtual method would not be needed 
anymore.

Should I fall back to the ordinary qrand() when the other methods fail?

> Document the shortcoming with something like this:
>  
> "This implementation of WebSockets uses cryptographically weak random numbers 
> during communication. If you allow user generated or downloaded scripts to 
> access WebSockets, then malicious scripts could abuse this implementation to 
> attack some vulnerable web proxy servers (e.g. for cache poisoning). In this 
> case it is recommended that you reimplement getNextMaskValue to use 
> cryptographically strong random numbers."
> (maybe add a link to the paper)



Cheers,

Kurt

_______________________________________________
Development mailing list
[email protected]
http://lists.qt-project.org/mailman/listinfo/development

Reply via email to