├── README.md
├── README.zh-cn.md
├── df-bypass.py
├── img
├── 1.png
├── 2.png
└── 3.jpg
└── putenv-ld_preload.py
/README.md:
--------------------------------------------------------------------------------
1 | # ScanDF
2 |
3 | [中文版本(Chinese version)](README.zh-cn.md)
4 |
5 | >The purpose of this script is to bypass disablefund, provide some useful information, and dig the hook function of PHP extension.
6 |
7 | ### df-bypass.py
8 |
9 | Use: Python df-bypass.py - U URL (phpinfo information)
10 |
11 | EG1: Test [geek challenge 2019] rce me
12 |
13 | 
14 |
15 | You can directly use the hook function to bypass the DL - runtime load a PHP extension
16 |
17 | EG2: [Blue Hat Cup 2021] one pointer PHP
18 |
19 | 
20 |
21 | Direct hit FPM modify ant sword source code!!
22 |
23 | ### putenv-ld_preload.py
24 |
25 | By bypassing the putenv hook function, we can scan the available functions, load more plug-ins and use them better. It can be used with DF bypass.py
26 |
27 | Use: Python putenv LD_ Preload.py (scan the internal value function of the current PHP environment by default)
28 |
29 | 
30 |
31 | python putenv-ld_ Preload.py module
32 |
33 | Test the function provided by the module, which can better bypass.
34 |
35 | >reference resources:
36 | >
37 | >https://github.com/AntSwordProject/AntSword-Labs/tree/master/bypass_disable_functions
38 | >
39 | >https://blog.bi0s.in/2019/10/26/Web/bypass-disable-functions/
40 | >
41 | >https://www.anquanke.com/post/id/197745
42 |
43 |
--------------------------------------------------------------------------------
/README.zh-cn.md:
--------------------------------------------------------------------------------
1 | # ScanDF
2 |
3 | >该脚本是为了绕过disablefuntion 提供一些可用的信息,和挖php扩展的hook函数。
4 |
5 | ### df-bypass.py
6 |
7 | 使用:python df-bypass.py -u url(phpinfo信息)
8 |
9 | eg1:测试[极客大挑战 2019]RCE ME
10 |
11 | 
12 |
13 | 可以直接利用 hook 函数来绕过,dl — 运行时载入一个 PHP 扩展
14 |
15 |
16 |
17 | eg2: [蓝帽杯 2021]One Pointer PHP
18 |
19 | 
20 |
21 | 直接打fpm 修改蚁剑源代码!!
22 |
23 | ### putenv-ld_preload.py
24 |
25 | **通过putenv hook 函数的原理来绕过,来扫描可用的函数,加载更多的插件能更好的使用,可配合df-bypass.py使用**
26 |
27 | 使用:python putenv-ld_preload.py (默认扫描当前php环境的内值函数)
28 |
29 | 
30 |
31 | python putenv-ld_preload.py (模块)
32 |
33 | 测试该模块提供的函数,能更好的bypass。
34 |
35 | >参考:
36 | >
37 | >https://github.com/AntSwordProject/AntSword-Labs/tree/master/bypass_disable_functions
38 | >
39 | >https://blog.bi0s.in/2019/10/26/Web/bypass-disable-functions/
40 | >
41 | >https://www.anquanke.com/post/id/197745
42 |
43 |
--------------------------------------------------------------------------------
/df-bypass.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*
2 | # /usr/bin/python3
3 | # @Author:Firebasky
4 | '''
5 | 扫描思路
6 | 1.获得全部可以利用的函数
7 | 2.匹配漏网之鱼
8 | 3.根据感觉判断是不是uaf
9 | 4.判断fpm利用 ban了putenv
10 | 5.判断putenv利用hook so
11 | '''
12 |
13 | import argparse
14 | import requests
15 | import re
16 |
17 | parser = argparse.ArgumentParser()
18 | parser.add_argument("-u", help="phpinfo URL: eg. https://example.com/phpinfo.php")
19 | parser.add_argument("-f", help="phpinfo localfile path: eg. dir/phpinfo")
20 |
21 | args = parser.parse_args()
22 |
23 | class colors:
24 | reset='\033[0m'
25 | red='\033[31m'
26 | green='\033[32m'
27 | orange='\033[33m'
28 | blue='\033[34m'
29 |
30 | print(colors.green + """
31 | ____ ____ _____
32 | / ___| ___ __ _ _ __ | _ \| ___|
33 | \___ \ / __/ _` | '_ \| | | | |_
34 | ___) | (_| (_| | | | | |_| | _|
35 | |____/ \___\__,_|_| |_|____/|_|
36 | """ + "\n\t\t\t\t" + colors.blue + "authors: " + colors.orange + "Firebasky" + "\n" + colors.reset)
37 |
38 | def Get_phpinfo(args):
39 | if (args.u):
40 | url = args.u
41 | phpinfo = requests.get(url).text # 获得phpinfo信息
42 | return phpinfo
43 | elif (args.f):
44 | phpinfofile = args.f
45 | phpinfo = open(phpinfofile, 'r').read() # 获得phpinfo信息
46 | return phpinfo
47 | else:
48 | print(parser.print_help())
49 | exit()
50 |
51 | dis_fun = []
52 | phpinfo = Get_phpinfo(args)
53 |
54 | dis_fun = phpinfo.split('disable_functions
')[1].split("")[0].split(',')[:-1]
55 |
56 | phpversion = re.findall("PHP (.*) - phpinfo\(\)",phpinfo)
57 |
58 | serverapi = re.findall(" | Server API | (.*) |
",phpinfo)
59 |
60 | lwzy = ['system', 'shell_exec', 'exec', 'passthru', 'popen', 'proc_open', 'pcntl_exec', 'dl']
61 |
62 | #我们能够的函数
63 | dangerous_functions = ['pfsockopen','fsockopen','stream_socket_client','stream_socket_client','pcntl_alarm','pcntl_fork','pcntl_waitpid','pcntl_wait','pcntl_wifexited','pcntl_wifstopped','pcntl_wifsignaled','pcntl_wifcontinued','pcntl_wexitstatus','pcntl_wtermsig','pcntl_wstopsig','pcntl_signal','pcntl_signal_get_handler','pcntl_signal_dispatch','pcntl_get_last_error','pcntl_strerror','pcntl_sigprocmask','pcntl_sigwaitinfo','pcntl_sigtimedwait','pcntl_exec','pcntl_getpriority','pcntl_setpriority','pcntl_async_signals','error_log','system','exec','shell_exec','popen','proc_open','passthru','link','symlink','syslog','mail']
64 |
65 | def Get_Dafun(dangerous_functions):#通过匹配ini获得扩展的危险函数然后利用
66 | modules = []
67 | if("mbstring.ini" in phpinfo):#安装的mbstring模块
68 | modules += ['mbstring']
69 | dangerous_functions += ['mb_send_mail']
70 |
71 | if("imap.ini" in phpinfo):#安装的imap扩展
72 | modules += ['imap']
73 | dangerous_functions += ['imap_open','imap_mail']
74 |
75 | if("libvirt-php.ini" in phpinfo):#安装的libvert扩展
76 | modules += ['libvert']
77 | dangerous_functions += ['libvirt_connect']
78 |
79 | if("gnupg.ini" in phpinfo):#安装的gnupg模块
80 | modules += ['gnupg']
81 | dangerous_functions += ['gnupg_init']
82 |
83 | return dangerous_functions
84 |
85 | def Scan_Fun(dangerous_functions):
86 | exploitable_functions = []
87 | for i in dangerous_functions:
88 | if i not in dis_fun:
89 | exploitable_functions.append(i)#筛选过滤
90 | if len(exploitable_functions)==0:
91 | print('\nThe disable_functions I don\'t know')
92 | else:
93 | print('\nThis functions can used:')
94 | print(','.join(exploitable_functions))
95 |
96 | #1.漏网之鱼,可以直接执行命令
97 | def Get_LWZY(lwzy):
98 | exploitable_functions = []
99 | for i in lwzy:
100 | if i not in dis_fun:
101 | exploitable_functions.append(i)#筛选过滤
102 | if len(exploitable_functions)==0:
103 | print('\nNot easy!!')
104 | Get_uaf()
105 | else:
106 | print(colors.red+'\nnice,can exec!!! use below function'+colors.red)
107 | print(','.join(exploitable_functions))
108 |
109 | #2.php>7 一般是uaf
110 | def Get_uaf():
111 | if(int(phpversion[0].split(".")[0])>=7):
112 | print("mayby have uaf,yijian uaf used\n")
113 | Get_fpm()
114 | else:
115 | Get_fpm()
116 |
117 | #3.fpm利用 过滤了函数,使用其他函数实现功能
118 | def Get_fpm():
119 | if ("FPM/FastCGI" in serverapi[0]):
120 | print(colors.orange+"Maybe fpm can exploit,This functions pfsockopen,stream_socket_sendto,stream_socket_client,fsockopen can also to exploit FPM,maybe modify yijian source code!!!"+colors.orange)
121 | else:
122 | Get_putenv(dis_fun)
123 |
124 | #4.putenv-LD_PRELOAD
125 | def Get_putenv(dis_fun):
126 | if("putenv" not in dis_fun):
127 | print(colors.blue+"Almost use putenv-LD_PRELOAD to hook\n"+colors.blue)
128 | if ("imagick.ini" in phpinfo):
129 | print(colors.blue+'\nPHP-imagick module is present. It can be exploited using LD_PRELOAD method\n'+colors.blue)
130 | else:
131 | print("mayby this is 0day!!\n maybe use extend's function to trigger putenv, can use putenv-ld_preload.py to fuzz")
132 |
133 | Scan_Fun(Get_Dafun(dangerous_functions))
134 | Get_LWZY(lwzy)
135 |
136 | # print(serverapi[0])
--------------------------------------------------------------------------------
/img/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Firebasky/ScanDF/f20a210ce2c24f1440cbbdb303900d4f91d1f498/img/1.png
--------------------------------------------------------------------------------
/img/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Firebasky/ScanDF/f20a210ce2c24f1440cbbdb303900d4f91d1f498/img/2.png
--------------------------------------------------------------------------------
/img/3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Firebasky/ScanDF/f20a210ce2c24f1440cbbdb303900d4f91d1f498/img/3.jpg
--------------------------------------------------------------------------------
/putenv-ld_preload.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*
2 | # @Author:Firebasky
3 | # strace -f php -r "xxx" 2>&1 | grep -E "execve|fork|vfork"
4 | '''
5 | 1.获得该函数的参数
6 | 2.获得该函数的参数的数据类型
7 | 3.去fuzz执行函数看是否有调用外部函数从而hook
8 | '''
9 | import os
10 | import sys
11 | import re
12 |
13 | def getAllDefinedFunc():#获取全部函数
14 | get_defined_function = os.popen("php -r 'print_r(get_defined_functions()['internal']);'").readlines()
15 | #print get_defined_function
16 | b = get_defined_function[2:-1]
17 | b = map(str.strip, b)
18 | for i in range(len(b)):
19 | b[i] = re.sub(r'.*> ', '', b[i])
20 | get_defined_function = b # all defined PHP functions
21 | get_defined_function.remove(get_defined_function[0])
22 | get_defined_function.remove(get_defined_function[0])
23 | get_defined_function.remove('readline')
24 | return get_defined_function
25 |
26 |
27 | def getModuleFunc(phpModuleName,getDefinedFunction):#获取模块函数
28 | moduleFunc = []
29 | for func in getDefinedFunction:
30 | getExtNameCmd = 'php -r "echo (new ReflectionFunction("{}"))->getExtensionName();"'.format(func)
31 | extName = os.popen(getExtNameCmd).readlines()[0]
32 | if extName == phpModuleName:
33 | moduleFunc.append(func)
34 | return moduleFunc
35 |
36 | def fuzzFunc(getDefinedFunction):
37 | for func in getDefinedFunction:
38 | maxParaNumCmd = 'php -r "echo (new ReflectionFunction("{}"))->getNumberOfParameters();"'.format(func)
39 | minParaNumCmd = 'php -r "echo (new ReflectionFunction("{}"))->getNumberOfRequiredParameters();"'.format(func)
40 | maxParaNum = int(os.popen(maxParaNumCmd).readlines()[0])
41 | minParaNum = int(os.popen(minParaNumCmd).readlines()[0])
42 | print(maxParaNum)
43 | print(minParaNum)
44 | for paraNum in range(minParaNum,maxParaNum + 1):#获得输入参数的范围
45 | paraMeters = ['\'1../../../../../../../../../etc/passwd\'' for i in range(paraNum)]#给参数需要字符串
46 | paraMeters = ','.join(paraMeters)
47 | newPhpCmd = "php -r \"{}({});\"".format(func,paraMeters)#去添加参数执行
48 | print(newPhpCmd)
49 | newFuzzCmd = "strace -f {} 2>&1 | grep -E 'execve|fork|vfork'".format(newPhpCmd)#去执行strace看是否满足条件
50 | print(newFuzzCmd)
51 | out = re.findall(r'execve', ''.join(os.popen(newFuzzCmd).readlines()[1:]))
52 | print(out)
53 | if len(out) >= 1:
54 | with open('fuzz-out.txt','a+') as file:
55 | file.write(newPhpCmd + "\n")
56 | break
57 | if __name__ == "__main__":
58 | if len(sys.argv) > 1:
59 | phpModuleName = sys.argv[1]
60 | getDefinedFunction = getAllDefinedFunc()
61 | moduleFunc = getModuleFunc(phpModuleName,getDefinedFunction)
62 | if len(moduleFunc) == 0:
63 | print ('没有找到与指定模块相关的函数,检查名称是否正确')
64 | else:
65 | #print moduleFunc
66 | fuzzFunc(moduleFunc)
67 | else:
68 | print ('fuzz all')
69 | getDefinedFunction = getAllDefinedFunc()
70 | fuzzFunc(getDefinedFunction)
--------------------------------------------------------------------------------