parsing - PHP YAML 파서




(8)

최종 업데이트 : 2017 년 7 월 26 일

다음은 PHP에서 YAML의 상태를 요약 한 것입니다.

  • C 라이브러리의 래퍼 : 속도가 필요한 경우에는 다음을 원할 것입니다.
  • 순수한 PHP 구현 :

    • sfYaml : Symfony의 YAML 구성 요소. 저자의 동기를 here 볼 수 있습니다. 그는 " 사용하기 쉽고, 빠르고, 단위 테스트를 거쳤으며 명확한 오류 메시지가있는 것을 원했습니다 ."
    • spyc : 의존성이없는 YAML 파서

이 글을 쓰는 시점에서 최신 버전은 앞서 언급 한 라이브러리의 날짜를 제공하며 YAML 사양 (1.2는 최신 버전 임)의 버전은 다음과 같습니다.

php-yaml   1.3.0     2016-09-24     YAML 1.1  [PHP 5]
php-yaml   2.0.0     2016-09-24     YAML 1.1  [PHP 7]
syck       0.9.3     2008-11-18     YAML 1.0
sfYaml     3.3.5     2017-06-15     YAML 1.1, most of 1.2
spyc       0.6.2     2017-02-24     YAML 1.1 

누구든지 PHP에 대한 좋은 YAML Parser를 알고 있습니까? 그렇다면이 도서관의 장단점은 무엇입니까?


시도 sfYaml , 내가 아는 최고입니다.

Symfony와 Doctrine ORM이 이것을 사용하고 있습니다.

그것을 얻으려면 Doctrine 1.2를 다운로드 하고 vendor 디렉토리에서 sfYaml 을 추출 sfYaml .

귀하의 필요에 부합하는지 알려주십시오.


프로젝트에서 YAML을 많이 사용하고 있다면 spyc 또는 Symfony YAML과 같은 순수 PHP 라이브러리가 빠르지 않다는 것을 알 수 있습니다. C YAML 파서에는 최소한 두 가지 PHP 바인딩이 있습니다.

  • yaml - LibYAML YAML 1.1 파서 라이브러리의 래퍼
  • syck - Syck YAML 1.0 파서 라이브러리 용 래퍼

Spyc : spyc

순수한 PHP 구현이므로 설치를 위해 서버를 수정할 필요가 없습니다. 속도가 심각한 문제라면, 이상적인 해결책은 아니 겠지만 YAML을 사용하여 구성이나 비교적 적은 볼륨으로 사용한다면 환상적인 솔루션입니다.

YAML 문서가 주어지면 Spyc는 사용할 수있는 배열을 반환하지만 적합하다고 생각합니다.

require_once "spyc.php";
$data = Spyc::YAMLLoad($myfile);

주어진 배열을 통해, Spyc은 데이터로부터 구축 된 YAML 문서를 포함하는 문자열을 반환 할 것입니다.

$yaml_str = Spyc::YAMLDump($myarray);




이 대답은 잘못 작성된 PHP 사용자 유효성 검사 코드를 우회하는 방법,이 공격의 작동 방식 및 사용 방법, 이전 MySQL 기능을 안전한 준비된 문으로 대체하는 방법을 보여주기 위해 작성되었습니다. 기본적으로 사용자 (아마 많은 담당자와 함께) 코드를 개선하기위한 질문을하는 신규 사용자들에게는 짖고있다.

먼저,이 테스트 mysql 데이터베이스 (나는 광산 준비라고 불렀다)를 만들어야한다.

mysql> create table users(
    -> id int(2) primary key auto_increment,
    -> userid tinytext,
    -> pass tinytext);
Query OK, 0 rows affected (0.05 sec)

mysql> insert into users values(null, 'Fluffeh', 'mypass');
Query OK, 1 row affected (0.04 sec)

mysql> create user 'prepared'@'localhost' identified by 'example';
Query OK, 0 rows affected (0.01 sec)

mysql> grant all privileges on prep.* to 'prepared'@'localhost' with grant option;
Query OK, 0 rows affected (0.00 sec)

이렇게하면 PHP 코드로 이동할 수 있습니다.

다음 스크립트가 웹 사이트의 관리자를위한 확인 프로세스라고 가정 해 봅니다 (테스트를 위해 복사하여 사용하는 경우 간단하지만 작동 함).

