nodejs:对“==”的定时攻击

nodejs: timing attack on "=="

最近我路过 this 写了一篇关于 hackerone 的 CTF。在这篇文章中,完成挑战的部分是执行计时攻击。它激起了我的兴趣,我想创建一个容易受到定时攻击的网站。

为此,我决定使用 nodejs,因为这是我最熟悉的。但是,我无法复制它,所以我不得不创建自己的 strcmp 函数并在该函数内引入时差。现在代码看起来像这样

const { urlencoded } = require('body-parser');
const express = require('express')
const session = require('express-session')
const app = express()

app.use(express.static(__dirname+'/public'));
app.use(express.urlencoded({extended: false}))
app.set('view engine', 'ejs')

//im using this function with some bullcrap code in it to just extend the time it runs
const strcmp_test = (op1, op2) => {
    if(op1.length != op2.length) return false;
    for(let i = 0; i < op1.length; ++i) {
        if (op1[i] != op2[i]) return false;
        for(let bleh = 1; bleh < 10000000; bleh++){
            let test = 1000+bleh
            let test2 = test/155
        }
    }
    return true;
}

//MAIN SITE
app.get('/', (req,res) => {
    res.render('index')
})

app.get('/some/place', (req,res) => {
    res.render('a-view')
})


//LOGIN
app.post('/', (req,res) => {
    //I didnt care for setting up a db
    password_hash="c3e9fee675716951c547abe11e49e58190f9b1854924fa605b92d423be8716ab"
    username="admin"

    //if no body
    if(!req.body){
        console.log('NO BODY SENT')
        res.render('index')
    }
    //missing param
    if(!req.body.password || !req.body.login){
        console.log('MISSING PARAMETER')
        res.render('index')
    }
    //if password dont match. I know there is no check of username here, I guess that wont matter for the timing attack...?
    //before I used my own made function I used-->
    //if(req.body.login==username && req.body.password == password_hash) //
    if(strcmp_test(req.body.password,password_hash)){
        res.redirect('/some/place')
    } else {
        res.render('index')
    }
})



//IF NO ROUTE EXISTS
app.use(function(req, res, next) {
    res.status(404)
    res.render('error')
});

app.listen(3000)

为了测试我使用 pythons requests 库的时间。我的代码与 writeup 中使用的代码非常相似,看起来像这样

def padding(h):
    r = h + ('f' * (64 - len(h)))
    return r
   
def send(payload):
    URL = 'http://127.0.0.1:8080/'
    r = requests.post(URL, data={'hash':payload})
    return r.elapsed.total_seconds()
    
if __name__ == '__main__':
    times = {}
    for x in range(0,0xff):
        times[format(x, 'x').zfill(2)] = send(padding(format(x, 'x').zfill(2)))
    print(times)

我的问题是:为什么在我的案例中仅使用 == 执行定时攻击不起作用?如果它应该有效并且我想实施它,我需要在网站上做些什么不同的事情?

我认为设置和处理 HTTP POST 请求所需的时间比比较字符串中的两个字符所花费的时间 多。

尝试汇总具有相同值的多次调用所需的时间。也许那时你会看到不同:

def send(payload):
    URL = 'http://127.0.0.1:8080/'
    t = 0.0
    # Might help to make one initial call to set up the HTTP pathway
    # requests.post(URL, data={'hash':payload})
    for _ in range(10000):
        t += requests.post(URL, data={'hash':payload}).elapsed.total_seconds()
    return t