VERYIDE sql注入+ssrf

VERYIDE漏洞集合

SSRF漏洞分析

	case "proxy":
	
		//载入网关
		require VI_ROOT.'source/class/frivoller.php';
	
		//关闭缓冲
		ob_end_clean();		
	
		//获取参数
		if ( $execute ){
		
			$referer	= getgpc('referer');
		
			new Frivoller( urldecode($execute), $referer );
			
		}else{
			exit('Access Denied');
		}
	
	break;

getgpc为VeryIde自写的_GET/_POST/COOKIE获取函数

function getgpc($k, $type='GP') {
	$type = strtoupper($type);
	switch($type) {
		case 'G': $var = &$_GET; break;
		case 'P': $var = &$_POST; break;
		case 'C': $var = &$_COOKIE; break;
		default:
			if(isset($_GET[$k])) {
				$var = &$_GET;
			} else {
				$var = &$_POST;
			}
		break;
	}

	return isset($var[$k]) ? $var[$k] : NULL;
}

正常获取且无过滤

new Frivoller( urldecode($execute), $referer );

知道了如何传参进入Frivoller

public function __construct( $link, $referer = NULL ){
	 
		// parse the http link 
		$this->parseLink( $link, $referer ); 
		// begin to fetch the image 
		$stream = fsockopen($this->host, $this->port, $errno, $errstr, $this->timeout); 
		if (!$stream) die ("ERROR: $errno - $errstrn"); 

		fputs($stream, $this->buildHeaders()); 

如果host以及port可控的话便可直接通过fsockopen连接导致ssrf

private function parseLink( $link, $referer ){ 
		$this->link = $link; 
		$this->components = parse_url($this->link);
		$this->host = $this->components['host']; 
		$this->path = $this->components['path']; 
		$this->referer = isset($referer) ? $referer : $this->components['scheme'] . '://' . $this->components['host'];
		$this->filename = basename($this->path); 

		// extract the content type 
		$ext = substr(strrchr($this->path, '.'), 1); 
		if ($ext == 'jpg' or $ext == 'jpeg')

通过parse_url解析我们输入的内容并分别赋予host以及path但没有

	protected $method = 'GET'; 

	/** 
	* The HTTP port, 80 for default 
	* 
	* @var int 
	*/ 
	protected $port = 80; 

	/** 
	* Timeout period on a stream 
	* 
	* @var int 
	*/ 
	protected $timeout = 30; 

	/** 
	* The filename of image 
	* 
	* @var string 
	*/ 
	protected $filename; 

在类中定死了只能请求80端口的显得有点稍微限制除非端口总体无任何限制。

前台SQL注入

首先veryIDE存在一个很搞笑的问题

	public static function check_login( $jump = TRUE ){
		global $_G;
		
		if(!$_G['manager']['account'] && strpos(strtolower($_SERVER['PHP_SELF']),"admin.login.php")==0){
			header("Location:".VI_BASE."module/system/admin.login.php".($jump?'?jump='.GetCurUrl():''));
		}
	}

这是他的全局验证是否登录的函数,整体都没毛病但就是光header却没有exit();导致代码还可以继续往以下执行

	public static function check_page(){
		global $_G;
		
		//当前模块	
		$appid = str_replace( VI_BASE.'module/', '', dirname($_SERVER["REQUEST_URI"]) );
		
		if( $appid == "system" && array_key_exists(GetCurFile(),$_G['project']['page']) && !array_key_exists(GetCurFile(),$_G['group']) && !array_key_exists("*",$_G['group']) ){
			header("Location:".VI_BASE."module/system/serve.error.php?action=page&page=".GetCurFile());
			exit();
		}
	}

但是在全局文件的下面还存在一个验证页面权限的函数,这里有进行exit();但是通过$_SERVER["REQUEST_URI"]来获取appid,只要满足appid非system时则可以绕过。

	public static function check_func( $func, $debug = NULL ){
		global $_G;
		
		//调试模式
		if( isset( $debug ) ){			
			if( !array_key_exists( $func, $_G['group'] ) && !array_key_exists("*",$_G['group']) ){	
			
				//显示错误
				if( $debug ){
					return "<div id='state' class='failure'>当前用户组没有 <strong>".$func."</strong> 权限,您可能无法完成本页某些操作</div>";
				}else{
					ob_end_clean();
					header("Location:".VI_BASE."module/system/serve.error.php?action=func&func=".$func);
					exit;	
				}
			}
		}else{
			//返回状态
			return array_key_exists( $func, $_G['group'] );
		}
		
	}

但是在功能内却还有check_func这种函数用来检测是否具备权限使用该功能因为如果我们未登录则一定不满足$_G['Group']所以存在这种函数的功能都是无法使用的

 $start = getgpc('start');
    $end = getgpc('end');
    
    //search
    $s = getgpc("s");
    $q = getgpc('q');
    $event = getgpc("event");
	$account = getnum("account",0);
    
    //sql
    $sql="SELECT * FROM `sys:event` WHERE 1=1 ";
    
    //权限检查
	
	/*
    if( $s && $q && System :: check_func( 'system-event' ) == false){
    
        $sql.=" and  event = 'login' and aid=".$_G['manager']['id'];
		
        $_G['project']['message']="<b>提示:</b> 没有权限查看其他用户的日志!";
        
    }else{
		
		*/
        if($s && $q){
            $sql.=" and `".$s."` like '%".$q."%'";
        }
        
        if($event){
            $sql.=" and  event = '".$event."'";
        }
        
        if($account){
            $sql.=" and  aid = '".$account."'";
        }
        
    //}
	
	//无权限查看其它用户日志
	if( System :: check_func( 'system-event' ) == false ){
		$sql.=" and  aid=".$_G['manager']['id'];
	}
    
    if ($start && $end){
        $sql.=" and  dateline >=".strtotime($start)." and modify <= ".strtotime($end.' 23:59:59');
    }
    
    $sql.=" ORDER BY id DESC ";

经典的拼接注入出现在S参数上虽然下面有进行check_func验证函数但也只是不允许我们只想if内容的sql拼接并不影响我们注入

1 个赞

图挂了

阿!我没图吧!

本地复测那里有个图

阿!我记得不是删除了?