joeware - never stop exploring... :)

Information about joeware mixed with wild and crazy opinions...

11/21/2021

New Releases of AdFind/AdMod Available For Download

by @ 7:57 pm. Filed under general

I have uploaded the new versions of AdFind and AdMod to www.joeware.net for download.

Note that I know that a lot of anti-malware has been reporting AdFind.exe as malware now, usually some form of LOLBIN or PUA. The reason for this is because the hacker collectives are using the tool for scanning Active Directory environments as part of ransomware attacks. There is nothing inherently dangerous with AdFind, it is just fast and useful so hackers are like we should use this because it is so good.

I have seen an article that said AdFind is deploying malware. That is absolutely incorrect, AdFind has no capability to deploy or change anything. It is purely an LDAP query tool. It submits LDAP queries and outputs the responses from LDAP Servers.

    joe

EDIT: Updated malware to be anti-malware. I had a Freudian slip because I consider AV and anti-malware software to be some of the most evil malware. Smile

Rating 4.63 out of 5

10/23/2021

Binary Format Security Descriptor Export/Import

by @ 10:30 am. Filed under general

I was about to add some code to AdFind to export Security Descriptors in binary export/import format and found out I already had written that code.

I apparently used a bad switch name for it though because I didn’t intuitively know what it was and find it by accident. That or my brain was in a much more computer sciencey mode when I named the switch before versus now.

So instead of adding the code to make AdFind be able to do that functionality, I added a new switch -sdbinout which is an alias for -sdblob.

Oh I also set it up so that if you are outputting CSV format it will automatically remove the [BLOB] label on the hex export string.

And AdMod can already import that format just fine btw with BIN##ntsecuritydescriptor::<blob hex string> or if using CSV input you can do BIN##ntsecuritydescriptor::{{SD fieldname}} so probably something like BIN##ntsecuritydescriptor::{{ntsecuritydescriptor}} or in shortcut form… BIN##ntsecuritydescriptor::{{.}}

Rating 3.00 out of 5

7/4/2021

LOL

by @ 6:40 pm. Filed under general

image

Rating 4.75 out of 5

5/31/2021

Dear Microsoft….

by @ 2:14 pm. Filed under tech

F.U.2.

SNAGHTMLeb36d51

Rating 4.78 out of 5

AdFind Enemy #1 for AV Tools

by @ 1:58 pm. Filed under tech

Ok not really enemy #1, but they are getting stupid about it.

Once again the AV Tool companies have their panties in a bunch over a joeware tool. Now it is AdFind. The digests on the website are accurate, I also uploaded it to virustotal before anyone but me had touched it so their digests are accurate as well.

https://www.virustotal.com/gui/file/929345d356424b35188a8bff6b71c7183e170554042276339085d3cc68435558/detection

One of the community comments is on point

“Sure, AdFind is a lolbin. But so are dsquery, dsget and cvsde. I’m concerned that the myriad PUP/PUA and GenericML have gone unchallenged for this valuable tool.”

Let me repeat one again, the joeware tools aren’t malware. The issue is that hackers like joeware because the joeware tools do a lot of stuff faster and better than anything else.

No I am not going to debate it with the AV/Malware companies. I learned a long ago that it is absolutely pointless. They are generally clueless when you speak to them and it isn’t worth my frustration to deal with them. Your options are to override your AV/Malware tools locally (and complain to your AV/Malware company that they forgot to mark dsquery, dsget, csvde, ldifde, ldapsearch, ADSI, PowerShell, and anything else that can submit LDAP search queries as malware) or to not use the tool.

I have also heard about SOCs / IR Teams that have gotten trigger happy with AdFind as well figuring every occurrence of it is a bad guy trying to do something without intelligently looking at the queries and trying to figure out does this really look like an attack?? You will have to work with them too if they start doing that. Most of them are quite reasonable when you explain the use of the tool and what you are doing. For those that are picking up on AdFind usage via command line scraping I even recently added an undocumented null switch for folks if they want to use it which can be used to send a code/message to SOC/IR. That switch is called –SOC. It does nothing at all except allow you to type in an arbitrary message that you want SOC/IR to see if they are monitoring your command line journeys. For example:

