知识点总结

  1. 一: 正则
  2. 1. 正则可以用数组绕过 89
  3. 2. 正则 如果不是多行匹配可以用%0a绕过
  4. 二: intval
  5. intval ( mixed $var [, int $base = 10 ] ) : int
  6. Note:
  7. 如果 base 0,通过检测 var 的格式来决定使用的进制:
  8. 如果字符串包括了 "0x" (或 "0X") 的前缀,使用 16 进制 (hex);否则,
  9. 如果字符串以 "0" 开始,使用 8 进制(octal);否则,
  10. 将使用 10 进制 (decimal)。
  11. 绕过方法主要有 科学计数法,进制转换,浮点数,还有数据类型转换的时候会自动去除空格

89 正则数组绕过

源码

  1. <?php
  2. include("flag.php");
  3. highlight_file(__FILE__);
  4. if(isset($_GET['num'])){
  5. $num = $_GET['num'];
  6. if(preg_match("/[0-9]/", $num)){
  7. die("no no no!");
  8. }
  9. if(intval($num)){
  10. echo $flag;
  11. }
  12. }

正则匹配了所有的数字,可以利用数组绕过
正则的返回
返回完整匹配次数(可能是0),或者如果发生错误返回FALSE。
数组会返回报错,且程序会正常进行

90 intval绕过

源码

  1. <?php
  2. include("flag.php");
  3. highlight_file(__FILE__);
  4. if(isset($_GET['num'])){
  5. $num = $_GET['num'];
  6. if($num==="4476"){
  7. die("no no no!");
  8. }
  9. if(intval($num,0)===4476){
  10. echo $flag;
  11. }else{
  12. echo intval($num,0);
  13. }
  14. }
  15. ?>

官方文档

  1. intval ( mixed $var [, int $base = 10 ] ) : int
  2. Note:
  3. 如果 base 0,通过检测 var 的格式来决定使用的进制:
  4. 如果字符串包括了 "0x" (或 "0X") 的前缀,使用 16 进制 (hex);否则,
  5. 如果字符串以 "0" 开始,使用 8 进制(octal);否则,
  6. 将使用 10 进制 (decimal)。

直接传入一个4476a解决

91 正则%0a绕过

源码

  1. <?php
  2. show_source(__FILE__);
  3. include('flag.php');
  4. $a=$_GET['cmd'];
  5. if(preg_match('/^php$/im', $a)){
  6. if(preg_match('/^php$/i', $a)){
  7. echo 'hacker';
  8. }
  9. else{
  10. echo $flag;
  11. }
  12. }
  13. else{
  14. echo 'nonononono';
  15. }

这题第一个正则是不区分大小写和多行模式 第二个不是多行模式
直接传入?cmd=a%0aphp

92 科学计数法 intval绕过

源码

  1. include("flag.php");
  2. highlight_file(__FILE__);
  3. if(isset($_GET['num'])){
  4. $num = $_GET['num'];
  5. if($num==4476){
  6. die("no no no!");
  7. }
  8. if(intval($num,0)==4476){
  9. echo $flag;
  10. }else{
  11. echo intval($num,0);
  12. }
  13. }

和前面的有点不同,前面的第一个if是和’4476’强比较第二个是经过intval转换和int 4476进行强比较
可以用4476a绕过
但是这里因为第一个是和4476弱比较,所以传入4476a是等于4476的,4476a被强制转换为整型
这里可以传入4476.1,就可以绕过第一个比较,经过invtal4476.1变为4476就ok了
但是这道题的预期其实是4476e0,因为4476e1

  1. <?php
  2. echo (int)'4476e2'; //447600
  3. echo "\r\n";
  4. echo intval('4476e2',0);//4476因为是字符串所以科学计数法没用,直接把e看成普通字母
  5. echo "\r\n";
  6. var_dump('4476e2'==4476);//bool:false
  7. ?>

93 进制转换 intval绕过

源码

  1. include("flag.php");
  2. highlight_file(__FILE__);
  3. if(isset($_GET['num'])){
  4. $num = $_GET['num'];
  5. if($num==4476){
  6. die("no no no!");
  7. }
  8. if(preg_match("/[a-z]/i", $num)){
  9. die("no no no!");
  10. }
  11. if(intval($num,0)==4476){
  12. echo $flag;
  13. }else{
  14. echo intval($num,0);
  15. }
  16. }

过滤了字母,上一道题的预期接4476e2就没用了,4476.1照样可以用
这里要讲的是进制绕过
传入010574,第一个if的时候很弱比较很明显不等于,第三个if判断的时候,因为字符串以0开头就是八进制会转换为八进制数字,成功绕过

94 浮点数 加intval绕过

源码

  1. include("flag.php");
  2. highlight_file(__FILE__);
  3. if(isset($_GET['num'])){
  4. $num = $_GET['num'];
  5. if($num==="4476"){
  6. die("no no no!");
  7. }
  8. if(preg_match("/[a-z]/i", $num)){
  9. die("no no no!");
  10. }
  11. if(!strpos($num, "0")){
  12. die("no no no!");
  13. }
  14. if(intval($num,0)===4476){
  15. echo $flag;
  16. }
  17. }

过滤了开头为0的数字,而且一定要数字中有0,不然还会再第三个if中die了,直接传入4476.0

95 数据类型转换自动去除空格

源码

  1. include("flag.php");
  2. highlight_file(__FILE__);
  3. if(isset($_GET['num'])){
  4. $num = $_GET['num'];
  5. if($num==4476){
  6. die("no no no!");
  7. }
  8. if(preg_match("/[a-z]|\./i", $num)){
  9. die("no no no!!");
  10. }
  11. if(!strpos($num, "0")){
  12. die("no no no!!!");
  13. }
  14. if(intval($num,0)===4476){
  15. echo $flag;
  16. }
  17. }

过滤了小数点,过滤了进制转换,emm没想到 看了大师傅的文章是空格加进制转换,真的没想到 010574,php在类型转换的时候会过滤掉字符串前面的空格…