7天学习Go语言-尾声+一次险些翻车的任意文件读取漏洞小记

接口

接口的定义

接口(interface )类型是对其他类型行为的概括和抽象,接口类型定义了一组方法,但是不包括这些方法的具体实现
接口本质是一种指针类型,可以实现多态功能。如果一个类型实现了某个接口,则所有使用这个接口的地方都支持这种类型的值。接口的定义格式如下:

type 接口名称 interface {
    
    
method1 (参数列表) 返回值列表
method2 (参数列表) 返回值列表
}

例如:

type Num interface {
    
    
Eq (i Num) bool
}

如果接口没有任何方法声明,则它就是一个空接口(interface {})。它的用途类似面向对象的根类型,可以被赋值为任何类型的对象。接口变量默认值是nil,如果实现接口的类型支持相等运算,则可以乘坐相等运算,否则会报错。

接口的赋值

Go语言的接口不支持直接实例化,但支持赋值操作,从而快速的实现接口与实现类的映射。接口赋值在Go语言中分如下两种情况:
1.将实现接口的对象实例赋值给接口
2.将一个接口赋值给另一个接口

将实现接口的对象实例赋值给接口
将指定类型的对象实例赋值给接口,要求该对象对应的类实现了接口要求的所有方法否则就不能算实现了该接口。例如,先定义一个color结构体类型以及对应的方法

// 定义一个结构体
type color struct {
    
    
	white string
	red   string
}

func (s color) a() string {
    
    
	return s.white
}

func (s color) b() string {
    
    
	return s.red
}

然后,相应的定义一个接口

type phone interface {
    
    
	a() string
	b() string
}

这里面的对象对应的类与接口要求的方法对应

package main

import (
	"fmt"
)

// 定义一个接口
type phone interface {
    
    
	a() string
	b() string
}

// 定义一个结构体
type color struct {
    
    
	white string
	red   string
}

func (s color) a() string {
    
    
	return s.white

}


func (s color) b() string {
    
    
	return s.red
}

func main() {
    
    
	struct_value := color{
    
    white: "2998", red: "1111"} //结构体赋值
	var a color                                       //因为color实现了phone接口,所以可以直接赋值,类型需要一致
	a = struct_value
	money := a.a() //调用接口的方法a()
	fmt.Println(money)
}

在这里插入图片描述

将一个接口赋值给另一个接口

在Go语言中,只要两个接口拥有相同的方法列表,则他们就是等同的,可以相互赋值。

后言:
基础方面就结束了,其实一直很纠结接口这里,因为我是自学的,很多东西我也觉得书里的怪怪的,很多东西都是从书里的+别人的博客+b站然后才有了这几篇烂烂的文章,写这个的目的一个是加深自己对go语言的理解,一个是想给大家分享一下go语言的基础语法,看完这点垃圾文章是写不出来什么脚本的,但是却的确能让大家对Go语言有一个基础的认知以及以后的铺垫,如果有机会,我会继续整合一些go语言的东西,比如如何写一些简单的脚本,当然了,我比较垃圾,还不太会写有用的脚本,都是照着人家的框架然后改的,这里就先不献丑了,哈哈哈,谢谢大家一直以来的支持。

下面为大家带来一次由黑盒转代码审计的一次小案例

没有废话连篇,首先测试场景为常规的测试,有一处功能为“模板导出”
在这里插入图片描述
为保狗命,码子厚了点,但是不难发现,下载的文件是以文件名为命名的编码格式,那么盲猜后台代码可能是

XxxPath = new Path("xxxplates/" + fileName);

诚然,我承认我都赌的成分。如果是介个样子的代码那么必然是存在任意文件下载/读取漏洞的,成因是因为服务器获取的filename参数,未经过任何形式的过滤、校验,直接打开文件对象并创建输入流,只要改变文件名成为 …/…/…/…/etc/passwd 或者直接把文件名替换为 …/存在的文件 即可读取到对应的文件

二者的区别就是,第一个可以直接穿越出网站根目录读取到任意文件,后者则是在程序包为jar的时候,跳不出jar包 ,这个时候需要知道包内都有哪些文件,才能读取到,有点像用友NC任意文件读取漏洞,也是只能读他的代码部分

首先我们按照常规测试,去尝试去读 /…/…/…/…/…/…/…/etc/passwd

在这里插入图片描述

可以看到,读取失败了,但是根据我八级的英语水平,配合百度翻译之后,明白了,说是?web-inf目录下没有这个文件哈,于是赶紧查了一下,果然是这个吊样, 我现在是一个高雅的人,果然不出老夫所料
在这里插入图片描述

而后就只能去找代码了,最起码也得找到该方法的目录,而后才能仿造要读取的路径
但是后台程序有十几个jar包,一个一个的找怕不是得找一天,所以这里建议大家遇到类似情况可以将他们全都解压,当做压缩文件解压就行
而后直接使用notepad++随便打开一个文件,直接全文检索该方法即可

在这里插入图片描述

按照搜索到的结果,直接打开idea即可

在这里插入图片描述

可以看到,没有什么过滤,直接就加载了,那么也救构成了我们这次想要发现的漏洞

在这里插入图片描述

目录文件就在这个数据包外,恰好与我们获取的代码一一对应,我们尝试读取banner文件

…/banner.txt

在这里插入图片描述

成功读到banner文件,漏洞探测完毕

修复方式:
可以将下载的文件路径和名称存储在数据库中或者改成对应的编号,当有用户下载的时候直接下载文件的路径和名称在数据库中对应的编号,而后再调用文件进行下载即可。或者可以在生产file类之前,开发者对用户传入的下载路径进行合法性校验,判断是否路径在合法路径下,是否是允许下载的文件等。

修复后的酱紫

在这里插入图片描述

哈哈哈,没想到吧,最后一张图是假的,我瞎找的一张图,不过最好的修复方式的确是通过加密或者是将文件名存储在数据库内,而后通过读取数据库内的特定编号进行文件比对从而修复此类漏洞。可以说任意文件读取在测试中其实是比较常见的一种漏洞,也算是代码审计中比较简单的吧​

猜你喜欢

转载自blog.csdn.net/weixin_48421613/article/details/123333141