LoginSignup
2
0

More than 5 years have passed since last update.

PHPのソースコードを徘徊してたらctypeのテストコードにぶつかった

Last updated at Posted at 2017-07-23

PHPの脆弱性探しで、PHPのソースコードを徘徊してたら、以下のようなテストコードにぶつかりました。

--TEST--
ctype on strings
--SKIPIF--
<?php require_once('skipif.inc'); ?>
--FILE--
<?php 

setlocale(LC_ALL,"C");
print "LOCALE is '" . setlocale(LC_ALL,0) . "'\n";

function ctype_test_002($function) {
    $n1 = $n2 = $n3 = 0;
    // test portable POSIX characters 0..127
    for ($a=0;$a<128;$a++) {
        $c = chr($a);
        if($function($a)) $n1++;
        if($function("$c$c$c")) $n2++;
        if($function("1-$c$c$c-x")) $n3++;
    }
    print "$function $n1 $n2 $n3\n";
}

ctype_test_002("ctype_lower");
ctype_test_002("ctype_upper");
ctype_test_002("ctype_alpha");  
ctype_test_002("ctype_digit");  
ctype_test_002("ctype_alnum");      
ctype_test_002("ctype_cntrl");  
ctype_test_002("ctype_graph");
ctype_test_002("ctype_print");
ctype_test_002("ctype_punct");
ctype_test_002("ctype_space");
ctype_test_002("ctype_xdigit");

?>
--EXPECTF--
LOCALE is '%s'
ctype_lower 26 26 0
ctype_upper 26 26 0
ctype_alpha 52 52 0
ctype_digit 10 10 0
ctype_alnum 62 62 0
ctype_cntrl 33 33 0
ctype_graph 94 94 94
ctype_print 95 95 95
ctype_punct 32 32 0
ctype_space 6 6 0
ctype_xdigit 22 22 0

ctypeとは、文字タイプを判別する関数群のようで、ここでは、
ctype_lower
ctype_upper
ctype_alpha
ctype_digit
ctype_alnum
ctype_cntrl
ctype_graph
ctype_print
ctype_punct
ctype_space
ctype_xdigit
などの関数が実行されています。

setlocale(LC_ALL,"C");

で、ロケールを"C"にする。"C"とは、アプリケーションのデフォルトのロケールのことで、例えば、ユーザーがロケールを変更していた場合でも、アプリケーションのデフォルトのロケールに戻す。

setlocale(LC_ALL,0)

この関数は、現在設定されているロケールを文字列で返す関数です。"C"が設定されていることを確認していますね。

function ctype_test_002($function)

この関数の、$functionに、関数名の文字列を渡すことで、関数を渡すことになる。

chr($a)

chr関数は、0から255までの値を引数として設定できます。以下のように、256以上の場合は、256で割った余りの数字のasciiコードを返します。0以下の場合は、0以上になるまで、256を足されます。

while ($ascii < 0) {
    $ascii += 256;
}
$ascii %= 256;

ここでは、0から127までしか使ってないですね。これには、空白、記号、数字、大文字のアルファベット、小文字のアルファベットが入ります。

$function($a)

この関数によって、\$aが、そのまま、\$functionに定義された関数に引数として入力されます。
\$functionが"ctype_lower"として定義されていると、$aが小文字に対応する数字の時だけ、trueを返します。
ここでは、chrでascii文字に変換する前の、ただの数字を入力しています。この時も、該当する文字が小文字の時は、trueを返します。具体的には、97から122です。

$function("$c$c$c")

この関数によって、ascii文字が、3つ連結された文字列が、\$functionに引数として導入されます。\$function(\$a)と同じく、\$functionが"ctype_lower"として定義されていると、$cが小文字の時だけ、trueを返します。

$function("1-$c$c$c-x")

この場合、例えば、\$functionが、"ctype_lower"に定義されていて、\$cが小文字だったとしても、trueは返されません。理由は、1と-が混じっていて、これらはアルファベットの小文字ではないからです。
しかし、\$functionが"ctype_print"に定義されていると、$cが印字可能な文字が入力されていた場合、trueが返されます。なぜかというと、1と-が共に印字可能だからです。

ところで、最近は、技術ブログを書きたいなら、OSSのソースコードを読んだ方がいいのではと考え始めました。ということで、これからもOSSのソースコードを読んでいこうかと思います。
これからもよろしくお願いします。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0