[Mon 05/31/2021 13:31:45.46]
E:\DEV\cpp\vs\AdFind\Release>adfind -h lockout.test.loc -ldappingex -soc "CompanyID2021"

AdFind V01.56.00cpp Joe Richards (support@joeware.net) April 2021

Using server: LO-DC3.lockout.test.loc:389
Directory: Windows Server 2016

dn:
> OpCode: 0x17
> Flags: 0x3F1FD
> Flags: DS_PDC_FLAG
> Flags: DS_GC_FLAG
> Flags: DS_LDAP_FLAG
> Flags: DS_DS_FLAG
> Flags: DS_KDC_FLAG
> Flags: DS_TIMESERV_FLAG
> Flags: DS_CLOSEST_FLAG
> Flags: DS_WRITABLE_FLAG
> Flags: DS_FULL_SECRET_DOMAIN_6_FLAG
> Flags: DS_WS_FLAG
> Flags: DS_DS_8_FLAG
> Flags: DS_DS_9_FLAG
> Flags: DS_DS_10_FLAG
> Flags: DS_KEYLIST_FLAG_JW
> DomainGuid: {56AD59A0-75A9-4ED4-B22A-1C987461A917}
> DnsForestName: lockout.test.loc
> DnsDomainName: lockout.test.loc
> DnsHostName: LO-DC3.lockout.test.loc
> NetbiosDomainName: LOCKOUT
> NetbiosComputerName: LO-DC3
> UserName: [EMPTY]
> DcSiteName: SITE2
> ClientSiteName: SITE2
> NextClosestSiteName: Default-First-Site-Name

1 Objects returned

Unfortunately the way the keystroke logging usually works when they are doing that it won’t catch environment variable predefines because they only watch what is typed… So if you had set something like

set joeware-default-adfind-soc=CompanyID2020

It wouldn’t be picked up. Sad really because then it would be child’s play to allow actual proper users to flag things to the SOC/IR as it would be unlikely that the bad actors would know to do it, well unless they were so deep into your environment that they watched you do it to lol. And some of you… Guess what, they are.

As an aside, over the years I have seen several cases where IR people were targeted by the hackers because they now often have some of the widest access to things and if you can pop an IR person you probably own most of the environment then and can also get into all of the tools watching everything. That is another reason why, IMO, IR people shouldn’t have admin rights to anything, they should have to reach out to the people who own the support for things to get their assistance. That is how we used to do it back in the day.

    joe

Rating 4.57 out of 5

4/28/2021

New Versions of AdFind and AdMod Posted

by @ 11:27 pm. Filed under tech, updates

I have released new versions of AdFind and AdMod.

Yeah I know I just said that I had released the last versions of both. I know. Trust me I know. I had packed the code away.

