SQL 注入按原样返回注入的代码

SQL Injection returns injected code as it is

提问人:Fabio R. 提问时间:10/22/2021 最后编辑:Fabio R. 更新时间:10/22/2021 访问量:286

问:

我试图击败这个 CTF:一个正在建设中的网站,有一个简单的登录页面,您可以在其中登录或注册新用户。

它使用 和 DB。node expressSQLite

分析源代码,我发现了这个查询:

getUser(username){
        return new Promise((res, rej) => {
            db.get(`SELECT * FROM users WHERE username = '${username}'`, (err, data) => {
                if (err) return rej(err);
                res(data);
            });
        });
    },

此函数在中间件检查会话 cookie 后调用,以便在 GET 时检索用户名。jsonwebtoken'/'

这就是它的名字:

router.get('/', AuthMiddleware, async (req, res, next) => {
    try{
        let user = await DBHelper.getUser(req.data.username);
        if (user === undefined) {
            return res.send(`user ${req.data.username} doesn't exist in our database.`);
        }
        return res.render('index.html', { user });
    }catch (err){
        return next(err);
    }
});

AuthMiddleware:

module.exports = async (req, res, next) => {
    try{
        if (req.cookies.session === undefined) return res.redirect('/auth');
        let data = await JWTHelper.decode(req.cookies.session);
        req.data = {
            username: data.username
        }
        next();
    } catch(e) {
        console.log(e);
        return res.status(500).send('Internal server error');
    }
}

由于这似乎是唯一以这种方式格式化的查询(其他查询都使用 ),并且通常是唯一明显的漏洞,因此我怀疑该标志存储在数据库中的某个地方。?

由于调用该函数的唯一方法是有一个活动会话,我使用“恶意”sql代码注册了一个用户作为用户名。起初,我试图关闭报价并附加一个以获取所有用户:OR WHERE

SELECT * FROM users WHERE username = '${username}' +

bob' OR WHERE username IS NOT NULL =

SELECT * FROM users WHERE username = 'bob' OR WHERE username IS NOT NULL

这至少应该抛出一个错误,因为它应该在网页上呈现为时返回一个包含数据库中所有用户的集合WHERE username = 'bob' OR WHERE username IS NOT NULL

欢迎 {{ user.username }}
本网站正在开发中。
请稍后再来。

我期望至少“数组上没有用户名属性”或类似的东西。相反,它总是返回我给他的完整用户名

欢迎 bob' 或 WHERE 用户名 IS NOT NULL
此网站正在开发中。
请稍后再来。

我错过了什么吗?有没有办法逃避在cookie读取过程中可能添加的最终引号?

编辑:

这是尝试登录时调用的函数 /auth 路由:

router.post('/auth', async (req, res) => {
    const { username, password } = req.body;
    if((username !== undefined && username.trim().length === 0) 
        || (password !== undefined && password.trim().length === 0)){
        return res.redirect('/auth');
    }
    if(req.body.register !== undefined){
        let canRegister = await DBHelper.checkUser(username);
        if(!canRegister){
            return res.redirect('/auth?error=Username already exists');
        }
        DBHelper.createUser(username, password);
        return res.redirect('/auth?error=Registered successfully&type=success');
    }

    // login user
    let canLogin = await DBHelper.attemptLogin(username, password);
    if(!canLogin){
        return res.redirect('/auth?error=Invalid username or password');
    }
    let token = await JWTHelper.sign({ // Maybe something can be done with this function?
        username: username.replace(/'/g, "\'\'").replace(/"/g, "\"\"")
    })
    res.cookie('session', token, { maxAge: 900000 });
    return res.redirect('/');
});

attemptLogin():

attemptLogin(username, password){
        return new Promise((res, rej) => {
            db.get(`SELECT * FROM users WHERE username = ? AND password = ?`, username, password, (err, data) => {
                if (err) return rej();
                res(data !== undefined);
            });
        });
    }

编辑 2.0:

我刚刚注意到它存储会话cookie的部分:

let token = await JWTHelper.sign({ 
            username: username.replace(/'/g, "\'\'").replace(/"/g, "\"\"")
        })

它显然用 .我可以通过转义引号来解决其中的一半,使其变成 .这允许我关闭语句,但我仍然需要找到一种方法来使第二个 .'\'\'\\'\'username=''\'

javascript 节点.js sqlite sql 注入 ctf

评论

0赞 S.Visser 10/22/2021
当查询成功时,它会设置为用户对象,对吧?我不确定 CTF 的目标是什么,但似乎您可以进行通配符攻击来查找管理员帐户。req.data.username
0赞 Fabio R. 10/22/2021
@S.Visser 目标是找到旗帜,没有给出其他描述。我只是尝试了 和 with,但无济于事,它只是将它们打印出来bob' OR WHERE username LIKE '%64_[^!_%65/%aa?F%64_D)_(F%64)_%36([)({}%33){()}£$&N%55_)$*£()$*R”_)][%55](%66[x])%ba][$*”£$-9]_%54'bob' OR WHERE username LIKE 'admin'
0赞 S.Visser 10/22/2021
如果您输入了错误的用户名会怎样?
0赞 Fabio R. 10/22/2021
@S.Visser 调用 ,error 参数仅用于向用户填充消息。我将编辑问题以包含登录功能/auth?error=Invalid%20username%20or%20password
0赞 Liam 10/22/2021
为什么不直接修复漏洞呢?SQL注入是一个众所周知的漏洞,无论你现在是否可以重现问题,都没有理由像这样连接SQL。

答: 暂无答案