PHP项目&MVC文件安全&上传&包含&下载&删除&读取等
文件安全-文件包含-动态调试-xhcms
1.安装好xhcms,查看index.php文件。
2.存在include关键字,可以存在文件包含漏洞。看上面代码的逻辑,对r的传参添加魔术引号,如果r没有值,则变量action默认为index,否则就为r的值。先看下file文件夹有哪些文件,随便选择一个进行传参。
当给r传参为download时,直接就跳转到了下载界面,并且是以php文件解析。所以如果files文件下有一个txt文件,也会按照php文件解析执行。
3.在files文件下新建一个1.txt.php文件,里面写上phpinfo函数。
4.给r传参1.txt,phpinfo函数就被执行了。
5.这个文件不一定要放在files目录下,可以放在任意地方,通过目录穿透来进行访问。例如在根目录下创建shell.php文件。
6.给r传参"../shell",phpinfo函数就会被执行。
文件安全-文件删除-关键字搜索-zzzcms
1.跟文件删除有关的函数为unlink,所以全局搜索unlink关键字。
2.可以看到del_file函数中有unlink函数,并且会删除变量file的文件,如果要造成任意文件删除,就得看变量file能不能被我们控制。所以先查看哪里调用了del_file函数。
3.可以看到save.php文件中的delfile函数调用了del_file函数,并且变量file是由我们的传参决定的,所以此处肯定存在任意文件删除。接下来就看哪里调用delfile函数了。
4.可以看到还是在save.php文件中会调用delfile函数,只需要让变量act的值为delfile即可,这里变量act是由我们控制的。所以就可以构造利用链了,访问save.php,对变量act进行get传参,赋值为delfile,再对变量path进行post传参,赋值为我们想要删除的文件路径。但是这里需要注意,在delfile函数中做了一定的过滤。文件路径中必须带有upload、template、runtime、backup四个关键字中的一个才能进入if循环执行删除文件。
5.先在template目录下新建一个1.txt文件。
6.这里还需要注意一点,必要要进入后台登录之后才能触发,如果没有进行登录,则会返回false,下面的代码就不会执行了。
7.但当给path传参"../template/1.txt",发现文件并没有删除,有可能是路径出现了问题。所以在代码中将路径进行输出。
8.说明$_SERVER['DOCUMENT_ROOT']的值为"D:/phpStudy/PHPTutorial/WWW",重新构造路径。
发现template目录下的1.txt被删除了。
9.可以利用该漏洞删除install目录下的install.lock文件,重新安装cms,就可以执行很多操作了。
文件安全-文件下载-功能点定位-earmusic
1.由于文件下载没有特定的函数,通过搜索关键字没什么用,只能根据应用的功能去尝试。
2.抓包,看下下载功能触发的是哪段代码。
点击查看代码
GET /template/default/source/audio.php?id=13 HTTP/1.1
Host: 127.0.0.1:8086
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:122.0) Gecko/20100101 Firefox/122.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Referer: http://127.0.0.1:8086/index.php/music/13/
Cookie: in_userid=1; in_username=admin; in_userpassword=49ba59abbe56e057
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
3.找到audio.php文件,看下源代码。
4.看到了readfile函数,这就是一个下载功能的函数。$file是通过geturl函数和$row['in_audio']获得。查看下geturl函数。
geturl函数位于/source/system/function_common.php文件中
geturl函数会对$file进行判断,如果符合正则表达式的判断,就会对url进行拼接;如果file为空,也会根据不同情况进行url拼接;如果都不是,就会把file直接赋值给url,即你传入什么,url就为什么。
再看下$row['in_audio'],$row是通过SQL查询语句获得的,看下music表的结构。
那$row['in_audio']取的就是music表中的in_audio字段的值。
SQL查询语句是根据$id来取值的,$id是通过intval和SafeRequest函数对get传参的id处理后得到。intval函数用于获取变量的整数值。SafeRequest函数位于/source/system/function_common.php文件中。
所以如果能够控制music表中in_audio字段的值,就可以实现任意文件下载。所以去查找哪里可以修改in_audio的值。发现add.php文件中可以修改。
根据文件路径source/user/music/add.php,应该是跟添加音乐相关的功能。找到对应界面,查看源代码,搜索in_audio关键词,发现对应的是音频地址。
5.尝试上传一个音乐,看看数据库是否存在。
证实音频地址的内容对应数据库中的in_audio字段。
6.在audio.php文件的同目录下新建一个1.php文件,尝试去下载它。
成功下载,但是文件中的内容不一致。
7.抓包看一下,发现是能够读到文件内容的,也不知道是什么原因。
8.在实战中,会去下载一些数据库的相关配置文件,数据库配置文件位于/source/system/config.inc.php.
构造payload。
下载,发现文件名变成了Safety filter,数据库中in_audio字段也变成了Safety filter。
看来是做了过滤。搜索Safety filter关键字,看下是哪里做了过滤。是/source/system/function_common.php文件中的checkrename函数做的过滤.
checkrename函数通过正则表达式进行匹配,过滤了"./"等,所以可以通过写绝对路径来绕过。
下载,成功读取到配置文件。
CNVD拿1DAY-删除&读取&写入-梦想CMS
任意文件删除漏洞
先上cnvd官网,查找关于梦想CMS相关的漏洞,这里有一个任意文件删除漏洞,查看详情。
漏洞点位于后台Ba.cl.php文件,上梦想CMS官网下载源码,看下后台文件有哪些是Ba开头的文件。
只存在两个Ba开头的文件。又由于是文件删除漏洞,所以可以搜索unlink关键字。在BackdbAction.class.php文件中找到一处。
$dir由ROOT_PATH、file/back/、$filename进行拼接得到,如果$filename可以被控制就可以实现任意文件删除。看下哪里调用了delOne函数。
有两处地方调用了,先看下第一处地方delbackdb函数。$filename由get传参得到,如果该文件存在就会被删除。在file/back目录下创建一个1.txt文件。
访问BackdbAction.class.php文件,调用delbackdb函数,给filename传参1.txt。
已经被删除了。如果要删除其他目录的文件,利用目录穿透实现,尝试删除install目录下的install_ok.txt文件。
删除成功。
任意文件读取漏洞&写入漏洞
看下官网通报。
由于是个低危漏洞,大概率存在于后台。搜索文件读取的函数(file_get_contents、fopen等)。
查找到一处变量可控的,如果读到内容就返回,没有读到内容就提示。看哪里调用了getcon函数。
只有在editfile函数中调用了,会读取"$this->config['template'].$dir"对应文件的内容。先看$this->config['template']对应的是什么。
$dir是由get传参获得,如果想要读取template目录下的文件不需要目录穿透,如果要读取其他目录下的文件就需要目录穿透。
尝试读取根目录下的admin.php
成功读取。
尝试读取inc/db.inc.php文件。
读取完之后,在文件里随便写点东西后提交。
再看源代码中的db.inc.php文件,发现我们写的内容被写到了源代码中。
这个功能还是跟editfile函数挂钩,再看editfie函数,确实存在修改文件的功能。
看下put函数的定义。
调用了file_put_contents函数,该函数就是用来写文件的,所以put函数就是一个写文件函数。
"$this->config['template'].$dir.'/'.$_POST['filename']"是写入的文件名,"string::stripslashes($_POST['temcontent'])"是写入的内容。如果temcontent传参是有值的,就会执行写入操作。尝试向1.php文件中写入phpinfo函数
查看template目录下,成功生成1.php。