<?php 

    if(!empty($_POST['user']))
    {
        $user=$_POST['user'];
    }   
    else
    {
        $user='bob';
    }
    if(!empty($_POST['pass']))
    {
        $pass=$_POST['pass'];
    }
    else
    {
        $pass='bob';
    }

    $database='prep';
    $link=mysql_connect('localhost', 'prepared', 'example');
    mysql_select_db($database) or die( "Unable to select database");

    $sql="select id, userid, pass from users where userid='$user' and pass='$pass'";
    //echo $sql."<br><br>";
    $result=mysql_query($sql);
    $isAdmin=false;
    while ($row = mysql_fetch_assoc($result)) {
        echo "My id is ".$row['id']." and my username is ".$row['userid']." and lastly, my password is ".$row['pass']."<br>";
        $isAdmin=true;
        // We have correctly matched the Username and Password
        // Lets give this person full access
    }
    if($isAdmin)
    {
        echo "The check passed. We have a verified admin!<br>";
    }
    else
    {
        echo "You could not be verified. Please try again...<br>";
    }
    mysql_close($link);

?>

<form name="exploited" method='post'>
    User: <input type='text' name='user'><br>
    Pass: <input type='text' name='pass'><br>
    <input type='submit'>
</form>

언뜻보기에 합법적 인 것 같습니다.

사용자는 로그인과 비밀번호를 입력해야합니다.

훌륭함, 다음을 입력하지 마십시오 :

user: bob
pass: somePass

그것을 제출하십시오.

출력은 다음과 같습니다.

You could not be verified. Please try again...

감독자! 예상대로 작업하면 실제 사용자 이름과 비밀번호를 사용해 볼 수 있습니다.

user: Fluffeh
pass: mypass

놀랄 만한!안녕하세요 - 파이브 모든 라운드, 코드가 올바르게 관리자를 확인했습니다. 그것은 완벽!

글쎄,별로.사용자가 현명한 작은 사람이라고합니다. 그 사람이 저라고합니다.

다음을 입력하십시오.

user: bob
pass: n' or 1=1 or 'm=m

출력은 다음과 같습니다.

The check passed. We have a verified admin!

축하해, 방금 허위 사용자 이름과 허위 비밀번호를 입력하여 슈퍼 보호 관리자 섹션 만 입력하도록 허용했습니다. 진심으로, 당신이 나를 믿지 않는다면, 내가 제공 한 코드로 데이터베이스를 만들고,이 PHP 코드를 실행하십시오. 정말로 눈에 띄게 사용자 이름과 암호를 검증하는 것 같습니다.

그래서, 대답에서, 당신은 왜 황량하게 들리고 있습니까.

그래서, 무엇이 잘못되었는지 살펴보고 왜 내가 방금 슈퍼 관리자 전용 박쥐 동굴에 들어 왔는지 보도록하겠습니다. 나는 당신이 당신의 입력을 신중하게 생각하지 않고 단순히 데이터베이스에 직접 전달했다고 생각했습니다. 실제로 실행중인 쿼리를 변경하는 방식으로 입력을 구성했습니다. 그래서, 그것이 무엇이되어야하고, 그것은 결국 무엇이 되었습니까?

select id, userid, pass from users where userid='$user' and pass='$pass'

이것이 쿼리이지만, 우리가 사용한 실제 입력 값으로 변수를 대체하면 다음과 같이됩니다.

select id, userid, pass from users where userid='bob' and pass='n' or 1=1 or 'm=m'

먼저 "암호"를 구성하여 암호 주위에 작은 따옴표를 닫고 완전히 새로운 비교를 도입하는 방법을 살펴보십시오. 그런 다음 안전을 위해 또 다른 "문자열"을 추가하여 원래 인용 부호에 단일 인용 부호가 예상대로 닫힐 수 있도록했습니다.

그러나 이것은 지금 당신에게 소리 치는 사람들에 관한 것이 아니라 코드를 더 안전하게 만드는 방법을 보여줍니다.

좋아요. 그래서 무엇이 잘못됐으며 어떻게 해결할 수 있습니까?

이것은 고전적인 SQL 주입 공격입니다. 그 일에 가장 간단한 것 중 하나입니다. 공격 벡터의 척도에서, 이것은 탱크를 공격하는 유아이며 승리합니다.

그렇다면 신성한 관리자 섹션을 어떻게 보호하고 안전하고 안전하게 만들 수 있습니까? 가장 먼저 할 일은 사용하지 않는 mysql_*기능을 사용하지 않는 것입니다. 나는 당신이 온라인에서 찾은 튜토리얼을 따랐다.하지만 작동은 오래되었지만 오래되었다. 그리고 몇 분의 공간에서 나는 땀을 흘리지 않고 과거를 깨뜨렸다.

