Express服务器提交‘1 or 1=1’无响应问题排查求助
问题分析与解决方案
核心原因
提交1 or 1=1时服务器无响应,本质是异步SQL查询卡住且未被捕获错误,导致请求处理流程停滞:
- 代码直接拼接用户输入生成SQL语句,当输入包含
or 1=1这类内容时,会生成恶意查询(比如SELECT * FROM web_user WHERE user=1 or 1=1 AND password=xxx)。如果mysql.validateString没有正确转义SQL特殊字符,数据库会执行这个异常查询,可能陷入全表扫描或语法错误,导致await systemdb.query的Promise一直处于pending状态。 - 异步中间件和路由中没有错误捕获逻辑,一旦
query抛出错误或卡住,错误会被静默吞掉,请求得不到响应,也不会输出日志。 - 你添加的
app.post("*")没触发,是因为请求还卡在前面的app.use中间件里(中间件的await systemdb.query没完成,next()没执行),根本没走到后续路由。
修复步骤
1. 彻底替换为参数化查询(必做)
直接拼接用户输入是SQL注入的高危操作,必须改用参数化查询,避免恶意SQL生成:
// 登录接口修改示例 app.post('/login', async (req, res) => { cubing.info("post login") try { // 用参数化查询代替字符串拼接 const result = await systemdb.query( 'SELECT * FROM web_user WHERE user = ? AND password = ?', [req.body.username, req.body.password] ) if (result.length > 0) { const token = uuid.v4() // 更新token也用参数化 await systemdb.query( "UPDATE web_user SET token = ? WHERE user = ? AND password = ?", [token, req.body.username, req.body.password] ) res.cookie('login', { token: token }, { httpOnly: false }) res.redirect('/') } else { res.render('login.ejs', { loginName: req.loginName, error: true, }) } } catch (err) { cubing.error('Login query error:', err) res.status(500).send('Server error') } })
同时修改中间件里的token查询:
// 中间件中的token验证 const result = await systemdb.query( "SELECT user,admin FROM web_user WHERE token = ?", [req.cookies.login.token] )
2. 给所有异步操作添加错误捕获
在async中间件和路由中用try/catch包裹异步代码,避免错误静默丢失:
// 全局中间件修改 app.use(async (req, res, next) => { cubing.info("use") let redir = false try { // ... 原重定向逻辑 ... if (redir) { res.redirect('https://speedcubing.top' + req.url) } else { if (req.url != 'myip') { req.loginName = '' req.admin = false if (req.cookies.login !== undefined) { const result = await systemdb.query( "SELECT user,admin FROM web_user WHERE token = ?", [req.cookies.login.token] ) if (result.length > 0) { req.loginName = result[0].user req.admin = result[0].admin.lastIndexOf(1) !== -1 } } } next() } } catch (err) { cubing.error('Middleware error:', err) res.status(500).send('Server error') // 不要调用next(),避免后续逻辑执行 } })
3. 检查并修正mysql.validateString(可选)
如果这个函数的作用是转义SQL字符,确保它能正确处理单引号、双引号、关键字等;如果它只是简单过滤,直接弃用即可——参数化查询已经足够安全。
4. 给数据库查询添加超时
在你的SQL.js中配置查询超时,防止异常查询长时间卡住:
// 示例:在创建数据库连接时设置超时 const connection = mysql.createConnection({ host: host, user: user, password: pass, connectTimeout: 5000, acquireTimeout: 5000, timeout: 5000 })
验证
修改后提交1 or 1=1,会被参数化查询当作普通字符串处理,不会生成恶意SQL;同时如果出现错误会被捕获并输出日志,请求不会再无响应。
内容的提问来源于stack exchange,提问作者hi12167pies
相关产品推荐
相关产品推荐

