%0a绕过
1
2
3
4
5
6
|
if($_GET['num'] !== '23333' && preg_match('/^23333$/', $_GET['num'])){
echo '1st ok'."<br>";
}
else{
die('23333333');
}
|
%0A绕过(%0A经URL编码后是回车)
tac
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
$query = $_SERVER['QUERY_STRING'];
if (strlen($cmd) > 8){
die("too long :(");
}
if( substr_count($query, '_') === 0 && substr_count($query, '%5f') === 0 ){
$arr = explode(' ', $cmd);
if($arr[0] !== 'ls' || $arr[0] !== 'pwd'){
if(substr_count($cmd, 'cat') === 0){
system($cmd);
}
else{
die('ban cat :) ');
}
}
else{
die('bad guy!');
}
}
else{
die('nonono _ is bad');
}
|
禁用cat ls pwd
system(tac f*)
linux tac命令
这里相当于system(tac f*)
此题system(tac fl*)也可以
MD5绕过
0e绕过
练习地址
http://chinalover.sinaapp.com/web17/index.php?a=s1885207154a&b=s1836677006a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
<?php
if (isset($_GET['a']) && isset($_GET['b'])) {
$a = $_GET['a'];
$b = $_GET['b'];
if ($a != $b && md5($a) == md5($b)) {
echo "flag{XXXXX}";
} else {
echo "wrong!";
}
} else {
echo 'wrong!';
}
?>
|
上面只要传入参数a=s1885207154a,b=s1836677006a,即可,为什么呢?看一下这两个字符串的md5值可以返现分别如下:
1
2
3
|
MD5值
md5("s1885207154a") => 0e509367213418206700842008763514
md5("s1836677006a") => 0e481036490867661113260034900752
|
二者都是0e开头,在php中0e会被当做科学计数法,就算后面有字母,其结果也是0,所以上面的if判断结果使true,成功绕过
preg_replace函数
题目(xctf ics-05)(攻防世界有复现)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
<?php
//方便的实现输入输出的功能,正在开发中的功能,只能内部人员测试
if ($_SERVER['HTTP_X_FORWARDED_FOR'] === '127.0.0.1') {
echo "<br >Welcome My Admin ! <br >";
$pattern = $_GET[pat];
$replacement = $_GET[rep];
$subject = $_GET[sub];
if (isset($pattern) && isset($replacement) && isset($subject)) {
preg_replace($pattern, $replacement, $subject);
}else{
die();
}
}
?>
|
函数作用:搜索subject中匹配pattern的部分, 以replacement进行替换。
$pattern: 要搜索的模式,可以是字符串或一个字符串数组。
$replacement: 用于替换的字符串或字符串数组。
$subject: 要搜索替换的目标字符串或字符串数组。
preg_replace函数存在命令执行漏洞
此处明显考察的是preg_replace 函数使用 /e模式,导致代码执行的问题。
参考[https://www.cnblogs.com/dhsx/p/4991983.html]
/e 修正符使 preg_replace() 将 replacement 参数当作 PHP 代码(在适当的逆向引用替换完之后)。提示:要确保 replacement 构成一个合法的 PHP 代码字符串,否则 PHP 会在报告在包含 preg_replace() 的行中出现语法解析错误。
也就是说,pat和sub有相同部分,rep的代码就会执行。
根据源码分析X-Forwarded-For改成127.0.0.1之后,GET进三个参数。然后调用了preg_replace函数。并且没有对pat进行过滤,所以可以传入"/e"触发漏洞
最终结果
1
2
3
4
5
6
7
8
9
10
11
|
<?php
$flag='xxx';
extract($_GET);
if(isset($shiyan)){
$content=trim(file_get_contents($flag));
if($shiyan==$content){
echo'flag{xxx}';
}else{
echo'Oh.no';
}
}
|
代码大概的意思是可以从get获得的参数,设置入GET超全局数组里面,并且覆盖之前的变量
这样子只需要重新设置$shiyan 和 $content,绕过if的检测就可以了
strcmp比较字符串
1
2
3
4
5
6
7
8
9
|
<?php
$flag = "flag{xxxxx}";
if (isset($_GET['a'])) {
if (strcmp($_GET['a'], $flag) == 0) //如果 str1 小于 str2 返回 < 0; 如果 str1大于 str2返回 > 0;如果两者相等,返回 0。
//比较两个字符串(区分大小写)
die('Flag: '.$flag);
else
print 'No';
}
|
传数组
url二次编码绕过
1
2
3
4
5
6
7
8
9
10
|
<?php
if(eregi("hackerDJ",$_GET[id])) {
echo("not allowed!");
exit();
}
$_GET[id] = urldecode($_GET[id]);
if($_GET[id] == "hackerDJ"){
echo "Access granted!";
echo "flag";
}
|
- ergei() 函数正则匹配 等于erge()函数 只是匹配的时候忽略大小写
需要匹配 hackerDJ 只要在他url编码后任意一个编码前加上25就行 %25 url解码后是 %
md5函数
1
2
3
4
5
6
7
8
9
10
11
|
<?php
error_reporting(0);
$flag = 'flag{test}';
if (isset($_GET['username']) and isset($_GET['password'])) {
if ($_GET['username'] == $_GET['password'])
print 'Your password can not be your username.';
else if (md5($_GET['username']) === md5($_GET['password']))
die('Flag: '.$flag);
else
print 'Invalid password';
}
|
0e绕过好像没用 直接数组绕过
数组返回NULL绕过
1
2
3
4
5
6
7
8
9
10
|
<?php
$flag = "flag";
if (isset ($_GET['password'])) {
if (ereg ("^[a-zA-Z0-9]+$", $_GET['password']) === FALSE)
echo 'You password must be alphanumeric';
else if (strpos ($_GET['password'], '--') !== FALSE)
die('Flag: ' . $flag);
else
echo 'Invalid password';
}
|
弱类型整数大小比较绕过
1
2
3
4
5
|
<?php
$temp = $_GET['password'];
is_numeric($temp)?die("no numeric"):NULL;
if($temp>1336)
echo $flag;
|
科学计数法 也可以传数组
sha()函数比较绕过
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
<?php
$flag = "flag";
if (isset($_GET['name']) and isset($_GET['password'])){
var_dump($_GET['name']);
echo "";
var_dump($_GET['password']);
var_dump(sha1($_GET['name']));
var_dump(sha1($_GET['password']));
if ($_GET['name'] == $_GET['password'])
echo 'Your password can not be your name!';
else if (sha1($_GET['name']) === sha1($_GET['password']))
die('Flag: '.$flag);
else
echo 'Invalid password.';
}else{
echo 'Login first!';
}
|
- var_dump() 打印变量相关信息
- sha1() 计算字符串的 sha1 散列值
数组绕过
md5加密相等绕过
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<?php
$md51 = md5('QNKCDZO');
$a = @$_GET['a'];
$md52 = @md5($a);
if(isset($a)){
if ($a != 'QNKCDZO' && $md51 == $md52) {
echo "flag{*}";
} else {
echo "false!!!";
}
}else{
echo "please input a";
}
|
虽然说不用看也知道一定是0e绕过。。。。
十六进制与数字比较
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
<?php
error_reporting(0);
function noother_says_correct($temp)
{
$flag = 'flag{test}';
$one = ord('1'); //ord — 返回字符的 ASCII 码值
$nine = ord('9'); //ord — 返回字符的 ASCII 码值
$number = '3735929054';
// Check all the input characters!
for ($i = 0; $i < strlen($number); $i++){
// Disallow all the digits!
$digit = ord($temp{$i});
if ( ($digit >= $one) && ($digit <= $nine) ){
// Aha, digit not allowed!
return "flase";
}
}
if($number == $temp)
return $flag;
}
$temp = $_GET['password'];
echo noother_says_correct($temp);
|
变量覆盖(平台挂掉了)
ereg正则%00截断
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
<?php
$flag = "xxx";
if (isset ($_GET['password'])){
if (ereg ("^[a-zA-Z0-9]+$", $_GET['password']) === FALSE){
echo 'You password must be alphanumeric';
}else if (strlen($_GET['password']) < 8 && $_GET['password'] > 9999999){
if (strpos ($_GET['password'], '-') !== FALSE){ //strpos — 查找字符串首次出现的位置
die('Flag: ' . $flag);
}else{
echo('- have not been found');
}
}else{
echo 'Invalid password';
}
}
|
法1.php对字符串是数字的部分进行截取进行判断 还有就是 erge %00截断匹配了
法2.数组返回 null null !== false
strpos数组绕过
1
2
3
4
5
6
7
8
9
10
|
<?php
$flag = "flag";
if (isset ($_GET['ctf'])) {
if (@ereg ("^[1-9]+$", $_GET['ctf']) === FALSE)
echo '必须输入数字才行';
else if (strpos ($_GET['ctf'], '#biubiubiu') !== FALSE)
die('Flag: '.$flag);
else
echo '骚年,继续努力吧啊~';
}
|
跟上一题一样 没什么好解释
数字验证正则绕过
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
<?php
error_reporting(0);
$flag = 'flag{test}';
if ("POST" == $_SERVER['REQUEST_METHOD']){
$password = $_POST['password'];
if (0 >= preg_match('/^[[:graph:]]{12,}$/', $password)){ //preg_match — 执行一个正则表达式匹配
echo 'flag';
exit;
}
while (TRUE){
$reg = '/([[:punct:]]+|[[:digit:]]+|[[:upper:]]+|[[:lower:]]+)/';
if (6 > preg_match_all($reg, $password, $arr))
break;
$c = 0;
$ps = array('punct', 'digit', 'upper', 'lower'); //[[:punct:]] 任何标点符号 [[:digit:]] 任何数字 [[:upper:]] 任何大写字母 [[:lower:]] 任何小写字母
foreach ($ps as $pt){
if (preg_match("/[[:$pt:]]+/", $password))
$c += 1;
}
if ($c < 3) break; //>=3,必须包含四种类型三种与三种以上
if ("42" == $password) echo $flag;
else echo 'Wrong password';
exit;
}
}
|
要长度超过12字母符号数字大小写超过三种 但是实际测试符合条件的都不行 不符合条件的就直接出flag 不懂不懂。。。。。
网上版本都是直接post空值就行 应该是哪里出了问题?题目本意应该不是这个?
简单的waf(靶机挂了)