Then I had a single week where I was alerted to one absolutely horrible bug in AD (https://blog.joeware.net/2021/04/19/6068/) which absolutely required that I update AdFind and then a coworker stumbled upon a couple of other bugs or what I feel are bugs but would likely be argued by MSFT to not be bugs and instead be intended design that made me update AdMod. So I unpacked the code and made the changes along with some other things I had thought of after the “final compile”.

You can find the new versions in the normal places.

http://www.joeware.net/freetools/tools/adfind/

http://www.joeware.net/freetools/tools/admod/

Now to pack them away again…

    joe

Rating 4.67 out of 5

4/19/2021

Do NOT Use msds-memberTransitive and msds-memberOfTransitive

by @ 9:34 pm. Filed under general, tech

Ok, let me pull that title back a teeny tiny bit…

Do NOT Use msds-memberTransitive and msds-memberOfTransitive UNLESS you are absolutely positive that the number of values returned is guaranteed to be less than 4501 values.

What are you talking about joe and why are you railing about an attribute that has been around since Windows Server 2012 R2 and you haven’t let out the slightest peep about it before now???

The answer as to why I haven’t gotten the word out on this before is simply that I have been busy. But I digress…

Back to specific tirade for this issue… So while I had previously looked at msds-memberTransitive and msds-memberOfTransitive in a cursory manner and saw that yes, if I use it on administrators it shows me all 10 or less people/groups with that membership no matter how nested I didn’t have an opportunity to perform any real testing on it, much like MSFT apparently. Open-mouthed smile 

[Sun 04/18/2021 16:40:20.90]
E:\DEV\cpp\vs\AdFind\Release>adfind -f name=administrators -dsq | adfind msds-membertransitive -base

AdFind V01.56.00cppBETA Joe Richards (support@joeware.net) April 2021

Using server: LO-DC4.lockout.test.loc:389
Directory: Windows Server 2019 (10.0.17134.1)

dn:CN=Administrators,CN=Builtin,DC=lockout,DC=test,DC=loc
> msds-memberTransitive: CN=$$joe,CN=Users,DC=lockout,DC=test,DC=loc
> msds-memberTransitive: CN=$joe,CN=Users,DC=lockout,DC=test,DC=loc
> msds-memberTransitive: CN=Domain Admins,CN=Users,DC=lockout,DC=test,DC=loc
> msds-memberTransitive: CN=Enterprise Admins,CN=Users,DC=lockout,DC=test,DC=loc
> msds-memberTransitive: CN=Administrator,CN=Users,DC=lockout,DC=test,DC=loc

1 Objects returned

See… That actually IS pretty cool.

Certainly easier than trying to work through using LDAP_MATCHING_RULE_IN_CHAIN like so:

[Sun 04/18/2021 16:50:09.50]
E:\DEV\cpp\vs\AdFind\Release>adfind -f memberof:NEST:=CN=Administrators,CN=Builtin,DC=lockout,DC=test,DC=loc -bit -dn

AdFind V01.56.00cppBETA Joe Richards (support@joeware.net) April 2021

Transformed Filter: memberof:1.2.840.113556.1.4.1941:=CN=Administrators,CN=Builtin,DC=lockout,DC=test,DC=loc
Using server: LO-DC4.lockout.test.loc:389
Directory: Windows Server 2019 (10.0.17134.1)
Base DN: DC=lockout,DC=test,DC=loc

dn:CN=Administrator,CN=Users,DC=lockout,DC=test,DC=loc
dn:CN=Enterprise Admins,CN=Users,DC=lockout,DC=test,DC=loc
dn:CN=Domain Admins,CN=Users,DC=lockout,DC=test,DC=loc
dn:CN=$joe,CN=Users,DC=lockout,DC=test,DC=loc
dn:CN=$$joe,CN=Users,DC=lockout,DC=test,DC=loc

5 Objects returned

So, there you go, I didn’t look at it in any deep manner, just a quick and dirty check. For example I didn’t test (but I assumed based on how AD works) that it had the same issues I have pointed out previously with the Attribute Scoped Query control and Nested Membership control where if a linked value is out of scope for the DSA processing the request it will be missed so you won’t get a complete picture. People with single domains don’t have to worry about it (yet another reason to keep your forests very simple) but people with multiple domains in a forest need to be aware and watching out for it if they are using these advanced cool features.

Note that I *still* haven’t tested that “missing information due to DSA scope use case” because something else has been brought to my attention now that is even more silly. To be blunt, they implemented these constructed attributes completely outside the normal standards used in AD for returning multiple values. I am forced to wonder if the person who wrote the code for this functionality had ever used AD and pulled groups with large memberships before. Problems like this is what you see out of small time vendors who have an AD with 20 groups and 10 people and use that for all of their testing.

So the problem I am raising here with these attributes, msds-memberTransitive and msds-memberOfTransitive, comes into play when it has to leverage value ranging and its complete failure to do it properly.

You should already know what value ranging is, but as a reminder… Value ranging is when the number of values returned for an attribute would exceed the 1500 values limit policy that Active Directory has (MaxValRange) such that it sends back the values in batches of 1500 members. The LDAP client gets a response from the query for the object and attribute with the attribute listed but with no values and another attribute entry of the format attributename;range=0-1499 that contains the first batch of 1500 values (e.g. member;range=0-1499). This functionality is to help protect AD. If you have millions of users in a group you don’t want that all being returned in one single long response as it would tie up too much of the limited domain controller resources.

For example:

Query for all members of the group called biggroup. That group has 5000 members in it as you can see…

[Sun 04/18/2021 17:17:15.12]
E:\DEV\cpp\vs\AdFind\Release>adfind -b CN=biggroup,OU=TestBigGroup,DC=lockout,DC=test,DC=loc -base -csv -cv member
"dn","member"
"CN=biggroup,OU=TestBigGroup,DC=lockout,DC=test,DC=loc","5000"

The query for the actual direct members looks something like:

adfind -b CN=biggroup,OU=TestBigGroup,DC=lockout,DC=test,DC=loc member

On the wire, it looks like:

SNAGHTML1856d34f 

The response from Active Directory is:

SNAGHTML1859209a

SNAGHTML191e1e69

The presence of the “attribute” member;range=0-1499, really the originally requested attribute with the ranging option tacked on, alerts the LDAP client that there were more values available than AD was willing to send in one pass.

The LDAP client processes those 1500 values and then sends another LDAP query to retrieve the next 1500. That next query is similar to the first, it looks like this next query… Don’t worry AdFind does this under the covers for you but you can do it manually too if you like.

adfind -b CN=biggroup,OU=TestBigGroup,DC=lockout,DC=test,DC=loc member;range=1500-*

On the wire that looks like:

SNAGHTML191f0f32

and the response looks like:

SNAGHTML19204f05

SNAGHTML1921044b

So then the client processes those 1500 values and asks for member;range=3000-*…

This game of ping pong continues until the domain controller gets to the end of the values to be returned at which point the response from the domain controller changes slightly:

SNAGHTML1927f0c1

SNAGHTML192941da

Note that the response with the final result shows member;range=4500-*. The last value is “*” instead of an actual number. That alerts the LDAP client all of the data has been returned for that attribute and it doesn’t need to ask for any more values.

It is all quite simple.

Now to show how the msds-memberTransitive and msds-memberOfTransitive attributes completely fail to do any of this properly. Someone, apparently, in their infinite wisdom decided that you will only ever need to return 4500 values for these attributes and didn’t even do it the normal way. So they are wrong on both counts.

Given the following query:

adfind -b CN=biggroup,OU=TestBigGroup,DC=lockout,DC=test,DC=loc msds-membertransitive -base

On the wire it looks like:

SNAGHTML193dd9b4

and the response looks like:

SNAGHTML193ec675

SNAGHTML1940f3f4

As you can see, someone involved in the design or coding decided to return 4500 values instead of 1500 – completely against the policy defined in the LDAP query policy which could break some applications that assume that that policy is being followed. Well ok, that is fine, anyone that hard coded to that is probably asking for troubles anyway and any flexibly written ranging code should work just fine and handle that as it popped up. Instead of asking for msds-memberTransitive;range=1500-* for the next set, the code will ask for msds-memberTransitive;range=4500-*… Which one could reasonably expect to return another 4500 results.

One who assumes that would be completely wrong. Because… Well, some unknown person at MSFT.

Instead you ask for the next set like:

SNAGHTML1941d1a2

and get a very unexpected result of:

SNAGHTML1942c652

So literally no attributes returned and still a LDAP_SUCCESS result code.

Interestingly, if you try *any* range other than one that starts with 0 (even ;range=1-10) the operation fails with an LDAP_SUCCESS result code.

SNAGHTML1945897a

SNAGHTML194678ac

Note, I did not stumble upon this myself. Sadly. Instead, I was talking to someone in a AD software company that writes some top notch AD software and has the largest number of the best AD folks (and all a bunch of my long time friends) in any single company out there anymore. We were discussing how best to gather certain info and they mentioned this attribute and how AdFind crashes when it tries to enumerate the attribute if there are more than 4500 members. My initial response was “The hell it does!!!”. I knew my ranging code was generic enough and was solid. I wrote that routine 15 years ago and it has worked for millions, if not hundreds of millions or even billions of of queries and never had any issues reported around it.

So I tested it and they were right, <(*&#@%()^#*>, AdFind crashed when trying to enumerate msds-memberTransitive and msds-memberOfTransitive when they contained more than 4500 values. That started me looking at the adfind debug output which looked like:

DEBUG: In ranging… [1][msds-memberTransitive;range=0-4499]
DEBUG: Getting next range – [msds-membertransitive;Range=4500-*]

before the big crash dialog popped up…

First I thought “4500… WTAH? That is weird”. Later when I had a chance to dig more I pulled out WireShark and started watching the sequence and again my response was “WTAH??”.

I was able to find my bug quickly enough. I had never seen a ranging request come back with a STATUS_SUCCESS with no data. And the ranging subroutine was being stupid and just assumed there would be data so never validated that data came back and of course that meant I was trying to read data from memory that wasn’t there and so that landed me a nice unfriendly crash boom bang your app has crashed.

It was an easy fix. Make sure data was returned before trying to use it. Really it should have been there before but I will cut myself some little bit of slack because I barely knew what I was doing with the AD coding 15 years ago. Open-mouthed smile 

BUT, there is still a huge problem here… Incomplete data for this could be disastrous. Part of me actually liked the crash versus just returning data that I knew was incomplete. But another part of me really really hated that crash (and really really really hated not knowing it was crashing), so now what I do is return the data that is returned, *but* at the beginning of the result set it will now say:

ERROR:
ERROR: Failure in Range Retrieval for msds-membertransitive;range=4500-*
ERROR: LDAP_SUCCESS but range attribute not returned.
ERROR: Output for attribute msds-membertransitive is incomplete.
ERROR:

Because I consider this an absolutely critical issue and very possibly reporting dangerous misinformation for security purposes I have that same error message in the output whether or not it is standard output or CSV so it *will* screw up the CSV output. I *want* it to screw up the output.

Looking at the documentation for msds-memberTransitive and msds-memberOfTransitive there is no mention of this limitation or the odd value range handling. It is clearly the intended behaviour because it is so unlike standard ranging that someone had to make this decision purposefully. My expectation, as mentioned above, is that someone figured that 4500 was a larger number of members or memberships than any object would have. It is clearly wrong, I mean absolutely 100% wrong, especially on the msds-memberTransitive side but it is also very possible to be wrong on the msds-memberOfTransitive side. Not all groups are Security Enabled which maybe would have a reason for such a low ceiling. For example, I have seen companies that use non-Security Enabled groups for LDAP based applications and users were in thousands of non-Security enabled groups. I have also seen companies that were very heavy on Exchange Distribution Lists that do not have to be Security Enabled.

Further googling shows I am not the first to find this, though there seems to be some confusion around it and what might be going on so I thought I would spend the time to publish this blog post for it. Worse there are posts saying use this mechanism with no caveat of where it might go sideways on you. I have also found some hits where it has been specified that msds-memberOfTransitive isn’t a problem because authentication will break before you get to that many group memberships for a user. As mentioned above, that is absolutely incorrect. That statement assumes that every group is Security Enabled and that is not a valid assumption.

I thought about bugging this with MSFT but I am conflicted on whether or not it is the worth the time. From what I have seen the last few years, MSFT is letting Active Directory die on the vine. Unless the change drives Azure adoption the likelihood of a change seems to be about 0% so I am not sure it is worth my time to raise it to only be told again that they aren’t spending time working on on-premises AD/ADLDS.

 

    joe

Rating 4.57 out of 5

4/13/2021

AdFind / AdMod *Back* in the Garage.

by @ 12:38 am. Filed under general

I know I said I was putting them away, and I did. I locked down the code and started looking into other things.

However, three separate bugs in Windows, well two bugs in the OS and one in a Windows tool (my opinion on the bugs, not an admission from MSFT) that I couldn’t stand so I had to branch the code and update it to work around the issues found so now I am testing those changes making sure I didn’t mess something else up.

More to come on the issues encountered and the work arounds.

   joe

Rating 4.60 out of 5

4/11/2021

OpenLiveWriter and HTTP 409 Conflict Errors

by @ 10:49 pm. Filed under general

My blogging ability has been hampered for a while because OpenLiveWriter wasn’t working for me and throwing 409 Conflict errors when trying to talk to my blog. My last couple of posts were done through the web interface and anyone who knows me knows I don’t much like web interfaces, including the WordPress editor interface.

I figured something changed in WordPress in an update as I have it set up with auto-updates so spent a good amount of time digging through that and no joy. I started googling and quite a few complaints out there about XML-RPC and error 409 but no answers.

I dug into the raw web logs and noticed there was no record of the hits even if I just asked for the file itself with no POST (which actually would return the standard error) so I thought that perhaps my provider was mucking with access to the file under the covers so I copied the file to another filename in the same folder and specified that new name for the xmlrpc.php file in OpenLiveWriter and BOOM, it immediately worked.

   joe

Rating 4.60 out of 5

3/17/2021

New Versions of AdFind and… GASP…. AdMod Released

by @ 10:53 pm. Filed under tech, updates

I have released AdFind V01.55.00 and AdMod V01.22.00. 🙂  

AdFind

There are quite a few fixes and additions since the pre-Pandemic release. You can find a breakdown at http://www.joeware.net/freetools/tools/adfind/

AdMod

Surprise, it only took nine years to have a version of this I was comfortable enough to publicly release. Unlike AdFind, AdMod is exceptionally dangerous. If something is wrong it can really cause a lot of pain. So I am much slower to release updates.

The most exciting changes in AdMod in my mind are around the security descriptor functionality. In my opinion it is easier and WAAAAY faster than DSACLS and where DSACLS can only do a single object at a time AdMod will pop the security descriptors on multiple… Though… I will admit that DSACLS has better “you screwed up” assistance. I didn’t add code to catch every single bad/wrong thing that could be done which could result in it looking like it updated something but doesn’t or bail out with an error. It still uses the MSFT SDDL string to Security Descriptor functionality which has its own (sometimes apparently random) rules. I thought about writing the code to build my own binary security Descriptors but decided against it. 

When using the Security Descriptor functionality always add –exterr to get the better error messages, and possibly you will need to use –log and look at the admod.log file to see what it thought it was doing. Always test in lab environments to make sure you understand what it will do. Check out the Security Descriptor Shortcuts as they do some of the most common things people need in an easy manner and are less likely to be messed up.

You can find a breakdown on most of the changes/additions at http://www.joeware.net/freetools/tools/admod/

NOTE: You may notice that there are version jumps from whatever versions you may have. Yes, especially for AdMod I have versions that are not publicly released. It isn’t you, it’s me. 🙂  

NOTE 2: As of right now I am thinking these will be the last public releases of these tools unless I find some bad bugs or some cool functionality I absolutely want to put in and share. Microsoft’s investment in Active Directory has gotten worse and worse over the last 5 or so years and I don’t see it turning around unless someone there quickly figures out that that all Cloud all the time isn’t the future and I don’t see that happening; it is way better money for them right now to have people paying for Azure. So if they aren’t going to be investing in it and improving it etc there really isn’t a lot to with AdFind and AdMod now other than maybe focusing some energy on making them better for OpenLDAP which, you never know, may happy. Or it could be a whole new pair of tools written from scratch for OpenLDAP. The only think I have really thought about doing is to see how much work it will be to get them to compile successfully and run as x64 binaries. If that works out to not be too much work I will release those binaries.

If this is the end of the updates for these tools I would like to say it has been a pleasure working on them and making them better for folks and I love all of the emails over the years telling me how much time has been saved with them and how much has been accomplished that folks wouldn’t otherwise accomplish. I really loved hearing how people could dump “professional” tools that they had to pay for and use that money for other things.

I have a ton of other ideas I am planning on working on. Which ones I am really going to work on next? I am not sure yet.

    joe

Rating 4.60 out of 5

[joeware – never stop exploring… :) is proudly powered by WordPress.]