이제 mysqli_ 또는 PDO 를 사용하는 것이 더 좋다 . 필자는 개인적으로 PDO에 대한 열렬한 팬입니다. 그래서이 답변의 나머지 부분에서 PDO를 사용하게 될 것입니다. 프로와 사기가 있지만, 개인적으로 나는 프로가 사기를 능가한다는 것을 발견합니다. MySQL이나 오라클을 사용하든 피 묻은 것에 관계없이 여러 데이터베이스 엔진에 이식 할 수 있습니다. 단지 연결 문자열을 변경하여 사용하려는 모든 멋진 기능을 갖추고 있으며 훌륭하고 깨끗합니다. 나는 깨끗해.

이제 PDO 객체를 사용하여 작성된이 코드를 다시 살펴 보겠습니다.

<?php 

    if(!empty($_POST['user']))
    {
        $user=$_POST['user'];
    }   
    else
    {
        $user='bob';
    }
    if(!empty($_POST['pass']))
    {
        $pass=$_POST['pass'];
    }
    else
    {
        $pass='bob';
    }
    $isAdmin=false;

    $database='prep';
    $pdo=new PDO ('mysql:host=localhost;dbname=prep', 'prepared', 'example');
    $sql="select id, userid, pass from users where userid=:user and pass=:password";
    $myPDO = $pdo->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
    if($myPDO->execute(array(':user' => $user, ':password' => $pass)))
    {
        while($row=$myPDO->fetch(PDO::FETCH_ASSOC))
        {
            echo "My id is ".$row['id']." and my username is ".$row['userid']." and lastly, my password is ".$row['pass']."<br>";
            $isAdmin=true;
            // We have correctly matched the Username and Password
            // Lets give this person full access
        }
    }

    if($isAdmin)
    {
        echo "The check passed. We have a verified admin!<br>";
    }
    else
    {
        echo "You could not be verified. Please try again...<br>";
    }

?>

<form name="exploited" method='post'>
    User: <input type='text' name='user'><br>
    Pass: <input type='text' name='pass'><br>
    <input type='submit'>
</form>

주요 차이점은 더 이상의 mysql_*기능 이 없다는 것 입니다. 그것은 모두 PDO 객체를 통해 수행됩니다. 둘째, 준비된 명령문을 사용하고 있습니다. 자, 당신이 묻는 준비된 진술은 무엇입니까? 쿼리를 실행하기 전에 데이터베이스에 알려주는 방법, 우리가 실행할 쿼리를 알려주는 방법입니다. 이 경우 데이터베이스에 "안녕하세요, id, userid를 원하는 select 문을 실행하고 userid가 변수이고 패스가 변수 인 테이블 사용자로부터 전달할 것입니다.".

그런 다음 execute 문에서 데이터베이스에 현재 예상되는 모든 변수가 포함 된 배열을 전달합니다.

결과는 훌륭합니다. 다시 이전의 사용자 이름과 암호 조합을 사용해보십시오.

user: bob
pass: somePass

사용자가 확인되지 않았습니다. 굉장해.

어때?

user: Fluffeh
pass: mypass

오, 방금 흥분했는데, 효과가있었습니다 : 수표가 통과되었습니다. 우리는 검증 된 관리자가 있습니다!

자, 우리의 작은 검증 시스템을 통과하기 위해 영리한 균열이 입력 할 데이터를 시도해보십시오.

user: bob
pass: n' or 1=1 or 'm=m

이번에는 다음을 얻습니다.

You could not be verified. Please try again...

이것이 질문을 게시 할 때 소리를 지르는 이유입니다. 사람들이 코드를 시도해도 무시할 수 있음을 알 수 있기 때문입니다. 이 질문과 답변을 사용하여 코드를 개선하고보다 안전하고 최신 기능을 사용하십시오.

마지막으로 이것은 이것이 PERFECT 코드라는 말은 아닙니다. 당신이 그것을 개선하기 위해 할 수있는 많은 것들이 있습니다. 예를 들어 암호 해시를 사용하면 데이터베이스에 감각 정보를 저장할 때 일반 텍스트로 저장하지 않고 여러 수준의 검증을 할 수 있습니다. 당신은 단지 오래된 주입 경향이있는 코드를이 코드로 바꾼다. 좋은 코드를 작성하는 길을 따라 잘 될 것이다. - 그리고 지금까지 읽었던 것과 아직도 읽고있는 사실은 나에게 당신이이 타입을 구현하지 않을 것이라는 희망을 준다. 귀하의 웹 사이트 및 응용 프로그램을 작성할 때 코드를 작성해야하지만, 앞서 언급 한 다른 것들을 연구하고 연구하는 것이 좋습니다. 간신히 기능하는 가장 기본적인 코드가 아닌 최상의 코드를 작성하십시오.







php parsing yaml