识别struts2

来自https://github.com/coffeehb/struts2_check

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2018/01/23 下午2:14
# @Author  : Komi
# @File    : struts2_hunt.py
# @Project : POC-T
# @Ver:    : 0.4
# Referer   https://threathunter.org/topic/594a9f0fde1d70c20885ccd5

import time
import re
import sys
import requests
import platform

ERROR_KEYS = ['Struts Problem Report','org.apache.struts2','struts.devMode','struts-tags',
              'There is no Action mapped for namespace']

# check suffix :.do,.action
def checkBySuffix(info):
    if info['code'] == 404:
        return False
    html = info['html']
    matchs_action = re.findall(r"""(['"]{1})(/?((?:(?!\1|\n|http(s)?://).)+)\.action)(\?(?:(?!\1).)*)?\1""", html,
                        re.IGNORECASE)

    matchs_do = re.findall(r"""(['"]{1})(/?((?:(?!\1|\n|http(s)?://).)+)\.do)(\?(?:(?!\1).)*)?\1""", html,
                        re.IGNORECASE)

    if len(matchs_do)+len(matchs_action)> 0 and (".action" in str(matchs_action) or ".do" in str(matchs_do)):
        return True
    else:
        return False

# check devMode page
def checkDevMode(url):
    target_url = url+"/struts/webconsole.html"
    info = gethtml(target_url)

    if info['code'] == 200 and "Welcome to the OGNL console" in info['html']:
        return True
    else:
        return False

# check Error Messages.
def checActionsErrors(url):
    test_tmpurls = []

    test_tmpurls.append(url+"/?actionErrors=1111")
    test_tmpurls.append(url+"/tmp2017.action")
    test_tmpurls.append(url + "/tmp2017.do")
    test_tmpurls.append(url + "/system/index!testme.action")
    test_tmpurls.append(url + "/system/index!testme.do")

    for test_url in test_tmpurls:
        info = gethtml(test_url)
        for error_message in ERROR_KEYS:
            if error_message in info['html'] and info['code'] == 500:
                print ("[+] found error_message:",error_message)
                return True
    return False

# check CheckboxInterceptor.
def checkCheckBox(url):
    # url = "https://www.vuln.org/?keyword=aaa&loginname=admin&password=888"
    """
        https://www.vuln.org/?__checkbox_keyword=aaa&loginname=admin&password=888
        https://www.vuln.org/?keyword=aaa&__checkbox_loginname=admin&password=888
        https://www.vuln.org/?keyword=aaa&loginname=admin&__checkbox_password=888
        em:
           http://wsbs.wgj.sh.gov.cn/shwgj_zwdt/core/web/welcome/index!search.action

    """
    for match in re.finditer(r"((\A|[?&])(?P<parameter>[^_]\w*)=)(?P<value>[^&#]+)", url):

        info = gethtml(url.replace(match.group('parameter'), "__checkbox_"+match.group('parameter')))
        check_key = 'name="{}"'.format(match.group('parameter'))
        check_value = 'value="false"'

        html = info['html']
        matchs_inputTags = re.findall(r"""<\s*input[^>]*>""", html,re.IGNORECASE)
        for input_tag in matchs_inputTags:
            if check_key in input_tag and check_value in input_tag:
                return True

    return False
# 给 2 个测试站,没有找到好的实现思路
# 初步想法: 对比三次请求返回的文本大小差异,超时请求况,文本是否保护request_locale来做决策
#
# https://eservices.customs.gov.hk/MSOS/wsrh/001s0?request_locale=en_US
# https://ctc.camds.org/camds/mainpage.action?request_locale=zh_CN
# https://ctc.camds.org/camds/mainpage.action?request_locale=en_US
# http://www.quamnet.com/newsUScontent.action?request_locale=zh_CN&articleId=3436914

def checkl18n(target):

    info_orgi = gethtml(target)
    time.sleep(0.5)
    info_zhCN = gethtml(target+"?"+'request_locale=zh_CN')
    time.sleep(0.5)
    info_enUS = gethtml(target+"?"+ 'request_locale=en_US')
    time.sleep(0.5)

    if "request_locale=zh_CN" in info_orgi['html'] and "request_locale=en_US" in info_orgi['html']:
        return True

    if abs(len(info_zhCN['html']) - len(info_enUS['html'])) > 1024:
        return True

    return False

def gethtml(url):
    try:
        headers = {}

        headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:21.0) Gecko/20100101 Firefox/21.0'
        headers['Accept-Language'] ='en-us;q=0.5,en;q=0.3'
        headers['Referer'] = url

        u = requests.get(url, timeout=3, headers=headers, allow_redirects=True)
        content = u.text
        return {"html":content,"code":u.status_code,"url":url}

    except Exception as e:
        return get_html_phantomJS(url)

# 使用PhantomJS获取网页源码
def get_html_phantomJS(url):
    try:
        from selenium import webdriver
        dr = webdriver.PhantomJS()
        dr.get(url)
        time.sleep(2)
        return {"html": dr.page_source, "code": 200, "url": url}

    except Exception as e:
        # http://phantomjs.org/
        print (e)
        return {"html":"", "code":500, "url":url}


def poc(target):
    ori_target = target

    if not target.lower().startswith('http://') and not target.lower().startswith('https://'):
        target = 'http://' + target

    p_version = platform.python_version()

    if "2.7" in p_version:
        from urlparse import urlparse
    elif "3.5" in p_version:
        from urllib.parse import urlparse

    target = urlparse(target).scheme + "://" + urlparse(target).netloc

    index_html = gethtml(target)
    ori_html = gethtml(ori_target)

    if checkDevMode(target):
        return "[success] %s is struts2! [checkDevMode]" % target

    if checkBySuffix(index_html):
        return "[success] %s is struts2! [checkBySuffix]" % target


    if checkBySuffix(ori_html):
        return "[success] %s is struts2! [checkBySuffix]" % ori_target

    if checActionsErrors(target):
        return "[success] %s is struts2! [checActionsErrors]" % target

    if checkCheckBox(target):
        return "[success] %s is struts2! [checkCheckBox]" % target

    if checkl18n(target):
        return "[success] %s is struts2! [checkl18n]" % target

    return False

if __name__ == "__main__":
    if len(sys.argv) > 1:
        result = poc(sys.argv[1])
        if not result:
            print("[*] %s is not struts2!" % sys.argv[1])
        else:
            print(result)
    else:
        print("\n[*]usag: python poc.py http://www.demo.com")
posted @ 2020-08-19 17:12  山野村夫z1  阅读(601)  评论(0)    收藏  举报