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
最近我路过 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