Zend Framework의 SQL 모델을 사용할 때의 SQL 주입 취약점


15

테이블을 조인 할 때 Zend Framework의 SQL 모델을 사용합니다. 예를 들어 실제 코드를 수정했지만 요점을 알 것입니다.

$this->getSelect()->join(
                      array('sections' => $sectionsTableName),
                      'main_table.banner_id = pages.banner_id',
                      array()
                    )
                  ->where("sections.section= '$section' OR sections.section = '0' OR (sections.section = '6' AND ? LIKE main_table.url)",$url)
                  ->group('main_table.banner_id'); 

페이지에 ajax가로드되고 $ section 매개 변수가 GET 매개 변수 ( www.example.com/controllerName/index/display/3?paremeter1=example&section=www.example2.com) 로 전송됩니다 .

누군가 다음과 같은 것을 수행하면 문제가 있습니다.

www.example.com/controllerName/index/display/3?paremeter1=example&url=(SELECT 3630 FROM(SELECT COUNT(*),CONCAT(0x7170786a71,(SELECT (ELT(3630=3630,1))),0x717a716b71,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.CHARACTER_SETS GROUP BY x)a)

이런 식으로 사용자는 전체 데이터베이스를 덤프 할 수 있습니다. 데이터는 표시되지 않지만 SQL은 덤프를 수행하여 SQL 과부하를 유발할 수 있습니다.

질문 :

  1. 이러한 시나리오를 방지하는 가장 좋은 방법은 무엇입니까?
  2. 이제는 이전 고객이 걱정됩니다. 이 코드를 사용하여 테이블을 변경하거나 변경하는 것과 같이 더 위험한 작업을 수행 할 수 있습니까? subselect 내에 SELECT 이외의 다른 명령문을 넣을 수 없으므로 DELETE가 SQL 구문 오류를 생성하지 않기 때문에 추측하지 않습니다. 내가 맞아?

업데이트 : 내 예제는 'arround $ sections'기호가 있으므로 주입을 할 수 없기 때문에 SQL 주입의 올바른 그림이 아닙니다. 어쨌든 이것은 정수 값을 기대하고 정수 입력을 필터링하지 않을 때 가능합니다. 아래 내 의견을 참조하십시오.


1
당신은 사용할 수 있습니다 $db = Mage::getSingleton('core/resource')->getConnection('core_read');$db->quote()심지어 귀하의 경우 봐 $db->quoteInto. 경우 $this자원이, 당신은 할 수 있습니다 : $this->getConnection('core_read')->quoteInto()그것은 컬렉션 있다면 당신은 할 수있다 : $this->getResource()->getConnection('core_read')->quoteInto(). 그 라인을 따라. 그것이 목표를 향해 당신을 안내하는 데 도움이된다면.
ash

방금 값이 정수 인 경우에만이 시나리오가 가능하다는 것을 깨달았습니다. value가 varchar이면 '부호 앞에 (부호 가 항상 표시 되므로 (SELECT문자열과 같고 기능이 아닙니다. field가 정수이면 '필요하지 않으며 이러한 시나리오가 가능합니다. 그러나 정수는 항상 필터링되어야 intval()하므로 이것이 문제가되지 않습니다.
JohnyFree

닫는 것으로 시작하면 '어떻게됩니까? 그래서 ' AND (SELECT ...) '? 그건 그렇고, Zend가 이것을 인용하지 않는다고 생각하지 않습니다 ... 바인딩을 사용하면 PDO 가이를 처리합니다. 다음과 같은 찌르는 연결을 사용하지 마십시오."sections.section= '$section'"
7ochem

이 경우 @ 7ochem?를 사용하여 매개 변수를 바인딩해야합니다. '\가됩니다. 그러나 정수 값을 사용하는 경우 intval () php 함수를 사용하여 정리할 수 있고 '0이됩니다.
JohnyFree

답변:


8

입력을 확인하십시오!

당신이 할 수있는만큼 훌륭하고

검증을위한 몇 가지 제안 :

  1. GET 매개 변수를 통해 얻는 변수의 길이를 확인하십시오. 끝없는 긴 문자열을 받아 들일 필요가 없습니다.

  2. 도메인 이름을 확인하십시오. 예상되는 도메인 이름의 형식은 무엇입니까? 항상 www.mydomain.tld입니까? 일치 또는 더 나은 사용을 확인하는 정규식을 만듭니다 Zend_Validate_Hostname.

    $validator = new Zend_Validate_Hostname();
    if ($validator->isValid($hostname)) {
        //hostname is valid - continue
    }
  3. 허용 목록 : 예상 할 도메인 이름을 알고 있습니까? 허용 된 도메인 목록을 만들어 확인할 수 있습니다. 나머지는 버려

    $allowedDomains = array('www.domain1.tld','www.domain2.tld');
  4. 도메인 이름 및 / 또는 문자를 블랙리스트에 추가 : 도메인 이름이 필요한 경우 az 및 0-9와 "."이외의 다른 문자를 사용할 필요가 없습니다. (특별한 도메인 이름으로 작업하지 않는 한).

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.