象棋王子
签到题,jsfuck解密
丢到console得到flag
电子木鱼
后面两道都是代码审计,这题是rust,题目给出了源码,下载下来看
关键代码:
由于限制,quantity只能为正数
功德也只能是正数(负数的话无法执行到这里)
关键代码:
cost *= body.quantity;
cost变量由 cost原始值 乘 quantity 得到
由于cost是int32类型变量,这里可以试着溢出
GONGDE.set(GONGDE.get() - cost as i32);
其实我也不太清楚这里底层原理,但是我觉得整个代码里面就是这里是有机会的
虽然我不知道溢出后的结果是什么,我还是尝试了一下
当尝试int32最大值的时候,很明显,减变加了
简单分析
name: Cost的默认cost值是10
事实上只要 cost * quantity >= int32_max值 即可达到溢出
至于溢出之后内存中究竟是cost变负数了还是发生了其他问题我也不太清楚,但至少我们的目的达到了
BabyGo
go的代码审计题
思路:通过文件上传功能上传zip,利用unzip功能可以将zip解压到任意路径,做到文件覆盖的效果,然后获得backdoor的访问权限,backdoor允许自定义模块,通过文件覆盖,令后端代码使用我们编写的恶意go模块并同时获得RCE
首先是文件上传,禁止上传go、gob文件
我看到代码有unzip功能,果断将go文件压缩成zip并上传
文件路径:
/tmp/xxx/uploads/
通过unzip进行解压,也会解压到/tmp/xxx/uploads/
查看unzip的实现代码,能够看出zip解压路径由 固定的/tmp/xxx/uploads/ + 我们可控的path http参数
那就简单了直接设置get参数path为../ 就能解压到任意路径
在看看最后一个功能 backdoor
这里判断用户是否admin,而用户信息从/tmp/xxx/中的user.gob读取的
而关于user.gob的初始化关键代码:
很明显,struct和序列化代码都给我们了,直接照着抄过来,吧Power改admin就可以了
这段代码生成一个新的user.gob
利用刚刚的任意路径解压文件功能,将我们的user.gob上传到/tmp/xxx/
达到覆盖掉原始的user.gob文件目的
这样我们就有权限使用backdoor了
RCE
关键代码:
有了backdoor访问权限之后,新的问题又来了
这里Eval()函数执行的命令我们居然不可控,什么奇葩后门。
不过还好,它使用的模块我们可控:
http Get参数pkg,默认值为:fmt
我们可以想办法调用我们编写的fmt模块,并调用我们编写的Println()函数
由于这里禁止了使用相对路径模块调用,所以我们只能将我们编写的模块上传到:
/usr/local/go/src/
这里是存放go模块的地方,我们可以通过刚刚的漏洞将文件上传到那里并且调用它
创建一个hackerM的文件夹打开cmd输入:
go mod init fmt
这样我们将得到一个go.mod文件,在文件中添加以下内容:
require hackerM/fmt v0.0.0
replace hackerM/fmt v0.0.0 => ../fmt
在hackerM目录下创建fmt.go文件,内容如下:
package fmt
import "os/exec"
import "fmt"
func Println(cmd string) {
// out, _ := exec.Command("cat", "/ffflllaaaggg").Output()
out, _ := exec.Command("whoami").Output()
fmt.Println(string(out))
}
// /usr/local/go/src/
现在hackerM结构应该是这样:
将hackerM文件夹压缩为zip,上传
解压到 /usr/local/go/src/ :
转到/backdoor页面,添加pkg参数:
?pkg=hackerM/fmt
这样我们编写的fmt模块代码将会被执行,flag在根目录
最后一道题有点难度,也是代码审计吧,只不过要审计cms最新版本,得自己审计出漏洞,我php能力有限,等大佬wp